Daily updates from Odoo
Friday, July 10, 2026
386 changes
21 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
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid. Single font files parsing for the shortestNamedFont now also correctly keeps the weight for the targetFonts. Description of the issue/feature this PR addresses: Uploaded fonts with spaces in the name are not working. Current behavior before PR: When uploading a font with a space in the filename like "FontName 123 Light.otf" the css declaration in the attachement i
Original PR description
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid. Single font files parsing for the shortestNamedFont now also correctly keeps…
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid.
Single font files parsing for the shortestNamedFont now also correctly keeps the weight for the targetFonts.
Description of the issue/feature this PR addresses:
Uploaded fonts with spaces in the name are not working.
Current behavior before PR:
When uploading a font with a space in the filename like "FontName 123 Light.otf" the css declaration in the attachement is wrong and not working:
```css
@font-face {
font-family: FontName 123 Light;
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}@font-face {
font-family: FontName 123 Light;
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}
```
Desired behavior after PR is merged:
The font name is now correctly quoted and the font attributes are no longer overwritten for the shortestNameFont:
```css
@font-face {
font-family: "FontName 123 Light";
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}@font-face {
font-family: "FontName 123 Light";
font-style: normal;
font-weight: 300;
src: url("/web/content/1057/FontName 123 Light.otf");
}
```
Info @wt-io-it
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273534
Forward-Port-Of: odoo/odoo#268842When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The exception handler uses `.sudo().activity_schedule()`, which bypasses the write access restriction but leaves `env.uid` as the portal user. Therefore, the restricted portal user permanently becomes the `create_uid` (Author) of the activity. System exception activities should always be authored by the s
Original PR description
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The…
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The exception handler uses `.sudo().activity_schedule()`, which bypasses the write access restriction but leaves `env.uid` as the portal user. Therefore, the restricted portal user permanently becomes the `create_uid` (Author) of the activity. System exception activities should always be authored by the system (OdooBot), never by a portal or public user. This context leak corrupts the activity metadata by injecting an external user ID into internal backend logs. Chain `.with_user(SUPERUSER_ID)` to the `.sudo()` call in `stock_orderpoint.py` when scheduling the exception activity. This ensures the environment context is stable and the activity is authored by OdooBot, which transcends multi-company record rules. Steps to Reproduce on Runbot/Fresh Database on version 17.0: 1. Enable Multi-Company with Company A and Company B. Set Company B as the active company for the website. 2. Restrict the main Admin (Runbot) user strictly to Company A. 3. Create a Shared Product (Company field left blank). 4. Set a Reordering Rule (Orderpoint) for the product that is guaranteed to fail routing. 5. Navigate to the frontend website and sign up as a new user (this creates a Portal User in Company B). 6. As the newly signed-up Portal User, complete an eCommerce checkout for the shared product. 7. The checkout succeeds, but the backend triggers the orderpoint failure and logs the exception activity on the product template. 8. Check the chatter for this product: the `create_uid` is incorrectly set to the Portal User instead of OdooBot (1). 9. (In 19.0 Upgrade) Log in as the Admin user (set strictly to view Company A), navigate to the product, and the AccessError for reading will appear due to this leaked id. [opw-6253978](https://www.odoo.com/odoo/my-support-tasks/6253978?debug=assets) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275140 Forward-Port-Of: odoo/odoo#269395
Issue: pos_self_order overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 D
Original PR description
Issue: pos_self_order overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 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#275227 Forward-Port-Of: odoo/odoo#269260
This update strengthens the security of our payment processing by ensuring only the transaction reference is used, rather than all payment data. This prevents potential vulnerabilities and ensures the system only processes data it needs to find and trigger payment processing, improving overall system stability.
Original PR description
The `/payment/custom/process` was blindly processing any payment data it was receiving while its only purpose is to find the transaction from the posted arguments and trigger its processing. This commit clarifies that only the transaction reference is expected as an argument and reconstructs the payment data payload from it.
This update fixes an issue where the list price set when creating a product from an invoice wasn't being saved to the product template. Now, the list price accurately reflects the setting, ensuring consistent product information across the system. This improves data accuracy for pricing and reporting.
Original PR description
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the…
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the products list, the set list price is not shown. Steps to reproduce: 1. Go to Accounting > Customers > Invoices 2. Create a new invoice 3. Create and edit a new product from the invoice line and set a new list price for the new product 4. Go to Sales > Products and open the created product 5. Check the list price of the product 6. Notice how the set list price is not shown on the product form view Cause: Product variants show lst_price while product templates show list_price on their form views. When creating a product from the invoice line, the shown form is for the product variant. When setting the list price on the product variant form (lst_price in that case), the inverse method of llst_price, which sets the list_price in return, is called during the creation of the variant, after the template has been created and saved. As a result, editing the list price does not trigger a write on the already saved product template, causing the list_price of the variant to be different than the list_price of the template. opw-6272825 Forward-Port-Of: odoo/odoo#270614
This update fixes an issue where a process was unnecessarily triggered repeatedly, slowing down French VAT (PDP) operations. The change now ensures the process runs only when needed, improving performance and stability. This resolves a technical inefficiency impacting the French VAT reporting workflow.
Original PR description
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set. Forward-Port-Of: odoo/odoo#275019
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 fixes a minor issue where the 'invoice' button was visible on repair orders that hadn't reached a completed state. This change ensures that invoices are only generated when a repair is fully finished, improving data accuracy and preventing potential invoicing errors. The fix was part of a standard bug resolution process.
Original PR description
task 6379961 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
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#274764This update ensures Odoo's warning system consistently handles deprecation notices, regardless of the Python version used. The change corrects a compatibility issue where the system required a specific string format for warnings, preventing proper functioning on older Python versions. This ensures consistent and reliable warning messages for developers.
Original PR description
The native `warnings.deprecated` decorator strictly requires a string literal as its first positional argument and cannot be applied as a bare decorator. This commit enforces the same type verification in the fallback implementation for Python < 3.13. Follow-up of odoo/odoo@42fcc766af0584ef720a1cee5beb7878cdd1a572 runbot-941402 Forward-Port-Of: odoo/odoo#275531 Forward-Port-Of: odoo/odoo#275037
This update fixes a potential issue where multiple users reconnecting after downtime could cause errors in the system's background thread. By adding a lock around the thread starting process, we ensure only one thread is initiated, preventing errors and improving system stability. This resolves a potential compatibility problem with third-party monitoring tools like Sentry.
Original PR description
`ImDispatch.subscribe()` lazily starts the dispatcher thread with: ```py if not self.is_alive(): self.start() ``` However, this check isn't atomic: two subscribers can reach it at the same instant (a…
`ImDispatch.subscribe()` lazily starts the dispatcher thread with:
```py
if not self.is_alive():
self.start()
```
However, this check isn't atomic: two subscribers can reach it at the same instant (a bunch of clients reconnecting after a downtime/restart/etc..) and two of them can have the condition "is not alive" and both of them will call `start()`.
Technically, this is not a big deal, since `Thread.start()` will only successfully starts once and raise an Error `Threads can only be start3e once` which is already catch and ignored with `contextlib.suppress(RuntimeError)`.
But this is a problem with some APM (like sentry) where they override `threading.Thread.start` to do something different than stdlib, and so something we can not know nor control.
The RuntimeError guard only tells us who's allowed to actually spawn the thread. It says nothing about code attached to `start()`/`run()` that runs on every attempt, win or lose, and that's exactly the part we don't control.
For example, sentry-sdk (before 2.34) patches `Thread.start` to wrap `self.run` on *every* call, not only the one that actually starts the thread:
```py
def sentry_start(self, *a, **kw):
self.run = wrap(self.run) # <- side effect, runs unconditionally
return real_start(self, *a, **kw)
```
Under the race described above, every losing call still wraps `self.run` before failing. Each wrapper forwards its own extra argument to the one it wraps, without dropping what it already received, so each layer adds one more positional argument. By the time the thread actually starts, `ImDispatch.run()` ends up called with N positional arguments instead of one:
```
TypeError: ImDispatch.run() takes 1 positional argument but N were given
```
N varies from one report to the next simply because it depends on how many subscribers happened to race on that particular restart.
Rather than relying on the RuntimeError to paper over a race we still allow to happen, we remove the race itself: wrapping the check and the `start()` call in a lock guarantees at most one caller ever gets past the "not alive" check. `start()` is called exactly once, so there's nothing left for third-party instrumentation to react to more than once.
Note:
Reproduced locally by firing many concurrent `subscribe()` calls at a freshly created `ImDispatch` with sentry-sdk 1.39.2 installed: the TypeError appears reliably, with the reported argument count matching the number of racing calls. The same scenario no longer fails once the lock is in place, regardless of the sentry-sdk version installed.
sentry-3928947199
Forward-Port-Of: odoo/odoo#275084This update quietly fixes a warning that appeared when the HTML editor attempted to remove a node that had already been removed. The change ensures the editor functions correctly without displaying this misleading alert, improving the user experience. This was a minor technical issue with no impact on functionality.
Original PR description
When applying a "remove" mutation on a node that was already removed, a warning was shown because the node's parent didn't match the mutation's parent, since the node doesn't have a parent. We're warned of the fact that the node couldn't be removed but it was already removed so there's actually no problem. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update clarifies how dates are grouped in reports and dashboards. Previously, date ranges were displayed ambiguously using 12-hour time formats, leading to confusion about AM/PM. Now, all date groupings use a 24-hour format, providing a clear and unambiguous representation of time ranges.
Original PR description
Description of the issue/feature this PR addresses: When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`. In Babel/LDML formatting, `hh` represents…
Description of the issue/feature this PR addresses:
When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`.
In Babel/LDML formatting, `hh` represents a 12-hour clock. Since the format does not include an AM/PM marker, afternoon/evening hours are displayed ambiguously in grouped views.
Current behavior before PR:
A datetime value in the afternoon is grouped under a 12-hour label without AM/PM.
For example, records around `13:50` are displayed under:
01:00 20 Mar
Similarly, a datetime value around `16:20` may be grouped under:
04:00 26 Mar
This is ambiguous because the group header does not indicate whether the hour is AM or PM.
Example screenshot showing records around 13:xx grouped under `01:00`:
<img width="310" height="240" alt="image" src="https://github.com/user-attachments/assets/8768f2e8-9aaa-436b-af9f-40055a6032e9" />
Desired behavior after PR is merged:
Hour-based datetime group labels should be unambiguous.
The hour grouping format now uses `HH:00 dd MMM`, so grouped datetime labels render using a 24-hour clock.
For example:
13:00 20 Mar
16:00 26 Mar
This fixes the datetime hour grouping label shown in grouped list views and other `read_group` consumers.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275219
Forward-Port-Of: odoo/odoo#274724A recent test failure related to API documentation generation was resolved. The issue stemmed from the test taking too long to complete due to the increasing number of Odoo modules installed. This change ensures the test runs reliably regardless of the modules used, improving overall system stability.
Original PR description
The test_cache test failed a couple times on a timeout error, this is because the more modules are installed, the longer it takes to index them all and generate the json document. [runbot-240550](https://runbot.odoo.com/odoo/error/240550) Forward-Port-Of: odoo/odoo#274773
This update corrects a temporary visual glitch that appeared on the address page during initial loading. The team switched from using the incorrect CSS attribute ('t-att-class') to the correct one ('t-att-style') to ensure styles were applied properly. This resolves a minor cosmetic issue without impacting core functionality.
Original PR description
In this PR https://github.com/odoo/odoo/pull/237069 we used t-att-class for applying the style and because of that style was not properly applying and ICE was visible on address page on initial rendering for a moment even it does not have anything to do with MA. Used t-att-style instead t-att-class. task-5208254 Forward-Port-Of: odoo/odoo#274678
This update fixes a technical issue that caused an error when deleting pages on the website. The fix ensures that all dependencies related to deleted pages are accessed with the necessary permissions, preventing access errors and maintaining website functionality. This improves the stability and reliability of the website for all users.
Original PR description
Steps to reproduce: 1. Install website_hr_recruitment and hr_appraisal modules. 2. Remove `Appraisals`'s rights from admin. 3. Create appraisal & add `contactus` link in employee feedback. 3. Go to Website > Site > Pages. 4. Delete the contact us page. > An access error is raised on the employee_feedback field. Employee_feedback has field level access rights so when preparing the list of records depending on a deleted page, the search was performed with sudo, but the records were later accessed without sudo. This could trigger an access error on related fields. Use sudo while preparing the dependency list, as we only search the records and read their names. No sensitive fields are being exposed. task-6267364 Forward-Port-Of: odoo/odoo#274324 Forward-Port-Of: odoo/odoo#269790
18 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
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 - Open a PoS session and add any other product B to the order Issue: The discount was applied even though the order contained none of the rule's valid products. Cause: In `pointsForPrograms`, a rule was only gated on its quantity and amount thresholds (`totalProductQty < rule.minimum_qty`), nev
Original PR description
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 -…
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 - Open a PoS session and add any other product B to the order Issue: The discount was applied even though the order contained none of the rule's valid products. Cause: In `pointsForPrograms`, a rule was only gated on its quantity and amount thresholds (`totalProductQty < rule.minimum_qty`), never on the actual presence of a valid product in the order. Program templates (promotion, promo_code, next_order_coupons) create rules with minimum_qty = 0, so a product-restricted rule passed with zero matching items and, in "order" point mode, granted its points unconditionally. The same hole existed in `_canGenerateRewards` for scanned coupon programs, where rules act as conditions. The backend does not have this issue: `_program_check_compute_points` in sale_loyalty skips any rule whose valid products are not present in the order. Fix: Mirror the backend behavior in the PoS frontend: skip a product-restricted rule in `pointsForPrograms` when no (non-reward) order line matches its valid products, and make `_canGenerateRewards` return false in the same situation. Gift card and eWallet flows are unaffected since their "money"/"unit" point modes already gave 0 points when the trigger product was absent. opw-6357241 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275073
The native `warnings.deprecated` decorator strictly requires a string literal as its first positional argument and cannot be applied as a bare decorator. This commit enforces the same type verification in the fallback implementation for Python < 3.13. Follow-up of odoo/odoo@42fcc766af0584ef720a1cee5beb7878cdd1a572 runbot-941402 Forward-Port-Of: odoo/odoo#275037
Original PR description
The native `warnings.deprecated` decorator strictly requires a string literal as its first positional argument and cannot be applied as a bare decorator. This commit enforces the same type verification in the fallback implementation for Python < 3.13. Follow-up of odoo/odoo@42fcc766af0584ef720a1cee5beb7878cdd1a572 runbot-941402 Forward-Port-Of: odoo/odoo#275037
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid. Single font files parsing for the shortestNamedFont now also correctly keeps the weight for the targetFonts. Description of the issue/feature this PR addresses: Uploaded fonts with spaces in the name are not working. Current behavior before PR: When uploading a font with a space in the filename like "FontName 123 Light.otf" the css declaration in the attachement i
Original PR description
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid. Single font files parsing for the shortestNamedFont now also correctly keeps…
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid.
Single font files parsing for the shortestNamedFont now also correctly keeps the weight for the targetFonts.
Description of the issue/feature this PR addresses:
Uploaded fonts with spaces in the name are not working.
Current behavior before PR:
When uploading a font with a space in the filename like "FontName 123 Light.otf" the css declaration in the attachement is wrong and not working:
```css
@font-face {
font-family: FontName 123 Light;
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}@font-face {
font-family: FontName 123 Light;
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}
```
Desired behavior after PR is merged:
The font name is now correctly quoted and the font attributes are no longer overwritten for the shortestNameFont:
```css
@font-face {
font-family: "FontName 123 Light";
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}@font-face {
font-family: "FontName 123 Light";
font-style: normal;
font-weight: 300;
src: url("/web/content/1057/FontName 123 Light.otf");
}
```
Info @wt-io-it
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273534
Forward-Port-Of: odoo/odoo#268842Use 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
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#274764Currently the number grouping for Portuguese and Hindi is missing. Number grouping is used to separate long numbers in logical groups to make then easier to read. In Western countries, the grouping is usually done in groups of three digits (e.g. `1,000,000` instead of `1000000`), while in India, the grouping is done in groups of two digits after the first three digits (e.g. `10,00,000` instead of `1000000`). Source: https://www.unicode.org/cldr/charts/48/by_type/numbers.number_formatting_patt
Original PR description
Currently the number grouping for Portuguese and Hindi is missing. Number grouping is used to separate long numbers in logical groups to make then easier to read. In Western countries, the grouping is usually done in groups of three digits (e.g. `1,000,000` instead of `1000000`), while in India, the grouping is done in groups of two digits after the first three digits (e.g. `10,00,000` instead of `1000000`). Source: https://www.unicode.org/cldr/charts/48/by_type/numbers.number_formatting_patterns.html#24a93b3d14ba17b2 All languages will be revised in a follow-up `master` PR. [task-6320391](https://www.odoo.com/odoo/project.task/6320391) Forward-Port-Of: odoo/odoo#275237 Forward-Port-Of: odoo/odoo#274443
#### 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
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
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The exception handler uses `.sudo().activity_schedule()`, which bypasses the write access restriction but leaves `env.uid` as the portal user. Therefore, the restricted portal user permanently becomes the `create_uid` (Author) of the activity. System exception activities should always be authored by the s
Original PR description
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The…
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The exception handler uses `.sudo().activity_schedule()`, which bypasses the write access restriction but leaves `env.uid` as the portal user. Therefore, the restricted portal user permanently becomes the `create_uid` (Author) of the activity. System exception activities should always be authored by the system (OdooBot), never by a portal or public user. This context leak corrupts the activity metadata by injecting an external user ID into internal backend logs. Chain `.with_user(SUPERUSER_ID)` to the `.sudo()` call in `stock_orderpoint.py` when scheduling the exception activity. This ensures the environment context is stable and the activity is authored by OdooBot, which transcends multi-company record rules. Steps to Reproduce on Runbot/Fresh Database on version 17.0: 1. Enable Multi-Company with Company A and Company B. Set Company B as the active company for the website. 2. Restrict the main Admin (Runbot) user strictly to Company A. 3. Create a Shared Product (Company field left blank). 4. Set a Reordering Rule (Orderpoint) for the product that is guaranteed to fail routing. 5. Navigate to the frontend website and sign up as a new user (this creates a Portal User in Company B). 6. As the newly signed-up Portal User, complete an eCommerce checkout for the shared product. 7. The checkout succeeds, but the backend triggers the orderpoint failure and logs the exception activity on the product template. 8. Check the chatter for this product: the `create_uid` is incorrectly set to the Portal User instead of OdooBot (1). 9. (In 19.0 Upgrade) Log in as the Admin user (set strictly to view Company A), navigate to the product, and the AccessError for reading will appear due to this leaked id. [opw-6253978](https://www.odoo.com/odoo/my-support-tasks/6253978?debug=assets) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275140 Forward-Port-Of: odoo/odoo#269395
The translate button next to a translatable field saves the record before opening the translation dialog for its id. Since https://github.com/odoo/odoo/commit/a85ca9679e3855936afc66b034d05d75f672dd26 it saves record.model.root rather than the record itself. When the field belongs to a new record still edited inside an x2many, for example an answer added in the survey question popup, saving the root only saves the parent and the new line keeps no database id. The dialog then opens with the id set
Original PR description
The translate button next to a translatable field saves the record before opening the translation dialog for its id. Since https://github.com/odoo/odoo/commit/a85ca9679e3855936afc66b034d05d75f672dd26…
The translate button next to a translatable field saves the record before opening the translation dialog for its id. Since https://github.com/odoo/odoo/commit/a85ca9679e3855936afc66b034d05d75f672dd26 it saves record.model.root rather than the record itself. When the field belongs to a new record still edited inside an x2many, for example an answer added in the survey question popup, saving the root only saves the parent and the new line keeps no database id. The dialog then opens with the id set to false and calls update_field_translations on it, which builds WHERE id = false and the database rejects it with operator does not exist: integer = boolean. Such a record gets no id of its own, and after a save and reload there is no reliable way to match the saved line back to the one that was clicked, so the dialog can never open for it. A canTranslate getter in TranslationButton returns false for a new record whose model root is another record, which is exactly a line still edited inside an x2many, and the template only renders the button when it is true. The variant in editable lists, where model.root is a list rather than a record, was handled in https://github.com/odoo/odoo/commit/cb34b318004c3ca9db755d8dbbad429609220df3. Steps to reproduce: 1. Activate a second language in Settings > Translations > Languages 2. Open the Surveys app and create a survey 3. Add a question, then in the Answers tab add a line and type a value 4. Click the EN button next to the answer, fill the second language, and Save => RPC error operator does not exist: integer = boolean from WHERE id = false Ticket [link](https://www.odoo.com/odoo/project.task/6260427) opw-6260427 Forward-Port-Of: odoo/odoo#270635 Forward-Port-Of: odoo/odoo#267781
`ImDispatch.subscribe()` lazily starts the dispatcher thread with: ```py if not self.is_alive(): self.start() ``` However, this check isn't atomic: two subscribers can reach it at the same instant (a bunch of clients reconnecting after a downtime/restart/etc..) and two of them can have the condition "is not alive" and both of them will call `start()`. Technically, this is not a big deal, since `Thread.start()` will only successfully starts once and raise an Error `Threads c
Original PR description
`ImDispatch.subscribe()` lazily starts the dispatcher thread with: ```py if not self.is_alive(): self.start() ``` However, this check isn't atomic: two subscribers can reach it at the same instant (a…
`ImDispatch.subscribe()` lazily starts the dispatcher thread with:
```py
if not self.is_alive():
self.start()
```
However, this check isn't atomic: two subscribers can reach it at the same instant (a bunch of clients reconnecting after a downtime/restart/etc..) and two of them can have the condition "is not alive" and both of them will call `start()`.
Technically, this is not a big deal, since `Thread.start()` will only successfully starts once and raise an Error `Threads can only be start3e once` which is already catch and ignored with `contextlib.suppress(RuntimeError)`.
But this is a problem with some APM (like sentry) where they override `threading.Thread.start` to do something different than stdlib, and so something we can not know nor control.
The RuntimeError guard only tells us who's allowed to actually spawn the thread. It says nothing about code attached to `start()`/`run()` that runs on every attempt, win or lose, and that's exactly the part we don't control.
For example, sentry-sdk (before 2.34) patches `Thread.start` to wrap `self.run` on *every* call, not only the one that actually starts the thread:
```py
def sentry_start(self, *a, **kw):
self.run = wrap(self.run) # <- side effect, runs unconditionally
return real_start(self, *a, **kw)
```
Under the race described above, every losing call still wraps `self.run` before failing. Each wrapper forwards its own extra argument to the one it wraps, without dropping what it already received, so each layer adds one more positional argument. By the time the thread actually starts, `ImDispatch.run()` ends up called with N positional arguments instead of one:
```
TypeError: ImDispatch.run() takes 1 positional argument but N were given
```
N varies from one report to the next simply because it depends on how many subscribers happened to race on that particular restart.
Rather than relying on the RuntimeError to paper over a race we still allow to happen, we remove the race itself: wrapping the check and the `start()` call in a lock guarantees at most one caller ever gets past the "not alive" check. `start()` is called exactly once, so there's nothing left for third-party instrumentation to react to more than once.
Note:
Reproduced locally by firing many concurrent `subscribe()` calls at a freshly created `ImDispatch` with sentry-sdk 1.39.2 installed: the TypeError appears reliably, with the reported argument count matching the number of racing calls. The same scenario no longer fails once the lock is in place, regardless of the sentry-sdk version installed.
sentry-3928947199Steps to reproduce: - Open Helpdesk app on smartphone - Go to a ticket - the star priority_field is black with a gray background => bug task-6369589 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Steps to reproduce: - Open Helpdesk app on smartphone - Go to a ticket - the star priority_field is black with a gray background => bug task-6369589 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Description of the issue/feature this PR addresses: Currently, in the website_sale_stock module, there is no backend validation when subscribing to notifications for products without stock. This allows public users to potentially use emails that belong to registered accounts. Current behavior before PR: Users could subscribe to stock notifications for products that don’t exist or cannot be added (no stock). Public users could use emails already associated with registered accounts, allowi
Original PR description
Description of the issue/feature this PR addresses: Currently, in the website_sale_stock module, there is no backend validation when subscribing to notifications for products without stock. This…
Description of the issue/feature this PR addresses: Currently, in the website_sale_stock module, there is no backend validation when subscribing to notifications for products without stock. This allows public users to potentially use emails that belong to registered accounts. Current behavior before PR: Users could subscribe to stock notifications for products that don’t exist or cannot be added (no stock). Public users could use emails already associated with registered accounts, allowing them to subscribe on behalf of another user. No validation is enforced, leading to potential security issues. Desired behavior after PR is merged: Adding a subscription for a non-existent or unavailable product raises a ValidationError. Public users trying to subscribe with an email that belongs to a registered user receive an AccessError prompting them to sign in first. Backend validation prevents misuse of registered user emails and improves security. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274937 Forward-Port-Of: odoo/odoo#271880
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the products list, the set list price is not shown. Steps to reproduce: 1. Go to Accounting > Customers > Invoices 2. Create a new invoice 3. Create and edit a new product from the invoice line and set a new list price for the new product 4. Go to Sales > Products and open the created product 5. Che
Original PR description
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the…
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the products list, the set list price is not shown. Steps to reproduce: 1. Go to Accounting > Customers > Invoices 2. Create a new invoice 3. Create and edit a new product from the invoice line and set a new list price for the new product 4. Go to Sales > Products and open the created product 5. Check the list price of the product 6. Notice how the set list price is not shown on the product form view Cause: Product variants show lst_price while product templates show list_price on their form views. When creating a product from the invoice line, the shown form is for the product variant. When setting the list price on the product variant form (lst_price in that case), the inverse method of llst_price, which sets the list_price in return, is called during the creation of the variant, after the template has been created and saved. As a result, editing the list price does not trigger a write on the already saved product template, causing the list_price of the variant to be different than the list_price of the template. opw-6272825 Forward-Port-Of: odoo/odoo#270614
Since [1] elements within the link preview can be focused. However, when pressing tab an error is raised. This commit prevents this error from happening. [1]: https://github.com/odoo/odoo/commit/34db19f4a2b42d7e41205d7d793f5b3f408c19af task-6366337 Forward-Port-Of: odoo/odoo#275336 Forward-Port-Of: odoo/odoo#274682
Original PR description
Since [1] elements within the link preview can be focused. However, when pressing tab an error is raised. This commit prevents this error from happening. [1]: https://github.com/odoo/odoo/commit/34db19f4a2b42d7e41205d7d793f5b3f408c19af task-6366337 Forward-Port-Of: odoo/odoo#275336 Forward-Port-Of: odoo/odoo#274682
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set. Forward-Port-Of: odoo/odoo#275019
Original PR description
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set. Forward-Port-Of: odoo/odoo#275019
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 corrects a warning message appearing when editing a partner view in Odoo. The warning incorrectly indicated a missing 'true' field, despite the field being intentionally hidden. This change ensures a smoother user experience by removing the misleading warning.
Original PR description
There is a warning saying that there is no "true" field when editing the view. But in reality this is currently working as expected and the field is hidden. related to opw-5947987 Forward-Port-Of: odoo/odoo#275218 Forward-Port-Of: odoo/odoo#273041
10 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
Enhancements to existing features
This update ensures the iMin printer driver continues to function correctly with recent changes to Odoo's core point-of-sale system. The configuration has been moved to align with new standards, preventing potential errors and ensuring seamless receipt printing. This update also includes improvements to testing and reliability.
Original PR description
Following recent updates to the base `pos.printer` architecture in the point_of_sale module, the iMin driver configuration must be adapted to maintain compatibility and ensure seamless integration.…
Following recent updates to the base `pos.printer` architecture in the point_of_sale module, the iMin driver configuration must be adapted to maintain compatibility and ensure seamless integration. This commit backports the alignment logic and structure originally introduced in saas-19.3. Previously, iMin configuration lived inside the general POS settings overrides. To align with the updated base class interface and prevent tracebacks or broken flows, the driver's configuration logic is now migrated directly into the native `pos.printer` model ecosystem. This adaptation includes: - Moving the configuration views and logic to inherit from `pos.printer`. - Restricting iMin devices strictly to receipt printing via a new constraint. - Adding a 3-second timeout to the WebSocket availability check to comply with the base class's expectations for non-blocking status checks. - Updating backend testing support by patching `TestEPos`. opw-6218933 Forward-Port-Of: odoo/odoo#265709
Resolved issues and error corrections
This update corrects a previous issue where a process was unnecessarily triggered repeatedly, impacting performance. Now, the update runs only when a specific date is set, streamlining the French VAT (PDP) processing and improving system efficiency. This change ensures smoother operations for our French clients.
Original PR description
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set. Forward-Port-Of: odoo/odoo#275019
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-prThis update addresses a warning message appearing when editing the partner view in Odoo. The warning was caused by a hidden field being flagged as missing. The change ensures the warning disappears while maintaining the intended functionality of the hidden field.
Original PR description
There is a warning saying that there is no "true" field when editing the view. But in reality this is currently working as expected and the field is hidden. related to opw-5947987 Forward-Port-Of: odoo/odoo#275218 Forward-Port-Of: odoo/odoo#273041
This update ensures that deprecation warnings in Odoo consistently use string messages, resolving a compatibility issue with older Python versions. This change improves the reliability of warning messages and prevents potential errors when using the Odoo platform.
Original PR description
The native `warnings.deprecated` decorator strictly requires a string literal as its first positional argument and cannot be applied as a bare decorator. This commit enforces the same type verification in the fallback implementation for Python < 3.13. Follow-up of odoo/odoo@42fcc766af0584ef720a1cee5beb7878cdd1a572 runbot-941402 Forward-Port-Of: odoo/odoo#275037
This update fixes an issue where the list price set when creating a product from an invoice wasn't being saved to the product's template. Now, the list price will consistently reflect the value set during product creation, ensuring accurate product pricing information.
Original PR description
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the…
Problem: When creating a product from an invoice form view, the list price set on the product is not saved on the product template. After creating the product, when checking the product from the products list, the set list price is not shown. Steps to reproduce: 1. Go to Accounting > Customers > Invoices 2. Create a new invoice 3. Create and edit a new product from the invoice line and set a new list price for the new product 4. Go to Sales > Products and open the created product 5. Check the list price of the product 6. Notice how the set list price is not shown on the product form view Cause: Product variants show lst_price while product templates show list_price on their form views. When creating a product from the invoice line, the shown form is for the product variant. When setting the list price on the product variant form (lst_price in that case), the inverse method of llst_price, which sets the list_price in return, is called during the creation of the variant, after the template has been created and saved. As a result, editing the list price does not trigger a write on the already saved product template, causing the list_price of the variant to be different than the list_price of the template. opw-6272825 Forward-Port-Of: odoo/odoo#270614
This update fixes an ambiguity in how dates are grouped by hour in Odoo. Previously, hour labels lacked AM/PM indicators, leading to unclear grouping of times like 1:00 PM. Now, all hour labels use a 24-hour format (HH:00), ensuring dates are grouped unambiguously and consistently.
Original PR description
Description of the issue/feature this PR addresses: When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`. In Babel/LDML formatting, `hh` represents…
Description of the issue/feature this PR addresses:
When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`.
In Babel/LDML formatting, `hh` represents a 12-hour clock. Since the format does not include an AM/PM marker, afternoon/evening hours are displayed ambiguously in grouped views.
Current behavior before PR:
A datetime value in the afternoon is grouped under a 12-hour label without AM/PM.
For example, records around `13:50` are displayed under:
01:00 20 Mar
Similarly, a datetime value around `16:20` may be grouped under:
04:00 26 Mar
This is ambiguous because the group header does not indicate whether the hour is AM or PM.
Example screenshot showing records around 13:xx grouped under `01:00`:
<img width="310" height="240" alt="image" src="https://github.com/user-attachments/assets/8768f2e8-9aaa-436b-af9f-40055a6032e9" />
Desired behavior after PR is merged:
Hour-based datetime group labels should be unambiguous.
The hour grouping format now uses `HH:00 dd MMM`, so grouped datetime labels render using a 24-hour clock.
For example:
13:00 20 Mar
16:00 26 Mar
This fixes the datetime hour grouping label shown in grouped list views and other `read_group` consumers.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275219
Forward-Port-Of: odoo/odoo#274724A recent test failure related to API documentation generation was resolved. The issue stemmed from the test taking longer to complete as more Odoo modules are installed. This change ensures the test runs reliably regardless of the number of modules used.
Original PR description
The test_cache test failed a couple times on a timeout error, this is because the more modules are installed, the longer it takes to index them all and generate the json document. [runbot-240550](https://runbot.odoo.com/odoo/error/240550) Forward-Port-Of: odoo/odoo#274773
This update strengthens the website's security by preventing users from subscribing to products that don't exist or using another user's email address. It now validates product availability and requires users to sign in before subscribing, reducing the risk of unauthorized access and misuse of accounts.
Original PR description
Description of the issue/feature this PR addresses: Currently, in the website_sale_stock module, there is no backend validation when subscribing to notifications for products without stock. This…
Description of the issue/feature this PR addresses: Currently, in the website_sale_stock module, there is no backend validation when subscribing to notifications for products without stock. This allows public users to potentially use emails that belong to registered accounts. Current behavior before PR: Users could subscribe to stock notifications for products that don’t exist or cannot be added (no stock). Public users could use emails already associated with registered accounts, allowing them to subscribe on behalf of another user. No validation is enforced, leading to potential security issues. Desired behavior after PR is merged: Adding a subscription for a non-existent or unavailable product raises a ValidationError. Public users trying to subscribe with an email that belongs to a registered user receive an AccessError prompting them to sign in first. Backend validation prevents misuse of registered user emails and improves security. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274937 Forward-Port-Of: odoo/odoo#271880
28 changes
New functionality added to Odoo
[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
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
Enhancements to existing features
Following recent updates to the base `pos.printer` architecture in the point_of_sale module, the iMin driver configuration must be adapted to maintain compatibility and ensure seamless integration. This commit backports the alignment logic and structure originally introduced in saas-19.3. Previously, iMin configuration lived inside the general POS settings overrides. To align with the updated base class interface and prevent tracebacks or broken flows, the driver's configuration logic is n
Original PR description
Following recent updates to the base `pos.printer` architecture in the point_of_sale module, the iMin driver configuration must be adapted to maintain compatibility and ensure seamless integration. This commit backports the alignment logic and structure originally introduced in saas-19.3. Previously, iMin configuration lived inside the general POS settings overrides. To align with the updated base class interface and prevent tracebacks or broken flows, the driver's configuration logic is now migrated directly into the native `pos.printer` model ecosystem. This adaptation includes: - Moving the configuration views and logic to inherit from `pos.printer`. - Restricting iMin devices strictly to receipt printing via a new constraint. - Adding a 3-second timeout to the WebSocket availability check to comply with the base class's expectations for non-blocking status checks. - Updating backend testing support by patching `TestEPos`. opw-6218933
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
**Steps to reproduce:** - Go to Contact app - Open any record - Press "Space" key - Traceback: `Cannot read properties of undefined (reading 'groupId')` **Issue:** `quickCreateState` props is undefined (as it is optional). **Fix:** Add check to safely handle such cases. [introduced by] https://github.com/odoo/odoo/commit/22c07c7dcb2a93d9ebef5a83e48aa3d252128519 opw-6377425
Original PR description
**Steps to reproduce:** - Go to Contact app - Open any record - Press "Space" key - Traceback: `Cannot read properties of undefined (reading 'groupId')` **Issue:** `quickCreateState` props is undefined (as it is optional). **Fix:** Add check to safely handle such cases. [introduced by] https://github.com/odoo/odoo/commit/22c07c7dcb2a93d9ebef5a83e48aa3d252128519 opw-6377425
Steps to reproduce: - Open Chrome. - Set the browser zoom below or above 100%. - Edit a website page. - Hover a resize or padding handle in the overlay. => A white line appears in the middle of the handle. Before this commit, overlay handles changed their inner outline color on hover. With Chrome zoom levels different from 100%, this could leave a white line visible in the middle of the handle. After this commit, overlay handles change their background color on hover and use a consiste
Original PR description
Steps to reproduce: - Open Chrome. - Set the browser zoom below or above 100%. - Edit a website page. - Hover a resize or padding handle in the overlay. => A white line appears in the middle of the handle. Before this commit, overlay handles changed their inner outline color on hover. With Chrome zoom levels different from 100%, this could leave a white line visible in the middle of the handle. After this commit, overlay handles change their background color on hover and use a consistent inner outline width, so no white line is visible. task-6048647 Forward-Port-Of: odoo/odoo#273722
Steps to reproduce ------------------- - Install sale_project, accountant and project_timesheet_forecast_sale modules; - Activate analytic accounting in the settings; - Add an outstanding account to the bank journal’s manual outgoing payment method; - Create a new billable project; - Open the top menu, add vendor bills and open it; - Create a new bill from there, it should use the project’s analytic distribution; - Confirm it and create a payment; - Open the payment’s journal entry, i
Original PR description
Steps to reproduce ------------------- - Install sale_project, accountant and project_timesheet_forecast_sale modules; - Activate analytic accounting in the settings; - Add an outstanding account to…
Steps to reproduce ------------------- - Install sale_project, accountant and project_timesheet_forecast_sale modules; - Activate analytic accounting in the settings; - Add an outstanding account to the bank journal’s manual outgoing payment method; - Create a new billable project; - Open the top menu, add vendor bills and open it; - Create a new bill from there, it should use the project’s analytic distribution; - Confirm it and create a payment; - Open the payment’s journal entry, it is using the analytic distribution too; Why is it happening -------------------- When opening a vendor bill from the project, the project_id is added to the account.move's context to use the correct analytic distribution when we create a bill. If we create a payment after accessing the bill from this route, the context is transfered to account.payment.register, and then to the payment's entry lines in the `_create_payments` method. Due to the `_compute_analytic_distribution` method, the project's distribution is used on the payment's entry. We propose to filter out payment lines in this compute method. opw-6329475 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275076
When we create a company with a EU VAT, we used to do 2 IAP call to verify the VAT number. One was on the create() and the other one on the write(). For performance reason and because the vies check service may limit ip address, the verification was already disable when importing files (in both create and write). This commit remove the compute on the create one (and keep the one on write), so that it only do 1 IAP call to verify the VAT. Task-6139346 Forward-Port-Of: odoo/odoo#275181
Original PR description
When we create a company with a EU VAT, we used to do 2 IAP call to verify the VAT number. One was on the create() and the other one on the write(). For performance reason and because the vies check service may limit ip address, the verification was already disable when importing files (in both create and write). This commit remove the compute on the create one (and keep the one on write), so that it only do 1 IAP call to verify the VAT. Task-6139346 Forward-Port-Of: odoo/odoo#275181 Forward-Port-Of: odoo/odoo#274644
# How to reproduce - Create a new product - Add a reordering rule to that product with : - Trigger : Auto - Min : > Forecast - Activate dev mode - Go to Seetings > Technical > Automation > Scheduled Actions - Find the "Procurement: run Scheduler" action & run it manually # The issue We get a traceback : psycopg2.errors.SerializationFailure: could not serialize access due to concurrent update # Cause In Odoo, we use an isolation level of "REPEATABLE READ" for transactions : htt
Original PR description
# How to reproduce - Create a new product - Add a reordering rule to that product with : - Trigger : Auto - Min : > Forecast - Activate dev mode - Go to Seetings > Technical > Automation > Scheduled…
# How to reproduce - Create a new product - Add a reordering rule to that product with : - Trigger : Auto - Min : > Forecast - Activate dev mode - Go to Seetings > Technical > Automation > Scheduled Actions - Find the "Procurement: run Scheduler" action & run it manually # The issue We get a traceback : psycopg2.errors.SerializationFailure: could not serialize access due to concurrent update # Cause In Odoo, we use an isolation level of "REPEATABLE READ" for transactions : https://github.com/odoo/odoo/blob/7c35e183d6cc33a6e5d20e5e97ffef79e03b49d4/odoo/sql_db.py#L373 Even with that isolation level psql can throw a `SerializationFailure` if a transaction attempts to update a row that was modified by another transaction after the isolation snapshot was taken. ### Example that will raise an error : Session 1 ```SQL BEGIN ISOLATION LEVEL REPEATABLE READ; UPDATE accounts SET balance = balance - 100 WHERE id = 1; ``` Session 2 ```SQL BEGIN ISOLATION LEVEL REPEATABLE READ; UPDATE accounts SET balance = balance - 50 WHERE id = 1; COMMIT; ``` Back to Session 1 ```SQL COMMIT; ``` When running our action, we do this : https://github.com/odoo/odoo/blob/dff0835346f30fd1ef77260d94bcceeeab4d9051/addons/stock/models/stock_rule.py#L697-L703 Which correspond exactly to the first example : We first update some records with their compute Then `orderpoints.sudo()._procure_orderpoint_confirm(...)` creates a new transaction, update some rows & commits : https://github.com/odoo/odoo/blob/dff0835346f30fd1ef77260d94bcceeeab4d9051/addons/stock/models/stock_orderpoint.py#L716-L719 https://github.com/odoo/odoo/blob/dff0835346f30fd1ef77260d94bcceeeab4d9051/addons/stock/models/stock_orderpoint.py#L781-L783 Finally, we commit the original transaction with `_commit_progress(1)` # Proposed solution Inverse the order of `_commit_progress(1)` and `orderpoints.sudo()._procure_orderpoint_confirm(...)` so we commit the first transaction before starting the second one. opw-6261675 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268616
When opening a table that has no order, `setTable` recycles an existing empty floating order instead of creating a new one (to avoid leaving dangling blank orders behind). The filter only checked for the absence of a table, lines and finalized state, so it could grab any empty floating order, including one deliberately created for takeout or delivery. Steps to reproduce: - Open a restaurant POS with presets enabled (e.g. Dine in / Takeaway). - Cashier A creates a new floating order for a ph
Original PR description
When opening a table that has no order, `setTable` recycles an existing empty floating order instead of creating a new one (to avoid leaving dangling blank orders behind). The filter only checked for…
When opening a table that has no order, `setTable` recycles an existing empty floating order instead of creating a new one (to avoid leaving dangling blank orders behind). The filter only checked for the absence of a table, lines and finalized state, so it could grab any empty floating order, including one deliberately created for takeout or delivery. Steps to reproduce: - Open a restaurant POS with presets enabled (e.g. Dine in / Takeaway). - Cashier A creates a new floating order for a phone customer: selects the Takeaway preset with a future time slot, but has not added any product yet. - Meanwhile, cashier B opens an empty table from the floor screen. - => The takeout order is assigned to the table and becomes a dine-in order, losing its takeout context. Only recycle blank direct sale orders: skip orders that have a floating order name, a scheduled preset time or a preset different from the config default, as those were created on purpose. Tapping a table while on a blank dine-in scratch order still converts it as before. opw-6041750 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262573
\* : website, web_editor, html_editor Commit [1]: Steps to reproduce: replacing image stuck issue when deleted 1. Go to Website > Edit. 2. Add any picture snippet (e.g., Text-Image). 3. Click the 'Replace' button and upload an image. 4. Open the media dialog again and delete the uploaded image. 5. Click the 'Discard' button. 6. Try to save the changes. Issue: - The website gets stuck in the same position and does not allow saving. - In the Python terminal, a missing error warnin
Original PR description
\* : website, web_editor, html_editor Commit [1]: Steps to reproduce: replacing image stuck issue when deleted 1. Go to Website > Edit. 2. Add any picture snippet (e.g., Text-Image). 3. Click the…
\* : website, web_editor, html_editor Commit [1]: Steps to reproduce: replacing image stuck issue when deleted 1. Go to Website > Edit. 2. Add any picture snippet (e.g., Text-Image). 3. Click the 'Replace' button and upload an image. 4. Open the media dialog again and delete the uploaded image. 5. Click the 'Discard' button. 6. Try to save the changes. Issue: - The website gets stuck in the same position and does not allow saving. - In the Python terminal, a missing error warning appears because the image is deleted from both `ir.ui.view` and `ir.attachment`. Expected behaviour: - Saving should be allowed with a default image, that is similar to other images. This commit catch the warning response and replaces the deleted image, allowing the website to save changes without getting stuck. Commit [2]: resolve traceback when leaving edit mode via browser Steps to reproduce: 1. Go to Website > Edit. 2. Open the snippet modal and select any snippet. 3. Press the 'Back' button in your browser. 4. A dialog will appear asking to discard changes; click 'OK'. 5. A traceback error occurs, and an empty space appears in the editor. Issue: - Previously, a commit addressed a similar scenario, but that time the browser had an event listener bind on hashchange. - Now, that `hashchange` event of browser has been replaced with `popstate`, which triggers before the 'window' event listener. - As a result, the editor is left in an unstable state, causing a traceback error. Solution: - This commit ensures the 'window' event executes before the browser event. - It verifies if the editor is open and forces a `skipLoad`, preventing the `route_change` call in the browser. task-4570164 Forward-Port-Of: odoo/odoo#275150 Forward-Port-Of: odoo/odoo#199193
The native `warnings.deprecated` decorator strictly requires a string literal as its first positional argument and cannot be applied as a bare decorator. This commit enforces the same type verification in the fallback implementation for Python < 3.13. Follow-up of odoo/odoo@42fcc766af0584ef720a1cee5beb7878cdd1a572 runbot-941402 Forward-Port-Of: odoo/odoo#275037
Original PR description
The native `warnings.deprecated` decorator strictly requires a string literal as its first positional argument and cannot be applied as a bare decorator. This commit enforces the same type verification in the fallback implementation for Python < 3.13. Follow-up of odoo/odoo@42fcc766af0584ef720a1cee5beb7878cdd1a572 runbot-941402 Forward-Port-Of: odoo/odoo#275037
Description of the issue/feature this PR addresses: When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`. In Babel/LDML formatting, `hh` represents a 12-hour clock. Since the format does not include an AM/PM marker, afternoon/evening hours are displayed ambiguously in grouped views. Current behavior before PR: A datetime value in the afternoon is grouped under a 12-hour label without AM/PM. For example, records around `13:50` are dis
Original PR description
Description of the issue/feature this PR addresses: When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`. In Babel/LDML formatting, `hh` represents…
Description of the issue/feature this PR addresses:
When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`.
In Babel/LDML formatting, `hh` represents a 12-hour clock. Since the format does not include an AM/PM marker, afternoon/evening hours are displayed ambiguously in grouped views.
Current behavior before PR:
A datetime value in the afternoon is grouped under a 12-hour label without AM/PM.
For example, records around `13:50` are displayed under:
01:00 20 Mar
Similarly, a datetime value around `16:20` may be grouped under:
04:00 26 Mar
This is ambiguous because the group header does not indicate whether the hour is AM or PM.
Example screenshot showing records around 13:xx grouped under `01:00`:
<img width="310" height="240" alt="image" src="https://github.com/user-attachments/assets/8768f2e8-9aaa-436b-af9f-40055a6032e9" />
Desired behavior after PR is merged:
Hour-based datetime group labels should be unambiguous.
The hour grouping format now uses `HH:00 dd MMM`, so grouped datetime labels render using a 24-hour clock.
For example:
13:00 20 Mar
16:00 26 Mar
This fixes the datetime hour grouping label shown in grouped list views and other `read_group` consumers.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275219
Forward-Port-Of: odoo/odoo#274724The test_cache test failed a couple times on a timeout error, this is because the more modules are installed, the longer it takes to index them all and generate the json document. [runbot-240550](https://runbot.odoo.com/odoo/error/240550) Forward-Port-Of: odoo/odoo#274773
Original PR description
The test_cache test failed a couple times on a timeout error, this is because the more modules are installed, the longer it takes to index them all and generate the json document. [runbot-240550](https://runbot.odoo.com/odoo/error/240550) Forward-Port-Of: odoo/odoo#274773
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 - Open a PoS session and add any other product B to the order Issue: The discount was applied even though the order contained none of the rule's valid products. Cause: In `pointsForPrograms`, a rule was only gated on its quantity and amount thresholds (`totalProductQty < rule.minimum_qty`), nev
Original PR description
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 -…
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 - Open a PoS session and add any other product B to the order Issue: The discount was applied even though the order contained none of the rule's valid products. Cause: In `pointsForPrograms`, a rule was only gated on its quantity and amount thresholds (`totalProductQty < rule.minimum_qty`), never on the actual presence of a valid product in the order. Program templates (promotion, promo_code, next_order_coupons) create rules with minimum_qty = 0, so a product-restricted rule passed with zero matching items and, in "order" point mode, granted its points unconditionally. The same hole existed in `_canGenerateRewards` for scanned coupon programs, where rules act as conditions. The backend does not have this issue: `_program_check_compute_points` in sale_loyalty skips any rule whose valid products are not present in the order. Fix: Mirror the backend behavior in the PoS frontend: skip a product-restricted rule in `pointsForPrograms` when no (non-reward) order line matches its valid products, and make `_canGenerateRewards` return false in the same situation. Gift card and eWallet flows are unaffected since their "money"/"unit" point modes already gave 0 points when the trigger product was absent. opw-6357241 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275073
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid. Single font files parsing for the shortestNamedFont now also correctly keeps the weight for the targetFonts. Description of the issue/feature this PR addresses: Uploaded fonts with spaces in the name are not working. Current behavior before PR: When uploading a font with a space in the filename like "FontName 123 Light.otf" the css declaration in the attachement i
Original PR description
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid. Single font files parsing for the shortestNamedFont now also correctly keeps…
When uploading a font file "FontName 123 Light.otf" the baseFontName needs to be quoted in the font-face CSS to be valid.
Single font files parsing for the shortestNamedFont now also correctly keeps the weight for the targetFonts.
Description of the issue/feature this PR addresses:
Uploaded fonts with spaces in the name are not working.
Current behavior before PR:
When uploading a font with a space in the filename like "FontName 123 Light.otf" the css declaration in the attachement is wrong and not working:
```css
@font-face {
font-family: FontName 123 Light;
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}@font-face {
font-family: FontName 123 Light;
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}
```
Desired behavior after PR is merged:
The font name is now correctly quoted and the font attributes are no longer overwritten for the shortestNameFont:
```css
@font-face {
font-family: "FontName 123 Light";
font-style: normal;
font-weight: 400;
src: url("/web/content/1057/FontName 123 Light.otf");
}@font-face {
font-family: "FontName 123 Light";
font-style: normal;
font-weight: 300;
src: url("/web/content/1057/FontName 123 Light.otf");
}
```
Info @wt-io-it
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273534
Forward-Port-Of: odoo/odoo#268842In python-stdnum 2.0+, the upstream issue regarding the zeep Transport class timeout handling has been resolved arthurdejong/python-stdnum@6cbb9bc09c25fbda7a032521bc57b44e0ce18ec4), and the method signature for `get_soap_client` was updated to include the `verify` parameter. Applying our legacy monkey patch on python-stdnum >= 2.0 causes signature mismatch issues and is no longer necessary. This commit: - Restricts the `get_soap_client` monkey patch to run only for `python-stdnum < 2.0`.
Original PR description
In python-stdnum 2.0+, the upstream issue regarding the zeep Transport class timeout handling has been resolved arthurdejong/python-stdnum@6cbb9bc09c25fbda7a032521bc57b44e0ce18ec4), and the method signature for `get_soap_client` was updated to include the `verify` parameter. Applying our legacy monkey patch on python-stdnum >= 2.0 causes signature mismatch issues and is no longer necessary. This commit: - Restricts the `get_soap_client` monkey patch to run only for `python-stdnum < 2.0`. - Updates `requirements.txt` to use python-stdnum 2.2 for Python 3.14+ to ensure compatibility with Ubuntu Resolute. Forward-Port-Of: odoo/odoo#275360 Forward-Port-Of: odoo/odoo#275046
This update fixes an issue where numbers were not being formatted correctly for Portuguese (pt_PT) and Hindi (hi_IN languages). Number grouping, which separates large numbers into logical groups, has been adjusted to align with international standards – three digits for Western countries and two digits after the first three for India, improving readability and accuracy.
Original PR description
Currently the number grouping for Portuguese and Hindi is missing. Number grouping is used to separate long numbers in logical groups to make then easier to read. In Western countries, the grouping is usually done in groups of three digits (e.g. `1,000,000` instead of `1000000`), while in India, the grouping is done in groups of two digits after the first three digits (e.g. `10,00,000` instead of `1000000`). Source: https://www.unicode.org/cldr/charts/48/by_type/numbers.number_formatting_patterns.html#24a93b3d14ba17b2 All languages will be revised in a follow-up `master` PR. [task-6320391](https://www.odoo.com/odoo/project.task/6320391) Forward-Port-Of: odoo/odoo#275237 Forward-Port-Of: odoo/odoo#274443
This update resolves an issue where website builder option titles were missing translations, causing errors in the builder interface. The fix ensures that all titles are now correctly translated, improving the user experience and allowing for consistent branding across the website. This improves the website's appearance and functionality for customers.
Original PR description
Steps to reproduce: - Open the website editor. - Go to the Theme tab. - Inspect the Primary or Secondary color picker title. => The title prop is undefined. - Go to a product page with several product images. - Edit the carousel thumbnail position option. => The Left and Bottom button titles are undefined. Before this commit, some builder option titles were passed as OWL expressions instead of translated string props. After this commit, these titles use translated string props and are properly available to the builder components. task-6034856 Forward-Port-Of: odoo/odoo#275235
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 corrects a technical problem where orderpoint failure activities incorrectly attributed the action to a user instead of the system. This prevented proper logging and could cause access issues. The fix ensures that system activities are always authored by OdooBot, maintaining data integrity and security.
Original PR description
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The…
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The exception handler uses `.sudo().activity_schedule()`, which bypasses the write access restriction but leaves `env.uid` as the portal user. Therefore, the restricted portal user permanently becomes the `create_uid` (Author) of the activity. System exception activities should always be authored by the system (OdooBot), never by a portal or public user. This context leak corrupts the activity metadata by injecting an external user ID into internal backend logs. Chain `.with_user(SUPERUSER_ID)` to the `.sudo()` call in `stock_orderpoint.py` when scheduling the exception activity. This ensures the environment context is stable and the activity is authored by OdooBot, which transcends multi-company record rules. Steps to Reproduce on Runbot/Fresh Database on version 17.0: 1. Enable Multi-Company with Company A and Company B. Set Company B as the active company for the website. 2. Restrict the main Admin (Runbot) user strictly to Company A. 3. Create a Shared Product (Company field left blank). 4. Set a Reordering Rule (Orderpoint) for the product that is guaranteed to fail routing. 5. Navigate to the frontend website and sign up as a new user (this creates a Portal User in Company B). 6. As the newly signed-up Portal User, complete an eCommerce checkout for the shared product. 7. The checkout succeeds, but the backend triggers the orderpoint failure and logs the exception activity on the product template. 8. Check the chatter for this product: the `create_uid` is incorrectly set to the Portal User instead of OdooBot (1). 9. (In 19.0 Upgrade) Log in as the Admin user (set strictly to view Company A), navigate to the product, and the AccessError for reading will appear due to this leaked id. [opw-6253978](https://www.odoo.com/odoo/my-support-tasks/6253978?debug=assets) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275140 Forward-Port-Of: odoo/odoo#269395
This update removes a confusing message ('Connect your software...') from sales quotations that appeared in PDFs for customers with portal access. The change ensures all quotes are clean and professional, regardless of whether the customer uses the Odoo portal. This improves the customer experience and aligns with the standard portal button appearance.
Original PR description
Steps to reproduce: 1. Install Contacts and Sales 2. Open any of the contacts, click on the gear icon at the top and click on "Grant portal access" 3. Grant access to all contacts 4. Create a Sale Quotation for that contact and print it Issue: The sentence 'Connect your software... ' appears in the pdf when sending the quote to a contact who was portal access, while it does not appear if the contact does not have portal access Expected behavior: Should not appear regardless of whether the customer has a portal account or not since they have it appear as a smart button in their portal. opw-6308357 Forward-Port-Of: odoo/odoo#272893
This update fixes an issue where a process was unnecessarily triggered repeatedly, slowing down VAT processing for French businesses. The change streamlines the process by now initiating the update only when a specific date is set, improving overall system performance and efficiency. This ensures smoother and faster VAT handling.
Original PR description
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set. Forward-Port-Of: odoo/odoo#275019
This update resolves an issue where attempting to send IT invoices to the tax agency caused an error in version 19.0. The fix ensures that users are guided to delete the PDF attachment before sending, mirroring the behavior in previous versions and preventing the error.
Original PR description
**Steps to reproduce:** - Install the `l10n_it_edi` module and switch to an IT Company. - Create and confirm an invoice for a non-Italian customer. - Send the invoice, making sure that only `by…
**Steps to reproduce:** - Install the `l10n_it_edi` module and switch to an IT Company. - Create and confirm an invoice for a non-Italian customer. - Send the invoice, making sure that only `by Email` is enabled. - Attempt to send the invoice again. **Issue:** - In `18.0`, the XML file is not generated when re-sending an invoice that was previously sent only by email. - Starting from `19.0`, attempting to `Send to Tax Agency` raises an error: `UnboundLocalError: cannot access local variable 'attachment_name' where it is not associated with a value` **Root cause:** At [1], `_get_alerts` method does not check whether the invoice was previously sent only by email. As a result, the warning banner is not displayed, and allows the user to `Send to Tax Agency`. **Fix:** Restore the expected behavior by preventing `Send to Tax Agency` when the invoice was previously sent only by email. Instead, display the appropriate warning message instructing the user to delete the PDF attachment before sending to the Tax Agency, matching the behavior in `17.0` (confirmed with PO). [1]: https://github.com/odoo/odoo/blob/c0d8d36481e106f0209521bbb127cb3b1ad1059a/addons/l10n_it_edi/models/account_move_send.py#L27-L33 opw-6293519 Forward-Port-Of: odoo/odoo#275498 Forward-Port-Of: odoo/odoo#269547
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
This update corrects a visual issue in the account module where the dropdown background for account types remained light when dark mode was enabled. The change ensures a consistent dark mode experience by applying the correct background color ($dropdown-bg) to the dropdown element. This improves the overall user interface for users in dark mode.
Original PR description
Steps to reproduce: - Install `account` module - Enable dark mode - Open `view_account_form` to create a record - On the Accounting page, open type dropdown - The dropdown background remains in light mode This commit applies $dropdown-bg on `o_field_account_type_selection` as in odoo/odoo@0cd148eb389078c896aaa719af5733d05377fd1c Forward-Port-Of: odoo/odoo#274626 Forward-Port-Of: odoo/odoo#271352
Miscellaneous changes
### Description: Processing batch payments for multiple invoices triggers the `_increase_rank` method across numerous partners. Previously, this could lead to Out-Of-Memory (OOM) errors in databases with extensive partner hierarchies (parent/child relationships), primarily due to cascaded writes triggered by `_commercial_sync_to_descendants`. This commit optimizes the rank increment process, significantly reducing both memory consumption and execution time. ### Benchmark: | Partner C
Original PR description
### Description: Processing batch payments for multiple invoices triggers the `_increase_rank` method across numerous partners. Previously, this could lead to Out-Of-Memory (OOM) errors in databases with extensive partner hierarchies (parent/child relationships), primarily due to cascaded writes triggered by `_commercial_sync_to_descendants`. This commit optimizes the rank increment process, significantly reducing both memory consumption and execution time. ### Benchmark: | Partner Count | Time Before | Time After | Memory After | |---------------|-------------|------------|--------------| | 191,946 | 2 min | 47s | 111 Mb | | 393,509 | OOM | 1 min 45 | 216 Mb | ### Reference: opw-5152687 Forward-Port-Of: odoo/odoo#259334
2 changes
Resolved issues and error corrections
Typing in an HTML field (e.g. a contact's Internal Notes) and validating a URL-like token with Enter or Space can crash the editor with "IndexSizeError: The index is not in the allowed range", leaving the user unable to continue typing. It happens on Safari (not Chromium). The trigger is a URL-like token that the editor auto-converts into a link. The splitText calls in prepareConvertToLink, run during beforeinput, leave Safari's native selection anchored on an empty text node with an out-of-ran
Original PR description
Typing in an HTML field (e.g. a contact's Internal Notes) and validating a URL-like token with Enter or Space can crash the editor with "IndexSizeError: The index is not in the allowed range",…
Typing in an HTML field (e.g. a contact's Internal Notes) and validating
a URL-like token with Enter or Space can crash the editor with
"IndexSizeError: The index is not in the allowed range", leaving the
user unable to continue typing. It happens on Safari (not Chromium).
The trigger is a URL-like token that the editor auto-converts into a
link. The splitText calls in prepareConvertToLink, run during
beforeinput, leave Safari's native selection anchored on an empty text
node with an out-of-range offset. Anything reading the selection
afterwards then works from a broken position: on Enter, splitBlock
reads it and makeActiveSelection ends up throwing in Range.setStart;
on Space, the browser inserts the character in the wrong node and the
selection is corrupted the same way.
```
UncaughtClientError > IndexSizeError
Uncaught Javascript Error > The index is not in the allowed range.
setStart@[native code]
createEditorSelection@.../web.assets_web.min.js:12239:15
getSelectionData@.../web.assets_web.min.js:12242:145
updateActiveSelection@.../web.assets_web.min.js:12230:92
@.../web.assets_web.min.js:12218:873
handler@.../web.assets_web.min.js:14366:121
```
Steps to reproduce:
1. Use Safari (Chromium-based browsers work fine)
2. Open any record with an HTML field (e.g. Contacts -> a contact ->
Internal Notes).
3. Type a URL-like token such as KF.16D2.0204.CG (.CG is a valid TLD,
so the editor auto-links it). Do not paste it.
4. Place the caret at the end of that token and press Enter or Space.
5. IndexSizeError is raised and the editor stops accepting input.
Fix it at the source: re-anchor the selection right after the splits in
prepareConvertToLink, so every consumer sees a valid caret position.
Since moving the selection during beforeinput makes WebKit cancel the
pending text insertion, the Space case now prevents the default and
performs the conversion, the space insertion and the caret placement
itself, in two history steps so that undo still reverts the link
conversion while keeping the typed space.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#270910This 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
7 changes
Resolved issues and error corrections
### Steps to reproduce: - Download 'Sales' application - From 'Configuration' > 'Settings', enable 'Promotions, Loyalty & Gift Card' - From 'Products' > 'Gift cards & eWallet', Configure an eWallet program with a top-up product - Have a customer with an existing eWallet balance - Create a new sale order for that customer and add the eWallet top-up product - Pay the order using the customer's eWallet > The order gets discounted by the eWallet, effectively allowing the user to top up their
Original PR description
### Steps to reproduce: - Download 'Sales' application - From 'Configuration' > 'Settings', enable 'Promotions, Loyalty & Gift Card' - From 'Products' > 'Gift cards & eWallet', Configure an eWallet…
### Steps to reproduce:
- Download 'Sales' application
- From 'Configuration' > 'Settings', enable 'Promotions, Loyalty & Gift Card'
- From 'Products' > 'Gift cards & eWallet', Configure an eWallet program with a top-up product
- Have a customer with an existing eWallet balance
- Create a new sale order for that customer and add the eWallet top-up product
- Pay the order using the customer's eWallet
> The order gets discounted by the eWallet, effectively allowing the user to top up their balance
using the balance itself (infinite money glitch).
### Cause of Issue:
When computing the discountable amount for payment programs (like eWallets and gift cards), `_discountable_order` includes the total order amount. However, it did not exclude the program's own top-up products (`trigger_product_ids`) from the discountable lines.
### Fix:
If an order consists solely of top-up products, attempting to apply the eWallet now correctly raises a `UserError` ("There is nothing to discount").
opw-6341410When an attachment is added to an email template and is linked to a journal, and then you try to send an invoice, the attachment is shown in the attachments box but is not sent via peppol, the reason is that we were filtering to send only manually added attachments, and the email attachment was not considered "manual". task-id-6241354
Original PR description
When an attachment is added to an email template and is linked to a journal, and then you try to send an invoice, the attachment is shown in the attachments box but is not sent via peppol, the reason is that we were filtering to send only manually added attachments, and the email attachment was not considered "manual". task-id-6241354
Cloud attachments downloaded through signed URLs were saved with generic blob names because the link did not carry the original mimetype. Embed Content-Disposition and Content-Type in Azure and Google download URLs, and set Content-Type when uploading. GCS signed URL v4 validation requires alphabetically sorted query parameters once response headers are added to the signature. task-6359564 https://github.com/odoo/documentation/pull/18770 Description of the issue/feature this PR addre
Original PR description
Cloud attachments downloaded through signed URLs were saved with generic blob names because the link did not carry the original mimetype. Embed Content-Disposition and Content-Type in Azure and Google download URLs, and set Content-Type when uploading. GCS signed URL v4 validation requires alphabetically sorted query parameters once response headers are added to the signature. task-6359564 https://github.com/odoo/documentation/pull/18770 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
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set.
Original PR description
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set.
Issue: On an invoice PDF, using a layout with the address on the left. If a contact has a delivery address, but the option "Customer address" is not set, address will be displayed on the right instead of the left. Steps to reproduce: - Create a customer - Add a Delivery address to the customer - Ensure "Customer Address" is not set in the settings - Choose a layout with the address on the left (bubble, wave, ...) - Create an invoice to the customer - print the PDF Current behavior:
Original PR description
Issue: On an invoice PDF, using a layout with the address on the left. If a contact has a delivery address, but the option "Customer address" is not set, address will be displayed on the right instead of the left. Steps to reproduce: - Create a customer - Add a Delivery address to the customer - Ensure "Customer Address" is not set in the settings - Choose a layout with the address on the left (bubble, wave, ...) - Create an invoice to the customer - print the PDF Current behavior: - Customer address is on the right Expected behavior: - Customer address is on the left Cause: Address is displayed on the right if there is an information bloc . The information bloc was set to an empty div. Therefore, as it is set, address was displayed on the right. opw-6334130
This update resolves an issue that prevented Odoo from importing large Peppol invoices due to a technical error in the XML parsing process. By pre-processing the invoices to remove problematic data, the system is now more stable and reliable when handling these large attachments, ensuring seamless invoice import.
Original PR description
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References: opw-6085893 [^1]: https://lxml.de/6.0/FAQ.html#is-lxml-vulnerable-to-xml-bombs
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