Daily updates from Odoo
Navigate
Branch
Monday, July 20, 2026
218 changes
12 changes
Enhancements to existing features
The French balance sheet report now presents establishment costs before fixed assets and includes several previously missing impairment accounts in tangible fixed asset lines. This improves the accuracy and alignment of statutory French financial reporting.
Original PR description
Move establishment costs before fixed assets in the French balance sheet, and include the missing 2912, 2913, 2914, and 2915 impairment accounts in the relevant tangible fixed asset amortization/provision lines. task-6226138 Forward-Port-Of: odoo/enterprise#124562 Forward-Port-Of: odoo/enterprise#117689
Resolved issues and error corrections
The payroll payslip list now handles the Off-Cycle filter correctly in debug mode. This prevents an error from appearing when viewing payslips without an associated pay run, improving reliability for payroll users.
Original PR description
Before this commit, when the user is in debug mode, goes to payslips list view and applies `Off-Cycle` filter, a traceback is occured saying `Invalid props for component 'PayslipActionHelper': 'payrunId' is not a number`.
The reason is because we search the id of the payrun by parsing the domain applied to fetch payslips displayed inside the list view but `Off-Cycle` filter will apply the following domain: `[('payslip_run_id', '=', False)]` and so False is given to PayslipActionHelper but it is not a number.
This commit makes sure to set undefined to payrunId prop of PayslipActionHelper when `payrun_id` found is falsy.
runbot-error-241053
Forward-Port-Of: odoo/enterprise#124854Fixes an issue where Mexican payroll CFDI documents failed for employers registered as individuals under fiscal regime 621. The system now uses the RFC length to identify individual employers and includes the required CURP in the XML, allowing payslip CFDI generation to complete successfully.
Original PR description
Issue: ---------------------------------------- There is a fiscal regime where the company is actually an individual but is authorized to generate documents. Steps to reproduce:…
Issue: ---------------------------------------- There is a fiscal regime where the company is actually an individual but is authorized to generate documents. Steps to reproduce: ---------------------------------------- - Install "l10n_mx_hr_payroll_account_edi" - Change the current company fiscal regime to '621' - Add an VAT of length 13 to the current company - Add a CURP number on the current company - In Payroll generate a payslip, validate it - Post the Journal entry - On the payslip, click "Generate CFDI" - An error is returned, saying the Emisor:Curp applies to individuals Cause: ---------------------------------------- An RFC of length 13 means that the sender is an individual. It's intended with the fiscal regime '621'. We add the curp number in the CFDI XML only when `self.company_id.partner_id.is_company` is `False`. Since saas-19.1, `is_company` is computed to be truely if a VAT is present. So as soon as the VAT is entered, the CURP number is absent from the XML. Solution: ---------------------------------------- We change the condition to add the CURP number in the XML: A VAT number of length 13 means the contact is an individual (12 for companies). This is what is used to validate the XML: if the vat is of length 13, then the curp number should be present. opw-6351558 Forward-Port-Of: odoo/enterprise#124728 Forward-Port-Of: odoo/enterprise#124027
Polish currency rate imports no longer shift the National Bank of Poland rate date by an extra day. This prevents rates from being dated incorrectly now that the system already selects the previous day's rate as required.
Original PR description
In Poland, it is mandatory to use the previous day's currency rate. We used to achieve this by shifting the rate's date by one day. Since https://github.com/odoo/odoo/pull/231948, we already use the previous day's rate, so the shift is no longer needed. See: https://www.odoo.com/mail/message/1118975071 Forward-Port-Of: odoo/enterprise#123849
The Timesheets shortcut now appears when a user can create timesheets in any selected company, not just the current one. This prevents eligible employees from missing the quick access option when working across multiple companies.
Original PR description
Steps to reproduce: - install Timesheets - create an employee for a user in company B - switch to company A (where the user has no employee) - the systray icon is hidden even though the user can…
Steps to reproduce: - install Timesheets - create an employee for a user in company B - switch to company A (where the user has no employee) - the systray icon is hidden even though the user can create timesheets in company B via the company selector Current behavior: the systray only checks the current company for a valid employee, ignoring other selected companies. Expected behavior: the systray should be visible whenever the user can create timesheets i.e. when they have an active employee in any of the selected companies. Issue: the check used a stored boolean on `res.partner` that has no company scope and becomes stale when an employee is archived (the stored dependency does not re-fire). the timesheet creation logic checks all selected companies for active employees, but the systray did not mirror that. Fix: use `employee_ids` a `One2many` that checks all selected companies and excludes archived employees, matching the timesheet creation logic exactly. task-6330539 Forward-Port-Of: odoo/enterprise#124761 Forward-Port-Of: odoo/enterprise#121730
Timesheet Assistant rule types now use updated colors so users can recognize different event types more quickly. This small visual fix improves readability and reduces confusion when reviewing timesheet-related suggestions.
Original PR description
This commit updates the color of AW rule types to help the user to quickly recognize the type of events based on the color. task-6186073
A subscription commission test now removes currency rate records across companies with the needed permissions, preventing demo data from other companies from affecting the result. This keeps commission calculations reliably tested when demo data is installed.
Original PR description
Steps to reproduce: 1- Initialize a new database with demo data 2- Run the test `test_sub_commission_no_currency_rate` Issue: `AssertionError: 0 != 10 : Regular invoice, 10 percent of 100` Why this happens: The test used to delete all rows in the res_currency_rate table for the current company only. When we load the database with demo data, the query in `_get_subscription_currency_rates` would find entries for the other companies and wouldn't resort to the default. Later when joining, it would find no rates for the current company and the test fails. runbot-243440 Forward-Port-Of: odoo/enterprise#116197
VoIP call screens now hide related record buttons when a call is not linked to a customer or contact, preventing unexpected errors. Subscription buttons are also shown consistently with the customer view, improving behavior across sales, CRM, helpdesk, and recruitment call workflows.
Original PR description
Same as in [1], we don't show smart buttons when no partner to prevent unexpected errors. Also remove `invisible="subscription_count == 0"` to make it same as smart button on res.partner. [1]: 0fbb730e02de22b196a45455f801e96321a75167 Forward-Port-Of: odoo/enterprise#124579
Users can no longer trigger a server error by creating a new unmatched name directly from the commission adjustments list. The change keeps sales commission adjustment entry stable by requiring selection of existing commission users instead of allowing an invalid quick-create action.
Original PR description
Steps to reproduce: - Go to Sales > Commission > Adjustments - In Add to/Reduce From, type a name with no match - Click Create '<name>' -> server crashes (RPC_ERROR) Cause: `sale.commission.plan.user._rec_name` is a Many2one (`user_id`). Default `name_create` wrote the typed text into that integer column, which Postgres rejected. Fix: - Disable quick-create on `add_user_id`/`reduce_user_id` in the Adjustments list view Version: saas-18.3 to master opw-6384909 Forward-Port-Of: odoo/enterprise#124431
AI-generated answers that include web citations now keep their original spacing, lists, and paragraph breaks. This prevents cited answers from appearing merged together, making responses easier for users to read and trust.
Original PR description
AI responses containing web citations lost their original formatting when a citation appeared at the end of a line, causing lists and paragraphs to be merged together. This commit limits the citation parser to ignore only horizontal whitespace around citations, preserving line breaks in the rendered response. task-6391187 Forward-Port-Of: odoo/enterprise#124457
Belgian payroll now correctly treats employees marked as judicially separated when calculating withholding taxes and special social contributions. This prevents affected payslips from missing required deductions and producing incorrect net pay amounts.
Original PR description
**Steps to Reproduce:** 1. Create a new employee. 2. Set their marital status to "Judicially Separated". 3. Generate a payslip. **Reason:** - The "Judicially Separated" marital status was not explicitly included in the conditions for calculating withholding taxes or special social contributions. As a result, employees with this status bypassed the calculations entirely, receiving a rate of 0 for both and a significantly larger reduction on master which also appears to be incorrect. **Solution:** - Included the 'separated' status in isolated tax and CSSS logic. Task-6321245 Forward-Port-Of: odoo/enterprise#122749 Forward-Port-Of: odoo/enterprise#121457
### Issue: The 'Schedule an appointment' and 'Next Events' CTA buttons were not updated even when their conditions were satisfied. ### Steps to reproduce: - Install only Website. - In the configurator, choose 'Schedule Appointments' as the main objective. - Complete the setup and create the website. - The CTA button remains 'Contact Us' instead of 'Schedule an appointment'. ### Reason: The `get_cta_data()` method is overridden in specific modules to update the CTA button base
Original PR description
### Issue: The 'Schedule an appointment' and 'Next Events' CTA buttons were not updated even when their conditions were satisfied. ### Steps to reproduce: - Install only Website. - In the configurator, choose 'Schedule Appointments' as the main objective. - Complete the setup and create the website. - The CTA button remains 'Contact Us' instead of 'Schedule an appointment'. ### Reason: The `get_cta_data()` method is overridden in specific modules to update the CTA button based on conditions. However, it is called before those modules are installed, so the overridden logic is never executed. ### Fix: Ensure that `get_cta_data()` is called and the CTA button is updated after the required modules are installed. task-[6383681](https://www.odoo.com/odoo/project/974/tasks/6383681) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261781
10 changes
Enhancements to existing features
Adds an automatic cleanup script for the Belgian POS blackbox module so copied or neutralized databases no longer keep device IP addresses or establishment identifiers. This helps prevent test or staging environments from accidentally retaining production point-of-sale configuration details.
Original PR description
Add a `neutralize.sql` file to the `l10n_be_pos_blackbox` module to reset the blackbox `local_ip` and the config's `l10n_be_pos_id` and `establishment_number`. FW of PR: https://github.com/odoo/enterprise/pull/124258
The French balance sheet report now presents establishment costs before fixed assets and includes additional impairment accounts in tangible fixed asset provision lines. This improves report accuracy and alignment with expected French accounting presentation.
Original PR description
Move establishment costs before fixed assets in the French balance sheet, and include the missing 2912, 2913, 2914, and 2915 impairment accounts in the relevant tangible fixed asset amortization/provision lines. task-6226138 Forward-Port-Of: odoo/enterprise#124562 Forward-Port-Of: odoo/enterprise#117689
Resolved issues and error corrections
Fixes an issue where clicking the AI icon could fail if the default AI prompt had been duplicated. The system now selects one matching AI composer record, preventing an error and keeping the AI menu accessible for users.
Original PR description
Currently an error is generated when the user clicks on the AI icon as per the below steps: - Install `ai_app` - Go to `AI` > Configuration > Default Prompts - Duplicate `Ask AI` record…
Currently an error is generated when the user clicks on the AI icon as per the below steps: - Install `ai_app` - Go to `AI` > Configuration > Default Prompts - Duplicate `Ask AI` record (`ai.composer`) - An error occurs on clicking the `AI` icon on the navbar menu systray Error: `ValueError: Expected singleton: ai.composer(4, 14)` This issue was introduced during the refactoring in [1]. In the previous implementation, the AI Composer search was executed with `limit=1` (see [2]), ensuring that only a single composer record was returned. After the changes in [1], the limit=1 constraint was removed (see [3]), causing the search to return multiple composer records. As a result, the code now encounters an error when it expects a single record. This commit fixes the issue by adding `limit=1` to the AI Composer search, ensuring that only a single record is returned. [1]: https://github.com/odoo/enterprise/commit/800208fdc485b9e37f77648a01100b8eff118490 [2]: https://github.com/odoo/enterprise/blob/188dcc5078be7c7fee1a52f86505144d3b6309cf/ai/models/ai_composer.py#L71-L83 [3]: https://github.com/odoo/enterprise/blob/2972805fd1a4daacd7f1c47d5e3c7672e2aec61c/ai/models/ai_composer.py#L74-L77 Sentry-7549108967
This fix updates the project forecasting screen so its subtask button correctly connects to the current subtask action. It prevents the button customization from targeting an outdated control, helping users access subtasks reliably.
Original PR description
Issue --- The inherited xpath still targets the old action-based subtask button Fix --- Update the inherited xpath to target action_open_subtasks. task-5966684 Forward-Port-Of: odoo/enterprise#124063 Forward-Port-Of: odoo/enterprise#123035
Polish currency rates from NBP are no longer shifted by an extra day because the system already applies the required previous-day rate. This prevents rates from being dated too far back and helps ensure currency conversions use the correct official rate.
Original PR description
In Poland, it is mandatory to use the previous day's currency rate. We used to achieve this by shifting the rate's date by one day. Since https://github.com/odoo/odoo/pull/231948, we already use the previous day's rate, so the shift is no longer needed. See: https://www.odoo.com/mail/message/1118975071 Forward-Port-Of: odoo/enterprise#123849
AI-generated answers with web citations now keep their original line breaks and spacing. This prevents lists and paragraphs from being merged together, making cited AI responses easier to read and understand.
Original PR description
AI responses containing web citations lost their original formatting when a citation appeared at the end of a line, causing lists and paragraphs to be merged together. This commit limits the citation parser to ignore only horizontal whitespace around citations, preserving line breaks in the rendered response. task-6391187
This fix stops the spreadsheet view from continuing a synchronization step when the spreadsheet model fails to load. Users will still receive the intended notification, but the system will avoid an additional traceback that could disrupt the experience.
Original PR description
Current behavior before PR: - In 4204ceb, model creation errors were caught and a notification was shown to the user. - However, syncSheetFromRouter() was still called afterward. Since it relies on model getters, it raise a traceback when no model existed. Desired behavior after PR is merged: - Call syncSheetFromRouter() only after the model has been created successfully. - This prevents accessing model getters when model creation fails and avoids the resulting traceback. Task: [6355245](https://www.odoo.com/odoo/project/2328/tasks/6355245)
Belgian payroll now correctly treats employees marked as judicially separated when calculating withholding tax and special social security contributions. This prevents affected payslips from incorrectly applying a zero rate or excessive reductions, improving payroll accuracy and compliance.
Original PR description
**Steps to Reproduce:** 1. Create a new employee. 2. Set their marital status to "Judicially Separated". 3. Generate a payslip. **Reason:** - The "Judicially Separated" marital status was not explicitly included in the conditions for calculating withholding taxes or special social contributions. As a result, employees with this status bypassed the calculations entirely, receiving a rate of 0 for both and a significantly larger reduction on master which also appears to be incorrect. **Solution:** - Included the 'separated' status in isolated tax and CSSS logic. Task-6321245 Forward-Port-Of: odoo/enterprise#122263 Forward-Port-Of: odoo/enterprise#121457
The Commission Adjustments screen no longer offers a quick-create option that could crash when entering a new unmatched user name. This helps sales teams avoid errors while managing commission adjustments.
Original PR description
Steps to reproduce: - Go to Sales > Commission > Adjustments - In Add to/Reduce From, type a name with no match - Click Create '<name>' -> server crashes (RPC_ERROR) Cause: `sale.commission.plan.user._rec_name` is a Many2one (`user_id`). Default `name_create` wrote the typed text into that integer column, which Postgres rejected. Fix: - Disable quick-create on `add_user_id`/`reduce_user_id` in the Adjustments list view Version: saas-18.3 to master opw-6384909 Forward-Port-Of: odoo/enterprise#124431
This PR hides the Upgrade button for modules imported via file, as these modules cannot be upgraded without re-importing a file. Displaying the upgrade button in such cases could lead to confusion or unexpected behavior. Task: 4643890 Forward-Port-Of: odoo/odoo#213122
Original PR description
This PR hides the Upgrade button for modules imported via file, as these modules cannot be upgraded without re-importing a file. Displaying the upgrade button in such cases could lead to confusion or unexpected behavior. Task: 4643890 Forward-Port-Of: odoo/odoo#213122
10 changes
Enhancements to existing features
The timesheet assistant now supports keyboard controls for moving through and selecting suggestions. This improves accessibility and helps users manage timesheet entries more efficiently without relying on a mouse.
Original PR description
Implement full keyboard controls for managing timesheet suggestions to improve accessibility and user efficiency. This adds support for the following interactions: - ArrowUp / ArrowDown to navigate focus through rows - Space to select/deselect the focused item (and set the selection anchor) - Shift + Arrows to select continuous ranges of suggestions task: 6267620
The French balance sheet report now places establishment costs before fixed assets and includes additional impairment accounts in the relevant tangible fixed asset lines. This improves report consistency and helps ensure fixed asset values are presented more completely for French reporting.
Original PR description
Move establishment costs before fixed assets in the French balance sheet, and include the missing 2912, 2913, 2914, and 2915 impairment accounts in the relevant tangible fixed asset amortization/provision lines. task-6226138 Forward-Port-Of: odoo/enterprise#124562 Forward-Port-Of: odoo/enterprise#117689
Resolved issues and error corrections
WhatsApp message lists no longer fail when a related calendar appointment or contact has been deleted. This keeps reminder history readable and prevents one broken reminder from stopping other queued WhatsApp messages from being sent.
Original PR description
Root cause: WhatsApp reminders are logged as mail.message records on calendar.attendee, which is not a mail.thread. Deleting a calendar event or a partner removes the attendees through the database…
Root cause: WhatsApp reminders are logged as mail.message records on calendar.attendee, which is not a mail.thread. Deleting a calendar event or a partner removes the attendees through the database cascades on calendar.attendee.event_id and calendar.attendee.partner_id, which do not call calendar.attendee.unlink, so each reminder keeps a model and res_id pointing to an attendee that no longer exists. mail.message access filters the related documents through exists() since https://github.com/odoo/odoo/commit/617d4a32409b730e0fb7d351553e4c6e10bf6c5f, so a reminder whose attendee is gone is no longer readable by anyone but its author or recipient. whatsapp.message.body reads mail.message.body without sudo, so opening WhatsApp > Messages raises an access error on the orphaned reminders, and the queue retry cron hits the same error and stops sending the rest of the queue. Fix: Read the related body with sudo. Orphaned messages are not specific to whatsapp, any model that is not a mail.thread keeps its messages after a record is deleted, so cleaning them up is a mail framework concern rather than a whatsapp one. One message the user cannot read should not block the whole message list. Who can read the body stays controlled by the access rights of whatsapp.message itself. Steps to reproduce: 1. Install WhatsApp and configure an account 2. Create an Appointment Type with a WhatsApp reminder 3. Book an appointment to create the calendar event 4. Settings > Technical > Automation > Scheduled Actions > Calendar: Event Reminder > Run Manually so the reminder is sent 5. Open the calendar event and delete it with the trash icon, not Cancel 6. Open WhatsApp > Messages => Access error, the user has no access to the mail.message Ticket [link](https://www.odoo.com/odoo/project.task/6297099) opw-6297099
QR-IBAN payment references are now sanitized before validation when generating ISO 20022 payment files. This helps prevent Swiss bank rejections caused by unsupported characters in payment references while keeping valid QR references intact.
Original PR description
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with…
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with a valid Swiss bank account. * Under **Accounting -> Configuration -> Settings** enable QR Payments. * Go to the vendor and enter the correct QR-IBAN number under the Accounting Section. * Navigate to **Accounting -> Configuration -> Journals** and in the **bank** journal, add the account number of QR-IBAN. * Create and post a vendor payment using the bank journal. * Set the payment reference (`ref`) to contain the `°` character. * Add the payment to a batch payment and generate the ISO 20022 payment file. * Inspect the generated XML. **Observed Behaviour:** The `°` character is preserved in the payment reference for QR-IBAN payments, producing an ISO 20022 file that may be rejected by Swiss banks because it does not comply with the EPC minimum character set. **Cause:** The QR-IBAN branch validates the structured reference before sanitizing it, allowing unsupported characters to remain in the generated XML. **Fix:** Sanitize the payment reference before validating it as a QR structured reference, ensuring invalid characters are removed while preserving valid QR references. opw - 6350931 Forward-Port-Of: odoo/enterprise#124299 Forward-Port-Of: odoo/enterprise#123267
The restaurant appointment point-of-sale test was adjusted to avoid repeating a data reload step that could cause false test failures. This improves test reliability without changing the normal user experience, since users are not expected to perform these immediate back-to-back reloads.
Original PR description
The `RestaurantAppointmentTour` performed two consecutive "Reload Data" actions. The first reload starts synchronizing data from the server to IndexedDB. If the second reload is triggered before the synchronization completes, it deletes the IndexedDB while it is still in use, causing the synchronization process to crash. This race condition can be reproduced locally by running the tour with `cpu_throttling` enabled. In practice, users never trigger two consecutive reloads, so the second reload step in the tour is unnecessary. Remove it to avoid the artificial race condition while preserving the intended test coverage. Task-[6364951](https://www.odoo.com/odoo/project/1737/tasks/6364951) Runbot Error-[941343](https://runbot.odoo.com/odoo/error/941343), [941344](https://runbot.odoo.com/odoo/error/941344), [941345](https://runbot.odoo.com/odoo/error/941345)
This fix keeps existing tax returns aligned when their allowed workflow steps are changed, such as during upgrades. It prevents errors when viewing return lists and moves returns out of statuses that are no longer valid.
Original PR description
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only…
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only accepts "review" and "submit" stages, not "paid" anymore 4) Go to the list of returns, remove the TODO filter => traceback The problem is here that the existing returns don't recompute their state when the workflow of the type is modified. In some cases, this is fine, but it others, it's annoying. In our example, the terminal state changed, so all the returns in that terminal stage should change their state to the new terminal one. "paid" is not an accepted value anymore, it should become "submitted". Moreover, when the workflow is changed, the selection field actually containing the state must also change. As it is, it seems to work because "state" of account.return is stored, but the value it's based on (the workflow field) won't be consistent with it. It's not annoying now, but those inconsistencies could become a big source of trouble in the future (we know that from experience ... I'm looking at you, version 8 ! è-é). This issue typically happens at upgrade. We had cases in FR and AE already. We solve that by a generic override of the write to sort things out when such change needs to happen. An upgrade PR will also be done to adapt the script so that we eventually solve the inconsistencies on dbs that have already migrated to 19.0. Forward-Port-Of: odoo/enterprise#124144
Users can no longer trigger a server error by typing an unknown name in the Add to or Reduce From fields on commission adjustments. The change removes an unsupported quick-create option, keeping the adjustment workflow stable and avoiding confusing error messages.
Original PR description
Steps to reproduce: - Go to Sales > Commission > Adjustments - In Add to/Reduce From, type a name with no match - Click Create '<name>' -> server crashes (RPC_ERROR) Cause: `sale.commission.plan.user._rec_name` is a Many2one (`user_id`). Default `name_create` wrote the typed text into that integer column, which Postgres rejected. Fix: - Disable quick-create on `add_user_id`/`reduce_user_id` in the Adjustments list view Version: saas-18.3 to master opw-6384909 Forward-Port-Of: odoo/enterprise#124431
Invoices marked as excluded from follow-up will no longer be attached to reminder emails or included in printed follow-up letters. This prevents customers from receiving payment reminders for invoices the business intentionally left out.
Original PR description
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the…
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the invoice. 3. Open the contact form and click on the Customer Statement smart button 4. Exclude the invoice using the 'No Follow-Up' toggle 5. In the Accounting tab in the contact form, click on send 6. Open the internal link of the Content Template, go to the options tab and select 'Print Follow-up Letter' in Dynamic Reports 7. Save the configuration and send the email Issue: Excluded invoices still appeared as PDF attachments in the follow-up email and were merged into the printed follow-up letter PDF. Why this happens: Both `default_get` in `account_followup.manual_reminder` and `_get_invoices_to_print` in `res.partner` traversed `unreconciled_aml_ids` without filtering out lines where `no_followup = True`, so excluded invoices were included regardless. opw-6310602 Forward-Port-Of: odoo/enterprise#124750 Forward-Port-Of: odoo/enterprise#122249
Polish currency rates from NBP are no longer shifted by an extra day because the system already uses the required previous day's rate. This prevents rates from being dated too far back and helps Polish accounting use the correct exchange rate dates.
Original PR description
In Poland, it is mandatory to use the previous day's currency rate. We used to achieve this by shifting the rate's date by one day. Since https://github.com/odoo/odoo/pull/231948, we already use the previous day's rate, so the shift is no longer needed. See: https://www.odoo.com/mail/message/1118975071 Forward-Port-Of: odoo/enterprise#123849
This PR hides the Upgrade button for modules imported via file, as these modules cannot be upgraded without re-importing a file. Displaying the upgrade button in such cases could lead to confusion or unexpected behavior. Task: 4643890 Forward-Port-Of: odoo/odoo#213122
Original PR description
This PR hides the Upgrade button for modules imported via file, as these modules cannot be upgraded without re-importing a file. Displaying the upgrade button in such cases could lead to confusion or unexpected behavior. Task: 4643890 Forward-Port-Of: odoo/odoo#213122
10 changes
Resolved issues and error corrections
Argentine electronic invoices for final consumers now validate the customer's identification type before processing. This prevents a technical error during invoice confirmation and instead shows a clear warning when the ID type is not accepted.
Original PR description
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina…
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina - Identification Type: `Passport` - Identification Number: `1234567890a` - AFIP Responsibility Type: `Consumidor Final` - Create a new invoice for this customer with: - Journal: `Electronic Invoice (FE)` - Document Type: `(6) INVOICES B` - Try to confirm the invoice. **Error:** ValueError: invalid literal for int() with base 10: '1234567890a' **Expected behaviour:** For Argentinean contacts with AFIP Responsibility Type `Consumidor Final`, the identification type must be `DNI` or `CUIL/CUIT`. If another identification type is used, the user should receive a proper warning instead of a traceback. (see [1]) **Root Cause:** After the community fix, `_get_id_number_sanitize()` can return an alphanumeric value, which is later converted with `int()` at [2] and [3], causing an error. **Fix:** This commit adds an explicit validation for Argentinean contacts with AFIP Responsibility Type Consumidor Final before converting the identification number to an integer, ensuring the user receives the proper warning message. [1]: https://www.odoo.com/mail/message/1118392033 [2]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L780-L798 [3]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L927-L931 Related community PR: https://github.com/odoo/odoo/pull/272651 opw-6333998 Forward-Port-Of: odoo/enterprise#123729
The planning kanban card now shows allocated time in a simpler, consistent format such as (4h30). Removing the separate percentage display fixes uneven spacing and makes schedules easier to scan.
Original PR description
Currently, the allocated hours and allocated percentage are misaligned in the planning kanban card, causing them to appear uneven or have inconsistent spacing. This fix removes the allocated percentage and formats the allocated hours to display like (4h30). task-5085363 Forward-Port-Of: odoo/enterprise#98776
Envia shipping rate requests now include insurance in the format expected by the carrier API. This ensures quotes reflect the selected insurance amount, so customers and sales teams see more accurate delivery costs.
Original PR description
Issue ----- Insurance request is not reflected on the rating given by Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - Create a MX client - Create a product (with some weight) - Create a SO - Add the product - Add envia delivery and get a rate - Update Envia delivery method - Set insurance to 50% - Go back to the SO - Add envia delivery and get a rate > The rate is the same both times Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment Follow up of 7258e4a ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#124700
Barcode transfers now apply a default limit when loading reusable packages, preventing very large package lists from slowing down the screen. This reduces long wait times for warehouses with tens of thousands of packages and makes transfer opening more reliable.
Original PR description
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local…
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local testing. The client of the tickets experiences loadings up to 120 seconds with 50k packages # Cause When opening a transfer, we load barcode data by doing an API call to `_get_stock_barcode_data` : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L85 During this we preload a lot of records, notably packages : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L128 The issue is that in the fields we read for the packages, two of them (`location_dest_id` & `contained_quant_ids`) have a `_read_group` in their compute (or in the compute of one of the fields they depend on) : https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L65 https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L146 Fortunately, this does not mean that we make a query for every records. Instead, in Odoo, we fetch records in batch of 1000. So, for the case of the client, every time he loads the database, the backend does 50 000 / 1000 x 2 = 100 queries, which hinders performance a lot A [PERF] commit was done to limit the number of packages that are fetched base on a config parameter. The problem is that this parameter does not have a default value, so clients still end up with the problem. [PERF]: https://github.com/odoo/enterprise/commit/efe18bc1ea479270e42846986d7ed449b0865617 # Proposed Solution Add a default value for that config parameter. The exact value is up to discussion opw-6200730 Forward-Port-Of: odoo/enterprise#123696
Philippine check printing now rounds the cents portion of amounts in words to two decimal places, even when the currency is configured with more precision. This prevents checks from showing incorrect fractional text such as 1268/100 instead of 13/100, reducing confusion and payment errors.
Original PR description
Current behavior: --- When paying with checks, if the currency has more than 2 decimals, the decimal amount is printed with more than 2 decimals. Steps to reproduce: --- 1. Switch to PH company 2. Set setting Check Layout as "Print Check - PH" 3. In the PHP currency, change rounding factor to 0.0001 4. In Decimal accuracy > product price, set 4 digits 5. Create a new Vendor Payment, payment method Check, amount 100.1268 PHP 6. Results: One Hundred and 1268/100, should be 13/100 Expected behavior: --- The xx/100 part of amount in words text in the check should always be rounded to 2 decimals. opw-6302337 Forward-Port-Of: odoo/enterprise#122581 Forward-Port-Of: odoo/enterprise#121913
This fixes an issue where tax returns could keep an outdated status after the allowed workflow steps were changed, which could cause errors when viewing return lists. Existing returns are now adjusted to valid statuses when workflows change, helping upgrades and country-specific tax processes run more reliably.
Original PR description
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only…
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only accepts "review" and "submit" stages, not "paid" anymore 4) Go to the list of returns, remove the TODO filter => traceback The problem is here that the existing returns don't recompute their state when the workflow of the type is modified. In some cases, this is fine, but it others, it's annoying. In our example, the terminal state changed, so all the returns in that terminal stage should change their state to the new terminal one. "paid" is not an accepted value anymore, it should become "submitted". Moreover, when the workflow is changed, the selection field actually containing the state must also change. As it is, it seems to work because "state" of account.return is stored, but the value it's based on (the workflow field) won't be consistent with it. It's not annoying now, but those inconsistencies could become a big source of trouble in the future (we know that from experience ... I'm looking at you, version 8 ! è-é). This issue typically happens at upgrade. We had cases in FR and AE already. We solve that by a generic override of the write to sort things out when such change needs to happen. An upgrade PR will also be done to adapt the script so that we eventually solve the inconsistencies on dbs that have already migrated to 19.0. Forward-Port-Of: odoo/enterprise#124144
Users can no longer trigger a server error by creating a new entry directly from the Add to or Reduce From fields in Sales Commission Adjustments. The change disables that shortcut so adjustments can be edited safely without interrupting the workflow.
Original PR description
Steps to reproduce: - Go to Sales > Commission > Adjustments - In Add to/Reduce From, type a name with no match - Click Create '<name>' -> server crashes (RPC_ERROR) Cause: `sale.commission.plan.user._rec_name` is a Many2one (`user_id`). Default `name_create` wrote the typed text into that integer column, which Postgres rejected. Fix: - Disable quick-create on `add_user_id`/`reduce_user_id` in the Adjustments list view Version: saas-18.3 to master opw-6384909 Forward-Port-Of: odoo/enterprise#124431
Payment references for Swiss QR-IBAN vendor payments are now sanitized before generating ISO 20022 payment files. This helps prevent bank rejections caused by unsupported characters while keeping valid QR payment references intact.
Original PR description
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with…
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with a valid Swiss bank account. * Under **Accounting -> Configuration -> Settings** enable QR Payments. * Go to the vendor and enter the correct QR-IBAN number under the Accounting Section. * Navigate to **Accounting -> Configuration -> Journals** and in the **bank** journal, add the account number of QR-IBAN. * Create and post a vendor payment using the bank journal. * Set the payment reference (`ref`) to contain the `°` character. * Add the payment to a batch payment and generate the ISO 20022 payment file. * Inspect the generated XML. **Observed Behaviour:** The `°` character is preserved in the payment reference for QR-IBAN payments, producing an ISO 20022 file that may be rejected by Swiss banks because it does not comply with the EPC minimum character set. **Cause:** The QR-IBAN branch validates the structured reference before sanitizing it, allowing unsupported characters to remain in the generated XML. **Fix:** Sanitize the payment reference before validating it as a QR structured reference, ensuring invalid characters are removed while preserving valid QR references. opw - 6350931 Forward-Port-Of: odoo/enterprise#124299 Forward-Port-Of: odoo/enterprise#123267
Employee appraisals now use the template assigned to the employee's department instead of keeping a generic default. This helps HR teams apply the right appraisal questions and process for each department without manual correction.
Original PR description
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create…
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create an appraisal template and restrict it to a department. 2. Make sure at least one global (no department) template also exists. 3. Open a new appraisal and select an employee of that department. 4. Observe the appraisal template stays on the global one. **Current behavior:** The global template that was auto-selected before an employee was chosen is kept, ignoring the department-restricted template. **Expected behavior:** The template restricted to the employee's department is selected. **Cause of the issue:** On a new appraisal the template is computed before an employee (and therefore a department) is set, so a global template is pre-selected. When the employee is then chosen, `_compute_appraisal_template` reruns but the `appraisal.appraisal_template_id or ...` clause short-circuits on the already set global template and never falls through to the department's template. **Fix:** Evaluating the department's template before the existing value ensures a department-restricted template takes precedence over a template that was only auto-selected as a default. The existing value is still preserved when the department has no template of its own, so deliberate choices are untouched. opw-6293936 Forward-Port-Of: odoo/enterprise#121377
This PR hides the Upgrade button for modules imported via file, as these modules cannot be upgraded without re-importing a file. Displaying the upgrade button in such cases could lead to confusion or unexpected behavior. Task: 4643890 Forward-Port-Of: odoo/odoo#213122
Original PR description
This PR hides the Upgrade button for modules imported via file, as these modules cannot be upgraded without re-importing a file. Displaying the upgrade button in such cases could lead to confusion or unexpected behavior. Task: 4643890 Forward-Port-Of: odoo/odoo#213122
4 changes
Resolved issues and error corrections
Argentine electronic invoices now validate that final consumer customers use an accepted identification type before invoice confirmation. Instead of a technical crash when a passport or other unsupported ID contains letters, users receive a clear warning so they can correct the customer record.
Original PR description
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina…
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina - Identification Type: `Passport` - Identification Number: `1234567890a` - AFIP Responsibility Type: `Consumidor Final` - Create a new invoice for this customer with: - Journal: `Electronic Invoice (FE)` - Document Type: `(6) INVOICES B` - Try to confirm the invoice. **Error:** ValueError: invalid literal for int() with base 10: '1234567890a' **Expected behaviour:** For Argentinean contacts with AFIP Responsibility Type `Consumidor Final`, the identification type must be `DNI` or `CUIL/CUIT`. If another identification type is used, the user should receive a proper warning instead of a traceback. (see [1]) **Root Cause:** After the community fix, `_get_id_number_sanitize()` can return an alphanumeric value, which is later converted with `int()` at [2] and [3], causing an error. **Fix:** This commit adds an explicit validation for Argentinean contacts with AFIP Responsibility Type Consumidor Final before converting the identification number to an integer, ensuring the user receives the proper warning message. [1]: https://www.odoo.com/mail/message/1118392033 [2]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L780-L798 [3]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L927-L931 Related community PR: https://github.com/odoo/odoo/pull/272651 opw-6333998 Forward-Port-Of: odoo/enterprise#123729
Commission adjustment screens no longer allow quick creation in the Add to or Reduce From fields, avoiding a server error when users type a new unmatched name. This keeps the adjustment workflow stable and prevents interruptions for sales commission administrators.
Original PR description
Steps to reproduce: - Go to Sales > Commission > Adjustments - In Add to/Reduce From, type a name with no match - Click Create '<name>' -> server crashes (RPC_ERROR) Cause: `sale.commission.plan.user._rec_name` is a Many2one (`user_id`). Default `name_create` wrote the typed text into that integer column, which Postgres rejected. Fix: - Disable quick-create on `add_user_id`/`reduce_user_id` in the Adjustments list view Version: saas-18.3 to master opw-6384909 Forward-Port-Of: odoo/enterprise#124431
Philippine check printing now rounds the cents portion of written payment amounts to two decimals, even when the currency is configured with more precision. This prevents checks from showing incorrect fractional amounts such as 1268/100 instead of 13/100.
Original PR description
Current behavior: --- When paying with checks, if the currency has more than 2 decimals, the decimal amount is printed with more than 2 decimals. Steps to reproduce: --- 1. Switch to PH company 2. Set setting Check Layout as "Print Check - PH" 3. In the PHP currency, change rounding factor to 0.0001 4. In Decimal accuracy > product price, set 4 digits 5. Create a new Vendor Payment, payment method Check, amount 100.1268 PHP 6. Results: One Hundred and 1268/100, should be 13/100 Expected behavior: --- The xx/100 part of amount in words text in the check should always be rounded to 2 decimals. opw-6302337 Forward-Port-Of: odoo/enterprise#122581 Forward-Port-Of: odoo/enterprise#121913
Swiss QR-IBAN payment references are now cleaned before payment files are generated. This prevents unsupported characters from causing ISO 20022 payment files to be rejected by Swiss banks.
Original PR description
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with…
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with a valid Swiss bank account. * Under **Accounting -> Configuration -> Settings** enable QR Payments. * Go to the vendor and enter the correct QR-IBAN number under the Accounting Section. * Navigate to **Accounting -> Configuration -> Journals** and in the **bank** journal, add the account number of QR-IBAN. * Create and post a vendor payment using the bank journal. * Set the payment reference (`ref`) to contain the `°` character. * Add the payment to a batch payment and generate the ISO 20022 payment file. * Inspect the generated XML. **Observed Behaviour:** The `°` character is preserved in the payment reference for QR-IBAN payments, producing an ISO 20022 file that may be rejected by Swiss banks because it does not comply with the EPC minimum character set. **Cause:** The QR-IBAN branch validates the structured reference before sanitizing it, allowing unsupported characters to remain in the generated XML. **Fix:** Sanitize the payment reference before validating it as a QR structured reference, ensuring invalid characters are removed while preserving valid QR references. opw - 6350931 Forward-Port-Of: odoo/enterprise#124299 Forward-Port-Of: odoo/enterprise#123267
2 changes
Resolved issues and error corrections
Philippine check printing now rounds the fractional amount in words to two decimal places, even when the currency is configured with more precision. This prevents checks from showing incorrect cent values such as 1268/100 instead of 13/100, reducing confusion and payment errors.
Original PR description
Current behavior: --- When paying with checks, if the currency has more than 2 decimals, the decimal amount is printed with more than 2 decimals. Steps to reproduce: --- 1. Switch to PH company 2. Set setting Check Layout as "Print Check - PH" 3. In the PHP currency, change rounding factor to 0.0001 4. In Decimal accuracy > product price, set 4 digits 5. Create a new Vendor Payment, payment method Check, amount 100.1268 PHP 6. Results: One Hundred and 1268/100, should be 13/100 Expected behavior: --- The xx/100 part of amount in words text in the check should always be rounded to 2 decimals. opw-6302337 Forward-Port-Of: odoo/enterprise#122581 Forward-Port-Of: odoo/enterprise#121913
Users can now turn an AI provider on or off without removing the saved API key. This makes AI configuration easier to manage and avoids unnecessary re-entry of credentials when temporarily disabling a provider.
Original PR description
Prior to this fix, user had to delete the API key set in order to disable the corresponding provider option in the ai config view. With this PR, we all allow the enable/disable provider option independently from the API key value. task: 6331248
33 changes
New functionality added to Odoo
Businesses in the Philippines can now send BIR 2306/2307 withholding tax certificates directly to vendors from vendor bills. The feature supports both individual and batch emailing, helping teams save time and streamline tax compliance communication.
Original PR description
Add a mechanism to email the BIR 2306/2307 withholding tax certificate to the vendor from a bill, both individually and in batch. task-6298456
Adds an Argentina-specific Daily Book XLSX export so businesses can summarize journal entries by ledger instead of reporting every invoice individually. This helps reduce reporting volume and related page-based costs, while allowing users to configure the starting entry number and select relevant ledgers.
Original PR description
Purpose: Implement the daily book export for Argentina which allows users to summarize and report journal entries of the same nature, such as all sales, to reduce reporting every single invoice which…
Purpose: Implement the daily book export for Argentina which allows users to summarize and report journal entries of the same nature, such as all sales, to reduce reporting every single invoice which incurs a cost per page. Users can use the multi-ledger system to summarize the journal entries. Ledgers can be created and set on the journal. Journals of the same nature can share the same ledger. Then, the user can view and select which ledgers they want to export on the general ledger and then export. By default, all ledgers will be selected, until the user deselects ledgers. A "Daily Book XLSX (AR)" button was added and can be accessed in the dropdown of the cog menu. Upon click, a wizard will pop up and it will display the starting entry number for the report. By default, it will display 1 if there's no history or the last entry number (that we store) + 1. The user can input their own number. Once the starting number is set, the XLSX file for the daily book will export. task-5244083
Enhancements to existing features
Online payment initiation now includes the payer's bank account information and account holder name when sending payment requests. This helps meet requirements from providers like Powens and banks that need these details to process payments reliably.
Original PR description
With Powens, some banks requires the payer's bank information such as bank account number and bank holder name. This commit adds those informations to the odoofin route to be sent to the payment providers. task-6373634 Forward-Port-Of: odoo/enterprise#124930 Forward-Port-Of: odoo/enterprise#124088
This update aligns the naming used for a Mexican electronic invoicing method in the website sales flow. It helps keep the checkout and invoicing experience consistent with related Odoo changes, with minimal visible impact for users.
Original PR description
see community for reference: https://github.com/odoo/odoo/pull/276851
Obox can now send service failure messages to the Odoo database, where they are stored as logs. This helps users in debug mode and support teams see when an Obox service has failed, making diagnosis easier.
Original PR description
This PR adds a controller which allows the obox to contact the db to send a message. The db then creates an `obox.log` record which is visible in debug mode to the user. This is currently used to notify the databse when a service fails on the obox Obox PR: https://github.com/odoo/obox/pull/192
Updated accounting-related test cases to reflect the current way invoice and bill due dates are calculated. This helps keep automated quality checks reliable by expecting due dates to follow invoice dates and payment terms instead of defaulting to today.
Original PR description
Before this commit: Several tests still relied on the previous behavior where the Due Date was automatically set to Today's Date by default. Since the due date computation was updated, these assumptions caused the tests to fail. With this change: Updated the affected test cases to match the new due date computation. Tests now expect the Due Date to be computed based on the Invoice/Bill Date and selected Payment Terms. Where no Payment Terms are configured, tests now expect the Due Date to match the Invoice/Bill Date. task-6309674 Related - [odoo/community](https://github.com/odoo/odoo/pull/271831/)
Users can now delete attachments or add them to Documents directly while previewing a file. This saves time by avoiding the need to return to the chatter to perform common document actions.
Original PR description
Users can currently delete attachments or add them to Documents from the chatter. However, when opening an attachment in the file viewer, these actions are not available. This commit adds Delete and Add to Documents buttons in the file viewer, allowing users to perform the same actions without leaving the viewer. Related Community PR: https://github.com/odoo/odoo/pull/247924 <img width="972" height="362" alt="image" src="https://github.com/user-attachments/assets/51581ef5-5855-4cc4-b850-12b7a8e1af5e" /> Task-[5408185](https://www.odoo.com/odoo/project/1519/tasks/5408185)
WhatsApp conversation threads now display their associated avatar in the discussion view. This makes it easier for users to recognize and distinguish WhatsApp channels at a glance.
Original PR description
Purpose of this commit: Show thread avatar for channel type whatsapp Before <img width="462" height="134" alt="image" src="https://github.com/user-attachments/assets/72bc9bab-877d-4a42-aa3e-a7cfb12c6065" /> After <img width="624" height="107" alt="image" src="https://github.com/user-attachments/assets/ba6fe94a-7751-42e9-a1cc-4976c3d5eaa5" /> task-6398499
The French balance sheet report now places establishment costs before fixed assets and includes additional impairment accounts for tangible fixed assets. This improves the accuracy and presentation of French financial statements for reporting users.
Original PR description
Move establishment costs before fixed assets in the French balance sheet, and include the missing 2912, 2913, 2914, and 2915 impairment accounts in the relevant tangible fixed asset amortization/provision lines. task-6226138 Forward-Port-Of: odoo/enterprise#124562 Forward-Port-Of: odoo/enterprise#117689
Resolved issues and error corrections
This fixes balance receipt printing for SIX payment terminals after a prior change caused the receipt template to be loaded incorrectly. The receipt layout is now provided as its own template file, restoring the expected balance receipt behavior after the module is upgraded.
Original PR description
odoo/enterprise#104683 broke the balance receipt for six terminals trying to load an html template in a template name param. We fix this by extracting the template in its own file. Note: clients will have to upgrade the module in order to make the template available. task-6391500 Forward-Port-Of: odoo/enterprise#124521
Studio approval rules now handle restricted fields without causing an access error for users who do not have permission to see those fields. This prevents sales order confirmations and similar actions from being unexpectedly blocked while keeping the approval logic in place.
Original PR description
Issue: A studio.approval.rule.domain includes a related field that calls an access rights group that the user who used the action isn't apart of, Is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5) create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Fix: add a sudo to the filtered_domain opw-6316069 Forward-Port-Of: odoo/enterprise#124722 Forward-Port-Of: odoo/enterprise#121856
The POS now loads only the Kenya e-invoicing code records that are actually used by products, instead of fetching entire code lists. This reduces unnecessary data loading and can improve POS startup performance for businesses using the Kenya OSCU localization.
Original PR description
Before `product.unspsc.code` and `l10n_ke_edi_oscu.code` records were loaded without domain, which could lead to loading all records of these models in POS, which is not necessary. This commit adds a domain to the loading of these records, so that only the records that are actually used in the products are loaded in POS. Forward-Port-Of: odoo/enterprise#124154 Forward-Port-Of: odoo/enterprise#123684
This fixes an error that could occur when opening a planning calendar popover in Field Service. The calendar now includes the needed user information so users can view planning details without hitting an unexpected crash.
Original PR description
add the user_ids field to the calendar view because its needed in a popover task: 6358644 Forward-Port-Of: odoo/enterprise#122684
VOIP call smart buttons now open the same full set of related records that they count, covering the customer’s company and related contacts. When creating a new record from a call, the system still defaults to the specific contact from the call, reducing confusion and keeping follow-up work accurate.
Original PR description
Commit [1] change the smart buttons on voip.call to count records from all family of the partner (count all record from all partners from the partner's company). However, the actions on the buttons stay the same, they will only open records from the partner itself. This is confusing, we change it to also show records from the whole partner family. [1]: 16772c5c1e604d6beb514f9e5b166fc0c2f452a7 Task-6379569 Forward-Port-Of: odoo/enterprise#123944
Polish currency rate imports now avoid applying an extra one-day date shift. This prevents rates from being dated too far back now that the system already uses the previous day's rate as required.
Original PR description
In Poland, it is mandatory to use the previous day's currency rate. We used to achieve this by shifting the rate's date by one day. Since https://github.com/odoo/odoo/pull/231948, we already use the previous day's rate, so the shift is no longer needed. See: https://www.odoo.com/mail/message/1118975071 Forward-Port-Of: odoo/enterprise#123849
Service sale order lines generated from planning now let Odoo calculate prices automatically instead of forcing a fixed unit price. This ensures customer or product pricelists are applied correctly, reducing incorrect billing for field service work.
Original PR description
Before this commit, in the method `_generate_service_sale_order_lines` the `price_unit` for sale order lines used an explicitly defined unit price. This prevented the pre-computation of the price. It may cause some issues, for example if there was a pricelist defined on the product, we didn't apply the prices from that pricelist. This commit removes explicit definition of the `price_unit` to let the sale order creation process handle it. [error-941068](https://runbot.odoo.com/odoo/error/941068) Forward-Port-Of: odoo/enterprise#124680
This fixes an error that could interrupt stock operations when using Kenya OSCU e-invoicing modules, especially in kit-related picking flows. The change helps ensure stock moves complete reliably without unexpected tracebacks.
Original PR description
**CAUSE** super()._action_done() delete a record from self, and return a new recordset of stock.moves. We filter the old recordset instead of filtering the new one, leading to an MissingError traceback. **STEP TO REPRODUCE** On a fresh db, install: `l10n_ke,l10n_ke_edi_oscu,l10n_ke_edi_oscu_mrp,l10n_ke_edi_oscu_pos,l10n_ke_edi_oscu_stock,l10n_ke_edi_tremol,l10n_ke_hr_payroll,l10n_ke_hr_payroll_account,l10n_ke_reports` and run `TestKitPicking.test_add_sml_with_kit_to_confirmed_picking`. runbot-241262 Forward-Port-Of: odoo/enterprise#124663
Mexican payroll CFDI generation now includes the employer CURP when the company represents an individual, identified by a 13-character RFC. This prevents validation errors for businesses under fiscal regime 621 and allows affected payslips to be generated correctly.
Original PR description
Issue: ---------------------------------------- There is a fiscal regime where the company is actually an individual but is authorized to generate documents. Steps to reproduce:…
Issue: ---------------------------------------- There is a fiscal regime where the company is actually an individual but is authorized to generate documents. Steps to reproduce: ---------------------------------------- - Install "l10n_mx_hr_payroll_account_edi" - Change the current company fiscal regime to '621' - Add an VAT of length 13 to the current company - Add a CURP number on the current company - In Payroll generate a payslip, validate it - Post the Journal entry - On the payslip, click "Generate CFDI" - An error is returned, saying the Emisor:Curp applies to individuals Cause: ---------------------------------------- An RFC of length 13 means that the sender is an individual. It's intended with the fiscal regime '621'. We add the curp number in the CFDI XML only when `self.company_id.partner_id.is_company` is `False`. Since saas-19.1, `is_company` is computed to be truely if a VAT is present. So as soon as the VAT is entered, the CURP number is absent from the XML. Solution: ---------------------------------------- We change the condition to add the CURP number in the XML: A VAT number of length 13 means the contact is an individual (12 for companies). This is what is used to validate the XML: if the vat is of length 13, then the curp number should be present. opw-6351558 Forward-Port-Of: odoo/enterprise#124868 Forward-Port-Of: odoo/enterprise#124027
The Sendcloud delivery test suite was corrected so it runs in regular CI instead of only nightly checks. This helps catch delivery integration issues earlier, including corrected expectations for multi-package weight handling.
Original PR description
Test class was tagged as external although calls are mocked. This means errors were only caught in nightly and not by CI. Removing the tag requires fixing some of the tests. For `test_multicollo`, we send the average weight of packages instead of the total since 97f82442c9fee7dcb3e8c5e9bacddcd6bb864e11. Forward-Port-Of: odoo/enterprise#121665 Forward-Port-Of: odoo/enterprise#111660
VoIP call screens now hide related record shortcuts when a call is not linked to a customer or contact, preventing errors from unexpected clicks. Subscription shortcuts are also shown consistently with the customer page behavior.
Original PR description
Same as in [1], we don't show smart buttons when no partner to prevent unexpected errors. Also remove `invisible="subscription_count == 0"` to make it same as smart button on res.partner. [1]: 0fbb730e02de22b196a45455f801e96321a75167 Forward-Port-Of: odoo/enterprise#124925 Forward-Port-Of: odoo/enterprise#124579
This update improves how email, SMS, and WhatsApp delivery failures and bounces are reflected in marketing automation campaigns. Businesses get more accurate campaign follow-up behavior and clearer failure information, while related tests were expanded to protect these workflows.
Original PR description
RATIONALE In order to prepare upcoming improvements for marketing automation application, as well as performance improvements, status update from sms / mail / whatsapp is checked, tested and fixed. Fixes are done in master mainly because it would be difficult in stable, and because those are not critical. SPECIFICATIONS See sub-commits for more details. Task-6401319: [mail_*] Fixup mail/sms/WA -> Trace -> MarketAuto update Task-4224152: [marketing_automation] Performance / Scalability
Fixed an issue where using the Off-Cycle filter in the payslips list could trigger an error in debug mode. The payroll screen now handles payslips without a pay run correctly, improving reliability for payroll users.
Original PR description
Before this commit, when the user is in debug mode, goes to payslips list view and applies `Off-Cycle` filter, a traceback is occured saying `Invalid props for component 'PayslipActionHelper': 'payrunId' is not a number`.
The reason is because we search the id of the payrun by parsing the domain applied to fetch payslips displayed inside the list view but `Off-Cycle` filter will apply the following domain: `[('payslip_run_id', '=', False)]` and so False is given to PayslipActionHelper but it is not a number.
This commit makes sure to set undefined to payrunId prop of PayslipActionHelper when `payrun_id` found is falsy.
runbot-error-241053
Forward-Port-Of: odoo/enterprise#124897
Forward-Port-Of: odoo/enterprise#124854AI-generated answers with web citations now preserve their original line breaks and spacing. This prevents lists and paragraphs from being accidentally merged, making cited responses easier to read and understand.
Original PR description
AI responses containing web citations lost their original formatting when a citation appeared at the end of a line, causing lists and paragraphs to be merged together. This commit limits the citation parser to ignore only horizontal whitespace around citations, preserving line breaks in the rendered response. task-6391187 Forward-Port-Of: odoo/enterprise#124457
The timesheet grid now uses updated colors for attendance/work rule types. This makes it easier for users to quickly recognize different event types at a glance.
Original PR description
This commit updates the color of AW rule types to help the user to quickly recognize the type of events based on the color. task-6186073 Forward-Port-Of: odoo/enterprise#124838
The Timesheets shortcut now appears whenever a user has an active employee profile in any selected company, not just the current company. This prevents eligible users from losing quick access to timesheet entry when working across multiple companies.
Original PR description
Steps to reproduce: - install Timesheets - create an employee for a user in company B - switch to company A (where the user has no employee) - the systray icon is hidden even though the user can…
Steps to reproduce: - install Timesheets - create an employee for a user in company B - switch to company A (where the user has no employee) - the systray icon is hidden even though the user can create timesheets in company B via the company selector Current behavior: the systray only checks the current company for a valid employee, ignoring other selected companies. Expected behavior: the systray should be visible whenever the user can create timesheets i.e. when they have an active employee in any of the selected companies. Issue: the check used a stored boolean on `res.partner` that has no company scope and becomes stale when an employee is archived (the stored dependency does not re-fire). the timesheet creation logic checks all selected companies for active employees, but the systray did not mirror that. Fix: use `employee_ids` a `One2many` that checks all selected companies and excludes archived employees, matching the timesheet creation logic exactly. task-6330539 Forward-Port-Of: odoo/enterprise#124830 Forward-Port-Of: odoo/enterprise#121730
Features or functions removed from Odoo
The India GST reporting flow now keeps only the newer HSN Summary format, which has been available for over a year. This simplifies maintenance and reduces duplicate reporting paths, while related test data for the retired format has also been removed.
Original PR description
As it has been more than a year since the new HSN Summary format was launched, this commit removes the old HSN Summary format for simplification. Additionally, it removes the related test cases as well. ref - https://github.com/odoo/enterprise/commit/8f3400d5037ea4aa23112ea7d65ae6afc7f488e4 https://github.com/odoo/enterprise/commit/d0df0f845ac2853d1247cae0d9543e92050bf2a4
Code cleanup and technical improvements
The Point of Sale code was updated as part of Odoo's OWL 3 migration, replacing older internal reference patterns with the newer approach. This is an internal modernization that helps keep PoS screens and related localizations maintainable without changing day-to-day user workflows.
Original PR description
pos*: pos_enterprise, l10n_at_pos, l10n_ke_edi_oscu_pos As part of the OWL 3 migration, this commit replaces `useRef` and `t-custom-ref` usages with `t-ref` and signal-based references across the PoS codebase. Task-6343663 Related Community PR: https://github.com/odoo/odoo/pull/272698
The grid view editing logic was updated to use newer platform APIs, replacing deprecated internals. This keeps spreadsheet-like grid inputs working reliably while reducing future maintenance risk as the web framework evolves.
Original PR description
Replaced two `useLayoutEffect` calls in `useInputHook` with OWL3 native APIs (`useListener`, `onMounted`, `onPatched`), since `useLayoutEffect` is deprecated in OWL3. The caller `GridCell` was…
Replaced two `useLayoutEffect` calls in `useInputHook` with OWL3 native APIs (`useListener`, `onMounted`, `onPatched`), since `useLayoutEffect` is deprecated in OWL3. The caller `GridCell` was updated to use `signal.ref()` instead of the compat `useRef`. The first effect attached `input`/`change`/`keydown` listeners to `inputRef.el` — a textbook `useListener` case. However, the compat `useRef` from `@web/owl2/utils` silently untracks the underlying signal on `.el` access, so `useListener(() => inputRef.el, ...)` never re-ran after mount and no listeners were attached. The fix passes the signal ref directly (`useListener(inputRef, ...)`) and upgrades the caller to use `signal.ref()` passed explicitly to the hook. The second effect (bare `useLayoutEffect` re-syncing the DOM value on every render) maps directly to `onMounted` + `onPatched`. The `useLayoutEffect` refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - `@web_grid/grid_view/grid_view_desktop/editing a value` - `@web_grid/grid_view/grid_view_desktop/Edition navigate with tab/shift+tab and enter key` - `@web_grid/grid_cells/float_time_grid_cell/FloatTimeGridCell in grid view` see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2624595/build/116553684
This change modernizes how scrolling behavior is connected in the Gantt and grid views. It should help keep these views aligned with the latest web framework patterns without changing the visible user experience.
Original PR description
The web `virtual_grid_hook` now attaches its scroll listener via `useListener` on a signal ref instead of `useLayoutEffect` on a compat `useRef`. This PR feeds it a signal ref from both enterprise callers:
- **web_gantt**: `scrollRef` becomes a `signal.ref` bound with `t-ref`; its own scroll `useLayoutEffect` becomes a `useListener` and all `.el` reads become calls. Layout's `contentRef` (now a signal, per the community PR) is adapted to an `{ el }` object ref for the draggable hooks (`useGanttDraggable`/`useGanttSchedulable`), which require an object ref.
- **web_grid**: `contentRef` prop type is now a function (signal) ref.This change keeps Enterprise list views in Web Studio and Data Cleaning compatible with an underlying platform update. It is an internal refactor with no expected change to day-to-day user workflows, helping prevent display or interaction issues after the core update.
Original PR description
That PR migrates the base `web.ListRenderer` `table` ref from the OWL2 compat `useRef`/`t-custom-ref='table'` to a native OWL3 `signal(null)` bound with `t-ref="this.tableRef"`. This PR updates the enterprise modules that still consume the old compat surface: - **web_studio** `ListEditorRenderer`: retargeted both xpath inheritors `//*[@t-custom-ref='table']` → `//*[@t-ref='this.tableRef']`, and `onTableHover` reads `this.tableRef()` instead of `this.tableRef.el`. - **data_cleaning** `DataMergeListRenderer.onGroupRowMouseEnter`: reads `this.tableRef()` instead of `this.tableRef.el`. Companion PR to odoo/odoo#272009.
Spreadsheet autofill for list and pivot data has been reorganized to align with the underlying spreadsheet engine. This is an internal cleanup that should preserve existing behavior while making the feature easier to maintain and slightly more efficient.
Original PR description
### [MOV] spreadsheet_edition: move list/pivot autofill plugins to helpers The list/pivot plugins were transformed into helpers in the last commit, this commit renames the files. ### [REF] spreadsheet_edition: make autofill plugin into a store The o-spreadsheet commit transformed the autofill plugin into a store. This made the necessary adaptations in odoo. Moslty, the list/pivot autofill plugin were changed into helpers that can be called from the autofill process (they had no state nor command handling). Also changed a bit the autofill helpers so we don't re-compile the cell formula when we already have a compiled formula. Task: [6395361](https://www.odoo.com/web#id=6395361&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form)
This update modernizes part of the grid view code to stay compatible with the next version of Odoo's interface framework. It preserves the expected keyboard navigation behavior, including correctly focusing the toggle button when users enter edit mode.
Original PR description
Replaced `useLayoutEffect` with `signal.ref` + `useEffect` because `useLayoutEffect` is deprecated in OWL3. The commented-out effect focused the toggle button when its DOM element became available, using an explicit dep array `[this.buttonRef.el]`. That dep only worked because the compat `useRef().el` getter untracks its underlying signal. Converting `buttonRef` to a real `signal.ref(HTMLButtonElement)` makes `useEffect` auto-subscribe to the ref signal: when edit mode is entered (button rendered under `t-if`) the ref updates, the effect re-runs, and the button is focused — no explicit dep array needed. The useLayoutEffect refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - `@web_grid/grid_cells/float_toggle_grid_cell/FloatToggleGridCell: keyboard navigation` see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2624596/build/116553766
The accounting reports code was updated to use the newer supported framework approach, reducing the risk of issues when Odoo moves to OWL3. A new automated test was added to confirm report filters continue to update correctly when switching reports.
Original PR description
Replaced `useLayoutEffect` with `useEffect` from `@odoo/owl` because `useLayoutEffect` is deprecated in OWL3. `useEffect` auto-tracks reactive reads inside the callback, so reading `this.controller.cachedFilterOptions?.report_id` directly in the effect body is sufficient to re-run when the report changes — no explicit dependency array is needed. When commenting out the useLayoutEffect there was no error, the code we refactored had NO TEST coverage. A test was written to ensure our fix was correct, and it was tested against the previous useLayoutEffect: - Passed with previous useLayoutEffect. - Failed with previous useLayoutEffect commented. - Passed with our OWL3 replacement.
18 changes
Enhancements to existing features
This update adds a cleanup script for the Belgian POS blackbox module. It helps prevent copied or test databases from retaining device network details and Belgian POS identifiers that should be reset before reuse.
Original PR description
Add a `neutralize.sql` file to the `l10n_be_pos_blackbox` module to reset the blackbox `local_ip` and the config's `l10n_be_pos_id` and `establishment_number`.
Resolved issues and error corrections
Fixed an issue where Project tasks could be accidentally duplicated after switching browser tabs during a drag action. Tasks now correctly reschedule when dropped unless the user is actively choosing to copy them, reducing accidental planning errors.
Original PR description
## Current behavior: When rescheduling a task in Project's Gantt chart view, if user switches to a different browser tab using the Ctrl shortcuts (either Ctrl + Tab, Ctrl + Shift + Tab or Ctrl + PgUp…
## Current behavior: When rescheduling a task in Project's Gantt chart view, if user switches to a different browser tab using the Ctrl shortcuts (either Ctrl + Tab, Ctrl + Shift + Tab or Ctrl + PgUp / PgDn), and navigate back to Gantt chart view, the task will get duplicated unexpectedly when getting dragged around even when the Ctrl button is released ## Expected behavior: Dropping a task without Ctrl held should reschedule even after a tab switch using the Ctrl shortcuts ## Steps to reproduce: 1. Install `project` module 2. Create a project and switch to Gantt chart view 3. Hold Ctrl and start dragging a task while switching browser tab with Ctrl+Tab, Ctrl+Shift+Tab, or Ctrl+PgUp/PgDn 4. Return to the Gantt tab and drop the task without holding Ctrl 5. The task is duplicated instead of rescheduled ## Cause of the issue: Copy and reschedule actions are tracked internally via interaction.dragAction, updated only on window keydown/keyup for Control. Currently, we're not keeping track of the `visibilitychange` event when switching tabs, causing the state of `ctrlPressed` to stale after a tab change, causing the dragAction to stay on copy mode ## Fix: Reset `dragAction` and `ctrlPressed` on document's `visibilitychange` when the tab has been changed opw-6298440
Lazada and Shopee order imports now handle discounts, vouchers, shipping fees, and small rounding differences in a way that matches the marketplace totals. This reduces mismatches during reconciliation and gives teams clearer order lines for discounts and shipping.
Original PR description
Marketplace orders with discount lines could not match the platform total: Odoo accumulated a small rounding residue vs Shopee's total_amount / Lazada's order price. sale_shopee ----------- Changes:…
Marketplace orders with discount lines could not match the platform total: Odoo accumulated a small rounding residue vs Shopee's total_amount / Lazada's order price. sale_shopee ----------- Changes: - Fetch buyer-side escrow amounts via `_fetch_order_income` and pass them through `self.env.context` (`order_income`). - Build item lines from the buyer-paid item price with `discount=0` and a recomputed tax-exclusive `price_unit`. - Distribute order-level discounts (seller/platform vouchers and coins) as dedicated negative lines per product tax group via `_prepare_discount_lines_values`. - Append a shipping line from `buyer_paid_shipping_fee` with fiscal-position mapped taxes. - Reconcile any leftover residue with `_adjust_order_total` using a single tax-free amount-adjustment line. - Register `default_discount_product` and configure it on upgrade (v1.1). sale_lazada ----------- - Port the same reconciliation model as shopee: reconciled line specs, discount=0 with discounted unit from paid_price, shipping line from shipping_fee, order-level "Discount line" distributed at order-level. task-6112062
Reconciliation models now use the correct currency when transactions involve multiple currencies. This prevents amounts from staying tied to the original transaction currency and helps businesses reconcile entries more accurately.
Original PR description
In the reconciliation model, the currency is not automatically converted if multiple currencies are being used. Instead, it remains stuck on the original currency of the transaction. This issue is resolved by this commit. runbot-https://runbot.odoo.com/runbot/bundle/190-reconciliation-model-currency-fix-andha-461793 task-5974154
Fixes an issue where selecting a customer in Point of Sale could show an AvaTax tax-loading error when an AvaTax fiscal position was used. This restores the checkout flow for businesses using AvaTax in PoS and avoids interruptions during sales.
Original PR description
Steps to reproduce: ------------------- 1. Install pos_avatax. 2. Enable Avatax in accounting, and use the testing credentials of Odoo. 3. Enable "Use AvaTax API" and "Detect Automatically" on the…
Steps to reproduce: ------------------- 1. Install pos_avatax. 2. Enable Avatax in accounting, and use the testing credentials of Odoo. 3. Enable "Use AvaTax API" and "Detect Automatically" on the default fiscal position (or another fiscal position available in PoS). 4. In a PoS shop, enable "AvaTax PoS Integration" 5. Find a product sell in that PoS, and assign it an "Avatax Category" 6. Open that PoS, add the prodct of step 5, and choose a customer (make sure the fiscal position of step 3 is being used). Observation: Error modal "Error while loading Avatax taxes", and error in the terminal `KeyError: 'base_line'`. Why it's happening: ------------------- Commit 0404086db567 changed the return of `_get_line_data_for_external_taxes`. Before, pos was returning something with `id`, `qty`, `price_subtotal` etc. After the commit the return should have a `base_line` key (the accounting base line we get from `_prepare_base_line_for_taxes_computation`). But that commit forgot to update the override in pos. So when avatax tries to read `line_data['base_line']` we get the KeyError. The fix: -------- Update the override in pos to return the new format, same way `sale_external_tax` is already doing it for sale orders. opw-6244141
Argentine electronic invoices now show a clear warning when a final consumer contact uses an unsupported identification type. This prevents a system error during invoice confirmation and helps users correct customer details before submitting invoices.
Original PR description
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina…
After applying the community fix, a new issue appears in enterprise. **Steps to reproduce:** - Install the `l10n_ar_edi` module. - Go to Customers and create a new customer with: - Country: Argentina - Identification Type: `Passport` - Identification Number: `1234567890a` - AFIP Responsibility Type: `Consumidor Final` - Create a new invoice for this customer with: - Journal: `Electronic Invoice (FE)` - Document Type: `(6) INVOICES B` - Try to confirm the invoice. **Error:** ValueError: invalid literal for int() with base 10: '1234567890a' **Expected behaviour:** For Argentinean contacts with AFIP Responsibility Type `Consumidor Final`, the identification type must be `DNI` or `CUIL/CUIT`. If another identification type is used, the user should receive a proper warning instead of a traceback. (see [1]) **Root Cause:** After the community fix, `_get_id_number_sanitize()` can return an alphanumeric value, which is later converted with `int()` at [2] and [3], causing an error. **Fix:** This commit adds an explicit validation for Argentinean contacts with AFIP Responsibility Type Consumidor Final before converting the identification number to an integer, ensuring the user receives the proper warning message. [1]: https://www.odoo.com/mail/message/1118392033 [2]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L780-L798 [3]: https://github.com/odoo/enterprise/blob/064812dd9f1074f287fee677ba35ea4aeef3ab3f/l10n_ar_edi/models/account_move.py#L927-L931 Related community PR: https://github.com/odoo/odoo/pull/272651 opw-6333998 Forward-Port-Of: odoo/enterprise#123729
The Commission Adjustments screen no longer offers a quick-create option that could crash the system when users entered an unmatched name. This prevents interruptions for sales teams managing commission adjustments and keeps the workflow stable.
Original PR description
Steps to reproduce: - Go to Sales > Commission > Adjustments - In Add to/Reduce From, type a name with no match - Click Create '<name>' -> server crashes (RPC_ERROR) Cause: `sale.commission.plan.user._rec_name` is a Many2one (`user_id`). Default `name_create` wrote the typed text into that integer column, which Postgres rejected. Fix: - Disable quick-create on `add_user_id`/`reduce_user_id` in the Adjustments list view Version: saas-18.3 to master opw-6384909 Forward-Port-Of: odoo/enterprise#124431
Philippine check printing now rounds the cents portion of written payment amounts to two decimals, even when the currency is configured with more precision. This prevents confusing or incorrect wording on checks and helps printed payments match standard check formatting.
Original PR description
Current behavior: --- When paying with checks, if the currency has more than 2 decimals, the decimal amount is printed with more than 2 decimals. Steps to reproduce: --- 1. Switch to PH company 2. Set setting Check Layout as "Print Check - PH" 3. In the PHP currency, change rounding factor to 0.0001 4. In Decimal accuracy > product price, set 4 digits 5. Create a new Vendor Payment, payment method Check, amount 100.1268 PHP 6. Results: One Hundred and 1268/100, should be 13/100 Expected behavior: --- The xx/100 part of amount in words text in the check should always be rounded to 2 decimals. opw-6302337 Forward-Port-Of: odoo/enterprise#122581 Forward-Port-Of: odoo/enterprise#121913
Appraisals now choose the template assigned to an employee's department instead of keeping a generic default. This helps HR teams use the right appraisal forms automatically while preserving deliberate template choices when they match the department.
Original PR description
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create…
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create an appraisal template and restrict it to a department. 2. Make sure at least one global (no department) template also exists. 3. Open a new appraisal and select an employee of that department. 4. Observe the appraisal template stays on the global one. **Current behavior:** The global template that was auto-selected before an employee was chosen is kept, ignoring the department-restricted template. **Expected behavior:** The template restricted to the employee's department is selected. **Cause of the issue:** On a new appraisal the template is computed before an employee (and therefore a department) is set, so a global template is pre-selected. When the employee is then chosen, `_compute_appraisal_template` reruns but the `appraisal.appraisal_template_id or ...` clause short-circuits on the already set global template and never falls through to the department's template. **Fix:** Evaluating the department's template before the existing value ensures a department-restricted template takes precedence over a template that was only auto-selected as a default. The existing value is still preserved when the department has no template of its own, so deliberate choices are untouched. opw-6293936
Planning kanban cards now move overflowing content onto the next line instead of squeezing or cutting it off. This makes schedule information easier to read when entries contain longer text.
Original PR description
Wrap the kanban card content onto the next line when it does not fit on a single line. task-5085363
Spanish VAT books now report tax amounts correctly for vendor bills using EU taxes with negative components. This prevents valid tax amounts from being shown as zero, improving the accuracy of VAT reporting.
Original PR description
Problem: In the Spanish VAT books, taxes with negative component (like 21% EU G) always show their amounts as zero. Steps to reproduce: 1. Install the l10n_es_reports module and select the Spanish company 2. Create a vendor bill with a vendor from another EU country and add a product 3. Make sure the tax applied to the product has a negative component (like 21% EU G) 4. Confirm the bill 5. Go to Accounting > Reporting > Tax Return 6. Generate the VAT books from the action menu and check the tax amounts 7. Notice how the tax amount is zero, even though the tax was applied to the bill Cause: When calculating the tax amounts, the negative component cancels out the positive component, leading to the amount always showing as zero in the VAT books. opw-6169766 Forward-Port-Of: odoo/enterprise#123738
Swiss QR-IBAN payment references are now sanitized before payment files are generated. This helps prevent ISO 20022 payment files from being rejected by Swiss banks due to unsupported characters in references.
Original PR description
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with…
**Steps to reproduce:** * Configure a Swiss company with the Swiss accounting localization. * Install `account_sepa`. * Configure a bank journal with a valid Swiss **QR-IBAN**. * Create a vendor with a valid Swiss bank account. * Under **Accounting -> Configuration -> Settings** enable QR Payments. * Go to the vendor and enter the correct QR-IBAN number under the Accounting Section. * Navigate to **Accounting -> Configuration -> Journals** and in the **bank** journal, add the account number of QR-IBAN. * Create and post a vendor payment using the bank journal. * Set the payment reference (`ref`) to contain the `°` character. * Add the payment to a batch payment and generate the ISO 20022 payment file. * Inspect the generated XML. **Observed Behaviour:** The `°` character is preserved in the payment reference for QR-IBAN payments, producing an ISO 20022 file that may be rejected by Swiss banks because it does not comply with the EPC minimum character set. **Cause:** The QR-IBAN branch validates the structured reference before sanitizing it, allowing unsupported characters to remain in the generated XML. **Fix:** Sanitize the payment reference before validating it as a QR structured reference, ensuring invalid characters are removed while preserving valid QR references. opw - 6350931 Forward-Port-Of: odoo/enterprise#124299 Forward-Port-Of: odoo/enterprise#123267
This fixes a failing automated test in the AI module by ensuring the test data matches the expected Gemini embedding response format. The change helps keep quality checks reliable and prevents unrelated demo data from causing false failures during validation.
Original PR description
_cron_generate_embedding retrieves all the sources that don't have an embedding and generate embeddings for those using the model from the provider of the agent configured on the source. The agent configured on the demo sources has OpenAI as the provider and these sources don't have embeddings. When _cron_generate_embedding runs in the test case, it retrieves these demo sources + the source defined in the test case (Which relies on embeddings from Google) and generates the embeddings but then fails. This happens because the _request method is mocked to return the response in Google's format as the test case is specific to Gemini models. runbot.build.error-944173
The point of sale barcode lookup flow now uses the standard permission check when deciding whether a user can create products. This avoids inconsistent behavior and helps ensure only authorized users see or use product creation options.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#124527 Forward-Port-Of: odoo/enterprise#123073
Resetting a submitted tax return no longer changes the company-wide tax lock date, preventing closed periods from being reopened for everyone by mistake. The fix also ensures companies can set the tax lock date before submitting a return, supporting safer workflows in larger accounting teams.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.
Forward-Port-Of: odoo/enterprise#124811The report screen layout was adjusted so the chatter panel remains visible on the right side of the screen even when reports are very wide. Users can now discuss and follow up on reports without needing to scroll horizontally to find the conversation panel.
Original PR description
Issue: - When reports are large/wide, the chatter component is pushed beyond the visible viewport, appearing only at the absolute right edge of the overflowing report rather than the right edge of the screen. Fix: - Updated the layout container to prevent the chatter from shrinking or overflowing with the report block, ensuring the main report scrolls independently while the chatter stays pinned to the screen viewport. Impact: - Keeps the chatter panel fully visible on the right side of the screen, allowing users to communicate without scrolling horizontally on wide reports. task-[6376792](https://www.odoo.com/odoo/project/967/tasks/6376792)
Peruvian electronic invoices now convert detraction withholding amounts to PEN correctly even when the company currency is set to USD. This prevents incorrect XML submissions to SUNAT and ensures PDF reports show the proper Peruvian sol amount and symbol.
Original PR description
**Steps to reproduce:** * Install the **l10n_pe_edi** module. * Change the company currency to **USD**. * Configure **Peruvian detraction** settings: * Set a **withholding percentage** on a product.…
**Steps to reproduce:**
* Install the **l10n_pe_edi** module.
* Change the company currency to **USD**.
* Configure **Peruvian detraction** settings:
* Set a **withholding percentage** on a product.
* Set a **withholding code** on the same product.
* Create a customer invoice in **USD**.
* Set the **Operation Type** to **[1001] Operation Subject to Detraction**.
* Add the configured product to the invoice.
* Confirm the invoice, **send it to SUNAT** by *process now**, and generate the ZIP which has XML.
**Observed behavior:**
* The generated XML contains: `<cbc:Amount currencyID="PEN">116.82</cbc:Amount>` The `currencyID` is `PEN` but the amount is the raw USD value instead of being converted to PEN using the exchange rate.
* The PDF report also shows the withholding amount with the wrong currency symbol.
**Cause:**
* `_l10n_pe_edi_get_spot()` computed `spot['amount']` as `amount_total_signed * percent`, where `amount_total_signed` is stored in the **company currency**. When the company currency is PEN this works correctly, but when it is changed to USD the value is in USD while the XML node hardcodes `currencyID="PEN"`.
* `spot['currency']` was also set to `company_id.currency_id`, so the PDF rendered the amount with the wrong currency symbol.
* In `_add_invoice_payment_terms_nodes`, `spot_amount` was selected via `spot['amount'] if invoice.currency_id == invoice.company_id.currency_id` which relied on company currency being PEN as a proxy for the invoice being in PEN, breaking when company currency is USD.
**Fix:**
* In `_l10n_pe_edi_get_spot()`, compute `spot['amount']` by explicitly converting `amount_total` from the invoice currency to PEN using `currency_id._convert(..., env.ref('base.PEN'), ...)`, ensuring the detraction amount is always in PEN regardless of the company currency.
* Set `spot['currency']` to `env.ref('base.PEN')` so the PDF report always displays the withholding amount with the correct PEN symbol.
* In `_add_invoice_payment_terms_nodes`, always use `spot['spot_amount']` (invoice currency amount) for the `FormaPago`/`Cuota` arithmetic, since `spot['amount']` is now exclusively the PEN amount for the detraction XML node.
opw-6327571Peruvian electronic invoices that were registered by SUNAT but temporarily lacked their confirmation receipt will no longer get stuck after a duplicate-document response. Odoo now treats this as a retryable warning, allowing automatic retries to continue until SUNAT provides the confirmation, reducing manual follow-up.
Original PR description
Steps to reproduce: - Post a Peruvian invoice so it is sent to SUNAT (directly or through Estela/Digiflow). - SUNAT's sendBill call hangs and Odoo's request times out (ReadTimeout / ConnectionError),…
Steps to reproduce: - Post a Peruvian invoice so it is sent to SUNAT (directly or through Estela/Digiflow). - SUNAT's sendBill call hangs and Odoo's request times out (ReadTimeout / ConnectionError), even though SUNAT actually finishes registering the document on its side a moment later. - Odoo retries sending the same invoice (either automatically through the EDI cron, or manually). SUNAT now replies with a "document already exists" SOAP fault (code 1033/4000), since it processed the previous attempt. - Odoo tries to recover from this by fetching the CDR through getStatusCdr, but SUNAT has not finished generating it yet, so the lookup also fails. Cause of the issue: _l10n_pe_edi_post_invoice_web_service() already has recovery logic for error codes 1033/4000: it calls _l10n_pe_edi_retrieve_cdr() to fetch the CDR and treat the invoice as sent. But when that lookup itself fails (CDR not generated yet), the resulting error keeps the 'blocking_level' set to 'error' from the original SOAP fault. Documents with blocking_level 'error' are excluded from the automatic EDI cron retries (see account.edi.document._cron_process_documents_web_services), so the invoice gets stuck needing a manual retry, which can lose the same race against SUNAT again and again. Solution: When the CDR can't be retrieved yet after a 1033/4000 duplicate error, mark the result as 'blocking_level': 'warning' instead of leaving it at 'error'. This keeps the invoice eligible for the automatic EDI cron retries, so Odoo keeps polling SUNAT until the CDR becomes available, instead of requiring manual intervention every time this race is lost. opw-6393231
1 change
Resolved issues and error corrections
Spanish VAT record books now include taxable accounting entries created outside standard invoices and bills, such as Point of Sale session closures. This helps businesses produce more complete VAT records and avoid missing tax-relevant POS activity in exports.
Original PR description
Currently, the Spanish VAT record books (Libros Registro de IVA) only include move types associated with invoices and bills. However, miscellaneous entries (type 'entry'), such as those generated by the Point of Sale session closures or manual liquidations, also carry tax obligations and must be reflected in these reports. Steps to reproduce: - Open a POS Session - Create an order, pay and close session - Go to Accouting > Reporting > Tax report - Select Generic Tax report - Print "VAT record Books" Issue: Only invoices and bills are visible in the excel file, and not the entry generated from point of sale. However, movements that are not related to invoices should be included in the VAT books. opw-5862529