Daily updates from Odoo
Tuesday, July 14, 2026
382 changes
18 changes
Enhancements to existing features
This update streamlines the tracking of continuous production processes within Odoo MRP. The changes enhance the clarity and efficiency of managing ongoing production runs, leading to better visibility and control over manufacturing operations. This improvement focuses on internal operational improvements.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update adds tests to ensure task templates, even those without a linked project, function correctly. This improves the reliability of our task creation process and prevents potential errors when using task templates. It follows up on previous development work to enhance the flexibility of our project and task management features.
Original PR description
This PR adds tests to ensure that task templates without a project are correctly handled when creating tasks from task templates or projects from project templates. Follow-up of task-5140018 task-6344060 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves an issue preventing guests in video calls from receiving notifications via the Odoo bus. Previously, a proxy system incorrectly handled subscriptions, leading to dropped notifications. Now, the system correctly identifies and delivers notifications to guests, ensuring seamless participation in video calls.
Original PR description
Guests never receive any bus notification when the websocket is not handled by Odoo itself but by a proxy that forwards subscriptions through `/websocket/peek_notifications` and dispatches the…
Guests never receive any bus notification when the websocket is not handled by Odoo itself but by a proxy that forwards subscriptions through `/websocket/peek_notifications` and dispatches the notifications on its own (which is how Odoo.sh serves databases).
The peek controller calls `ir.websocket._prepare_subscribe_data()` directly, bypassing `_subscribe()`, the only method decorated with `@add_guest_to_context`. The guest cookie is present on the request but never read, so the returned channel list only contains the anonymous channels (broadcast, res.groups) and lacks the guest's personal ones: ("mail.guest", id), ("discuss.channel", id) and presence. The proxy therefore never registers those channels, and every notification targeted at the guest is silently dropped.
Before this commit, discuss calls with a guest are broken: a 2-person call never connects (p2p offers/answers/ICE are delivered over the bus); in a 3+ person call, any guest who joined before the SFU threshold stays stuck in dead p2p (they never receive the `sfu_hot_swap` notification) while a guest joining as 3rd+ participant works, since the join RPC returns the SFU credentials synchronously.
We override `peek_notifications` with `add_guest_to_context` so the route is aware of guests.
opw-5490739
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275184
Forward-Port-Of: odoo/odoo#274743A recent update introduced an access error for users with Attendance app administrator rights but lacking access to employee records when viewing overtime rulesets. This fix restricts the visibility of a new 'Stat' button to authorized users, preventing the error and ensuring the feature remains available to those with the necessary permissions. This resolves a potential disruption for users managing overtime.
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-pr
Forward-Port-Of: odoo/odoo#275320This update simplifies account reconciliation settings by automatically marking accounts as non-reconcilable when bank or cash transactions aren't expected. This ensures that users only attempt reconciliation for accounts that actually require it, streamlining the accounting process and reducing potential errors. The change impacts several localization modules.
Original PR description
Changing the "payment reconciliation" boolean to false where it should be, ie. when no reconciliation with the bank nor cash transaction is expected. task-4902124 Forward-Port-Of: odoo/odoo#273305
This update resolves an error that occurred when multiple product images with identical content were added to a website product page. The fix ensures that the 'Optimize SEO' feature functions correctly by preventing duplicate key errors during image processing. This improves the reliability of the SEO optimization tool.
Original PR description
## Problem: when snippets with identical images are added in the e-commerce website product page, the "Optimize SEO" option in debug mode causes an error to occur with a traceback. The traceback…
## Problem:
when snippets with identical images are added in the e-commerce website product page, the "Optimize SEO" option in debug mode causes an error to occur with a traceback. The traceback calls out a duplicate key in the `t-foreach` of a loop over `state.altAttributes`. the `t-key` for this loop is `img.id` which is generated by the `/website/get_alt_images` controller endpoint.
## Steps to reproduce:
1. Go to a product page and click on "go to website" smart nav btn.
2. Add a snippet with an image in the `description_ecommerce` field
3. Add a snippet with the same image in the `website_description` field.
4. In debug mode, open `site > Optimize SEO`
5. An error `Got duplicate key in t-foreach` is thrown.
## Solution:
The solution was simple to add a qualifier in the compound key generated by the controller action for the `id` field. The chosen qualifier in this case was `model['field']`. `field` is the position in the template where the image came from.
So now the keys for the two identical images go
FROM
> `${model}-${id}-${index}`
>
> 1st image of `website_description`:
> `product.template-6-0`
>
> 1st image of `description_ecommerce`:
> `product.template-6-0`
TO
> `${model}-${id}-${field}-${index}`
>
> 1st image of `website_description`:
> `product.template-6-website_description-0`
>
> 1st image of `description_ecommerce`:
> `product.template-6-description_ecommerce-0`
task-6325786
Forward-Port-Of: odoo/odoo#275941
Forward-Port-Of: odoo/odoo#272846This update fixes an issue where discount lines in the TBAI XML file generated for electronic invoicing were incorrectly showing negative import values. The fix ensures that all monetary amounts, including discounts, are accurately represented as positive values, resolving a potential discrepancy in financial reporting. This ensures data integrity for tax compliance.
Original PR description
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from…
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from "TicketBai" page, open the "TicketBAI Post File" xml file Observation: - `ImporteUnitario` and `ImporteTotal` were exported as positive values for discount lines. cause: - Commit [1] assumed tax details are always positive. - This is not generally true, in case we have price_unit < 0 - The logic relied on `is_refund`, which depends on `qty * price`. - `_l10n_es_tbai_get_values` then multiplied values by `-1` again for refunds. https://github.com/odoo/odoo/blob/e751fa1e010dbda63903d598048ef415709b4af4/addons/l10n_es_edi_tbai_pos/models/pos_order.py#L177-L181 - For discount lines, `is_refund = True` and `price = -10`, resulting in `-10 * -1 = 10`. Fix: - Ensure tax detail values are always returned as positive values, matching the assumption introduced in commit [1] [1] https://github.com/odoo/odoo/commit/03d55104e49aa65aa4c6475e199747fe9132e754 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275451 Forward-Port-Of: odoo/odoo#265777
This update ensures that employee working schedules are consistently synchronized with their associated resource records, regardless of the version being used. Previously, changes to future employee versions could cause incorrect display of employee availability in the Attendance Gantt view. This fix resolves a visual discrepancy and improves data accuracy.
Original PR description
Steps to reproduce: 1. Create a new version on an employee with a future start date 2. Ensure the new version has a different working schedule 3. After the new version becomes active, observe that…
Steps to reproduce: 1. Create a new version on an employee with a future start date 2. Ensure the new version has a different working schedule 3. After the new version becomes active, observe that the working schedule on the employees record is different from the one on the employee's resource record Every employee has an associated resource record associated with them. Normally, the employee's working schedule (`hr_employee.resource_calendar_id`) should always be in sync with their associated resource record (`hr_employee.resource_id.calendar_id`). When we update the employee's working schedule through the UI on a currently active version, it will also update their associated resource record with the same working schedule. However, if we change the working schedule for a future version, when `_cron_update_current_version_id()` runs and changes the active version, there is no mechanism to update the associated resource with the new working schedule. This change will ensure we keep the working schedules in sync, as if they are not, strange behaviors can occur. One side effect of this problem: When a new version becomes active, and working schedules become de-synced, this can cause the Attendance gannt view to display incorrect unavailable intervals for an employee (this appears as a grayed-out time slot). This is because `_attendance_intervals_batch()` pulls from the working schedule of an employee's associated resource record, rather than the employee record itself. This is what occurred on the linked ticket. [opw-6352770](https://www.odoo.com/odoo/my-tasks/6352770?debug=assets) Forward-Port-Of: odoo/odoo#275430
This update corrects a bug where an attendance record was incorrectly created with overtime when an employee was on leave. The fix ensures that attendances are only generated when necessary, preventing misleading log notes and inaccurate reporting. This change was introduced in a previous version and is now resolved.
Original PR description
# How to reproduce - In the settings, enable Absence Mangement - Create an employee with a Contract - Create a Time off for that employee for yesterday - Manually run the scheduled action…
# How to reproduce - In the settings, enable Absence Mangement - Create an employee with a Contract - Create a Time off for that employee for yesterday - Manually run the scheduled action "Attendance: Detect Absences for employees" - Go to the attendance dashboard for that employee # The issue An attendance with no overtime was created for yesterday for that employee with a log note saying "This attendance was automatically created to cover an unjustified absence on that day." However, the absence was justified as the employee took a time off. # Cause of the issue When running the `_cron_absence_detection` cron job, we create "empty" attendances for the employees that were absent yesterday. If those attendance's `overtime_hours` are 0, then we unlink them : https://github.com/odoo/odoo/blob/a73428187112b3948a11810abae2a3c82c9c7bcd/addons/hr_attendance/models/hr_attendance.py#L659-L666 But, since `check_in` and `check_out` cannot be the same, we cannot really create an empty attedance. We instead create an attendance of 1 second : https://github.com/odoo/odoo/blob/a73428187112b3948a11810abae2a3c82c9c7bcd/addons/hr_attendance/models/hr_attendance.py#L652-L653 This will create an overtime of 0.003 seconds if there was a leave that day (which is our case). This duration will be reflected in the attendance's `overtime_hours`. The issue is that we simply do `== 0` when trying to find the attendances without overtime, so we don't unlink them. The issue was introduced by : https://github.com/odoo/odoo/commit/8d7859a569d9ac7303ca0b9be6c56496be14c544 Because `round(0.003, 3)` => 0 but `round(0.003, 4)` => 0.003 The issue is not present in 18.0+ because we don't create overtime if the duration is `float_is_zero(overtime_duration, 2)` : https://github.com/odoo/odoo/blob/39cce855aa27aa4af9225a61a3e1425383a9f49f/addons/hr_attendance/models/hr_attendance.py#L405 opw-6321883 Forward-Port-Of: odoo/odoo#275133 Forward-Port-Of: odoo/odoo#272089
This update enhances the reliability of Odoo's database rollback process, particularly when updating modules. It prevents errors that could leave the system in an inconsistent state after a rollback, ensuring smoother and more dependable updates.
Original PR description
Registry loading may fail to upgrade the modules and should reset the module state in such a scenario. However, the rollback can raise an exception leaving the modules in the previous state. We ensure that the rollback is more stable: - when resetting the transaction, make sure the transaction is clear before re-setting up models - when postrollback fails, retry the rollback without any hooks - sale_gelato: be more explicit that the call is in a separate cursor --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug where reverting an inventory adjustment with a package resulted in negative quantities appearing within the package. The fix ensures that quantities are accurately restored to their original state after a revert, preventing inconsistencies in inventory tracking. This improves data reliability and avoids potential errors in stock management.
Original PR description
Currently when the user reverts an inventory adjustment move line with a package the package contains extra line showing negative quantity of the product. ## Steps to produce: - Install Inventory…
Currently when the user reverts an inventory adjustment move line with a package the package contains extra line showing negative quantity of the product.
## Steps to produce:
- Install Inventory without demo data
- Settings Enable 'Packages'
- Create a product:
- Cheese burger
- On hand > Create a new quant
- Package: 'Burgerbox' and 'On Hand Quantity`: 1 and save
- Set the On Hand quantity to zero and save
- History > Revert the Inventory adjustment line from WH/stock to Inventory adjustment by selecting it and reverting via actions.
- Products > Packages > BurgerBox
## Observed Behaviour:
After reverting an inventory adjustment that set the product's physical quantity to 0, the package contains two lines for the same product with quantities 1 and -1.
This is inconsistent because a package should not contain a product with a negative quantity.
The package should be restored to its original state and contain only the expected positive quantity.
## Root cause:
When the user reverts the move line, `action_revert_inventory` is called. This method creates the revert move and then marks that move as done at [1].
Marking the move as done subsequently marks all related move lines as done at [2]. During this process, the system first unreserves the quantity from the virtual location / inventory adjustment and then removes the quantity from that location (resulting in a -1 quantity move line at that location). This is performed through `_synchronize_quant`, which is responsible for synchronizing the physical inventory with the move line at [3].
The `_synchronize_quant` method uses the move line's `package_id` when updating the corresponding quant at [4]. As a result, `_update_available_quantity` creates a new quant with the following values at [5]:
```
{
'product_id': 1,
'location_id': 14,
'lot_id': stock.lot(),
'package_id': 1,
'owner_id': res.partner(),
'in_date': datetime.datetime(2026, 6, 22, 12, 42, 11),
'quantity': -1.0,
}
```
This creates a quant with a negative quantity that is linked to the package because `package_id` is set on the newly created quant. Consequently, the move line with the negative quantity becomes associated with the package.
[1]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L1016-L1035
[2]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move.py#L1956 [3]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L662-L666
[4]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L678-L687
[5]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_quant.py#L1130-L1143
## Solution:
Remove the source `package_id` when creating revert moves for inventory adjustment locations.
When an inventory adjustment sets a product's quantity to 0, the adjustment is completed without a destination package, meaning the product is effectively removed from the package. Therefore, the corresponding revert move should not retain the package as its source. Keeping the package as the source is inconsistent because package information should not exist on a virtual inventory adjustment location, and the original inventory adjustment removes the product from the package (there is no destination package).
By removing the source `package_id` from the revert move, the system avoids creating negative quants associated with the package during quant synchronization. This also ensures that, after the inventory adjustment is reverted, the quantities of products inside the package are restored correctly and match their state prior to the adjustment.
opw-6285739
Forward-Port-Of: odoo/odoo#274663
Forward-Port-Of: odoo/odoo#271440This update resolves an issue where Odoo was incorrectly sending duplicate capture requests to Stripe for EFTPOS payments in Australia. By adjusting how the system handles these payments, the fix ensures that orders are completed successfully and avoids errors related to duplicate capture attempts, improving the reliability of POS transactions.
Original PR description
In Australia, Terminal payments using `payment_method_options.card_present.capture_method=manual_preferred` are not always captured later. When a payment is processed on the `eftpos_au` network, Stripe authorizes and captures it in a single step. However, the POS Stripe flow only skipped the extra capture based on the card brand instead of the processed network. As a result, payments such as `brand = visa` and `card_present.network = eftpos_au` were treated as capturable, and Odoo sent a second capture request. Stripe then rejected it with `payment_intent_unexpected_state` because the PaymentIntent had already been captured, leaving the POS order unfinished. This patch skips the extra capture call when the payment was processed on `card_present.network = eftpos_au`. opw-6228977 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271609 Forward-Port-Of: odoo/odoo#270293
This update fixes an issue where cash rounding records were incorrectly shared across all Indian companies. Previously, new companies would inherit records from the last created company, leading to errors. The change ensures each new Indian company has its own unique cash rounding record, resolving this conflict and improving data accuracy.
Original PR description
### Issue: When creating a new Indian company, the `Half Up` cash rounding is reassigned to the new company instead of being duplicated Previous Indian companies lose access to it, causing errors…
### Issue: When creating a new Indian company, the `Half Up` cash rounding is reassigned to the new company instead of being duplicated Previous Indian companies lose access to it, causing errors when opening invoices that reference the cash rounding if the user doesn't have access to that company ### Cause: `cash_rounding_in_half_up` was defined as a `data` record with a fixed XML ID (`l10n_in.cash_rounding_in_half_up`) `_get_in_account_cash_rounding` referenced that XML ID directly and set `company_id` to the current company on each chart of accounts installation This reassigned the single shared record to the new company instead of creating a new one Moving the definition to the `@template` decorator without a module-prefixed XML ID lets the chart of accounts system create one record per company, as intended ### Steps to reproduce: - Install `l10n_in` and switch to `IN Company` - Check the Cash Rounding records grouped by company - Create a new Indian company - Enable both `IN Company` and the new company - Check the Cash Rounding records grouped by company again Before the fix, only the last created Indian company has the Cash Rounding record opw-6318857 Forward-Port-Of: odoo/odoo#272866
This update ensures that the date and time of sales are now displayed on the 'Print Report' generated from the Point of Sale system. Previously, a recent update to the system's templates removed this important information. This fix restores the standard reporting functionality, providing users with complete sale details.
Original PR description
When printing the sale details report from the POS ("Print Report"), no date or time appeared on the ticket.
During the receipt refactor to shared backend templates, the sale details template and its frontend data builder stopped rendering the print date that previous versions displayed at the bottom of the report.
This commit adds the current date and time to the sale details `extra_data` and renders it after the totals, restoring the previous behavior.
opw-6348476
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273734This update ensures that loyalty rewards are only applied when a customer's order contains the specific products defined in the reward rule. Previously, a rule with no product restrictions would incorrectly grant rewards even with other products in the order. This fix aligns the POS frontend with the backend's behavior, improving the accuracy and reliability of the loyalty program.
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 barcode scanner check-in process in kiosk mode was previously inaccurate, with location data off by several kilometers. This update now uses the browser's geolocation to provide more precise location data, resolving this issue and improving the accuracy of check-in times.
Original PR description
**Issue** Check-in and check-out performed in kiosk mode via the barcode scanner were less accurate than those made via the manual selection. The reported inacurracy between the actual and real locations was several kilometers. **Cause** `attendance_barcode_scanned` was called without a location coming from the browser's geolocation API. In that case, the location was determined by the geoip database https://github.com/odoo/odoo/blob/51f59a293de1e86f66f30257f8fc0c419463d18c/addons/hr_attendance/controllers/main.py#L69-L70 which is generally not as accurate as the location provided by the browser. opw-5889102 Forward-Port-Of: odoo/odoo#273044 Forward-Port-Of: odoo/odoo#251478
This update resolves an issue where the company logo option wasn't consistently hiding after changing the logo type to text. The fix ensures the toggle correctly hides the logo when the 'Text' option is selected for the navbar logo, improving the user experience. It was necessary to update how the system reads configuration settings for the logo.
Original PR description
Steps to reproduce: - Enter in edit mode - Click on the navbar logo - Change "Logo" option from "Image" to "Text" - Toggle "Company Logo" in "Visuals" option - Traceback appears: it should hide the logo This commit awaits `loadConfigKey` so `websiteLogoParams` reads the loaded config; otherwise the button targeted the wrong brand view and collided on the `#o_fake_navbar_brand` xpath. task-6284593 Forward-Port-Of: odoo/odoo#276108 Forward-Port-Of: odoo/odoo#275363
Features or functions removed from Odoo
This update simplifies the restaurant POS system by standardizing payment method names from snake_case to camelCase. This change improves code consistency and prepares the system for future updates. It ensures the payment processing flow remains reliable and efficient.
Original PR description
In this commit: - Use the new method names in the payment adjustment flow. - Replace deprecated snake_case methods with their camelCase equivalents for payment lines, payment terminals, and order totals. Task:6049128 Forward-Port-Of: odoo/odoo#275870 Forward-Port-Of: odoo/odoo#271792
14 changes
Enhancements to existing features
This update enhances the testing framework for Odoo's mass mailing functionality. Specifically, it incorporates simulated user actions like email opens and replies to more accurately verify the scheduling and execution of marketing campaigns. This improves the reliability of marketing automation processes.
Original PR description
Improve (mass_)mailing asserts and tools, notably to use their usage in marketing automation where simulating user actions (open emails, reply, ...) is necessary to check marketing activities scheduling and execution. Task-4224152: [marketing_automation] Performance / Scalability Forward-Port-Of: odoo/odoo#275964
Resolved issues and error corrections
This update corrects a bug where an attendance record was incorrectly created when an employee took time off. The fix ensures that attendances are only generated when absences are justified, preventing misleading log notes and inaccurate attendance data. This change was introduced in a previous version and has been resolved.
Original PR description
# How to reproduce - In the settings, enable Absence Mangement - Create an employee with a Contract - Create a Time off for that employee for yesterday - Manually run the scheduled action…
# How to reproduce - In the settings, enable Absence Mangement - Create an employee with a Contract - Create a Time off for that employee for yesterday - Manually run the scheduled action "Attendance: Detect Absences for employees" - Go to the attendance dashboard for that employee # The issue An attendance with no overtime was created for yesterday for that employee with a log note saying "This attendance was automatically created to cover an unjustified absence on that day." However, the absence was justified as the employee took a time off. # Cause of the issue When running the `_cron_absence_detection` cron job, we create "empty" attendances for the employees that were absent yesterday. If those attendance's `overtime_hours` are 0, then we unlink them : https://github.com/odoo/odoo/blob/a73428187112b3948a11810abae2a3c82c9c7bcd/addons/hr_attendance/models/hr_attendance.py#L659-L666 But, since `check_in` and `check_out` cannot be the same, we cannot really create an empty attedance. We instead create an attendance of 1 second : https://github.com/odoo/odoo/blob/a73428187112b3948a11810abae2a3c82c9c7bcd/addons/hr_attendance/models/hr_attendance.py#L652-L653 This will create an overtime of 0.003 seconds if there was a leave that day (which is our case). This duration will be reflected in the attendance's `overtime_hours`. The issue is that we simply do `== 0` when trying to find the attendances without overtime, so we don't unlink them. The issue was introduced by : https://github.com/odoo/odoo/commit/8d7859a569d9ac7303ca0b9be6c56496be14c544 Because `round(0.003, 3)` => 0 but `round(0.003, 4)` => 0.003 The issue is not present in 18.0+ because we don't create overtime if the duration is `float_is_zero(overtime_duration, 2)` : https://github.com/odoo/odoo/blob/39cce855aa27aa4af9225a61a3e1425383a9f49f/addons/hr_attendance/models/hr_attendance.py#L405 opw-6321883 Forward-Port-Of: odoo/odoo#275133 Forward-Port-Of: odoo/odoo#272089
This update resolves an issue where invoices were incorrectly displaying a small additional charge (0.01$) due to a misinterpretation of loyalty programs as refunds. The fix ensures that loyalty programs are properly accounted for during tax calculations, resulting in accurate tax amounts on invoices. This improves the reliability of the POS order process.
Original PR description
When computing taxes for the order, we group the base lines based on a grouping key. One of the components of this key is `is_refund`, and reward lines where considered as refund lines, which caused…
When computing taxes for the order, we group the base lines based on a grouping key. One of the components of this key is `is_refund`, and reward lines where considered as refund lines, which caused them to be grouped separately. This caused a discrepency between the tax amount computed in the frontend and the one computed in the backend. Steps to reproduce: ------------------- * Change the rounding method to globally * Create a 21% tax not included in price * Create a product with a price of 76.01 and the tax created above * Create a loyalty program with a 10% discount * Create a POS order with the product above and apply the loyalty program * Validate the order and generate the invoice > Observation: The invoice states that 0.01$ is still due Why the fix: ------------ In `round_tax_details_tax_amounts`, we try to detect any delta with the expeced tax amount. To do that we group the base lines based on a grouping key. The grouping key `is_refund` was incorrectly set to `true` for reward lines, which caused them to not be grouped. The delta was then not detected and tax amounts were not adjusted. We now make sure not to consider reward lines as refund. opw-6052112 Forward-Port-Of: odoo/odoo#275350 Forward-Port-Of: odoo/odoo#271577
This update resolves a bug where the company logo option in the website navigation wasn't correctly hiding when switching between image and text logo formats. The fix ensures the logo toggle works as expected, providing a consistent brand experience for users. It was necessary to update how the system reads configuration settings for the website logo.
Original PR description
Steps to reproduce: - Enter in edit mode - Click on the navbar logo - Change "Logo" option from "Image" to "Text" - Toggle "Company Logo" in "Visuals" option - Traceback appears: it should hide the logo This commit awaits `loadConfigKey` so `websiteLogoParams` reads the loaded config; otherwise the button targeted the wrong brand view and collided on the `#o_fake_navbar_brand` xpath. task-6284593 Forward-Port-Of: odoo/odoo#275363
This update fixes a glitch that allowed customers to repeatedly top up their loyalty program balances using eWallets, effectively creating an unlimited credit. The fix ensures that an eWallet payment won't process if the order consists solely of top-up products, preventing this 'infinite money' scenario. This improves the stability and accuracy of our loyalty program transactions.
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-6341410
Forward-Port-Of: odoo/odoo#273419The barcode scanner check-in process was previously inaccurate due to relying on a less precise location database. This update now uses the browser's geolocation to determine location, significantly improving the accuracy of check-in times and locations, particularly in kiosk mode.
Original PR description
**Issue** Check-in and check-out performed in kiosk mode via the barcode scanner were less accurate than those made via the manual selection. The reported inacurracy between the actual and real locations was several kilometers. **Cause** `attendance_barcode_scanned` was called without a location coming from the browser's geolocation API. In that case, the location was determined by the geoip database https://github.com/odoo/odoo/blob/51f59a293de1e86f66f30257f8fc0c419463d18c/addons/hr_attendance/controllers/main.py#L69-L70 which is generally not as accurate as the location provided by the browser. opw-5889102 Forward-Port-Of: odoo/odoo#273044 Forward-Port-Of: odoo/odoo#251478
This update fixes an issue where discount lines in the TBAI XML file generated for electronic invoicing were incorrectly showing negative import values. The fix ensures that all monetary values, including discounts, are consistently represented as positive numbers, aligning with previous assumptions and improving data accuracy for tax reporting.
Original PR description
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from…
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from "TicketBai" page, open the "TicketBAI Post File" xml file Observation: - `ImporteUnitario` and `ImporteTotal` were exported as positive values for discount lines. cause: - Commit [1] assumed tax details are always positive. - This is not generally true, in case we have price_unit < 0 - The logic relied on `is_refund`, which depends on `qty * price`. - `_l10n_es_tbai_get_values` then multiplied values by `-1` again for refunds. https://github.com/odoo/odoo/blob/e751fa1e010dbda63903d598048ef415709b4af4/addons/l10n_es_edi_tbai_pos/models/pos_order.py#L177-L181 - For discount lines, `is_refund = True` and `price = -10`, resulting in `-10 * -1 = 10`. Fix: - Ensure tax detail values are always returned as positive values, matching the assumption introduced in commit [1] [1] https://github.com/odoo/odoo/commit/03d55104e49aa65aa4c6475e199747fe9132e754 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275451 Forward-Port-Of: odoo/odoo#265777
This update resolves an issue preventing guests in video calls from receiving notifications through the Odoo bus. Previously, a proxy system wasn't correctly identifying guest channels, leading to dropped notifications. Now, the system properly recognizes guest channels, ensuring all participants receive relevant updates during calls.
Original PR description
Guests never receive any bus notification when the websocket is not handled by Odoo itself but by a proxy that forwards subscriptions through `/websocket/peek_notifications` and dispatches the…
Guests never receive any bus notification when the websocket is not handled by Odoo itself but by a proxy that forwards subscriptions through `/websocket/peek_notifications` and dispatches the notifications on its own (which is how Odoo.sh serves databases).
The peek controller calls `ir.websocket._prepare_subscribe_data()` directly, bypassing `_subscribe()`, the only method decorated with `@add_guest_to_context`. The guest cookie is present on the request but never read, so the returned channel list only contains the anonymous channels (broadcast, res.groups) and lacks the guest's personal ones: ("mail.guest", id), ("discuss.channel", id) and presence. The proxy therefore never registers those channels, and every notification targeted at the guest is silently dropped.
Before this commit, discuss calls with a guest are broken: a 2-person call never connects (p2p offers/answers/ICE are delivered over the bus); in a 3+ person call, any guest who joined before the SFU threshold stays stuck in dead p2p (they never receive the `sfu_hot_swap` notification) while a guest joining as 3rd+ participant works, since the join RPC returns the SFU credentials synchronously.
We override `peek_notifications` with `add_guest_to_context` so the route is aware of guests.
opw-5490739
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275184
Forward-Port-Of: odoo/odoo#274743This update resolves a problem where employee working schedules weren't consistently synchronized with their associated resource records, particularly after creating future versions. This prevented incorrect scheduling data from appearing in the Attendance Gantt view, ensuring accurate employee availability. The fix ensures schedules are always up-to-date.
Original PR description
Steps to reproduce: 1. Create a new version on an employee with a future start date 2. Ensure the new version has a different working schedule 3. After the new version becomes active, observe that…
Steps to reproduce: 1. Create a new version on an employee with a future start date 2. Ensure the new version has a different working schedule 3. After the new version becomes active, observe that the working schedule on the employees record is different from the one on the employee's resource record Every employee has an associated resource record associated with them. Normally, the employee's working schedule (`hr_employee.resource_calendar_id`) should always be in sync with their associated resource record (`hr_employee.resource_id.calendar_id`). When we update the employee's working schedule through the UI on a currently active version, it will also update their associated resource record with the same working schedule. However, if we change the working schedule for a future version, when `_cron_update_current_version_id()` runs and changes the active version, there is no mechanism to update the associated resource with the new working schedule. This change will ensure we keep the working schedules in sync, as if they are not, strange behaviors can occur. One side effect of this problem: When a new version becomes active, and working schedules become de-synced, this can cause the Attendance gannt view to display incorrect unavailable intervals for an employee (this appears as a grayed-out time slot). This is because `_attendance_intervals_batch()` pulls from the working schedule of an employee's associated resource record, rather than the employee record itself. This is what occurred on the linked ticket. [opw-6352770](https://www.odoo.com/odoo/my-tasks/6352770?debug=assets) Forward-Port-Of: odoo/odoo#275430
This update resolves an issue where batch payment sequences were incorrectly created when a new company was initially set up. The change ensures sequences are properly associated with the correct company during creation, preventing errors in payment processing. This improves the reliability of our payment system.
Original PR description
Previously, batch payment sequence will be created by simply select to create new company due to having lambda in default. Hence, the created sequence does not have a correct company_id set as company hasn't yet created. Switch to creating sequence in ``create`` function to avoid this issue. Also use ``range_year`` for payment prefix because it was set to use date range. 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#273852 Forward-Port-Of: odoo/odoo#268689
This update resolves an issue where reverting an inventory adjustment with a package resulted in a negative quantity being displayed within the package. The fix ensures that quantities are accurately restored to their original state after a reversion, preventing inconsistencies in package inventory tracking. This improves data accuracy and reliability for stock management.
Original PR description
Currently when the user reverts an inventory adjustment move line with a package the package contains extra line showing negative quantity of the product. ## Steps to produce: - Install Inventory…
Currently when the user reverts an inventory adjustment move line with a package the package contains extra line showing negative quantity of the product.
## Steps to produce:
- Install Inventory without demo data
- Settings Enable 'Packages'
- Create a product:
- Cheese burger
- On hand > Create a new quant
- Package: 'Burgerbox' and 'On Hand Quantity`: 1 and save
- Set the On Hand quantity to zero and save
- History > Revert the Inventory adjustment line from WH/stock to Inventory adjustment by selecting it and reverting via actions.
- Products > Packages > BurgerBox
## Observed Behaviour:
After reverting an inventory adjustment that set the product's physical quantity to 0, the package contains two lines for the same product with quantities 1 and -1.
This is inconsistent because a package should not contain a product with a negative quantity.
The package should be restored to its original state and contain only the expected positive quantity.
## Root cause:
When the user reverts the move line, `action_revert_inventory` is called. This method creates the revert move and then marks that move as done at [1].
Marking the move as done subsequently marks all related move lines as done at [2]. During this process, the system first unreserves the quantity from the virtual location / inventory adjustment and then removes the quantity from that location (resulting in a -1 quantity move line at that location). This is performed through `_synchronize_quant`, which is responsible for synchronizing the physical inventory with the move line at [3].
The `_synchronize_quant` method uses the move line's `package_id` when updating the corresponding quant at [4]. As a result, `_update_available_quantity` creates a new quant with the following values at [5]:
```
{
'product_id': 1,
'location_id': 14,
'lot_id': stock.lot(),
'package_id': 1,
'owner_id': res.partner(),
'in_date': datetime.datetime(2026, 6, 22, 12, 42, 11),
'quantity': -1.0,
}
```
This creates a quant with a negative quantity that is linked to the package because `package_id` is set on the newly created quant. Consequently, the move line with the negative quantity becomes associated with the package.
[1]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L1016-L1035
[2]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move.py#L1956 [3]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L662-L666
[4]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L678-L687
[5]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_quant.py#L1130-L1143
## Solution:
Remove the source `package_id` when creating revert moves for inventory adjustment locations.
When an inventory adjustment sets a product's quantity to 0, the adjustment is completed without a destination package, meaning the product is effectively removed from the package. Therefore, the corresponding revert move should not retain the package as its source. Keeping the package as the source is inconsistent because package information should not exist on a virtual inventory adjustment location, and the original inventory adjustment removes the product from the package (there is no destination package).
By removing the source `package_id` from the revert move, the system avoids creating negative quants associated with the package during quant synchronization. This also ensures that, after the inventory adjustment is reverted, the quantities of products inside the package are restored correctly and match their state prior to the adjustment.
opw-6285739
Forward-Port-Of: odoo/odoo#274663
Forward-Port-Of: odoo/odoo#271440This update resolves an issue where Odoo was incorrectly sending duplicate capture requests to Stripe for EFTPOS payments in Australia. This resulted in payment failures and incomplete orders. The fix ensures that Stripe only captures payments on the EFTPOS network, streamlining the payment process and improving reliability.
Original PR description
In Australia, Terminal payments using `payment_method_options.card_present.capture_method=manual_preferred` are not always captured later. When a payment is processed on the `eftpos_au` network, Stripe authorizes and captures it in a single step. However, the POS Stripe flow only skipped the extra capture based on the card brand instead of the processed network. As a result, payments such as `brand = visa` and `card_present.network = eftpos_au` were treated as capturable, and Odoo sent a second capture request. Stripe then rejected it with `payment_intent_unexpected_state` because the PaymentIntent had already been captured, leaving the POS order unfinished. This patch skips the extra capture call when the payment was processed on `card_present.network = eftpos_au`. opw-6228977 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271609 Forward-Port-Of: odoo/odoo#270293
This update resolves a bug where duplicate stock availability messages were appearing on product pages when using mega menus. The fix ensures that stock messages are correctly cleared and updated, providing a consistent and accurate display of product availability to customers. This improves the user experience and prevents confusion.
Original PR description
Steps to reproduce: - Add an `s_add_to_cart` snippet inside a mega menu - Open a product detail page for a storable product - Change the product variant several times - Stock availability messages…
Steps to reproduce:
- Add an `s_add_to_cart` snippet inside a mega menu
- Open a product detail page for a storable product
- Change the product variant several times
- Stock availability messages keep appending under `availability_messages` instead of replacing the previous one
`_onChangeCombinationStock` removed existing messages with `document.querySelector('.oe_website_sale').querySelectorAll(...)`, but appended the new message with
`this.el.querySelector('div.availability_messages').append(...)`.
`document.querySelector('.oe_website_sale')` only returns the first `.oe_website_sale` element in the document. When a mega menu contains an `s_add_to_cart` snippet, that element appears before the product page container, so the removal step runs on the wrong subtree and never clears the messages on the product page.
Fix by scoping the removal to `this.el`, the current `WebsiteSale` interaction root, so both removal and insertion target the same product page container.
Forward-Port-Of: odoo/odoo#276007
Forward-Port-Of: odoo/odoo#274928This update resolves an issue where Chrome was incorrectly suggesting previous selections in empty 'SelectMenu' fields. This prevented users from starting fresh with each new record creation, leading to a confusing user experience. The fix disables browser autocomplete for these fields, ensuring a cleaner and more intuitive selection process.
Original PR description
Chrome keeps suggesting autocompletion on empty selection field. https://github.com/odoo/odoo/commit/5e7bc4ab851dba3d2e0b965f69e06cfeacec5674 is the commit introducing `autocomplete="selectMenuAutocompleteOff"` and I don't know why this value has been chosen but Chrome seem to consider this token as invalid Steps to reproduce: - Put a selection field on a form view with Studio - Create a record, complete the selection field and save - Create a new record and click on the selection field Current Behaviour: Chrome keeps suggesting the previously filled values Desired Behaviour: No autocomplete from the browser. Forward-Port-Of: odoo/odoo#274527 Forward-Port-Of: odoo/odoo#274086
18 changes
Enhancements to existing features
This update enhances the testing framework for Odoo's mass mailing functionality. Specifically, it improves the tools used to simulate user interactions (like email opens and replies) to accurately verify the scheduling and execution of marketing campaigns. This ensures marketing automation processes are reliable and perform efficiently.
Original PR description
Improve (mass_)mailing asserts and tools, notably to use their usage in marketing automation where simulating user actions (open emails, reply, ...) is necessary to check marketing activities scheduling and execution. Task-4224152: [marketing_automation] Performance / Scalability Forward-Port-Of: odoo/odoo#275964
Resolved issues and error corrections
This update resolves an issue where Chrome was incorrectly suggesting previously filled values in selection fields. The change prevents the browser from offering autocomplete suggestions, ensuring a cleaner and more predictable user experience when creating new records. This improves data entry consistency and reduces potential user confusion.
Original PR description
Chrome keeps suggesting autocompletion on empty selection field. https://github.com/odoo/odoo/commit/5e7bc4ab851dba3d2e0b965f69e06cfeacec5674 is the commit introducing `autocomplete="selectMenuAutocompleteOff"` and I don't know why this value has been chosen but Chrome seem to consider this token as invalid Steps to reproduce: - Put a selection field on a form view with Studio - Create a record, complete the selection field and save - Create a new record and click on the selection field Current Behaviour: Chrome keeps suggesting the previously filled values Desired Behaviour: No autocomplete from the browser. Forward-Port-Of: odoo/odoo#274527 Forward-Port-Of: odoo/odoo#274086
This update resolves an issue where users couldn't update company names through the portal, and new companies were incorrectly created as contacts. Now, company names can be updated correctly, and commercial fields are editable for customer addresses with a single direct child company, streamlining business processes.
Original PR description
### [FIX] portal: fix parent company handling Before this commit, users could not update the company name from the portal, and creating a company resulted in a regular contact instead of a company. This happened because the additional_values passed to mark the parent as is_company=True were overridden to False when the customer did not have a VAT number. This commit sets is_company after creating the company, ensuring the parent contact is always created as a company. ### [FIX] portal: make commercial fields editable Before this commit, there was no way to edit commercial fields after a user entered a company name in the address form. Setting a company name created a parent company, and editing commercial fields was blocked because the customer had a parent record. This commit allows commercial fields to be edited again for customer addresses whose parent company has only a single direct child. Forward-Port-Of: odoo/odoo#275207
This update ensures that all invoices sent via Peppol are regularly checked for validity, regardless of whether they are sent in batches or individually. Previously, this check was only performed manually, leading to potential issues with Peppol compliance. This change improves the reliability and accuracy of our Peppol invoice processing.
Original PR description
If you have a partner that wasn't on Peppol. If you only do batch sending, we never re-check its validity. You need to do it by hand, or open explicitely the send&print for an invoice for this customer. We should simply do that check in every case, in batch or in manual sending. task-6296017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273121
This update ensures that the Pos Cashmatic module's text is properly translated into other languages. By adding the module to the translation files (.weblate.json), the system will now display the correct text for users in different regions. This improves the user experience and expands the module's accessibility.
Original PR description
This commit add the pos_cashmatic module inside the .weblate.json file so that the srings are translated. 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#275863
This update fixes a visual issue in the API keys kanban view where scope and expiration information for scoped keys were displayed together, creating a cluttered appearance. The change separates these details into distinct lines for better readability and clarity. This ensures that key information is presented in a more organized and user-friendly manner.
Original PR description
The API keys kanban rendered the "Scope:" and "Expires on:" hints as two adjacent inline <small> elements. For a scoped key both are visible, so they were displayed stuck together, e.g. "Scope: rpcExpires on: ...". Render each hint as a block so they stack on their own lines. Keys without a scope are unaffected since the scope hint stays hidden. Description of the issue/feature this PR addresses: Current behavior before PR: <img width="980" height="414" alt="image" src="https://github.com/user-attachments/assets/6cd8b338-1d2e-4abb-a90b-03218aaef941" /> Desired behavior after PR is merged: <img width="979" height="389" alt="image" src="https://github.com/user-attachments/assets/83ffa680-ffb8-415f-af3f-8e53cb8e8351" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275869
This update fixes an issue where the amount to invoice was incorrectly calculated when products were ordered using a unit of measure (UoM) like 'pack of 6'. The change ensures accurate invoice amounts are generated for purchase orders and sales orders that utilize UoMs, improving financial reporting accuracy. This resolves a discrepancy in the billing process.
Original PR description
**PROBLEM** amount_to_invoice_at_date is not calculated correctly when using UoM. **STEP TO REPRODUCE** 1. Create a product tracked by unit. 2. Create a purchase order with a UoM of pack of 6 (or some multiples of the Units UoM). 3. Confirm the PO and receive the products. 4. Go to the accounting app, reviews>bill to receive 5. Notice the po line on bill to receive as an incorrect amount. opw-6305324 Forward-Port-Of: odoo/odoo#275385 Forward-Port-Of: odoo/odoo#270327
This update adds a check to ensure contact emails entered during the French PDP registration process are valid. Previously, invalid emails could cause errors later, leading to a poor user experience. This change improves data quality and prevents potential issues for users.
Original PR description
No verification was done on the contact email in the wizard but if the email is invalid the user would have an error later task-6344324 Forward-Port-Of: odoo/odoo#274065
This update resolves a critical issue where the purchase catalog feature crashed when accessed on mobile devices. The problem stemmed from a configuration error that prevented the catalog from properly displaying. This fix ensures the purchase catalog functions correctly on all device views, improving usability for mobile users.
Original PR description
Currently, th purchase catalog crashes in mobile view. Steps to reproduce: ------------------- * Open purchase order form on desktop * From the devtools put window size to mobile (don't refresh) * Select catalog > Traceback: Cannot find the definition of component "Dropdown" Why the fix: ------------ PurchaseSuggestCatalogSearchPanel extends AccountProductCatalogSearchPanel which also extends AccountProductCatalogSearchPanel. Components were completely overridden and not inherited. opw-6219505 Forward-Port-Of: odoo/odoo#271449
This fix prevents a crash in the HTML editor when users type URL-like tokens (automatically converted to links). The issue, specific to Safari, caused a 'IndexSizeError' preventing further input. By re-anchoring the selection, the editor now correctly handles these tokens and allows users to continue typing.
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#275587
Forward-Port-Of: odoo/odoo#270910This update ensures that the Point of Sale system always uses a fiscal position that is both allowed and suitable for a customer, regardless of order of preference. Previously, the system could unintentionally use an unauthorized fiscal position, leading to potential errors. This fix improves data accuracy and prevents issues related to tax calculations during sales transactions.
Original PR description
**Steps to reproduce:** - Create a fiscal position T1, with detect automatically - Create another one T2, without the detect automatically - When looking at the fiscal positions list, make sure T1 is…
**Steps to reproduce:** - Create a fiscal position T1, with detect automatically - Create another one T2, without the detect automatically - When looking at the fiscal positions list, make sure T1 is on top, followed by T2 - Go to the PoS settings, check flexible taxes - Put T2 as default and in allowed, don't put T1 in allowed - Go to the PoS, chose a customer - The fiscal position is T1 even though it's not allowed **Why the fix:** Currently, the fiscal position is chosen like this in order: - A FP specified on the customer's profile - A FP detected with the detect automatically setting - The default FP from the PoS settings When we have a tie, it's the first one in the fiscal positions list that is chosen. Before this commit, we did not check that the fiscal position was allowed to be used in the PoS, so we just fetched whatever fiscal position fit the best for a given customer and didn't check if we could actually use it. We now make sure that the fiscal position we try to use is allowed in the current PoS, and if it's not we fall back to the default one. opw-6032031 Forward-Port-Of: odoo/odoo#271343
This update resolves an issue where customers were not appearing in the POS list when using the Taiwan localization. The fix updates the Chart of Accounts to correctly display customer accounts, ensuring all customers are visible within the POS interface for Taiwan companies. This improves the user experience for Taiwanese businesses using Odoo POS.
Original PR description
## Current behavior: Currently, when we go into POS using l10n_tw localization, none of the customers appear on the list. ## Expected behavior: All customers should be shown when using Taiwan localization ## Steps to reproduce: 1. Install l10n_tw and POS modules 2. Use the default US company, observe the customer list in POS. All of them are shown 3. Create and switch to a Taiwan company, go back to POS 4. Observe that no customers are shown ## Cause of the issue: Since 19.0, there is a check where if the default payable or receivable account set on the partner is non-trade, those accounts do not appear ## Fix: - Updated AR accounts in COA template file - Added migration script to version 1.1 opw-6298634 Forward-Port-Of: odoo/odoo#270738
This update fixes a glitch that allowed customers to repeatedly top up their loyalty program balances using eWallet top-up products, effectively creating an unlimited credit. The fix now correctly prevents applying eWallets when an order consists solely of top-up products, ensuring accurate discount calculations and preventing abuse.
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-6341410
Forward-Port-Of: odoo/odoo#273419This update resolves an issue where batch payment sequences were incorrectly created when a new company was initially set up. The change ensures sequences are properly associated with the correct company during creation, preventing errors in payment processing. This improves the reliability of batch payments.
Original PR description
Previously, batch payment sequence will be created by simply select to create new company due to having lambda in default. Hence, the created sequence does not have a correct company_id set as company hasn't yet created. Switch to creating sequence in ``create`` function to avoid this issue. Also use ``range_year`` for payment prefix because it was set to use date range. 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#273852 Forward-Port-Of: odoo/odoo#268689
The barcode check-in process in kiosk mode was previously inaccurate, with location data off by several kilometers. This update fixes the issue by utilizing the browser's geolocation to provide more precise location data, improving the accuracy of check-in times.
Original PR description
**Issue** Check-in and check-out performed in kiosk mode via the barcode scanner were less accurate than those made via the manual selection. The reported inacurracy between the actual and real locations was several kilometers. **Cause** `attendance_barcode_scanned` was called without a location coming from the browser's geolocation API. In that case, the location was determined by the geoip database https://github.com/odoo/odoo/blob/51f59a293de1e86f66f30257f8fc0c419463d18c/addons/hr_attendance/controllers/main.py#L69-L70 which is generally not as accurate as the location provided by the browser. opw-5889102 Forward-Port-Of: odoo/odoo#273044 Forward-Port-Of: odoo/odoo#251478
This update fixes an issue where discount lines in the TBAI XML export were incorrectly showing negative import values. The fix ensures that all monetary values, including discounts, are consistently represented as positive numbers, aligning with the system's expected format. This ensures accurate reporting and compliance with tax regulations.
Original PR description
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from…
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from "TicketBai" page, open the "TicketBAI Post File" xml file Observation: - `ImporteUnitario` and `ImporteTotal` were exported as positive values for discount lines. cause: - Commit [1] assumed tax details are always positive. - This is not generally true, in case we have price_unit < 0 - The logic relied on `is_refund`, which depends on `qty * price`. - `_l10n_es_tbai_get_values` then multiplied values by `-1` again for refunds. https://github.com/odoo/odoo/blob/e751fa1e010dbda63903d598048ef415709b4af4/addons/l10n_es_edi_tbai_pos/models/pos_order.py#L177-L181 - For discount lines, `is_refund = True` and `price = -10`, resulting in `-10 * -1 = 10`. Fix: - Ensure tax detail values are always returned as positive values, matching the assumption introduced in commit [1] [1] https://github.com/odoo/odoo/commit/03d55104e49aa65aa4c6475e199747fe9132e754 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275451 Forward-Port-Of: odoo/odoo#265777
This update resolves an issue where web assets weren't correctly loaded within iframes, particularly in scenarios like displaying emails. The change ensures assets are properly added to secondary documents, improving functionality in complex use cases.
Original PR description
Commit [1] introduces the concept of "global" cache for optimization. However when loading a bundle inside a secondary document such as an iframe, containing source files that are already loaded in…
Commit [1] introduces the concept of "global" cache for optimization. However when loading a bundle inside a secondary document such as an iframe, containing source files that are already loaded in the main document, those source files are not properly added in the secondary document. Example: load `web.assets_web` inside an iframe (this use case can happen in `mass_mailing` where we have to wrap some component inside a sandboxed iframe in order to display unsafe content (poorly sanitized), such as emails). The issue is caused by an inconsistent usage of the `globalCache`: `getBundle` adds `bundleName` key to JS and CSS libs, but `computeAssetCaches` adds `url` keys to link or script elements. After this commit: - `globalCache` is only used in `getBundle` to map bundleNames to their libs - `loadCSS` and `loadJS` only use the documents caches to map urls to their element in the respective document. [1]: https://github.com/odoo/odoo/commit/5b1dc282b0f09c0fe6dcf9910a3a29cfd01d66a3
This update fixes a display issue where the 'To Review' invoice filter in the dashboard incorrectly showed multiple invoices. The change ensures that the filter only displays invoices that have been fully posted, providing a more accurate and reliable view of outstanding invoices for users. This improves data clarity and efficiency.
Original PR description
Steps to reproduce: Have one invoice Posted, To Review Have one invoice Draft, To Review Dashboard will only says 1 To Review When clicking the link it shows 2 invoices After this commit- We append the domain of the filter with only posted moves task-6385625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
11 changes
Enhancements to existing features
This update enhances the testing framework for Odoo's mass mailing functionality. Specifically, it incorporates simulated user actions like email opens and replies to more accurately verify the scheduling and execution of marketing campaigns. This improves the reliability of marketing automation processes.
Original PR description
Improve (mass_)mailing asserts and tools, notably to use their usage in marketing automation where simulating user actions (open emails, reply, ...) is necessary to check marketing activities scheduling and execution. Task-4224152: [marketing_automation] Performance / Scalability Forward-Port-Of: odoo/odoo#275964
Resolved issues and error corrections
This update resolves an issue where opening work entries from the Calendar view in Odoo caused a technical error. The fix removes an unnecessary property from a component, preventing a validation error and ensuring the Calendar view functions as expected. This improves the user experience when accessing work entries through the Calendar.
Original PR description
**Issue before this commit:** Opening a work entry from the Calendar view raises the following Owl error: ``` OwlError: Invalid props for component 'WorkEntryPopover': unknown key 'editArchInfo' ``` **Steps to reproduce:** 1. Install `hr_work_entry`. 2. Go to **Employees → Work Entries**. 3. Switch to the **Calendar** view. 4. Open any work entry. **Cause of the issue:** The `WorkEntryCalendarCommonRenderer` passes the `editArchInfo` prop to `WorkEntryPopover`. However, `editArchInfo` is not declared in `WorkEntryPopover`'s `static props` and is not used anywhere in the component. Owl validates component props and raises an error when an unknown prop is passed. **With this commit:** Remove the unused `editArchInfo` prop from `WorkEntryCalendarCommonRenderer` to prevent the Owl validation error and restore the expected behavior when opening work entries from the Calendar view.
This update resolves an issue where users with read-only access to products were prevented from confirming sale orders. The fix uses `sudo()` to bypass permission restrictions when updating product inventory levels, ensuring order confirmation works correctly for all users. This impacts both sales and purchase order processes.
Original PR description
Steps to produce: --- - Install the `sales` module. - Create a product and `enable track inventory.` - Log in as user with only view access rights in products and also have the sales access rights. -…
Steps to produce: --- - Install the `sales` module. - Create a product and `enable track inventory.` - Log in as user with only view access rights in products and also have the sales access rights. - Create a sale order containing product and confirm it. Issue: --- - An access error is raised during order confirmation. Root cause: --- - In [commit], to handle inventory tracking, the `qty_available` field was moved to `product.product`. Unlike before, this value is increased or decreased depending on the operation performed. - As a consequence, creating or updating a sale order triggers a write to this `qty_available` field on the related product. This write happens under the current user's permissions, so users who only have read access to products (but can create/edit sale orders) hit an `AccessError`, since they lack write access on `product.product`. Solution: --- - Use `sudo()` when accessing the required product quantity information to ensure the operation can be completed without requiring additional product access rights. The same issue also occurs when confirming a purchase order. [commit]: https://github.com/odoo/odoo/commit/ca96992919b11105da44238c3e522f8eec4a740b opw-6290608 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where closing POS sessions could result in incorrect accounting entries. The fix, mirroring a previous frontend change, ensures session data is balanced, preventing errors during order closure. This improves the reliability of the Point of Sale system.
Original PR description
This fix is the same as this one https://github.com/odoo/odoo/pull/271577 but for the backend part of the code. After the fix, if you followed the same steps to reproduce and tried to close the session you would have an unbalanced entry for the session. Steps to reproduce: ------------------- * Create a 21% tax not included in price * Create a product with a price of 76.01 and the tax created above * Create a loyalty program with a 10% discount * Create a POS order with the product above and apply the loyalty program * Validate the order and generate the invoice * Close the session > Observation: You need to force close the session because of unbalanced entry Why the fix: ------------ Apply the same fix for backend code. opw-6052112 Forward-Port-Of: odoo/odoo#275711 Forward-Port-Of: odoo/odoo#274985
The barcode scanner check-in process was previously inaccurate, with location data off by several kilometers. This update fixes the issue by utilizing the browser's geolocation to provide more precise location data, improving the accuracy of check-in times.
Original PR description
**Issue** Check-in and check-out performed in kiosk mode via the barcode scanner were less accurate than those made via the manual selection. The reported inacurracy between the actual and real locations was several kilometers. **Cause** `attendance_barcode_scanned` was called without a location coming from the browser's geolocation API. In that case, the location was determined by the geoip database https://github.com/odoo/odoo/blob/51f59a293de1e86f66f30257f8fc0c419463d18c/addons/hr_attendance/controllers/main.py#L69-L70 which is generally not as accurate as the location provided by the browser. opw-5889102 Forward-Port-Of: odoo/odoo#273044 Forward-Port-Of: odoo/odoo#251478
This update fixes an issue where discount lines in the TBAI XML export were incorrectly showing negative import values. The fix ensures that all monetary values, including discounts, are consistently represented as positive numbers, aligning with the original system logic. This ensures accurate reporting and compliance with tax regulations.
Original PR description
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from…
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from "TicketBai" page, open the "TicketBAI Post File" xml file Observation: - `ImporteUnitario` and `ImporteTotal` were exported as positive values for discount lines. cause: - Commit [1] assumed tax details are always positive. - This is not generally true, in case we have price_unit < 0 - The logic relied on `is_refund`, which depends on `qty * price`. - `_l10n_es_tbai_get_values` then multiplied values by `-1` again for refunds. https://github.com/odoo/odoo/blob/e751fa1e010dbda63903d598048ef415709b4af4/addons/l10n_es_edi_tbai_pos/models/pos_order.py#L177-L181 - For discount lines, `is_refund = True` and `price = -10`, resulting in `-10 * -1 = 10`. Fix: - Ensure tax detail values are always returned as positive values, matching the assumption introduced in commit [1] [1] https://github.com/odoo/odoo/commit/03d55104e49aa65aa4c6475e199747fe9132e754 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275451 Forward-Port-Of: odoo/odoo#265777
This update ensures that employee working schedules are consistently synchronized with their associated resource records, regardless of version changes. Previously, changes to future employee versions could cause incorrect attendance intervals to display in the Gantt view. This fix resolves a visual discrepancy and maintains accurate employee availability data.
Original PR description
Steps to reproduce: 1. Create a new version on an employee with a future start date 2. Ensure the new version has a different working schedule 3. After the new version becomes active, observe that…
Steps to reproduce: 1. Create a new version on an employee with a future start date 2. Ensure the new version has a different working schedule 3. After the new version becomes active, observe that the working schedule on the employees record is different from the one on the employee's resource record Every employee has an associated resource record associated with them. Normally, the employee's working schedule (`hr_employee.resource_calendar_id`) should always be in sync with their associated resource record (`hr_employee.resource_id.calendar_id`). When we update the employee's working schedule through the UI on a currently active version, it will also update their associated resource record with the same working schedule. However, if we change the working schedule for a future version, when `_cron_update_current_version_id()` runs and changes the active version, there is no mechanism to update the associated resource with the new working schedule. This change will ensure we keep the working schedules in sync, as if they are not, strange behaviors can occur. One side effect of this problem: When a new version becomes active, and working schedules become de-synced, this can cause the Attendance gannt view to display incorrect unavailable intervals for an employee (this appears as a grayed-out time slot). This is because `_attendance_intervals_batch()` pulls from the working schedule of an employee's associated resource record, rather than the employee record itself. This is what occurred on the linked ticket. [opw-6352770](https://www.odoo.com/odoo/my-tasks/6352770?debug=assets) Forward-Port-Of: odoo/odoo#275430
This update corrects a bug where the reference price wasn't displayed for product variants when a base unit count was greater than zero. The fix ensures the reference price is correctly shown on the product page for all variants, improving the accuracy of displayed pricing information. This impacts how customers see prices for different product options.
Original PR description
# How to reproduce - In Settings, enable Variants & Product Reference Price - Create a published Product with a Sales Price - Add 2 variants to the Product - In the product's variant list, select the…
# How to reproduce
- In Settings, enable Variants & Product Reference Price
- Create a published Product with a Sales Price
- Add 2 variants to the Product
- In the product's variant list, select the first one & set Base Unit Count to 0,
- Set the second variant's Base Unit Count to a value > 0
- Go to the Product's page
- Select the second variant
# The issue
The Reference Price is not displayed for the second variant, even though it should since it has a Base Unit Count > 0. Refreshing the page while being on the second variant will prevent the bug from happening.
# Cause
When loading the product's info, we call `_onChangeCombination`. This method is responsible for, among other things, updating the reference price and hiding it if Base Unit Count = 0 :
https://github.com/odoo/odoo/blob/68f258e99f42693131a5309b3606c3b95f93d824/addons/website_sale/static/src/js/variant_mixin.js#L277-L289
To do that, it will search for an html element with the `.o_base_unit_price` css class. If it does not find it, the reference price will not be updated. The issue is that this element is behind a condition in the template :
https://github.com/odoo/odoo/blob/68f258e99f42693131a5309b3606c3b95f93d824/addons/website_sale/views/templates.xml#L2083
When the first time the template is loaded, if
`combination_info.get('base_unit_price')` is False, then the Reference Price will never be added to the view and will never be found by `_onChangeCombination`.
Since our first variant has Base Unit Count = 0, then `base_unit_price` will equal 0, so `combination_info.get('base_unit_price')` will be evaluated to false.
opw-6367289
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274722This update corrects an issue where customer addresses weren't consistently displayed on the left side of invoices when using specific layouts. Previously, if a customer's delivery address was set without a 'Customer Address' defined, the address would appear on the right. This change ensures the address is always displayed on the left, improving invoice presentation.
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 Forward-Port-Of: odoo/odoo#273418
This update fixes an issue where the quantity displayed for kit products in the Point of Sale picking process was incorrect. The fix ensures that the correct quantity, based on the kit's components, is accurately reflected, resolving a discrepancy between the demand and quantity columns. This improves order accuracy and prevents potential fulfillment errors.
Original PR description
**Steps to reproduce:** - Create a product A, tracked by lots - Create a kit product, include a component A - Change the UoM to 0.5 - Go to the PoS, order this kit product - Also order the component…
**Steps to reproduce:** - Create a product A, tracked by lots - Create a kit product, include a component A - Change the UoM to 0.5 - Go to the PoS, order this kit product - Also order the component A, with a quantity of 2 - Pay for it, ask for an invoice - Go to the created picking - The Demand column is correctly computed and is 0.5 - The Quantity column is wrong and is 2 **Why the fix:** When getting the data from https://github.com/odoo/odoo/blob/e0d84c7fbb270d0d1f82572daefa96c2978d3785/addons/point_of_sale/models/stock_picking.py#L283 we always get the component's line, as the move's product is the component, even if it used to be the kit product's move. This is because when exploding a kit's moves, it gets the kit's component as a product instead of keeping the kit product. This was introducing a weird behavior because we took the quantity from the component line, and not from the kit line, meaning the kit would always have the same quantity as the component. We now check if the move is actually a kit product's move, and if it is we adapt the qty to correct one by fetching the correct line's qty, and adapting it with the correct UoM. Changing the line in itself would not work, as the kit itself is not tracked by lots, so we would not enter https://github.com/odoo/odoo/blob/e0d84c7fbb270d0d1f82572daefa96c2978d3785/addons/point_of_sale/models/stock_picking.py#L284 and the move line would not be correctly created. opw-6153000 Forward-Port-Of: odoo/odoo#275115 Forward-Port-Of: odoo/odoo#262551
This update fixes a bug where the 'retry' button after a failed initial message load wouldn't work. Now, clicking the button correctly attempts to re-fetch the messages, ensuring users can consistently access their communications. This improves the reliability of the messaging system.
Original PR description
The `retry` button shown after a failed initial fetch did nothing when clicked (it goes through `thread.fetchMoreMessages` which is for load older and load newer). This change routes the click through `fetchMessages` when the failure is an initial one. task-6223358 backport of #272153 Forward-Port-Of: odoo/odoo#275300
8 changes
Resolved issues and error corrections
This update fixes a glitch where customers could repeatedly top up their loyalty program balances using eWallets, effectively creating an unlimited credit. The change ensures that an eWallet payment won't process if the order consists solely of top-up products, preventing this 'infinite money' scenario. This improves the stability and accuracy of our loyalty program transactions.
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-6341410
Forward-Port-Of: odoo/odoo#273419This update resolves a crash that occurred when users deleted tabs within a website snippet. The issue stemmed from a technical glitch where tab elements weren't being fully removed from the website's code. Adding a specific setting ensures these tabs remain intact after deletion, improving website stability.
Original PR description
Steps to reproduce: 1. Drop a .s_tabs snippet 2. Click inside a tab to move the selection in it 3. Press backspace (remove each tab name + the last one should be empty) 4. Click on the "+" in the sidebar to add a Tab => Crash or on step 3: 3. Press backspace to delete one tab => Check the DOM: the tab has been removed, but the tab-pane element is still in the DOM and won't be deleted. This is easily fixed by adding `oe_unremovable` on tab links. task-4671317
This update resolves an issue where activity descriptions weren't consistently appearing in all chat tabs after duplicating a conversation. The fix removes unnecessary computed fields from activity broadcasts, ensuring descriptions are accurately reflected across the system. This improves the user experience when sharing and discussing activities.
Original PR description
**Steps to reproduce:** - Install Contacts app - Open any record - Go to the chatter - Create an activity with a description - Duplicate the tab - Go back to the initial tab - Description doesn't…
**Steps to reproduce:**
- Install Contacts app
- Open any record
- Go to the chatter
- Create an activity with a description
- Duplicate the tab
- Go back to the initial tab
- Description doesn't appear anymore
- Refreshing shows it but will remove it from the other tab
**Issue:**
Behavior comes from the broadcasting of activity changes between tabs `new browser.BroadcastChannel("mail.activity.channel");`.
Computed fields are not recomputed on the receiver side after value insertion in `_onActivityBroadcastChannelMessage` (also related components are not (re)mounted, e.g. when a new activity is created the other tab doesn't show it without a refresh).
This means that `isNoteEmpty` keeps its default value `true` (added by `this.toData()`) and the `note` stays hidden here [1]:
```xml
<div t-if="!props.activity.isNoteEmpty" class="o-mail-Activity-note text-break" t-out="props.activity.note"/>
```
**Fix:**
Remove computed fields in activity `serialize` before broadcasting them to ensure they don't force the default value.
(note installing `calendar` in 19.3+ removes this issue due to [2] which overrides the condition on `isNoteEmpty`)
[1] https://github.com/odoo/odoo/commit/eb9f0658c3da1a9fef69f1cc1117c2d44f9d61b1
[2] https://github.com/odoo/odoo/commit/44e2c2c5ca07849fd8964140f3ca61122c47f0c6
opw-6247412
Forward-Port-Of: odoo/odoo#275528This update fixes an issue where imported FatturaPA XML invoices weren't correctly applying Italian tax rules (like partial deductibility) to the line items. Now, the system accurately maps these tax rules from the fiscal position to the imported invoice lines, ensuring accurate tax calculations for Italian vendors. This improves compliance and reporting.
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 Forward-Port-Of: odoo/odoo#274738
This update resolves a flaky test related to marking inbox messages as read in Odoo. The fix adjusts a configuration setting to ensure the correct process is followed when opening a thread with a needaction message, guaranteeing that all messages are properly marked as read. This improves the reliability of the inbox functionality.
Original PR description
The "Opening thread with needaction messages should mark all messages of thread as read" test opens a channel that holds an inbox (needaction) message and asserts mark_all_as_read is sent. Two flows can mark that message as read: the channel messages fetch, through set_message_done, and mark_all_as_read, sent by markAsRead when the channel gets focused on open. When the self member's new_message_separator is 0, opening the channel fetches its messages around 0, and that fetch marks the message as read and drops the needaction counter to 0 before markAsRead runs. mark_all_as_read is then skipped and the step assertion receives nothing. Give the member a non-zero separator (the pre-existing message is already read) so opening the channel no longer fetches around 0, leaving mark_all_as_read as the flow that marks the inbox message read. https://runbot.odoo.com/odoo/error/243651
This update fixes an issue where batch payments weren't being created correctly in Odoo. By initializing the batch payment sequence immediately after the company is set up, the system now reliably handles payment processing, ensuring accurate financial records and smoother transactions. This change enhances the overall stability and reliability of the accounting module.
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#273905
This update corrects an issue where invoice addresses weren't displayed on the left as intended when using specific layouts. Previously, the address was always positioned on the right if the 'Customer Address' setting wasn't enabled. This change ensures invoices display the correct address layout, improving the customer experience.
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 Forward-Port-Of: odoo/odoo#273418
Features or functions removed from Odoo
This update removes a redundant check within the ‘pos_self_order’ module that was incorrectly verifying if the self-ordering mode was ‘qr_code’. As ‘qr_code’ is not a valid option, this check always returned true, consuming unnecessary processing power. This change ensures smoother operation and improved efficiency.
Original PR description
Description of the issue/feature this PR addresses: Removed obsolete code checking "this.config.self_ordering_mode !== 'qr_code'". Since "qr_code" is not a valid value of the "self_ordering_mode" selection field. The condition is always true. Forward-Port-Of: odoo/odoo#273245
9 changes
Resolved issues and error corrections
This update resolves a minor technical issue within the Odoo accounting module. A typographical error was corrected in a calculation field used for analyzing profitability. This ensures accurate reporting and avoids potential discrepancies in financial data.
Original PR description
Fix field name typo. @qrtl QT6381
A bug in a test related to currency conversion within the event sale module was resolved. The test now correctly initializes exchange rates, ensuring accurate currency conversion calculations. This fix improves the reliability of our event sale pricing tests.
Original PR description
Before this commit, in the test `test_ticket_price_with_currency_conversion` the exchange rate was not correctly assigned because `rate_ids` was not initialized when running tests on app install. As a result the the rate was left empty and the currency conversion was not applied. This commit creates the rate_ids in the test to make sure the rates are correctly applied. Runbot error: https://runbot.odoo.com/odoo/error/242431 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where a sale order item remained linked to a timesheet after switching to a non-billable project. The fix ensures that the 'is_so_line_edited' field is reset, preventing incorrect item associations and improving data accuracy within the timesheet reporting.
Original PR description
## Steps to reproduce: - Install sale_timesheet - Create a timesheet with a Sale order item linked to it - Change the sale order item on that timesheet - Change the project linked to the timesheet to a non-billable project - Notice the sale order item still linked to the timesheet ## Cause: When computing the so_line we filter out the records that has is_so_line_edited as true, so when changing the SOL before changing the project we don't reset so_line field when setting a non-billable project. ## Fix: We reset the is_so_line_edited field to false when changing the project to a non-billable one. opw-6311549
This update fixes a potential issue where the cloud storage migration process could delete attachments used in core business operations, such as invoice stamping. The fix now filters out attachments linked to specific models, ensuring these important files remain accessible within Odoo.
Original PR description
**PROBLEM** `_cron_migrate_local_to_cloud_storage()` is used to migrate attachment to a cloud storage. It delete the attachment from the database, rendering it innacessible from the server-side. The…
**PROBLEM** `_cron_migrate_local_to_cloud_storage()` is used to migrate attachment to a cloud storage. It delete the attachment from the database, rendering it innacessible from the server-side. The problem is it can delete attachment used in business logic. **STEP TO REPRODUCE** 1. Install and configure cloud_storage + a provider (e.g. cloud_storage_google) and cloud_storage_migration. 2. Install l10n_mx_edi and stamp a customer invoice. The CFDI XML is stored as an ir.attachment that: - is referenced by a business Many2one l10n_mx_edi.document.attachment_id (copied into account.move.l10n_mx_edi_cfdi_attachment_id), - has res_field = NULL (record attachment, not a field binary), - is posted to the chatter → it has a row in message_attachment_rel. 3. Add account.move to cloud_storage_migration_message_models and set a low enough cloud_storage_min_file_size. 4. Run the cron _cron_migrate_local_to_cloud_storage. 5. Open the invoice and trigger any recompute of the EDI chain (e.g. Update Payments, a reconciliation, or re-stamping). **FIX** Filters out attachment linked to a model listed by the already existing function `_get_cloud_storage_unsupported_models()` opw-6347198
This update resolves an issue where Odoo incorrectly identified valid invoices with negative tax amounts as credit notes during import. By updating the import logic to use TaxInclusiveAmount (UBL) and GrandTotalAmount (Factur-X), the system now accurately determines invoice status, preventing misclassification.
Original PR description
Before this commit: - When importing a **UBL** or **Factur-X (CII)** invoice, Odoo determines whether the document should be imported as an invoice or a credit note based on the `TaxExclusiveAmount…
Before this commit: - When importing a **UBL** or **Factur-X (CII)** invoice, Odoo determines whether the document should be imported as an invoice or a credit note based on the `TaxExclusiveAmount (UBL)` /` TaxBasisTotalAmount (Factur-X)`. - In some rare cases, a valid invoice can contain a negative `TaxExclusiveAmount` / `TaxBasisTotalAmount` while still having a positive `TaxInclusiveAmount` / `GrandTotalAmount`. - In such situations, Odoo incorrectly imports the document as a credit note. Technical reason: - The method `_get_import_document_amount_sign()` uses `TaxExclusiveAmount` / `TaxBasisTotalAmount `to determine whether the imported document is an invoice or a refund. After this commit: - **UBL** now uses `TaxInclusiveAmount` instead of `TaxExclusiveAmount`, and **Factur-X** now uses `GrandTotalAmount `instead of `TaxBasisTotalAmount` to determine whether the document should be imported as an invoice or a credit note. - Prevent valid invoices with negative `TaxExclusiveAmount` / `TaxBasisTotalAmount` from being incorrectly converted into credit notes. Task-6321262 Forward-Port-Of: odoo/odoo#271829
This update resolves a technical error preventing Spanish companies using EDI modules (Veri*Factu, SII, TBAI) from correctly sending invoices. The fix addresses a change in the Requests library that caused a certificate loading error when using version 2.32 or higher. By setting up the certificate during adapter creation, the issue is now consistently resolved across all Requests versions.
Original PR description
CertificateAdapter presents a client certificate stored in the database instead of on disk when opening an HTTPS connection (used by the l10n_es EDI modules verifactu, sii and tbai). It loaded that…
CertificateAdapter presents a client certificate stored in the database instead of on disk when opening an HTTPS connection (used by the l10n_es EDI modules verifactu, sii and tbai). It loaded that certificate on the connection path of requests 2.31, but requests >= 2.32 changed that path (no longer calls get_connection()), so the step was skipped and the call crashed with: "TypeError: expected str, bytes or os.PathLike object, not certificate" Odoo pins requests 2.31.0 (max depending on Python version), but online databases can use the version shipped by the OS (2.32.x on recent Ubuntu 26). Set the certificate up when the adapter is created instead of on that connection call. That step runs the same on every requests version, so the fix works both before and after 2.32. Steps to reproduce: - Spanish company with Veri*Factu and a certificate, on a server running requests >= 2.32 (saas-19.3 database for exemple on ubuntu 26) - Post a customer invoice and send it to Veri*Factu. => TypeError Reference: https://github.com/psf/requests/blob/f361ead047be5cb873174218582f7d8b9fcd9f49/HISTORY.md?plain=1#L146 Ticket [link](https://www.odoo.com/odoo/project.task/6366028) opw-6366028
This update resolves an issue where the website editor was experiencing performance problems due to incorrect use of asynchronous callbacks within its code. The team has replaced `forEach` loops with traditional `for` loops, resulting in a more stable and efficient editor experience. This change ensures smoother operation for website content creation.
Original PR description
*: website, website_sale `forEach` is a synchronous operation, so it doesn't support promises. We refactor its usage to use `for` loops. task-4794299 Forward-Port-Of: odoo/odoo#275262
This update corrects a visual issue in the resource scheduling module where flexible working hours caused unpredictable weekend days on timesheets and calendars. By restoring a weekly Monday anchor, the system now consistently displays standard workdays (Monday-Friday) on these views, ensuring accurate scheduling and reporting.
Original PR description
### Description of the issue/feature this PR addresses: This PR fixes an issue in the `resource` module where flexible working hours cause unpredictable and shifting non-working (greyed-out) days on…
### Description of the issue/feature this PR addresses: This PR fixes an issue in the `resource` module where flexible working hours cause unpredictable and shifting non-working (greyed-out) days on the Timesheets and Calendar views. It restores the weekly Monday anchor for flexible hour calculations while safely preserving a prior fix for partial-day work entries on public holidays. ### Current behavior before PR: In `_attendance_intervals_batch`, the calculation for flexible schedules sets `current_start_day = start_date`. Because `start_date` is often passed as the first day of the month or a requested period (which can fall on any day of the week), the 7-day calculation cycle becomes unanchored. Odoo blindly allocates 8 hours to the first 5 days of this arbitrary period and leaves the 6th and 7th days empty. This results in the visual "weekend" shifting randomly month-to-month (e.g., greying out Wednesdays and Thursdays instead of Saturdays and Sundays). ### Desired behavior after PR is merged: The `current_start_day` is correctly anchored back to Monday using `start_date - timedelta(days=start_date.weekday())`. This ensures the 5-day allocation always consistently spans Monday through Friday, keeping Saturday and Sunday as the standard non-working days on the UI grids. Furthermore, because the `min()` clamp on `remaining_hours` is retained, partial-day Work Entry generation (like a 2-hour gap on a Wednesday public holiday) continues to calculate correctly without attempting to over-allocate the remaining weekly hours. opw-6370301 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug in how overtime is calculated for employees with flexible work schedules. Specifically, it resolves a discrepancy in the week's starting day, leading to incorrect overtime calculations when tolerance time is adjusted. The fix ensures accurate overtime reporting for employees with varied working hours.
Original PR description
# How to reproduce - Set an employee's work schedule to flexible 40hrs/week with 8hrs of work per day - Create a new attendance for that employee that : - Is the very first attendance of that…
# How to reproduce - Set an employee's work schedule to flexible 40hrs/week with 8hrs of work per day - Create a new attendance for that employee that : - Is the very first attendance of that employee - Is not on a monday (e.g. a Friday) - Create a second attendance for that employee that : - Is atleast one week after the first attendance - Is one of the two days of the week before the day of the week of the first attendance (e.g. a Wednesday or a Thursday) - Go to the settings, update the value for "Tolerance Time In Favor Of Company" and save - Come back to the second attendance # The problem The Extra Hours have changed and are equal to the worked time # Cause When we update the tolerance time, we recompute the overtime of every attendance of every employee. In this recomputation, we compute the `expected_attendance` of every employee and transforms them into a dict of the expected working time for each day : https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/hr_attendance/models/hr_attendance.py#L349-L356 Later, if an attendace of the employee was not in their expected working days, then we consider that all hours worked were overtime : https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/hr_attendance/models/hr_attendance.py#L381-L384 This makes sense but our issue is that days in the middle of the week are considered "time-off" when they should not. That's because for flexible working schedules, we emulate the expected working hours based on the total hours per week and the maximum hours per day : https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/resource/models/resource_calendar.py#L384-L386 For every "week", we start from the first day and continue forward by greedily using all hours for that day until there is no more hours for the week. The problem is that since this PR, we don't start "weeks" on mondays, but on the `start_datime` : https://github.com/odoo/odoo/commit/af36e73108cef4326f6125c3af491b07a51534fe And in our case, `start_datetime` is the very first attendance day of the employee : https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/hr_attendance/models/hr_attendance.py#L344 So our expected working days are desynched with the days of the week # Proposed solution We partly revert https://github.com/odoo/odoo/commit/af36e73108cef4326f6125c3af491b07a51534fe opw-6289079
4 changes
Enhancements to existing features
This update makes the loading of availability information in the Manufacturing Order (MO) list view faster. Previously, this process was a significant delay, impacting user experience. By implementing a lazy loading approach similar to previous versions, this change dramatically improves the speed and responsiveness of the MO list view.
Original PR description
When loading the MO list view, loading the availability is what's taking the most time. Making this loading lazy as it was in 16.0 will greatly contribute to the UX. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves an issue where new products weren't consistently added to the bottom of sales orders when using the mobile interface. The fix adjusts how product sequences are managed within the system, ensuring that new items are correctly positioned at the end of the order. This improves the user experience for mobile sales order management.
This update fixes a display issue on the website where incorrect stock quantities were shown for product variants that didn't exist. The fix addresses a technical problem related to how stock levels are calculated when a variant is not created, ensuring accurate stock information is presented to customers. This improves the customer experience and prevents overselling.
Original PR description
Issue: --- If a product template has dynamic attributes, some variants might not exist. For those variants, we are showing wrong stock in the website. To reproduce: 1- Create a product with a dynamic attribute and two values. 2- Publish the product and uncheck sell when out-of-stock and check show product when the qty is less than 5. 3- Create a purchase order with qty = 4 for the first value, so a variant is created for it. 4- Go to the website shop. Open the product. 4 available qty in stock is shown for the first variant which is correct. 5- Select 2nd variant. As you see, still 4 available qty is shown which is wrong. As the out-of-stock sale is unchecked, an out-of-stock warning should be shown. Cause and Fix: --- This is due to `isMainProduct` being always False when `product_id` is not set which makes `free_qty` and `out_of_stock` not to be updated. opw-6237602
This update fixes an issue where newly created tasks were incorrectly defaulting to the first project's customer instead of the project selected by the user. The fix ensures that a new task always uses the customer associated with the project it's created within, improving data accuracy and user experience. This change was made to align task customer data with project assignments.
Original PR description
**Problem:** When creating a new task, the Customer does not follow the project the user selects: once a first project has filled it, selecting another project keeps the previous project's customer.…
**Problem:** When creating a new task, the Customer does not follow the project the user selects: once a first project has filled it, selecting another project keeps the previous project's customer. **Steps to reproduce:** 1. Create a new task and select a project that has a customer. 2. The Customer is set to that project's customer. 3. Select another project configured with a different customer. 4. Observe the Customer keeps the first project's customer. **Current behavior:** The Customer keeps the first selected project's customer. **Expected behavior:** The Customer follows the selected project and shows its customer. **Cause of the issue:** partner_id is filled by _compute_partner_id, which only assigns a partner while the field is empty. Once a project has filled it, selecting another project no longer refreshes the now non-empty Customer. **Fix:** Refresh the Customer from the project on project_id change, but only while the task is new (no _origin). An existing task's customer is left untouched, since it may already carry sale order lines, timesheets, materials or worksheets that must not be reset when the project changes. opw-6315902