Daily updates from Odoo
Tuesday, May 12, 2026
26 changes · 19.0
New functionality added to Odoo
This update introduces new payroll and attendance functionality for Egypt, building upon existing Saudi Arabia features. The changes include adjustments to views, salary rules, and an approval flow, aligning with local regulations. This enhancement supports accurate payroll processing and attendance tracking for Egyptian employees.
Original PR description
In this pr we introduce the new l10n_sa_hr_payroll_attendance & l10n_eg_hr_payroll_attendance modules to 19.0. the l10n_sa_hr_payroll_attendance module was already previously introduced in task-4598879 (PR: https://github.com/odoo/enterprise/pull/86699) to version 19.2 so we are just backporting it to 19.0 as well with slight view and payslip rule changes. for l10n_eg_hr_payroll_attendance it's being added now in v19 only and it has some slight changes from the original l10n_sa_hr_payroll_attendance including changes to the views, payslip rule, and button approval flow. There's a lot of duplicated code between these two modules but since we're pushing this in a stable version, I believe combining them in a common module is not an option since l10n_sa_hr_payroll_attendance already exists on 19.2. however this can be maybe done in master? task-5940564
Resolved issues and error corrections
The 'Waiting for me' filter in the Sign app was incorrectly displaying all documents instead of filtering those requiring the current user's signature. This update corrects a technical issue related to how the system searches for documents, ensuring the filter functions as intended and only shows relevant documents to users.
Original PR description
When applying the 'Waiting for me' filter in the Sign app, all documents are fetched instead of filtering out documents that do not need the current user's signature. Steps to reproduce: 1) Install…
When applying the 'Waiting for me' filter in the Sign app, all documents are fetched instead of filtering out documents that do not need the current user's signature.
Steps to reproduce:
1) Install sign with demo data
2) Open sign app and remove default filter
3) Add a filter Waiting for me
Observed Behavior:
All the documents are fetched.
Expected Behavior:
Documents should be filtered out to only show those where the current user is a signer.
Root Cause:
Since [commit](https://github.com/odoo/enterprise/pull/76079/changes/8b5048f63f91a38a710b611d17f5cf27fbd0a18a), The `_search_need_my_signature` method returned `NotImplemented` for any operator other than `in` at [1]. While the filter uses `=` at [2]. Following a recent ORM optimization with the mentioned commit, the operators are now standardized as shown
From:
`('need_my_signature', '=', True)]`
To:
`[('need_my_signature', 'in', [True])]`
This means the search method now receives the expected `in` operator. However, the return logic uses a `not in` condition when filtering documents waiting for signature.
As a result, instead of filtering documents, all documents are returned.
[1]- https://github.com/odoo/enterprise/blob/012b42c20b48e8e36298875e3291936e68e72375/sign/models/sign_request.py#L107-L108
[2]- https://github.com/odoo/enterprise/blob/012b42c20b48e8e36298875e3291936e68e72375/sign/views/sign_request_views.xml#L177
Fix:
Corrected the return domain logic to fetch the correct documents.
opw-6026935
Forward-Port-Of: odoo/enterprise#113760This update resolves an issue preventing new users from being created after migrating databases from v18 to v19. The fix ensures the necessary user settings are populated correctly during creation, preventing a 'missing field' error. This improves the reliability of user onboarding for our Enterprise customers.
Original PR description
Steps to reproduce: - Install web_enterprise and im_livechat on v18 - Migrate the database to v19 - Create a new user Issue: - On v18 → v19 migrated databases, creating a new user may fail with a…
Steps to reproduce: - Install web_enterprise and im_livechat on v18 - Migrate the database to v19 - Create a new user Issue: - On v18 → v19 migrated databases, creating a new user may fail with a ValidationError: The operation cannot be completed: Missing required value for the field 'Color Scheme' (color_scheme). Model: 'User Settings' (res.users.settings) - create/update: a mandatory field is not set - delete: another model requires the record being deleted, you can archive it instead <img width="1155" height="286" alt="image" src="https://github.com/user-attachments/assets/57ad515a-c5fd-4826-9a7b-84d70c711af7" /> Cause: - The im_livechat module defines a computed field livechat_lang_ids https://github.com/odoo/odoo/blob/19.0/addons/im_livechat/models/res_users.py#L24 with an inverse method that may run during user creation https://github.com/odoo/odoo/blob/19.0/addons/im_livechat/models/res_users.py#L114 before the res.users.settings record exists. In that case, the inverse method attempts to create the settings record without mandatory defaults. Fix: - By lowering the priority of the res.users.form.color_scheme view, the color_scheme field is loaded earlier, which triggers the proper creation of res.users.settings with default values. This ensures the livechat inverse updates an existing settings record instead of creating an incomplete one. - OPW - 5435731 - UPG - 3794624
This update corrects a UI issue where the `l10n_co_edi_ubl` field in the Units of Measure form was missing its label, causing confusion for users. The change ensures the field is clearly labeled, improving form clarity and usability within the CO Company settings.
Original PR description
Currently, the field `l10n_co_edi_ubl` is displayed without a label in the UoM form, confusing users. **Steps to reproduce:** - Install the `l10n_co_edi` module and switch to the CO Company. -…
Currently, the field `l10n_co_edi_ubl` is displayed without a label in the UoM form, confusing users. **Steps to reproduce:** - Install the `l10n_co_edi` module and switch to the CO Company. - Navigate to Invoicing > Settings. - Enable `Units of Measure & Packagings`. - Open `Units & Packagings` and click `New`. **Observation:** The `l10n_co_edi_ubl` field appears between the `Quantity` label and its corresponding field, but its own label is not visible. <img width="1905" height="324" alt="6180769_before" src="https://github.com/user-attachments/assets/f35c345a-f449-46e4-ad15-6981109fca7a" /> **Root Cause:** The inherited view [1] inserts the field `l10n_co_edi_ubl` before `relative_factor` in the base view [2]. In the base view, `relative_factor` is wrapped inside a `<div>` with a shared label (`Quantity`). Since the new field is inserted inside this structure, it inherits the same layout without having its own label, resulting in the label being hidden. **Fix:** This commit updates the view to ensure that the field `l10n_co_edi_ubl` is properly displayed with its own label, avoiding UI confusion and improving form clarity. **After:** <img width="1907" height="376" alt="6180769_after" src="https://github.com/user-attachments/assets/f96470d3-8df2-4ca4-acf8-f6511a49d725" /> [1]: https://github.com/odoo/enterprise/blob/7b0d07bce92fb4b2cb588344fb0f6e3dd5d94f4a/l10n_co_edi/views/product_uom_views.xml#L4-L13 [2]: https://github.com/odoo/odoo/blob/bae4fa4e0dde2d2e2e4fcdbb968f630c080af818/addons/uom/views/uom_uom_views.xml#L15-L34 opw-6180769 Forward-Port-Of: odoo/enterprise#115933
This update corrects a technical issue within the Odoo Enterprise payroll system for Kenya (l10n_ke_he_payroll) where a duplicate XML ID was causing problems. The fix ensures data integrity and stability by preventing redundant configurations, improving the accuracy of payroll calculations.
Original PR description
This commit avoids duplicated xml_id for `hr.salary.rule` model. In commit https://github.com/odoo/enterprise/commit/a7d51fa2ee8b1af0e807b3e9cb6e313d8885ff67, key `l10n_ke_employees_salary_pension_contribution` (sequence 72) was deleted and added key `l10n_ke_employees_salary_pension_contribution` (sequence 35). In commit https://github.com/odoo/enterprise/commit/c23243be9ca833acea7089defadbe0eaf869051d, key `l10n_ke_employees_salary_pension_contribution` (sequence 72) was added again. Forward-Port-Of: odoo/enterprise#116622 Forward-Port-Of: odoo/enterprise#85723
This update fixes a problem where adding rental products to the cart resulted in an error message about incompatible rental periods. The fix ensures that the system correctly handles rental durations, particularly for products priced by the day, preventing mismatched date calculations and allowing users to add rental products to their carts without issues.
Original PR description
Steps to reproduce: =================== 1. Go to the shop page and use the rental date picker to select a start and end date with hours. 2. Find a rental product configured with "Days" pricing. 3.…
Steps to reproduce: =================== 1. Go to the shop page and use the rental date picker to select a start and end date with hours. 2. Find a rental product configured with "Days" pricing. 3. Add to card directly from the product card 4. Add a rental product from product image that has date type value date 5. Go to that product details page. 6. Click add to cart -> Invalid operation, You cannot mix different rental periods... Cause: ====== When adding a product from the shop list view, the system uses the default start/end dates (from the rental period) exactly as first added. However, the "Add to Cart" logic on the product details page attempts to adapt the selected dates to the product's specific rental unit (e.g., normalizing the time component for 'Day' pricing). This re-calculation creates a timestamp mismatch between the item already in the cart (from the shop view) and the new item being added (from the details page). Solution: ========= The add-to-cart flow has been updated to correctly utilize the default duration values (the globally selected dates) if they exist. opw-5450576
This update fixes an inconsistency in how Odoo calculates rental prices when dealing with time-zoned dates. Previously, calculations were performed in UTC, leading to incorrect pricing discrepancies. Now, the system accurately calculates the duration of rentals based on the specific time zone of the rental start and end dates, ensuring accurate pricing.
Original PR description
Relativedelta on UTC dates or time-zoned dates doesn't return the same result. In order to calculate consistent prices (price for 1 month in December = price for 1 month in January), we need to work…
Relativedelta on UTC dates or time-zoned dates doesn't return the same result. In order to calculate consistent prices (price for 1 month in December = price for 1 month in January), we need to work on time-zoned dates. Example: Consider a website in UTC+1 (Brussels timezone DST off). And a rental from the 01/12/2025 to the 31/12/2025 = by design, from the 01/01/2025 00h00 (start_date) to the 31/12/2025 23h59 (end_date). Converted in UTC for the back-end, we have: from the 30/11/2025 23h00 to the 31/12/2025 22h59. relativedelta(end_date, start_date) = time between the 2 dates is calculated as follow: 30/11/2025 23h00 + 1 month = 30/12/2025 23h00 +23h59 = 31/12/2025 22h59. Time difference = 1 month, 23 hours, 59 minutes. Price = 2 months. Consider a second rental from the 01/01/2026 to the 31/01/2026. 31/12/2025 23h00 + 30 days = 30/01/2026 23h + 23h59 = 31/01/2026 22h59. Time difference = 30 days, 23 hours, 59 minutes. Price = 1 month. opw-5130762 Forward-Port-Of: odoo/enterprise#114086 Forward-Port-Of: odoo/enterprise#98571
This update resolves issues related to errors encountered during the processing of NOTI files in the Be payroll module. The changes ensure accurate data transmission and reporting, preventing potential discrepancies in payroll calculations and tax compliance. This improves the reliability of the Be payroll system.
This update fixes an issue where partners sharing the same VAT number but with low individual turnovers were incorrectly excluded from VAT reports. The change groups partners by VAT number and includes them in the report if their combined turnover exceeds the threshold, ensuring accurate reporting for Belgian businesses. This improves the reliability of VAT data.
Original PR description
When having different partners with the same vat number and their individual turnover values are less than the threshold they were not included in the partner vat listing report even though if the total turnover for their vat number is above the threshold. This commit handles this case by grouping by vat number and if the total turnover for a vat number is above the threshold then it will be shown in the report with another level beneath it to show the partners having this vat number even if their individual turnovers are below the threshold. task-6133010 Forward-Port-Of: odoo/enterprise#116495 Forward-Port-Of: odoo/enterprise#115251
This update resolves an issue where Swedish account numbers were incorrectly imported due to a character encoding mismatch. The fix ensures that account data from SIE files is accurately translated, preventing data errors and ensuring correct financial reporting for Swedish businesses using Odoo.
Original PR description
Issue: Non-ASCII charatcter from sie file were lost on import. Steps to reproduce: - in a Swedish company - import the SIE4 exemple file from sie website: https://sie.se/wp-content/uploads/2024/01/SIE4-Exempelfil-Sample-file-1.zip Current behavior: - The account 1090 is imported as "vriga imm anl tillg" instead of "Övriga imm anl tillg" Expected behavior: - The account 1090 is imported as "Övriga imm anl tillg" Cause: CP437 uses 8 bits to represent data. Ö is \x99. However, file was imported using either UTF-8 or ISO-8859-1, where Ö is \xC396 and \x99 doesn't link to anything. This commit update the test file as it was save in cp437 but read as UTF-8. opw-6167408 Forward-Port-Of: odoo/enterprise#116722
This update corrects a bug where timesheet reports incorrectly included public holidays from other companies. The fix ensures that planned hours are only considered for employees when the holiday is associated with their own company, improving the accuracy of timesheet analysis.
Original PR description
## Steps to reproduce: - Install project_timesheet_forecast module - Create a public holiday in one company - In another company create a planning slot for an employee that overlaps with the holiday - Go to Timesheets/Planning analysis report - Notice the report is not showing planned hours for the employee on the day of the public holiday ## Cause: When filtering the resource_calendar_leaves we don't check for the company so any public holiday in any company will be taken into account even if it doesn't affect the employee ## Fix: Exclude holidays that has different company than the planning slot opw-5027070 Forward-Port-Of: odoo/enterprise#116263
This update fixes a display issue where the number of ECOs listed on a Bill of Materials (BoM) was incorrect. The fix ensures that only ECOs directly associated with the current BoM version are counted, resolving a mismatch in the displayed ECO count. This improves the accuracy of BoM information for production planning.
Original PR description
Steps to Reproduce (Fresh Database): -------------------------------------- 1. Install `Manufacturing` (mrp) and `PLM` (mrp_plm) modules 2. Create a product > New -- Name: "Test Product" > Save 3.…
Steps to Reproduce (Fresh Database):
--------------------------------------
1. Install `Manufacturing` (mrp) and `PLM` (mrp_plm) modules
2. Create a product > New -- Name: "Test Product" > Save
3. Create BoM v1
- Go to Manufacturing > Products > Bills of Materials > New --Product: Test Product
- Add component: any
4. Create and apply ECO 1 on BoM v1
- Go to PLM > ECOs > New-- Product: Test Product | Apply on: Bill of Materials
- BoM: Test Product (v1) > Confirm > Apply Changes
- This creates BoM v2 (previous_bom_id = BoM v1)
5. Create and apply ECO 2 on BoM v2
- Same as step 4 but select BoM v2
- This creates BoM v3 (previous_bom_id = BoM v2)
6. Create a separate unrelated BoM for the same product
- Go to Manufacturing > Bills of Materials > New
- Product: Test Product | Component: "Component B" > Save
7. Create ECO 3 on the separate BoM
- Go to PLM > ECOs > New - Product: Test Product | Apply on: Bill of Materials
- BoM: select the separate BoM from step 6 > Confirm
Observed Bug:
-------------
- Open BoM v3 > ECO(s) stat button shows count = 2
- Click the button > opens 3 records (ECO 3 incorrectly included)
Explain:-
----------
The ECO stat button on the BoM form was showing a mismatched count vs
the actual records opened when clicking it. This happened because
[button_mrp_eco](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L56) was using all keys from [_get_previous_boms](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L67)() as the
domain, which includes BoMs from unrelated lineages of the same product
template, while [_compute_eco_data](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L20) only counts ECOs belonging to the
current BoM's version lineage.
Fixed by filtering the domain to only include BoM IDs whose lineage set
contains the current BoM ID, making the opened records consistent with
the displayed count.
Before Fix
<img width="1901" height="875" alt="image" src="https://github.com/user-attachments/assets/3208aed5-ebd3-47a3-a457-a7d61b7743cb" />
```
In [24]: labo = self.env['mrp.bom'].browse(710)
In [25]: previous_boms_mapping = labo._get_previous_boms()
In [26]: Test = ['&', ('bom_id', 'in', list(previous_boms_mapping.keys())), ('type', '=', 'bom')]
In [27]: Test
Out[27]:
['&',
('bom_id',
'in',
[710,
1991,
2049,
1913,
1840,
1823,
1676,
1759,
1794,
1651,
1604,
1544,
1537,
1527,
1506,
1460,
1265,
1259,
1196,
1221,
1223,
1060,
1029,
960,
858,
850,
791,
739,
723,
698]),
('type', '=', 'bom')]
```
With My Fix
<img width="1824" height="947" alt="image" src="https://github.com/user-attachments/assets/0d68fdbc-7e42-4ce4-a326-2fb030ba1d06" />
```
In [15]: labo = self.env['mrp.bom'].browse(710)
In [16]: previous_boms_mapping = labo._get_previous_boms()
In [17]: previous_boms_mapping
Out[17]:
{710: {710},
1991: set(),
2049: set(),
1913: set(),
1840: set(),
1823: set(),
1676: set(),
1759: set(),
1794: set(),
1651: set(),
1604: set(),
1544: set(),
1537: set(),
1527: set(),
1506: set(),
1460: set(),
1265: set(),
1259: set(),
1196: set(),
1221: set(),
1223: set(),
1060: set(),
1029: set(),
960: set(),
858: set(),
850: set(),
791: set(),
739: set(),
723: set(),
698: {710}}
In [18]: relevant_bom_ids = [
...: bom_id
...: for bom_id, current_bom_set in previous_boms_mapping.items()
...: if labo.id in current_bom_set
...: ]
In [19]: relevant_bom_ids
Out[19]: [710, 698]
```
Task-6065020This update fixes inconsistencies and errors related to timesheet timers within the Odoo Enterprise system. Specifically, the timer display was inaccurate and could reset or run backward, and multiple timers could run simultaneously. This fix ensures timers function correctly and reliably.
Original PR description
## Issues When starting a timer from a task within a project, the timer appears in two locations: the page header, and the task's *Timesheets* tab. The latter does not behave as expected: when…
## Issues When starting a timer from a task within a project, the timer appears in two locations: the page header, and the task's *Timesheets* tab. The latter does not behave as expected: when opening the *Timesheets* tab, the timer resets to 00:00, and if the timer was started more than a minute earlier, it begins counting down (00:00, then -00:59, and so on). (**I1**) A second issue (**I2**), introduced at the same time, is that two timers can run simultaneously if the database is reloaded while a timer is active. A third issue (**I3**) happens after starting and stopping a timer from the Project app: the timer seems to still be running in the Timesheet app. ## Steps to reproduce 1. Install *Timesheets* (`timesheet_grid`) 2. Create a Project P and a Task T 3. Start the timer for Task T, wait a few seconds, then open the *Timesheets* tab 4. **The timer from the _Timesheets_ tab does not match the one on top of the page** 5. Wait for the timer in the header to reach 00:01:00, then open the *Timesheets* tab again 6. **The timer is going backward** For the second issue (**I2**), after executing the steps above: 7. Do not stop the timer, but stop the database and start it again 8. Create a new Project P2 and a Task T2 9. Start the timer for Task T2 10. **The timer in the header blinks between the timer from T1 and the newly started timer for T2**  For the third issue (**I3**): 1. In the project app, (create a project and a task and) start then stop a timer. Log the time 2. Open the timesheet app 3. **A timer is running** ## Cause The issues are introduced by the following commit: https://github.com/odoo/enterprise/commit/f4c7115fdf. The commit aimed to resolve an issue in which timers for sample data would start automatically, and the *Stop* button would throw an error. The issue was addressed by updating the condition that defines the `timerRunning` variable, which controls whether the *Stop* button in the Timesheets app is displayed. https://github.com/odoo/enterprise/blob/ac186aa71cd7e1b80b307ea12c7eaca246afd649/timesheet_grid/static/src/components/timesheet_display_timer/timesheet_display_timer.js#L57-L64 Issue **I1** is a side effect of this change in the Project app, where the `timerRunning` variable is evaluated to `true`, causing the timer to be displayed when it should not. The multiple timers running simultaneously (**I2**) stems from the `timerRunning` variable being initiated to false by default in the props. https://github.com/odoo/enterprise/blob/64f813dab727d76286c1ff6c80c08cb6a6737b49/timesheet_grid/static/src/components/timesheet_display_timer/timesheet_display_timer.js#L47-L50 The *Stop* button appearing after logging a task (**I3**) stems from the condition of the patch using `is_timer_running` over `timer_start`. https://github.com/odoo/enterprise/blob/64f813dab727d76286c1ff6c80c08cb6a6737b49/timesheet_grid/static/src/hooks/sample_server_patch.js#L9-L15 ## Fix This commit reverts the problematic segments from the previous commit. opw-5870756 opw-5879176 opw-5961764
This update corrects a reporting issue where employees with overlapping flexible shifts were shown with double the hours worked. The fix ensures that the attendance analysis accurately reflects the actual planned time for shifts, regardless of overlap. This improves the accuracy of time tracking data.
Original PR description
__ ## Short functional explanation of the error When for an employee with a Flexible schedule, we set a shift overlapping on two days. The attendance report displays twice the worked hours. ##…
__ ## Short functional explanation of the error When for an employee with a Flexible schedule, we set a shift overlapping on two days. The attendance report displays twice the worked hours. ## Reproduction Steps 1. Create an employee with a flexible schedule and with Work Entry Source set at Planning. 2. Go to Planning. Create a Planning Slot for this employee from 9 pm to 5 am, then Send and Publish it. 3. Click on the Reporting tab > Planning / Attendance Analysis. ### Expected behavior The total for this Month for this employee under the Planned Time field should be equal to 8 hours, which is the duration of the planning slot. ### Unexpected behavior The total for this Month for this employee under the Planned Time field is equal to 16 hours. ## Origin of the issue This report is a view, for which the SQL is defined starting this line: https://github.com/odoo/enterprise/blob/7362f1c5be7f496bdab660ed8fad37a6dd283616/planning_attendance/report/planning_attendance_analysis_report.py#L27 the issue stems from here: https://github.com/odoo/enterprise/blob/7362f1c5be7f496bdab660ed8fad37a6dd283616/planning_attendance/report/planning_attendance_analysis_report.py#L56 where we don't select distinct the planning entries based on their ID. As our shift overlaps 2 days, there will be only one entry for this shift in the `planning_slot`, but because of that, it will be duplicated. __ opw-6146052
This update resolves an issue where invoice section lines were misaligned when prices were hidden and the country of origin was displayed. The fix ensures that tax and amount information within hidden sections are correctly formatted, improving invoice presentation and accuracy. This change impacts the visual consistency of invoices generated with the account_intrastat module.
Original PR description
The content of an invoice's section lines is not aligned with the columns when the prices of the section are hidden and the country of origin is displayed in the invoice Steps to reproduce: 1.…
The content of an invoice's section lines is not aligned with the columns when the prices of the section are hidden and the country of origin is displayed in the invoice Steps to reproduce: 1. Install account_intrastat module 2. Go to Invoicing > Customers > Products and create a new product with name "test" and in the Accounting tab, set the Country of Origin to Afghanistan 3. Go to Invoicing > Customers > Customers and change Acme Corporation's country to United Kingdom 4. Go to Invoicing > Customers > Invoices and create a new invoice for partner Acme Corporation, add a section line and in that section, add product "test" 5. Click on the three dots at the end of the section line and click on Hide Prices 6. Confirm the invoice and print it 7. The content of the section line in the invoice pdf are not aligned (the tax is in column Unit Price and the amount is in column Taxes) Issue: When a section is hidden, no column is added in the section to display the origin, resulting in a misalignment of the tax and the amount of the section Solution: Add a column for the origin country in hidden section lines and add the origin country in product lines of `_get_child_lines` opw-6147929
This update simplifies a confusing error message related to GST registrations, specifically for businesses using multiple GST numbers within the same organization. The new message clearly asks users to verify the connection between their GST username and number, reducing support requests and inaccurate reports. This change improves the user experience and streamlines troubleshooting.
Original PR description
Users operating with multiple GST registrations (GST-wise branches/companies) could encounter a misleading error when the GST username belonged to a different GST number within the same organization. Previously, the system raised an error directly received from the server: [AUTH4041] Invalid Parameter state-cd in request header This message was confusing and led to unnecessary support tickets and false reports, as the issue was actually a mismatch between GST username and number. The error message has been updated to be more explicit and user-friendly: Please confirm that <gst_username> is associated with <gst_number>. Additionally, refactored duplicated logic by extracting the common code into a single helper function and reusing it across all occurrences. task-6041510
This update resolves an issue where creating two overtime shifts on a Saturday (ending at midnight) would trigger an error. The fix addresses a timing discrepancy in how overtime start and end times are calculated, preventing the 'Expected singleton' error. This ensures overtime is correctly recorded for employees working multiple shifts on non-working days.
Original PR description
__ ## Short functional explanation of the error When we create 2 shifts for the same day for an employee, on a non-working day for their schedule. When trying to create the second one after setting…
__ ## Short functional explanation of the error When we create 2 shifts for the same day for an employee, on a non-working day for their schedule. When trying to create the second one after setting the end date to midnight, we get the error: `ValueError: Expected singleton: hr.attendance.overtime.line(2, 3)` ## Reproduction Steps 1. Create an Employee. In the Payroll tab, Make sure they have an active contract. Set their Working Hours to a fixed schedule, where they have saturdays as non-working days. In the Settings tab, set an Overtime Ruleset. 2. Click on the overtime ruleset. Then, for each rule, under Action, set the Work Entry Type To Use as Overtime Hours. 3. Go to Attendances. In Configuration > Settings, under Extra Hours, set the Extra Hours Validation as Approved By Manager. 4. Create an attendance for your Employee on a Saturday, from 12h to 18h. 5. Create a second attendance for your Employee on that same Saturday, from 18h to 00h00. Try to Save. Note: the timezone of your computer, the working schedule and the employee should be set at Brussels time. ### Expected behavior The Overtime is registered. ### Unexpected behavior An error occurs: `ValueError: Expected singleton: hr.attendance.overtime.line(2, 3)` ## Origin of the issue The end time of the overtime is defined as follows: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L54-L56 However, in the case where our shift ends after the computed end of the day (in our case, the end time of the shift is 00:00:00 and the end of the day is set at 23:59:59), it creates some problems. The end time of the overtime is set 1 second too early. Later we compute the start time of the overtime as follows: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L57 Thus, the time start of the overtime is also set one second too early. As our second shift starts right after the first one, after the execution of this code, we will get a second shift that starts before the end of the first one. Then, we add these values in a list: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L59 which will contain overlapping timeframes, and with which we create an Interval: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L60 But when we create an Interval with overlapping timeframes, we obtain only one interval as the timeframes are merged. https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L173 As a result, `overtime_intervals` will contain only one time frame with 2 different corresponding overtimes, which causes a singleton error when reaching: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L179 __ opw-6096454
This update fixes a minor visual issue in the Odoo Enterprise PDF Manager by removing an unnecessary styling class from action names. This ensures action names are displayed correctly and professionally, improving the user experience. The change is a simple refinement of the existing design.
Original PR description
Previously, pdf_manager actions used class "text-uppercase". Action names looked awkward. In this commit, we remove the class and properly display action names. task-6159317 Forward-Port-Of: odoo/enterprise#116382
This update resolves an issue where managers weren't seeing all their direct reports in the 'My Team' filter. The fix utilizes a more accurate domain filter ('is_subordinate') to ensure the filter correctly identifies and displays all subordinates within the management hierarchy. This improves reporting accuracy and manager oversight.
Original PR description
*: hr_attendance, hr_expense, hr_timesheet_attendance Before this commit: If A is a manager of B and B is a manager of C, A cannot see C under My Team filter. Fix: Use is_subordinate. task-6204754
This update fixes an issue where flexible employee time off wasn't accurately displayed in the attendance calendar. Now, the calendar correctly shows hours from midnight to 11 PM grayed out for flexible time off, ensuring accurate representation of absences across different views (day, week, month).
Original PR description
__ ## Short functional explanation of the error When setting a time off for an employee who has a flexible schedule, in the attendance app, on the calendar with the 'days' view. We can see that the…
__ ## Short functional explanation of the error When setting a time off for an employee who has a flexible schedule, in the attendance app, on the calendar with the 'days' view. We can see that the hours are grayed out from 8 hours to 16 hours. However, according to this message: https://www.odoo.com/mail/message/1027495005 "[...] the entire day of absence might not be represented as such, which is an issue (for example if a flexible employee with 8h/day takes a day off, the duration of the leave should be 1 day/8 hours but on the gantt view everything should be gray from midnight to midnight)". Moreover, when we select the Week or Month view on the calendar, the day off isn't grayed out. This comes from the fact that, for a flexible schedule, we consider that any time of the day can be a working hour; and we only grey out days in the calendar where no hour has been worked at all. Hence, the hours considered during a flexible day off should be from midnight to 23:59:59. ## Reproduction Steps 1. Go to an employee's profile and set their schedule to flexible. 2. Create a time off of a one-day duration for this employee. 3. Go to the attendance app and see the calendar. ### Expected behavior When clicking on the Day view, all hours from midnight to 11pm should be grayed out. When clicking on the Week/month view, the day of the time off should be grayed out. ### Unexpected behavior When clicking on the Day view, hours from 8am to 4pm are grayed out. When clicking on the Week/month view, the day of the time off isn't grayed out. ## Origin of the issue First, we only consider the leave if the resource is fully flexible, i.e if the employee has no working calendar set: https://github.com/odoo/odoo/blob/394a30f8a2814d460cfe220b5017e7ac95d8cddc/addons/resource/models/resource_calendar.py#L546 However, if the schedule of the employee is flexible, the leave resource isn't considered as fully flexible, thus leading us to a leave from 8 am to 4 pm. Moreover, when processing flexible leaves, we return the unavailable intervals with the timezone of the employee: https://github.com/odoo/odoo/blob/394a30f8a2814d460cfe220b5017e7ac95d8cddc/addons/resource/models/resource_calendar.py#L589-L592 Whereas when we process fixed leaves, we return the unavailable intervals under utc: https://github.com/odoo/odoo/blob/394a30f8a2814d460cfe220b5017e7ac95d8cddc/addons/resource/models/resource_calendar.py#L597-L601 This leads us to display problems: when the user is under European/ Brussels time in summer, the leave starts at 2 am and ends at 11pm, instead of starting at midnight. Note: after discussion with AJU, it has been agreed that the behavior should be the same on the Planning app. __ opw-6030212
This update fixes a bug that occurred when users tried to reschedule marketing activities within a running campaign. The change prevents errors related to activity hierarchy updates, ensuring campaigns run smoothly and avoiding disruptions. It prioritizes stability and prevents user errors during campaign management.
Original PR description
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the…
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save - An error will be thrown **Issue:** The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: `base_dt_str = trace.parent_id.schedule_date or trace.parent_id.mailing_trace_ids[0].write_date or trace.participant_id.create_date` **Fix:** Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-5362978
This update corrects a bug where unreconciling a payment from a recurring invoice would automatically generate a new draft invoice for the following period. The fix adds a context flag to prevent this behavior, ensuring invoices are created correctly after reconciliation. This improves invoice management and avoids unnecessary invoice generation.
Original PR description
Issue: Unreconciling a payment in a batch payment from a recurring invoice will cause an invoice for the next recurring period to be generated Steps to reproduce: 1. Create and confirm a monthly…
Issue: Unreconciling a payment in a batch payment from a recurring invoice will cause an invoice for the next recurring period to be generated Steps to reproduce: 1. Create and confirm a monthly recurring invoice 2. Create a payment for the invoice 3. Create a batch payment and add the payment created in step 2 then validate it 4. Create a bank statement line and reconcile it with the batch payment created in step 3 5. Unreconcile the payment from the invoice from the invoice form view 6. Notice that a draft invoice for the next month’s recurring invoice is created Cause: When unreconciling the payment from the invoice via the invoice form view, the method “delete_reconciled_line” is called. In the “account_accountant_batch_payment” override of that method, it will reset the invoice back to draft and repost it. However, when posting a recurring invoice, the default behavior is to create the invoice for the next recurrence period Solution: Adding a new context flag called “skip_recurring_copy” will prevent the next period’s recurring invoice from being generated when invoices are posted through “delete_reconciled_line” Community PR: https://github.com/odoo/odoo/pull/263991 opw-6158881
This update fixes an error in the Austrian localization reports by accurately reflecting the official VAT return and EC sales list filing deadlines. Previously, a fixed 15-day rule was used, which didn't align with Austrian regulations. This change ensures accurate reporting and compliance.
Original PR description
**[FIX] l10n_at_reports: correct Austrian return deadlines** The Austrian localization used a fixed `15 days` rule for both VAT returns and EC sales lists. This does not match the filing deadlines: the VAT return is due on the 15th day of the second following month while the EC sales list is due by the end of the following month (sources below). This fix replaces the hardcoded day offset with month-based deadline computation sources: https://www.usp.gv.at/themen/steuern-finanzen/umsatzsteuer-ueberblick/weitere-informationen-zur-umsatzsteuer/umsaetze-mit-auslandsbezug/zusammenfassende-meldung-zm.html https://www.usp.gv.at/en/themen/steuern-finanzen/umsatzsteuer-ueberblick/weitere-informationen-zur-umsatzsteuer/entstehen-der-steuerschuld-und-pflichten/umsatzsteuervoranmeldung.html opw-6147343
This update resolves an issue where rapid actions in the account reports module were creating duplicate records in the database. The fix prevents multiple simultaneous processes from attempting to create the same check, ensuring data integrity. This improves the stability and performance of the account reporting feature.
Original PR description
Issue -------------- When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to…
Issue
--------------
When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to the server. This created a race condition that resulted in duplicate `account.return.check` records being generated in the database.
steps to reproduce demonstrated in video: https://drive.google.com/file/d/1-A0ZHdYGdv-UL0dqClqK6Kos_iVXoZai/view?usp=sharing
When this happen the `runAllReturnChecks` method fires parallel RPC calls to [`refresh_checks`](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1974-L1992) on the server. In the case of instant multiple RPC calls, parallel threads are dispatched which causes the data preparation stage to run simultaneously.
Because both threads run in parallel, Thread 2 runs its [preparation and existing ](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1986-L1987 )check mechanism before Thread 1 has reached the actual `create()` function [trigger](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1998-L1999). Consequently, Thread 2's existence check fails to find the record (since Thread 1 hasn't committed it to the database yet), and it considers the record eligible for creation—even though the exact same record is already prepared for creation by Thread 1. This race condition leads to duplicate `account.return.check` records.
Logs to demonstrate the thread execution:
--------
```python
2026-04-16 08:30:51,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.000 0.002
2026-04-16 08:30:51,662 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.report/dispatch_report_action#account.report.dispatch_report_action HTTP/1.0" 200 - 17 0.006 0.012
2026-04-16 08:30:51,847 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 26 0.009 0.025
2026-04-16 08:30:52,099 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 95 0.029 0.064
2026-04-16 08:30:52,320 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.004
THREAD NAME: odoo.service.http.request.137360481711808 Thread ID: 137360481711808
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360481711808 -------------DATA PREPARING STAGE------------
Thread ID: 137360481711808
Thread ID: 137360481711808 RECORD EXISTING CHECK: None
2026-04-16 08:30:53,842 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:53] "GET /odoo/tax-report/tax-return?debug=1 HTTP/1.0" 200 - 29 0.020 0.021
2026-04-16 08:30:54,066 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/load_menus HTTP/1.0" 200 - 4 0.002 0.009
2026-04-16 08:30:54,351 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/manifest.webmanifest HTTP/1.0" 200 - 6 0.003 0.005
2026-04-16 08:30:54,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/translations?hash=bb5aa713d587cc7dd07b13d1d7efc2c525517e99&lang=en_US HTTP/1.0" 200 - 1 0.000 0.002
2026-04-16 08:30:54,586 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/bundle/web_tour.interactive?lang=en_US&debug=1 HTTP/1.0" 200 - 1 0.001 0.003
2026-04-16 08:30:54,640 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/action/load_breadcrumbs HTTP/1.0" 200 - 7 0.003 0.006
2026-04-16 08:30:54,710 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/ir.http/lazy_session_info#ir.http.lazy_session_info HTTP/1.0" 200 - 2 0.001 0.004
2026-04-16 08:30:54,753 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /bus/websocket_worker_bundle?v=19.0-2 HTTP/1.0" 304 - 3 0.004 0.006
2026-04-16 08:30:54,766 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/image?model=res.users&field=avatar_128&id=2 HTTP/1.0" 304 - 9 0.012 0.013
2026-04-16 08:30:54,777 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /mail/data HTTP/1.0" 200 - 34 0.034 0.020
2026-04-16 08:30:54,824 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 3 0.001 0.010
2026-04-16 08:30:54,934 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 88 0.029 0.051
2026-04-16 08:30:55,107 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.005
THREAD NAME: odoo.service.http.request.137360513177280 Thread ID: 137360513177280
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360513177280 -------------DATA PREPARING STAGE------------
Thread ID: 137360513177280
Thread ID: 137360513177280 RECORD EXISTING CHECK: None
2026-04-16 08:30:55,589 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.006
2026-04-16 08:30:56,702 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:56] "GET /web/service-worker.js HTTP/1.0" 200 - 1 0.000 0.003
2026-04-16 08:30:58,893 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:58] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.006 0.023
2026-04-16 08:31:05,296 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:05] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.002
Thread ID: 137360481711808 DATA to_create: 168
Thread ID: 137360481711808 done process create
2026-04-16 08:31:10,132 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:10] "POST /web/dataset/call_kw/account.return/refresh_checks#account.return.refresh_checks HTTP/1.0" 200 - 513 11.611 6.039
Thread ID: 137360513177280 DATA to_create: 168
Thread ID: 137360513177280 done process create
```
- OPW: 5917459This update resolves a problem where the tour worksheet wasn't being saved correctly due to a timing issue. The fix adds a delay to ensure the HTML field is fully loaded before the worksheet is saved, preventing the random failure. This ensures tour worksheets are reliably saved.
Original PR description
Currently, the test tour loads too quickly, so the worksheet is not saved properly. The issue happens because the worksheet is not yet visible on the portal view side. Therefore, i added an extra step to wait for the HTML field to load, giving enough time for the worksheet to be fully loaded. runbot error-242479
This update resolves a technical issue that prevented the system from correctly identifying project documents when a project lacked a designated folder. The fix ensures the system functions reliably regardless of whether a folder is specified, improving the stability of project document retrieval.
Original PR description
The `_compute_documents()` method was expecting that the `documents_folder_id` field was always set.
However, the field is not required and can be empty.
This is not an issue if the compute is called on a single record, but when called on a recordset with :
- A project with related folder with at least one document
- A project with `documents_folder_id` empty The compute will fail because it calls `startswith()` with a parameter that is `False`.
```python
File "/home/odoo/src/enterprise/19.0/documents_project/models/project_project.py", line 50, in <lambda>
document_ids = documents.filtered(lambda doc: doc.parent_path.startswith(project.documents_folder_id.parent_path))
TypeError: startswith first arg must be str or a tuple of str, not bool
```
Solution:
Check for project-related documents only if the dedicated folder is set.