Daily updates from Odoo
Friday, July 10, 2026
138 changes
7 changes
New functionality added to Odoo
This update introduces support for Georgian accounting standards, including a new chart of accounts, tax settings, and VAT reporting capabilities. This allows businesses operating in Georgia to accurately manage their financial records and comply with local tax regulations within Odoo.
Original PR description
[ADD] l10n_ge: add Georgian Chart of Accounts - This commit adds the Georgian accounting localization, including the chart of accounts, taxes, fiscal positions, tax groups, and VAT report required for standard accounting and tax reporting flows - It provides support for domestic VAT, reverse charge VAT, and the Georgian VAT declaration report. taskID-3927928 related PR (from 19.0 to saas-19.2) - https://github.com/odoo/odoo/pull/263452 Forward-Port-Of: odoo/odoo#263765
Enhancements to existing features
This update introduces a manual process for Know Your Customer (KYC) verification within the PEPPOL account setup. Previously, PEPPOL account creation relied on automated checks. Now, users can complete a manual KYC process, ensuring compliance with regulatory requirements and streamlining the account onboarding experience. This change improves the security and reliability of our PEPPOL service.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275371
This update streamlines the continuous production process in MRP by simplifying quantity updates and tracking changes. The system now automatically updates work order status based on production quantity, reducing manual intervention and improving data accuracy. UI enhancements have also been included.
Original PR description
A few points to improve continuous production: - Updating workorder produced qty will no longer update qty producing for the MO, because work orders quantity will always be updated and this will be done by several users simultaneously and updating MO's quantity producing at the same time will make it difficult to manage and its not needed. - Track work order quantites updates, for better tracking of who changed the quantity. - Improved continuous production tool tip. - Work order status will be updated from 'To Do' to 'in progress' when the produced quantity is updated. - Some UI changes. Task 6346515 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update fixes an issue where users could create multiple accounts with the same email address, leading to confusion and potential data inconsistencies. The change ensures that only one user account is created per email, improving user experience and data integrity. This applies to both free signup and invitation methods.
Original PR description
Login uniqueness is enforced by a `UNIQUE (login)` constraint that Postgres compares byte for byte, so signing up with foo@example.com and then Foo@example.com produces two separate accounts pointing…
Login uniqueness is enforced by a `UNIQUE (login)` constraint that Postgres compares byte for byte, so signing up with foo@example.com and then Foo@example.com produces two separate accounts pointing at the same real mailbox. https://github.com/odoo/odoo/blob/66a6c16551041543b5addfe846f15e769b4e9afe/odoo/addons/base/models/res_users.py#L274 Even if the DB constraint did catch an exact-case duplicate and `_signup_create_user` re-raised it as a `SignupError`, the controller's friendly "already registered" branch only triggers when the duplicate lookup finds a row, and that lookup goes through `_get_login_domain` with an exact `=` operator. Case variants would fall into the generic "Could not create a new account" branch instead. https://github.com/odoo/odoo/blob/66a6c16551041543b5addfe846f15e769b4e9afe/addons/auth_signup/controllers/main.py#L68-L75 https://github.com/odoo/odoo/blob/66a6c16551041543b5addfe846f15e769b4e9afe/odoo/addons/base/models/res_users.py#L749-L750 `_signup_create_user` now refuses creation when a user with the same email already exists, applying to both b2c free signup and token-based invitations. It raises `UserError` directly so the controller's `except UserError` surfaces the message without a redundant lookup. The check uses `_get_email_domain`, whose base implementation is switched from `=` to `=ilike` over a value escaped via `tools.escape_psql` so `%` and `_` are matched literally rather than as wildcards. Its only existing caller is `reset_password`, which already wants case-insensitive matching. Steps to reproduce: 1. In Settings, set Customer Account to "Free sign up" and save. 2. Log out, then on the login page click "Don't have an account?". 3. Register with foo@example.com. 4. Log out again and click "Don't have an account?". 5. Register with Foo@example.com. => Two distinct user accounts are created for the same mailbox. opw-6199441 Forward-Port-Of: odoo/odoo#273071 Forward-Port-Of: odoo/odoo#263864
This update fixes a usability issue in the mobile Discuss app where actions within the bottom sheet were too small to easily click. The change ensures that CSS styling is correctly applied only to the Discuss bottom sheet, improving the user experience. This resolves a visual inconsistency and makes the app easier to use on mobile devices.
Original PR description
Before this commit, when using discuss in mobile, actions in bottom sheet were too small and hard to click. Steps to reproduce: - open a conversation in discuss with a message - click on "..." or…
Before this commit, when using discuss in mobile, actions in bottom sheet were too small and hard to click. Steps to reproduce: - open a conversation in discuss with a message - click on "..." or long-press the message This comes from changes in spreadsheet_dashboard were some CSS rules that were meant to impact only bottom sheet of spreadsheet_dashboard were actually impacting all the bottom sheets [1], including discuss actions. This commit fixes the issue by putting a specific class on the bottom sheet menu in spreadsheet_dashboard, so that the CSS rule can be made specific to spreadsheet_dashboard and not affect other bottom sheets like the ones used in Discuss app. [1]: https://github.com/odoo/odoo/pull/239190 Before <img width="657" height="524" alt="Screenshot 2026-07-10 at 14 18 38" src="https://github.com/user-attachments/assets/6e4cd083-3d4c-4c38-af89-93819e6eb1a8" /> After <img width="656" height="527" alt="Screenshot 2026-07-10 at 14 18 25" src="https://github.com/user-attachments/assets/48e66648-7f5e-4e42-8a64-b85499aceb97" />
This update resolves an issue where sales orders could incorrectly show analytic distributions exceeding 100%, leading to confusion and inaccurate reporting. The change consolidates analytic distributions from multiple models into a single line, maintaining functionality while preventing this over-allocation. This ensures accurate reporting and simplifies the analytic distribution process.
Original PR description
Steps: 1. Create an analytic model filtered by partner. 2. Create an analytic model filtered by product. 3. Create a project with an analytic distribution. (Make sure the distributions use different plans) 4. Create an SO for a product within the project that both the models apply to. 5. Confirm the SO. 6. Notice the analytic distribution for the project account is at 200%. When an SOL is created, the analytic distribution from each model is added as a separte line The analytic account for the project is added to each analytic distribution line. This can easily cause the account to have >100% distribution for a given SOL. This is unintuitive and confusing behaviour. This PR changes the behaviour to only create one line for all the distributions from analytic models. This should prevent this behaviour while keeping the functionality of applying the project distribution to each line. opw-6250908 / opw-6304033 Forward-Port-Of: odoo/odoo#270151
This update resolves an issue where old, reconciled transactions were incorrectly linked to new invoices, causing errors. The fix ensures that only active, posted transactions are associated with invoices, preventing invoice generation problems with cancelled payments.
Original PR description
Use case -------- A recurring sale order, is automatically invoiced. The transaction is postprocessed and crash with this traceback ``` File…
Use case
--------
A recurring sale order, is automatically invoiced. The transaction is postprocessed and crash with this traceback
```
File "/home/odoo/src/enterprise/saas-19.2/sale_subscription/models/sale_order.py", line 1881, in _handle_automatic_invoices
invoice._post()
File "/home/odoo/src/custom/private/openerp_enterprise/models/subscription_assignation.py", line 439, in _post
posted_moves = super()._post(soft=soft)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/custom/private/openerp_enterprise/models/account.py", line 193, in _post
posted = super()._post(soft)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/hr_payroll_expense/models/account_move.py", line 21, in _post
res = super()._post(soft=soft) # Posting will automatically reconcile same-account-same-matching lines
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/l10n_in_reports/models/account_move.py", line 135, in _post
to_post = super()._post(soft=soft)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/account_loans/models/account_move.py", line 20, in _post
posted = super()._post(soft)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/sale_subscription/models/account_move.py", line 21, in _post
posted_moves = super()._post(soft=soft)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/account_invoice_extract/models/account_invoice.py", line 235, in _post
posted = super()._post(soft)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/account_asset/models/account_move.py", line 130, in _post
posted = super()._post(soft)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_it_edi/models/account_move.py", line 360, in _post
return super()._post(soft)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_in_edi/models/account_move.py", line 156, in _post
res = super()._post(soft=soft)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/account_peppol_response/models/account_move.py", line 42, in _post
res = super()._post(soft)
^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/sale/models/account_move.py", line 149, in _post
invoice.js_assign_outstanding_line(line.id)
File "/home/odoo/src/enterprise/saas-19.2/account_accountant/models/account_move.py", line 589, in js_assign_outstanding_line
super().js_assign_outstanding_line(line_id)
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_move.py", line 6430, in js_assign_outstanding_line
return lines.reconcile()
^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_move_line.py", line 3324, in reconcile
return self._reconcile_plan([self])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_move_line.py", line 2978, in _reconcile_plan
plan_list, all_amls = self._optimize_reconciliation_plan(reconciliation_plan)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_move_line.py", line 2940, in _optimize_reconciliation_plan
amls._check_amls_exigibility_for_reconciliation(shadowed_aml_values=shadowed_aml_values)
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/account_move_line.py", line 2832, in _check_amls_exigibility_for_reconciliation
raise UserError(_("You can not reconcile cancelled entries."))
You can not reconcile cancelled entries.
```
Because an old transaction: state = 'reconciled' but is_reconciled is false get attached to the new invoice. The the tx.payment_id.move_id was cancelled by the accounting team, and the invoice was reconcilled directly with the bank statement.
So we end up with a cancelled move that block any further invoice for this subscription.
Solution
--------
According to accounting team, the move_id of the payment is always posted except if there is some manual intervention. We make sure we link only transaction with payment with posted moved
opw-6368231
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275445
Forward-Port-Of: odoo/odoo#2747643 changes
New functionality added to Odoo
This update introduces support for Georgian accounting standards, including a new chart of accounts, tax settings, and VAT reporting capabilities. This expansion allows Odoo users operating in Georgia to comply with local accounting and tax regulations, streamlining their financial processes.
Original PR description
[ADD] l10n_ge: add Georgian Chart of Accounts - This commit adds the Georgian accounting localization, including the chart of accounts, taxes, fiscal positions, tax groups, and VAT report required for standard accounting and tax reporting flows - It provides support for domestic VAT, reverse charge VAT, and the Georgian VAT declaration report. taskID-3927928 related PR (from 19.0 to saas-19.2) - https://github.com/odoo/odoo/pull/263452
Enhancements to existing features
This update introduces a manual KYC (Know Your Customer) process for Odoo users utilizing the PEPPOL accounting module. Previously, PEPPOL account setup was automated. Now, users can complete a manual verification process, ensuring compliance with PEPPOL regulations and improving data security. This change enhances the reliability and security of transactions within the PEPPOL ecosystem.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275371
Resolved issues and error corrections
This update resolves an issue where sales orders could incorrectly show analytic distributions exceeding 100%, leading to confusing accounting reports. The change consolidates analytic distributions from multiple models into a single line, maintaining functionality while ensuring accurate reporting. This improves clarity and prevents potential over-allocation of costs.
Original PR description
Steps: 1. Create an analytic model filtered by partner. 2. Create an analytic model filtered by product. 3. Create a project with an analytic distribution. (Make sure the distributions use different plans) 4. Create an SO for a product within the project that both the models apply to. 5. Confirm the SO. 6. Notice the analytic distribution for the project account is at 200%. When an SOL is created, the analytic distribution from each model is added as a separte line The analytic account for the project is added to each analytic distribution line. This can easily cause the account to have >100% distribution for a given SOL. This is unintuitive and confusing behaviour. This PR changes the behaviour to only create one line for all the distributions from analytic models. This should prevent this behaviour while keeping the functionality of applying the project distribution to each line. opw-6250908 / opw-6304033 Forward-Port-Of: odoo/odoo#270151
2 changes
New functionality added to Odoo
This update introduces support for Georgian accounting standards, including a new chart of accounts, tax reporting, and VAT compliance. This expansion allows businesses operating in Georgia to utilize Odoo's accounting features fully, meeting local tax regulations.
Original PR description
[ADD] l10n_ge: add Georgian Chart of Accounts - This commit adds the Georgian accounting localization, including the chart of accounts, taxes, fiscal positions, tax groups, and VAT report required for standard accounting and tax reporting flows - It provides support for domestic VAT, reverse charge VAT, and the Georgian VAT declaration report. taskID-3927928 related PR (from saas-19.3 to master) - https://github.com/odoo/odoo/pull/263765 Forward-Port-Of: odoo/odoo#263452
Resolved issues and error corrections
A recent update introduced an access error for users without Employee record access when using the Overtime Rulesets feature. This fix restricts the visibility of a new 'Stat' button to authorized users, ensuring a smooth experience for administrators while maintaining the feature's functionality for those with appropriate permissions.
Original PR description
**Steps to reproduce:** 1. Install the **Attendance** app in saas-19.2 with demo data. 2. Log in as a user who has **Administrator** rights in the Attendance app but no access rights in the Employees…
**Steps to reproduce:**
1. Install the **Attendance** app in saas-19.2 with demo data.
2. Log in as a user who has **Administrator** rights in the Attendance app but no access rights in the Employees app.
3. Go to **Attendance → Configuration → Overtime Rulesets**.
4. Open any overtime ruleset.
An `AccessError` is raised:
```
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 3373,
in check_access
raise result[1]()
odoo.exceptions.AccessError: You are not allowed to access
'Employee Record' (hr.version) records.
This operation is allowed for the following groups:
- Employees/Administrator
- Employees/Officer: Manage all employees
Contact your administrator to request access if necessary.
```
**Issue:**
A new feature introduced an employee count stat button on `hr.attendance.overtime.ruleset` in [v19.2](https://github.com/odoo/odoo/pull/236555/changes).
Users who have administer right in Attendance app but do not have access to Employee records trigger an access error when opening the ruleset.
**Solution:**
The fix restricts the visibility of the [Stat button ](https://github.com/odoo/odoo/blob/7c6f31d730304bca3f6c996800e76d1e40ce4adf/addons/hr_attendance/views/hr_attendance_overtime_rule_views.xml#L114)to users with the required Employee groups, preventing the access error while keeping the feature available for authorized users.
opw- 6358550
upg- 4449776
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr5 changes
Enhancements to existing features
This update introduces a manual process for Know Your Customer (KYC) verification within the PEPPOL account setup in Odoo. Previously, this process was automated. Now, administrators can complete the necessary KYC documentation directly within Odoo, ensuring compliance with PEPPOL regulations and simplifying the account onboarding experience. This change improves the user experience and streamlines the account setup process for our PEPPOL customers.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275371
Resolved issues and error corrections
This update fixes an issue where credit notes renamed and sorted before invoices could incorrectly shift lot assignments on existing invoices. The change ensures that lot allocations remain stable after credit note modifications, preventing invoices from consuming the wrong lot. This improves accuracy in inventory tracking and reporting.
Original PR description
#### Issue: When a credit note is renamed so that it sorts before the related invoices, the lot assigned on invoice previews can become incorrect. Already posted invoices can appear to consume the…
#### Issue: When a credit note is renamed so that it sorts before the related invoices, the lot assigned on invoice previews can become incorrect. Already posted invoices can appear to consume the first lot again. Example: A sale order is delivered in 2 batches: 10 units from SN01, then 10 units from SN02. Invoice 1 correctly shows SN01 and Invoice 2 correctly shows SN02. If Invoice 1 is refunded, re-invoiced, and the credit note is then renamed so it sorts before the invoices, Invoice 2 can incorrectly switch back to SN01. #### Steps to reproduce: - Enable "Display Lots & Serial Numbers on Invoices". - Create a sale order for 20 units of a tracked product. - Deliver 10 units from the first lot/serial number and 10 units from a second one in a backorder. - Create and post 2 invoices, one for each delivery. - Create and post a credit note for the first invoice. - Create and post a new invoice for 10 units. - Reset the credit note to draft, rename it so that it sorts before the invoices, then repost it. - Check the lot previews on the invoices. #### Root Cause: _get_invoiced_lot_values() orders invoice lines with move_name, which is mutable, then computes the previously invoiced quantities from that order. When a refund is renamed so it sorts before the invoices, the set of "previous" invoice lines changes. On top of that, reversed invoices are filtered out too broadly, even when their reversing move should not yet impact the current invoice chronology. #### Fix: Order invoice lines with immutable move ids instead of move_name, and only ignore reversed invoices once their reversing move is also before the current invoice in the effective chronology. This keeps posted invoices stable while preserving the re-invoice behavior. opw-6110232 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264776
This update resolves an issue where sales orders could incorrectly show analytic distributions exceeding 100%, leading to confusing accounting reports. The change consolidates analytic distributions from multiple models into a single line, maintaining functionality while ensuring accurate reporting. This improves clarity and prevents potential over-allocation of costs.
Original PR description
Steps: 1. Create an analytic model filtered by partner. 2. Create an analytic model filtered by product. 3. Create a project with an analytic distribution. (Make sure the distributions use different plans) 4. Create an SO for a product within the project that both the models apply to. 5. Confirm the SO. 6. Notice the analytic distribution for the project account is at 200%. When an SOL is created, the analytic distribution from each model is added as a separte line The analytic account for the project is added to each analytic distribution line. This can easily cause the account to have >100% distribution for a given SOL. This is unintuitive and confusing behaviour. This PR changes the behaviour to only create one line for all the distributions from analytic models. This should prevent this behaviour while keeping the functionality of applying the project distribution to each line. opw-6250908 / opw-6304033 Forward-Port-Of: odoo/odoo#270151
This update resolves an issue where attachments added to email templates weren't correctly linked to scheduled messages. Previously, users would encounter access errors when viewing scheduled messages with different user accounts. This change ensures all attachments are properly associated with the scheduled message, improving data consistency and preventing these errors.
Original PR description
**Problem:** When scheduling a message using an email template with custom attachments, those attachments will not have their `res_model` and `res_id` updated to relate to the scheduled message…
**Problem:** When scheduling a message using an email template with custom attachments, those attachments will not have their `res_model` and `res_id` updated to relate to the scheduled message record. This can lead to access errors. **Cause:** When composing a message using an email template with attachments, those attachments are created with their `res_model` and `res_id` values corresponding to the mail composer record. However, when scheduling a message, only attachments with no `res_id` value (or a value of 0) are updated to correspond to the scheduled message record. https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mail/wizard/mail_compose_message.py#L1198-L1201 https://github.com/odoo/odoo/blob/30ca89b9e0d3c43d019167ec2de816c263f4bb92/addons/mail/models/mail_scheduled_message.py#L86 **Purpose:** Modify the `mail.scheduled.message` override of `create` to not require an attachment have no `res_id` value to be properly updated. **Steps to Reproduce in Runbot:** 1. Add an attachment to an email template. 2. Open a mail composer using that email template, then schedule the message for later. 3. Attempt to view the scheduled message with a different user. More specific example flow: 1. Add an attachment to the Sales: Send Quotation email template. 2. Create a Quotation and send it with the Send by Email button, selecting Send Later instead of Send. 3. Attempt to view the Quotation with a different user. opw-6293587 Forward-Port-Of: odoo/odoo#272261
This update fixes an issue where lost leads were not included in reporting totals when grouping leads. The change ensures that all leads, including inactive ones, are properly considered during filtering and grouping, leading to more accurate reporting. This improves the reliability of lead analysis.
Original PR description
Problem: When filtering lost leads and grouping them, the lost leads are not counted in the groups' totals. Steps to Reproduce: 1. Go to CRM 2. Go to Reporting > Leads 3. Select List View 4. Before…
Problem: When filtering lost leads and grouping them, the lost leads are not counted in the groups' totals. Steps to Reproduce: 1. Go to CRM 2. Go to Reporting > Leads 3. Select List View 4. Before applying any grouping, check the total number of leads and make sure there are some closed leads among the leads and that the applied filter includes the inactive/lost leads 5. Apply any grouping 6. Check how the sum of the groups totals doesn't equal the leads total Cause: When reading a group, the domain from the applied filter gets optimized, meaning that the applied rules get simplified logically. https://github.com/odoo/odoo/blob/f4d079cc5a9c47672cf1a6747bb073e8e74f7350/addons/web/models/models.py#L421 When looking for all leads, we filter by both active and inactive leads, but the optimize method removes both of them since active=TRUE OR active=FALSE = TRUE always. When removed, no filtering on the active field is in the domain now, which leads to the search method returning only active leads (default behaviour of search method when the active field is not set in the domain). opw-6302388 Forward-Port-Of: odoo/odoo#272390
1 change
Resolved issues and error corrections
This update resolves an issue where selecting an item in an autocomplete field would sometimes result in the selected value being lost. The fix ensures the field's value is correctly updated after selecting an item, improving data accuracy and user experience within the Project app. This was triggered by a specific interaction within the autocomplete component.
Original PR description
In this fix we only call the `props.onChange` when the ignoreBlur flag is flag, because it's only set to true when we click on the dropdown item[1]. Steps to reproduce: - Open Project app - Go to a task. - Click on Activity button - Select the "On the Assigned" to field CTRL + a => Delete Press a letter like 'e' Remove the letter Select a item inside the dropdown => the fields is value is empty and the selected item is lost => bug task-4504910 [1]: https://github.com/odoo/odoo/blob/9bc7638506262259ac54a962617884f3deff6b9b/addons/web/static/src/core/autocomplete/autocomplete.xml#L45 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275260
19 changes
New functionality added to Odoo
Turkish companies using TRY can now store official buying and selling exchange rates alongside the average rate. Invoices and bills automatically use the appropriate rate type by default, reducing manual corrections and helping accountants apply the correct rate consistently.
Original PR description
## Description of the issue/feature this PR addresses: Turkish accounting applies different exchange rates depending on whether the company is collecting foreign currency or paying it out. TCMB…
## Description of the issue/feature this PR addresses: Turkish accounting applies different exchange rates depending on whether the company is collecting foreign currency or paying it out. TCMB publishes both buying and selling rates daily but `currency_rate_live` only keeps the average, so accountants currently correct the rate by hand on every invoice and bill. ## Current behavior before PR: The TCMB daily update stores only the averaged rate on `res.currency.rate`. Invoices and bills use that same rate, and users have to adjust it manually per document. ## Desired behavior after PR is merged: - Both the buying and selling rates are stored on `res.currency.rate` next to the average. - Customer invoices and vendor bills get a Rate Type field, defaulting to "buying" for invoices and vendor refunds and to "selling" for bills and customer refunds. The user can override before posting. - The selected rate is written to `invoice_currency_rate`. The lookup uses the rate dated the document's date, or the most recent rate before it when no rate exists for that exact date. - Only TR companies with TRY as base currency are affected. task-5017817 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Enhancements to existing features
This update moves Odoo Enterprise screens and website snippets to the new shared icon system. Users should see more consistent icons across accounting, website, appointments, knowledge, sign, studio, room booking, and related areas, while reducing reliance on older icon assets.
Original PR description
Community PR: odoo/odoo#275347 task-5901783
Field Service shift notes can now include rich formatting such as links, images, and clearer instructions instead of plain text only. Product descriptions are also added automatically, helping technicians see relevant job details directly in their shift instructions.
Original PR description
Currently, the **Note** field only supports plain **text**, limiting the ability to include rich content such as links, images, and formatted instructions. This commit converts the **Note** field to **HTML** and automatically displays the product description in it, making Field Service shift instructions richer and easier for technicians to follow. Task-6285798
Sales users can now choose a subscription plan directly for optional subscription products in the configurator, instead of always receiving the first available plan. When a plan is already set by a parent product or cart subscription, the selector is locked so optional items stay aligned with the existing subscription.
Original PR description
Previously, optional subscription products in the configurator dialog would default to the first available subscription plan. This behavior was restrictive and did not allow users to choose a different plan. This change introduces an inline plan selector displayed next to the price of each optional subscription product in the configurator dialog: - The selector is editable when no plan is enforced (i.e., no parent subscription product and no existing subscription in the cart). - The selector is locked when a plan is already defined, ensuring optional products inherit the parent subscription plan. task-6130917
Validated tax returns can now be reset more flexibly when later returns already exist, as long as the report does not rely on carryover values. This reduces extra work for accounting teams that need to correct and resubmit an earlier period without undoing every subsequent return.
Original PR description
Let's consider we have validated the return of our tax report for January and February. Then, we realize we made an error in January, and want to modify this return and resubmit it. Before this…
Let's consider we have validated the return of our tax report for January and February. Then, we realize we made an error in January, and want to modify this return and resubmit it. Before this commit, an error message blocked the direct resetting of January's return, because February's had been posted. To be able to reset January, it was necessary to reset all subsequent returns. This was annoying. Such fixes need to happen in many countries (while some other rather make the adjustments in the next period to declare, like Belgium). This restriction was originally introduced to avoid inconsistencies in case the returns declared from the previously submitted returns. Two features could create such cases: 1) tax amount to recover, which was directly deduced from the closing entry when it contained something to pay 2) carryover, which created external values able to impact the following periods => Case 1) is not true anymore. When an amount needs to be recovered, we just show the balance taking it into account on the following returns, but don't change anything to their closing at all. => Case 2) still holds. So, all we need to put under control is carryover, which is what we do now. If the report doesn't use carryover at all, its returns can all safely be reset, whatever the state of the rest of the return chain.
The Sources tab for AI agents now has a clearer mobile-friendly layout. Adding a source also uses the same dialog as the list view, making the experience more consistent and easier to use on smaller screens.
Original PR description
The Sources tab in the AI agent form did not provide a dedicated kanban layout, resulting in a poor view on smaller screens. This commit adds a structured kanban view for AI agent sources and updates the 'Add Source' action to open the same creation dialog as the list view, providing a more consistent user experience. task-6366399
The bank reconciliation widget now loads less unnecessary data, especially on very large databases. This should make opening and using bank reconciliation faster for accounting teams without changing their workflow.
Original PR description
When opening the bank rec widget on huge DB's, it takes
a lot of time to load everything.
This commit aims to improve the loading performances by
removing some JS fields:
1 - reconciled_lines_ids: We only use the first element of
this recordset in JS, so we add a new computed field
to only send 1 record to the JS
2 - hasAttachment: replace the long JS computation of
`get hasAttachment` with a python computed field.
3 - Replace matched_credit_ids and matched_debit_ids
with exchange_diff_partial_ids.
Linked:https://github.com/odoo/odoo/pull/269119
task-6275945
Forward-Port-Of: odoo/enterprise#119557The timesheet assistant now gives clearer guidance when setup issues prevent activity tracking, including distinguishing server and CORS problems and warning when the browser watcher is missing or inactive. It also improves suggested timesheet entries by showing better context, restoring ActivityWatch suggestions after deleted Odoo events, and choosing more relevant projects for calendar events.
Original PR description
Forward-Port-Of: odoo/enterprise#122340 Forward-Port-Of: odoo/enterprise#115859
Resolved issues and error corrections
Vendor bills imported from Chilean electronic invoice files now use the correct foreign-currency amounts instead of mistakenly applying Chilean peso amounts. This prevents incorrect bill totals when companies work with currencies such as UF.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
This change prevents WhatsApp messages from failing to load when they are linked to business documents that the user cannot access directly. Existing WhatsApp message visibility rules still control who can see messages, helping affected upgrades proceed without disruption.
Original PR description
The `body` field on `whatsapp.message` was defined with `related_sudo=False` with the intent of restricting access to messages from restricted records. However, this was never actually providing any…
The `body` field on `whatsapp.message` was defined with `related_sudo=False` with the intent of restricting access to messages from restricted records. However, this was never actually providing any security value because [`mail.message.fetch()`] was overriding it with `self.sudo()` till `v19.1`, meaning the body was always fetched as superuser regardless:
```py
web_search_read() -> search_fetch()
-> fields.py _compute_related()
-> record[self.related_field.name] # triggers fetch of mail.message.body
-> models.py _fetch_field()
-> mail_message.py fetch()
-> self = self.sudo() # sudo hack overrides related_sudo=False silently
```
In `v19.2`, the `fetch()` sudo hack was intentionally removed (see commit odoo/odoo@4727f12d274a0b2d7c455363d189565bd8fb2e7a) as access rights are now cached and can be checked without a performance penalty. This exposed the broken `related_sudo=False` which now causes an `AccessError` when trying to read the body of a `whatsapp.message` whose linked `mail.message` points to a document the current user cannot access (e.g. `purchase.order`).
Access control on `whatsapp.message` is already correctly enforced at the `ir.rule` level:
- Regular users can only see messages they created (`create_uid = user.id`)
- WA Admins can see all messages
We have upgrade requests failing on this issue: TBG-[2765]
[`mail.message.fetch()`]: https://github.com/odoo/odoo/blob/saas-19.1/addons/mail/models/mail_message.py#L812-L819
[2765]: https://upgrade.odoo.com/odoo/tbg/2765?debug=1
Forward-Port-Of: odoo/enterprise#119867This fix ensures that when warehouse staff scan an existing package followed by a package type, the newly created destination package is correctly linked to the products. It prevents silent package creation errors in barcode delivery flows, improving inventory accuracy and reducing manual correction work.
Original PR description
When scanning a package then a package type, from the point of view of the user nothing happend, and in the backend it will created a new package but it will not link it to the products nor will it…
When scanning a package then a package type, from the point of view of the user nothing happend, and in the backend it will created a new package but it will not link it to the products nor will it show any warning. Steps to reproduce: ------------------- * Install barcode and stock * Enable packages in settings * Open Inventory * Create a product, * Create a Package Type -> barcode PACKTYPE, * Create a Package linked to this package type -> PACK, * Add at least 2 unit of product to this package, * Create a delivery for 2 unit of the product, Open Barcode * Operation > Delivery orders > your delivery * Erase the destination package from the first line * Scan PACK ( don't click on the green line) * Scan PACKTYPE **Actual behavior** create a new package but does not link it to the new products **Expected behavior** create a new package and set it as destination package. Observation: ------------- When scanning the package (PACK), we will go through ```_processPackage``` -> ```async _processPackage``` where in the end the line is unselected: https://github.com/odoo/enterprise/blob/39d8a473fe03038ca0494a6a8165e3eb75bd8492/stock_barcode/static/src/models/barcode_picking_model.js#L2090 When we scan our package type (PACKTYPE), we will go to ``` _processPackage``` -> ```_processPackage```->```_processPackageType``` where we will obtains packagesIds checking that we have a source package: https://github.com/odoo/enterprise/blob/7cd9834d1d918f12dec43844cae6f112309e5772/stock_barcode/static/src/models/barcode_picking_model.js#L2123-L2132 and will send us to ```_putPackInPack```: https://github.com/odoo/enterprise/blob/7cd9834d1d918f12dec43844cae6f112309e5772/stock_barcode/static/src/models/barcode_picking_model.js#L2133-L2136 Where we will avoid the empty packageIds since we checked on the source package and not the destination package: https://github.com/odoo/enterprise/blob/2b887d094c66be7aebd92fbf735b1852f5dde4b5/stock_barcode/static/src/models/barcode_picking_model.js#L2296-L2299 and will call ```action_put_in_pack``` from the packaging model: https://github.com/odoo/enterprise/blob/2b887d094c66be7aebd92fbf735b1852f5dde4b5/stock_barcode/static/src/models/barcode_picking_model.js#L2301-L2306 In ```action_put_in_pack``` will create a new packaging and put it as a the new destination package, but since the ```previous_dest_package``` (saved in db) was itself, he will [erase the link](https://github.com/odoo/odoo/blob/cda011dc8590773f6c3a26f4ae9d5242a3147024/addons/stock/models/stock_package.py#L354-L363) he just made. Which means that in our case, we created a package without linking it to anything. Even if we avoid the function to erase the destination package, since the destination package shown in barcode is the one from move line : https://github.com/odoo/enterprise/blob/d0d0a3cf4a02bf24cf502b533e494fe7ca155eb3/stock_barcode/static/src/components/line.js#L115-L117 It will not show the new package in barcode opw-5449729 Forward-Port-Of: odoo/enterprise#120335 Forward-Port-Of: odoo/enterprise#104876
Belgian payroll no longer applies a special public holiday eligibility rule for time credit contracts because that rule had no legal basis. This keeps payroll calculations aligned with Belgian legal requirements and reduces the risk of incorrect payslip handling.
Original PR description
The specific code related to the eligibility to public holiday for time credit contracts has no legal base. This commit removes it. task-6370653 Forward-Port-Of: odoo/enterprise#123303
The attendance Gantt view now includes employees who are currently checked in when calculating worked hours. This ensures progress information is accurate even before an employee checks out, helping managers see up-to-date attendance totals.
Original PR description
Isuue =========== If the `check_out` field on an attendance is not set, we don't take it into consideration in the computed worked hours, as we defined domains to retrieve attendances whose `check_out` ends before a certain limit, assuming `check_out` is set for all attendance records, and thus missing the worked hours that are still ongoing. Fix =========== - Update the domain of the employees' progress bar data to account for attendances with a `False` `check_out`. TaskID-6121547
The timesheet grid now marks public holidays, weekends, and approved personal time off according to the employee's own working schedule instead of always using the company default. This helps employees and managers see accurate unavailable days and keeps Timesheets aligned with Time Off behavior.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080 Forward-Port-Of: odoo/enterprise#123331 Forward-Port-Of: odoo/enterprise#95458
Lazada order syncing no longer adjusts individual item statuses in a way that can reduce ordered quantities below already delivered amounts. This prevents sync interruptions for orders with delivered items that later show item-level cancellations, improving reliability for Lazada sales operations.
Original PR description
Lazada stores order statuses at the item level. When an item is canceled, we mirrored this by decreasing the ordered quantity on the sale order line. But if the item was already delivered, decreasing the quantity below the delivered amount is forbidden and raises a `UserError`, which aborts the whole order sync:
```python
File ".../sale_stock/models/sale_order_line.py", line 420, in _update_line_quantity
raise UserError(_('The ordered quantity of a sale order line cannot be decreased below the amount already delivered. [...]'))
```
In practice, item-level statuses only differ from the order status in exceptional cases. Stop syncing statuses at the item level and assume the entire order shares a single status, which avoids the quantity decrease and the resulting traceback.
opw-6267730
Forward-Port-Of: odoo/enterprise#123365
Forward-Port-Of: odoo/enterprise#122851Auto Plan will no longer assign someone to a project planning slot just because they previously worked on the same project. It now also checks that the person matches the role requested for the slot, preventing incorrect staffing suggestions.
Original PR description
## Issue When using the *Auto Plan* feature on a planning slot with a Role and a Project set, a resource which operated on the same project will be chosen if available, without taking into account…
## Issue
When using the *Auto Plan* feature on a planning slot with a Role and a Project set, a resource which operated on the same project will be chosen if available, without taking into account the Role set on the slot.
## Steps to reproduce
1. Install Project Planning (`project_forecast`)
2. In Planning > Configuration > Roles, create two planning roles A and B
- Role A: Assign a resource R
- Role B: No resource
3. Open Planning (Schedule by Resource), and go back a few weeks (to prevent overlaps with potential demo data)
4. Create two new slots:
1. Set Role B and a random Project P, then click Auto Plan: there should be no available resource (because we didn't set any resource for Role B)
2. Set Role A and the same Project P, then click Auto Plan: it should assign the resource R assigned to Role A
5. After assigning a resource to the slot for Role A, edit the Open Shift for Role B again and click Auto Plan: **it assigns the same resource R, even though that resource is not assigned to Role B.**
## Cause
The `_get_open_shifts_resources` override in `project_forecast` looks for resources that were assigned to slots related to the same project. It does not filter resources based on the requested role.
https://github.com/odoo/enterprise/blob/885edbc270a86ab76e0a6eff4acb5767c0fe29d1/project_forecast/models/planning_slot.py#L104-L116
This means that resources that are not part of the requested role can be assigned to the slot, as long as the resource operated on another slot for the same project.
opw-6325744
Forward-Port-Of: odoo/enterprise#122813
Forward-Port-Of: odoo/enterprise#122035Merging manufacturing orders now removes pending quality checks from the cancelled source orders. This prevents outdated quality tasks from remaining visible and avoids confusion for manufacturing and quality teams.
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that…
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that product - Create and confirm multiple Manufacturing Orders - Verify that each MO generates a quality check - From the MO list view, select the MOs and merge them from the gear menu(merge) Issue: ------ When Manufacturing Orders are merged, All MOs are cancelled but it keep their quality checks in the 'To Do' state. As a result: - The quality checks remain linked to cancelled MOs - The 'Quality Checks' smart button is still displayed on cancelled MOs Expected behavior: ------------------ - Pending quality checks should be deleted when the MO is cancelled - The 'Quality Checks' smart button should no longer be displayed Cause: ------ A previous fix introduced logic to remove pending quality checks when a Manufacturing Order is cancelled: odoo-dev@db93bd2 This logic was implemented in `action_cancel()` by unlinking quality checks associated with the cancelled MO: https://github.com/odoo/enterprise/blob/20bc0eb5c2cec67eecd3b44450934e23370b48f2/quality_mrp/models/mrp_production.py#L94-L97 However, when MOs are merged, the merge flow does not call `action_cancel()`. Instead, it directly invokes `_action_cancel()` on the source Manufacturing Orders: https://github.com/odoo/odoo/blob/aca0b7289c68fc7a75d47ab313f5f791ebf30f7d/addons/mrp/models/mrp_production.py#L2480 Since the quality check cleanup is implemented only in `action_cancel()`, it is bypassed during the merge process. As a result, the source MOs are cancelled but their pending quality checks remain in place. --- opw-6260735 Forward-Port-Of: odoo/enterprise#121809 Forward-Port-Of: odoo/enterprise#119525
Bank reconciliation entries that use tax models now correctly show the taxable base amount instead of $0.00. This helps accounting teams review tax-related journal entries accurately without needing to reset entries to draft to refresh the value.
Original PR description
### Steps to reproduce the issue: 1. Download Accounting 2. Go to Journal entries and create a new one 3. Click Toggle Studio button and go to the view to add the tax_base_amount field to the list of…
### Steps to reproduce the issue: 1. Download Accounting 2. Go to Journal entries and create a new one 3. Click Toggle Studio button and go to the view to add the tax_base_amount field to the list of existing fields 4. Add 2 lines (example): 1. account Product Sales with 1000 dollars credit and 15% tax under Tax column 2. account Bank with 1000 dollars debit 5. Go to Dashboard > Bank > Click the 3 dots of one random bank matching line and click on Manage Models 6. Go to bank fees and add the 15% tax 7. Go back to bank reconciliation and create a new one of 2000 dollars with label bank fees (it will associate the tax automatically) 8. Go back to Journal Entries, group by Journal and search for the transaction of 2000 sollars for account Bank 9. Problem: see that the Base Amount for the 15% bank fees lines (251000 Tax Received account) is 0. Clicking on Reset to draft button the base amount column is automatically updated but this should happen automatically ### Cause of the issue: This occurs because the _lines_prepare_tax_line method in account.bank.statement.line fails to map this field in its return dictionary. ### Reason to introduce the fix: Currently, when applying a reconciliation model with taxes the generated tax lines incorrectly record a tax_base_amount of $0.00. Instead, it should be displayed and calculated. opw-6220948 Forward-Port-Of: odoo/enterprise#123603 Forward-Port-Of: odoo/enterprise#122139
Fixes an issue where quotations created from a sales opportunity could be hidden when viewing the opportunity's quotation list. This ensures rental-related filtering correctly recognizes standard quotations, helping sales teams find and manage all relevant quotes.
Original PR description
Steps to reproduce: 1. Install sale_crm and sale_renting_crm 2. Create an opportunity 3. On this opportunity, create two quotations from the `New quotation` button 4. From the opportunity's form…
Steps to reproduce:
1. Install sale_crm and sale_renting_crm
2. Create an opportunity
3. On this opportunity, create two quotations from the `New quotation` button
4. From the opportunity's form view, click on the `Quotation` smart button
Issue:
- The quotations are not visible in the list view
Why?
- In module `sale_renting_crm`, we override the domain to exclude rental quotations.
https://github.com/odoo/enterprise/blob/fda037c62a6661665611fb061718c01aec39ac1b/sale_renting_crm/models/crm_lead.py#L33-L36 But from the saas-19.3 `is_rental_order` field is no longer stored in the DB, It is computed now and filtered through `_search_is_rental_order`.
https://github.com/odoo/enterprise/blob/fda037c62a6661665611fb061718c01aec39ac1b/sale_renting/models/sale_order.py#L223-L227 The search method did not properly handle the Boolean search shape used by the ORM, so the quotations were incorrectly filtered out. In our case, we gave the domain `("is_rental_order", "=", False)` but the operator is translated to `not in` and value to `Orderedset([True])` by the domain optimiser
Solution:
- Update `_search_is_rental_order()` to handle the ORM-normalized boolean search correctly for rental and non-rental quotations.
opw-6304696
Forward-Port-Of: odoo/enterprise#1208691 change
Resolved issues and error corrections
This update fixes an issue where imported FatturaPA XML invoices weren't correctly applying Italian VAT rules (like partial deductibility) to the line items. Now, the system accurately maps these imported taxes to the fiscal position, ensuring correct VAT calculations for Italian businesses. This improves tax compliance and reporting accuracy.
Original PR description
### Before this PR When importing a FatturaPA XML, Odoo sets the fiscal position on the bill from the partner but does not apply it to the line taxes so a fiscal position that remaps taxes (partial deductibility, reverse charge, split payment) never map the imported lines. ### After this PR the fiscal position is correctly applied ### To reproduce 1. Apply to Italian vendor a fiscal position that maps the 22% purchase tax to a partial-deductibility tax (e.g. "22%" →"22% ind. 50%"). 2. Import a FatturaPA XML from that vendor with 22% lines. 3. The bill header shows the fiscal position, but the lines keep the plain 22% tax instead of the mapped one. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr