Wednesday, March 25, 2026
47 changes · saas-19.1
Resolved issues and error corrections
This update enhances payroll calculations, particularly for employees with changing contracts during a pay period. By grouping payslips and considering previously calculated amounts, the system now accurately avoids overpaying contributions and allowances, especially in Hong Kong. This ensures greater payroll precision and compliance.
Original PR description
This commit aims to provide better support for contract changes that happen in the middle of a pay period. It has a few impacting changes, notably: 1) Payslip calculation sequencing As of now, all…
This commit aims to provide better support for contract changes that happen in the middle of a pay period. It has a few impacting changes, notably: 1) Payslip calculation sequencing As of now, all payslips of a same payrun have their line calculated all at once. While this is better for performances, it has a negative effect when a single employee has multiple payslips in the same payrun. In such cases, we may want or need for the payslips to know what was already calculated in the same payrun to avoid overpaying contributions or allowances that have caps. To solve this issue, we now group payslips by employee, sort them chronologically, and evaluate them in horizontal "layers": - Layer 1: Computes the 1st payslip for ALL employees simultaneously. - Layer 2: Computes the 2nd payslip for the subset of employees who have one, etc 2) More tools in HK payroll to support these cases The payslip rules now have a `l10n_hk_payrun_totals` dict that contains the total amount already reported in previous payslips of a same payruns for a selection of rules that needs it. We also provides a `worked_days_prorata_rate` which gives the ratio of worked days vs unworked days in a month for cases where we need to adjust amounts based on that ratio. 3) Rule updates The last part of the fix requires some updates in a few rules that are fixed amounts/not based on the wage and ends up being counted double in our use case. These rules will now take into account already computed amounts as said above to avoid going over the limit. In most cases it will only affect that specific use case, with a small exception for fixed mpf voluntary contributions, which have been updated to be prorated based on the worked days in the month. Forward-Port-Of: odoo/enterprise#111570
This update resolves an issue where the AEAT tax report file was being rejected due to an incorrect date format. The fix ensures the file includes a default numeric date ('00000000') when the procuration date is not specified, meeting AEAT's requirements and allowing successful file uploads.
Original PR description
Steps to reproduce: - Install the `l10n_es_reports` module and switch to the `ES company`. - Go to Invoices and create an invoice with taxes, then confirm it. - Navigate to Accounting > Reporting >…
Steps to reproduce: - Install the `l10n_es_reports` module and switch to the `ES company`. - Go to Invoices and create an invoice with taxes, then confirm it. - Navigate to Accounting > Reporting > Tax Report. - From the smart button, select `Report: Tax Report (Mod 390) (ES)` and choose the year as `This Financial Year`. - Download the `BOE` file using the dropdown and fill the wizard fields (e.g., Natural Person – Name: Test, Principal activity: Test, Activity Code: 12345). - Upload the generated .txt file to the AEAT portal. (AEAT credentials are required) **Observation:** AEAT rejects the file with: `Caracteres no válidos '4. Representante - Personas Jurídicas - Represent. 1 - Fecha Poder (DDMMAAAA)'` **Root cause:** At [1], when `judicial_person_procuration_date` is `false`, an empty string is written to the BOE file, resulting in blank spaces in the exported file. This does not comply with AEAT’s required numeric format and causes the file to be rejected. **Fix:** This commit ensures the file contains '00000000' when `judicial_person_procuration_date` is false, complying with AEAT numeric format requirements. [1]: https://github.com/odoo/enterprise/blob/45d3a537c3b2eaccee425d959e89d26229e376cd/l10n_es_reports/models/aeat_tax_reports.py#L1696 opw-5995290 Forward-Port-Of: odoo/enterprise#109652
This update resolves two bugs preventing new employee creation in the Belgian payroll module. The first issue involved duplicate record creation due to a mail activity trigger. The second addressed a problem where activities were attempted before the employee record was fully saved. These fixes ensure reliable employee onboarding within the Belgian company setup.
Original PR description
First bug: Steps: - Switch to belgian company - Create new employee - Set contract start date - Click save manually -> boom Cause: in _trigger_l10n_be_next_activities, we create a new mail activity for the created employee which is already created in the default create function leading to duplicate follower records. Fix: in the super.create, pass the context variable mail_create_nosubscribe=True to disable adding the current user as a follower again to the same record Second bug: Steps: - Switch to belgian company - Create new employee - Set contract date - Add a wage then click anywhere -> boom Cause: _trigger_l10n_be_next_activities is called before the record is saved, hence trying to link to a null object Fix: check if the record is created before working on the activities Forward-Port-Of: odoo/enterprise#111780 Forward-Port-Of: odoo/enterprise#109799
This update fixes a potential issue where a user could indirectly change an employee's work email through contract settings. Previously, linking an employee to a user allowed for unintended email modifications. Now, the system ensures the work_email remains consistent if the employee is associated with a user, improving data integrity.
Original PR description
Due to https://github.com/odoo/enterprise/pull/106974,the employee's work_email may be reset to False when creating or updating an offer. This behavior is acceptable if the employee does not have a linked user. However, if the employee is linked to a user, resetting work_email can allow a user to indirectly modify their own work_email through salary confi. To prevent this, we now ensure that work_email never changes if employee has a user linked to it. Steps to reproduce: - Hire an applicant from Recruitment (the employee has no work_email). - Set a random work_email and create a user for the employee. - Open the hired applicant and create a new offer to update the contract. - work_email should not be modified, even after new contract. task: 6033382 Forward-Port-Of: odoo/enterprise#110810
A technical issue causing a tour to fail has been resolved. This change adjusted the company referenced within the tour, addressing a previously unreplicable access rights problem. The fix ensures the tour now runs correctly, improving the user experience.
Original PR description
Before this commit, the tour `hr_referral_utm_campaign_tour` was failing because of some weird access rights issues. The issue did not seem to be reproducible in local with similar condition. This commit changes the company used in that tour runbot issue 239152
This update significantly speeds up the bank reconciliation view, particularly when dealing with large volumes of financial data. The previous freezing issue was caused by redundant calculations, which has now been resolved by optimizing the system's performance. This results in a much faster and more responsive user experience.
Original PR description
The bank reconciliation view was freezing on large databases (50k+ invoices, 90k+ journal entries), making it impossible to expand lines, filter, or interact with the view in any way. Attempting to…
The bank reconciliation view was freezing on large databases (50k+ invoices, 90k+ journal entries), making it impossible to expand lines, filter, or interact with the view in any way. Attempting to open a line would sometimes result in a timeout. **Root cause:** The `reconciledLineName` getter was called multiple times per render cycle — once in `t-foreach` and again in the `t-if` condition. Since OWL re-evaluates the template on every reactive state change, this created an O(n×m) computation loop (n renders × m statement lines) that overwhelmed the browser. **Fix:** Cache the result in OWL reactive state via a dedicated `_computeReconciledLineName()` method, called once on setup and reactively via `useEffect` when `line_ids.records` changes. The template is updated to store `Object.entries(reconciledLineName)` in a `t-set` variable to avoid rebuilding the array on every iteration. | Metric | Before | After | |---|---|---| | Longest blocking task | 15 091 ms | 5 118 ms | | Total blocking time | 74 147 ms | 22 481 ms | | Avg. click response | 2 163 ms | 28 ms | | Max click response | 14 305 ms | 222 ms | | Total microtasks executed | 9 917 | 32 484 | opw-5879798 Forward-Port-Of: odoo/enterprise#107135
This update corrects an issue preventing Romanian SAFT reports from passing validation. The team restored a key data element and used a sanitized bank account number, ensuring compliance with Romanian tax regulations. This resolves a technical problem impacting report accuracy and preventing errors.
Original PR description
Problem --------- In odoo/odoo#184131 and odoo/enterprise#72206, UOM's categories where removed. Along side the removal, the Description tag in the Romanian SAFT UOM table tag. However, without this node, the SAFT is flagged as invalid by validator in Romanian. Furthermore, in the RO SAF-T, we use the bank account number and not the sanitized one, which may lead to some spaces in the document. Spaces that are not accepted either. Solution --------- Add back the Description node and use the UOM name instead of category. Use the sanitized account number. opw-5956277 Forward-Port-Of: odoo/enterprise#111664
This update resolves an issue where users could inadvertently create 'Requested Documents' instead of folders when syncing Peppol documents through the accounting settings. To avoid a confusing 'My Drive' folder creation, the ability to create or edit documents within the settings has been disabled, aligning with a previous fix.
Original PR description
Before this commit a user could create or edit a folder in the accounting settings to sync peppol documents to. The issue was that this created a 'Requested Document' instead of a folder. This commit removes the possibility to create or edit documents through the settings. An alternative would have been to add the contex to create a Folder instead of a Requested Document, however another problem then arises: the folder is created in My Drive, which does not make any functional sense. Therefore we are disabling creation and edit. This is the same logic applied in 8ada2a4f. Task-6063736 Forward-Port-Of: odoo/enterprise#111761
This update resolves a problem where invoices with discounts and decimal values (over 2 decimals) were failing to send to ARCA for electronic invoicing. The fix uses a simplified unit price to calculate discounts, ensuring accurate decimal calculations and successful invoice transmission. This improves the reliability of our ARCA integration.
Original PR description
After changes made in Odoo of how the decimal precision works some of the code we use to prepare the data to create EDI invoices now fails. We already adapt the code to fix the data depending of the expected webserive format but we miss a case related to when invovice has discounts. The problem is that any invoice with lines that has more than 2 decimals and also have a discount will fail when trying send it to ARCA because the computed amount has differences in the decimals. Now we use the truncated unit price to compute the discount instead of the full amount with decimal of the `line.price_unit` value. Forward-Port-Of: odoo/enterprise#110706
This update corrects a rounding error in the US payslip PDF that was causing incorrect overtime rates for very small work durations (like seconds). The fix now calculates the rate directly from the work entry, ensuring accurate overtime pay is displayed. This improves the precision of US payroll reporting.
Original PR description
The Rate column on the US payslip PDF is computed as amount / hours, but amount is a Monetary field rounded to 2 decimals. For small hour values (e.g. seconds from the attendance app), the rounding error causes us to compute the wrong rate. For example, working 6 seconds of overtime at an hourly rate of $26 with a 1.5x overtime multiplier results in this calculation: $26/hour * 1.5 * 0.00166667 hour = $0.065 ≈ $0.06 We then attempted to calculate the rate in reverse for the PDF: $0.06 / 0.00166667 hour = $35.9999 ≈ $36.00 Because of the rounding that happened, it doesn't show the expected $39/hour rate ($26 * 1.5). We now compute the rate directly from hourly_wage * multiplier on the work entry type instead. This is a manual forward-port of the work in Odoo 18 [1], to instead use the new amount_rate field on hr.work.entry.type instead. task-6052711 [1] https://github.com/odoo/enterprise/pull/111540 Forward-Port-Of: odoo/enterprise#111733
A recent update to Odoo Enterprise prevented the deletion of newly created approval rules within the Studio interface. This was caused by the way the system managed updates to these rules, leading to data inconsistencies. This fix ensures that these rules are properly managed, preventing data loss during updates.
Original PR description
Server and automated actions created by the ORM for the purpose of revoking approval rights are created without `noupdate=True` which leads to said records being removed by the ORM becuase of not being found in the source. Such records created on the fly should have `noupdate=True` to prevent that from happening. This bug can be reproduced by going to Settings > Technical > User Interface > Studio Approval Rules and creating a new record from there and updating `web_studio`. The update will drop the record from the database. Issue originally detected in the upgrade process from 18.0 to 19.0. This fix will be complemented by an upgrade script that fixes erronous records. Forward-Port-Of: odoo/enterprise#110065
This update fixes a technical issue that caused a traceback error when generating the 281.10 report for Belgian payroll. The fix ensures the report correctly identifies payslips without the Fleet module, preventing errors and improving report generation reliability. This resolves a disruption in generating key financial reports.
Original PR description
[FIX] l10n_be_payroll: fix traceback in 281.10 sheets
Bug reproduction: Go to any version>=17.0 -> select belgium company -> install only belgium payroll (don't install fleet one) -> fill in niss, certification level, address, Time in R&D -> generate payslip and confirm it -> try to generate 281.10 report -> traceback
Bug cause:
1 - In traceback it was saying payslip doesn't have vehicle_id, in 281.10 sheet preparation (in function _get_atn_nature), there is a term like that
2 - Payslip doesn't have it because fleet module is not there.
Bug solution:
1 - Instead of checking the payslip has vehicle like that, we calculated it by using paylsip line_ids
2 - If the code ATN.CAR is there and the total of it is not zero, which means this payslip has a vehicle indeed.
task - 6037206
Forward-Port-Of: odoo/enterprise#111506
Forward-Port-Of: odoo/enterprise#110860This update fixes a bug preventing the proper synchronization of XML documents (like e-invoices) related to accounting moves. Previously, invoices created from various sources didn't consistently attach the original XML files to the Documents app. This change ensures all XML files are now correctly linked, improving document management and compliance.
Original PR description
[FIX] documents_account: sync all XML documents for account moves Before this commit, the synchronization between accounting attachments and the Documents app was incomplete regarding XML files…
[FIX] documents_account: sync all XML documents for account moves Before this commit, the synchronization between accounting attachments and the Documents app was incomplete regarding XML files (e.g., e-invoices, Peppol). This caused several specific issues: 1. When creating an invoice via the Accounting upload interface, only the generated PDF was synced to the correct Documents folder, leaving the original XML file unsynced. 2. When creating an invoice from an existing file in the Documents app (via server action), the system correctly synced the generated PDF, but failed to move or sync the original XML source file to the target folder. 3. When receiving vendor bills via Peppol or other EDI networks, the proxy attaches the fetched XML to the `account.move` via an `ir.attachment` write. Because this bypassed the existing sync filters, the Peppol XMLs were never pushed to the Documents app. This commit updates the `ir.attachment` logic in both `create` and `write`. It ensures that whenever an XML file (mimetype `application/xml` or `text/xml`) is attached to an `account.move`—regardless of the move type or whether it was uploaded manually or fetched via EDI—the document synchronization logic is triggered, properly linking and filing the XML alongside the PDF. Task-5909245 Task-5917535 Forward-Port-Of: odoo/enterprise#106574
This update fixes an issue where project budget totals were incorrectly summing expenses and revenue. The code was adjusted to properly differentiate between expense and revenue budgets when calculating totals, ensuring accurate reporting of project financial status. This improves the reliability of project cost tracking.
Original PR description
### Steps to reproduce: - Create a billable project - Create two budgets one expense and the other revenue or both each for 100$ - Create a vendor bill with the analytic account of the created project - Notice in the project dashboard the two budgets are summed up in the total ### Cause: When calculating the total spent and total allocated we add up the amount whether it is an expense or revenue. https://github.com/odoo/enterprise/blob/1dccb87a48ac44735da4c78594e37d4783789cd6/project_account_budget/models/project.py#L120-L121 ### Fix: Set the expense budget to -ve and the revenue/both to +ve amount when calculating the total spent and total allocated opw-5488131 Forward-Port-Of: odoo/enterprise#106504
This update ensures that document creation times are displayed accurately for users, regardless of their location. Previously, times were inconsistent due to a failure to convert dates from UTC to the user's local timezone. Now, all times are correctly formatted for each user, improving data accuracy and user experience.
Original PR description
Step to reproduce: 1. Install `documents` 2. Upload a document and open the tree view 3. Compare the field `Created On` and the time from the `Manage Versions` action Issue: - The displayed time is inconsistent between the tree view and the dialog Cause: - The datetime used in Manage Versions is formatted without converting it from UTC to the user’s timezone Solution: - Use timezone-aware datetime helpers so values are converted from UTC to the user’s timezone. Before: <img width="1328" height="81" alt="image" src="https://github.com/user-attachments/assets/2a02f03c-714d-417d-a805-fd0dd7c52753" /> <img width="636" height="297" alt="image" src="https://github.com/user-attachments/assets/c4514469-2f51-493f-8991-32371fb7f338" /> After: <img width="641" height="312" alt="image" src="https://github.com/user-attachments/assets/3979ece8-635a-4b54-9b53-d8b28b3336ec" /> opw-5467782 Forward-Port-Of: odoo/enterprise#104443
This update resolves a technical issue that caused warnings during the initial setup of reports for Belgian accounting. The fix ensures that report generation works correctly by providing a backup method for identifying account references, even when standard XMLIDs are missing. This improves the reliability of financial reporting.
Original PR description
Description of the issue this commit addresses: On some migrated BE databases, account template refs a4121/a4521 are missing as XMLIDs. l10n_be_reports then fails to recover partner/reconcile account refs and logs warnings during post-init load. --- Desired behavior after this commit is merged: This commit adds a fallback in BE report chart template data to resolve a4121/a4521 by account code when XMLIDs are missing, preventing recovery warnings while keeping normal XMLID behavior unchanged. --- runbot-[233845](https://runbot.odoo.com/odoo/runbot.build.error/233845) Forward-Port-Of: odoo/enterprise#111325
This update corrects a technical issue where certain invoice PDFs (specifically for FCAM, FCAP, and FESP document types) were missing legally required 'complementos' data. The fix ensures that all invoices generated using the l10n_gt_edi module comply with tax regulations, preventing potential compliance problems. This change improves data accuracy and reduces risk.
Original PR description
**PROBLEM** For some documents types, the "complementos" are not present in the pdf while they are present in the xml. It's legally required that they are added in the pdf. **STEP TO REPRODUCE** 1. Install l10n_gt_edi. 2. Create an customer invoice. 3. Set the document type to FCAM, FCAP, or FESP. 4. Send the invoice using the cfdi. 5. download the xml and the pdf, notice the complementos are in the xml, but not in the pdf. opw-5970285 Forward-Port-Of: odoo/enterprise#109061
This update ensures that changes to a subscription's salesperson are automatically reflected on all associated contacts. Previously, updates only applied to the company partner, leading to inconsistencies. This improvement streamlines workflows and eliminates manual data updates.
Original PR description
Before this commit, changing the salesperson on a subscription only updated the company partner, leaving child contacts with outdated salesperson info. After this commit, updating the subscription's salesperson also updates all child contacts of the company, ensuring consistency across the portal and reducing manual work. An unit test was added to ensure this behavior. task-5917271 Forward-Port-Of: odoo/enterprise#111499 Forward-Port-Of: odoo/enterprise#108339
This update resolves an issue where equity transactions couldn't be created in currencies other than the company's default (USD). Now, users can set the equity currency for the first transaction, ensuring flexibility and accuracy when managing equity values in multiple currencies. Subsequent transactions will automatically use this selected currency.
Original PR description
### Issue: When a company is set in USD, it was not possible to create equity transactions in another currency (e.g., EUR) ### Cause: The equity_currency_id is initialized with the company currency at partner creation (or module installation) However, there was no way to override this value when creating transactions ### Fix: It is now possible to set the equity currency on the first transaction Subsequent transactions reuse this currency and the field becomes read-only ### Steps to reproduce: - Install `equity` with demo data (currency and equity_currency default to USD) - Enable the EUR currency - Create an equity transaction for a company - You can now choose EUR on this transaction - Create another transaction for the same company, the selector is hidden and the currency remains EUR opw-5382255 Forward-Port-Of: odoo/enterprise#108248
This update resolves a bug where removing an EPD line in bank reconciliation incorrectly removed associated tax lines. Now, only the EPD line and its corresponding tax line are properly removed, ensuring accurate reconciliation reporting. This improves the reliability of bank statement processing.
Original PR description
When removing an EPD line in the bank rec widget, if the invoice line added to the statement line contained a tax, the invoice line was removed aswell. Now, only the EPD line and its tax line are removed. no-task Forward-Port-Of: odoo/enterprise#110514
This update resolves a technical issue preventing users from generating VSME and CSRD reports within the ESG app. The fix removes an unnecessary check in the report search process, which was causing an error. This ensures reports can now be successfully printed.
Original PR description
Steps to reproduce:
1. From Accounting, create a Vendor bill with today's date, and containing a line
2. Confirm (post) it
3. Make the Payment ('Pay' stat button)
4. Create a VSME or CSRD report from the ESG App, for the current year
5. Try to print it
=> A traceback occurs (in _get_payment_terms_data()) as we are trying to search on the 'active' field of account.move, which does not exist. => Solution: remove this uneeded check
version-19.0
Forward-Port-Of: odoo/enterprise#111816This update prevents data merge operations from silently failing due to timeouts. Instead, a warning is displayed, suggesting users merge smaller groups of records. Upon successful completion, the model is automatically reloaded, ensuring data integrity and a smoother user experience.
Original PR description
Display a warning notification when the merge operation times out instead of failing silently. Suggest merging fewer records and reload the model on success. task-5912855 Forward-Port-Of: odoo/enterprise#110763
This update corrects a problem with importing invoices from the Italian tax authority (EDI) due to how attachments were handled within the XML files. The fix prevents data corruption and ensures attachments are correctly processed, improving the reliability of the EDI import process. Additionally, the naming of attachments has been improved.
Original PR description
PR #212726 removed a Many2One field and used an existing binary field, `l10n_it_edi_attachment_file`, to store E-invoice files as XMLs. This change was made for security reasons. However, this PR…
PR #212726 removed a Many2One field and used an existing binary field, `l10n_it_edi_attachment_file`, to store E-invoice files as XMLs. This change was made for security reasons. However, this PR also stores attachments embedded in the `<Allegati>` element of the XML in this same field. This results in three issues when importing invoices from the SDI: 1. The first embedded attachment will overwrite the XML file's contents, corrupting it. 2. Subsequent embedded attachments will continue to overwrite the previous attachment. 3. All embedded attachments are linked to the `account.move` record by the Many2one field `attachment_ids`, which is contrary to the stated goal of PR #212726. These behaviors cannot be replicated in a runbot environment, as there is no way to test the SDI import process in runbot at the time of writing. Localhost environments can replicate this issue by receiving an XML from the test l10n_it API server, or by passing similarly encrypted data to the method `_l10n_it_edi_process_downloads()`. See the method `test_decrypt_invoice_from_IAP()` from PR #250439 for an example of the encryption process. **Solution**: Do not overwrite the field `l10n_it_edi_attachment_file`. Add stored field(s) to master for attachment(s) within an XML's `<<Allegati>` element. This PR also improves how Allegati attachments are named, as my previous PR #246220 could result in files with two extensions (e.g. "filename.txt.TXT"). Ticket [link](https://www.odoo.com/odoo/project.task/5800658) opw-5800658 Forward-Port-Of: odoo/odoo#252806
This update resolves a gap in documentation for the Direct Deposit module within the l10n_us_account add-on. Now that the module is fully integrated, a link to the relevant direct deposit documentation has been added to the settings view, improving clarity for users.
Original PR description
When the Direct Deposit module was merged, there was no documentation created yet. Now that it has been merged we will add the link to the right documentation. task-none
This update fixes a potential error that occurred when creating returns for delivery orders. Previously, manually adjusting quantities after validation could cause calculations to fail. The change now prevents quantity updates on validated pickings, ensuring accurate return computations and data consistency.
Original PR description
Currently, an error occurs when creating a return for a delivery order whose quantity has been manually set to zero after validation. **Steps to reproduce:** - Install `stock_account` module. - Create and validate a delivery order. - Unlock the order and set the product quantity to 0. - Create a return order and validate it. **Error:** `ZeroDivisionError - float division by zero` **Cause:** The system allows quantities to be modified even after the picking is validated, leading to inconsistent data during return computations. **Fix:** This commit makes the quantity field read-only once the picking is in the done state to prevent invalid updates. sentry-7345265575