Daily updates from Odoo
Monday, March 23, 2026
7 changes · 19.0
New functionality added to Odoo
This update restores the display of a proxy token within the Odoo Enterprise system, specifically for the l10n_eg_iot module used in Egypt. Previously, this token was hidden to avoid a modal prompt, but it's now reintroduced to ensure proper VAT processing. This change improves functionality for Egyptian users.
Original PR description
Proxy token generation was removed to avoid showing a modal with a token nobody cares about except Egypt. We reintroduce token generation, but display it to the database instead of showing a modal. see odoo/odoo#255121
Resolved issues and error corrections
This update resolves an issue preventing invoices with the ICBPER tax code from generating correctly. The fix addresses a technical problem related to how the system handles fixed taxes, ensuring invoices with this tax now process without errors. This improves the reliability of invoice generation for Peru customers.
Original PR description
**Steps to reproduce:** 1. Install module `l10n_pe_edi`. 2. Switch company to PE. 3. Create a tax: - Name: ICBPER - Amount type: Fixed - Code: ICBPER - Amount: 0.5(e.g.) - Set the tax group to ICBPER…
**Steps to reproduce:**
1. Install module `l10n_pe_edi`.
2. Switch company to PE.
3. Create a tax:
- Name: ICBPER
- Amount type: Fixed
- Code: ICBPER
- Amount: 0.5(e.g.)
- Set the tax group to ICBPER (In Advance Option)
4. Create a invoice and add a product with ICBPER tax.
5. Post the invoice and click "Process Now" (at header).
**Issue:**
Processing the invoice raises:
AttributeError: 'dict' object has no attribute '_get_downpayment_lines'
**Cause:**
When `fixed_taxes_as_allowance_charges` is True, `_setup_base_lines()` calls `_turn_emptying_taxes_as_new_base_lines()`, which splits fixed taxes (e.g., ICBPER) into separate base lines.
During this process, `base_line['record']` is no longer the original `account.move.line` record. Instead, it becomes a dictionary containing record under `base_line['record']['record']`.
- With the flag enabled: `base_line['record']` -> dict `line._get_downpayment_lines()` -> AttributeError
- With the flag disabled: `base_line['record']` -> `account.move.line``line._get_downpayment_lines()` -> works correctly
The Peru EDI implementation directly accesses `base_line['record']` expecting an `account.move.line`. The the nested dict structure causes the crash during file generation.
**Solution:**
Override `_add_invoice_config_vals()` to explicitly set `fixed_taxes_as_allowance_charges = False`
- Add test to ensure invoices with ICBPER fixed taxes generate XML without error
**opw-5809939**This update fixes an issue where users weren't receiving email notifications for signature requests when their notification preferences were set to 'inbox'. Now, all signature requests will trigger email notifications, ensuring signers are promptly informed. This change maintains in-app visibility for users who track requests within Odoo.
Original PR description
When a user's notification preference is set to "inbox", no email is sent, which may prevent signers from being notified of signature requests. This commit enforces sending email notifications for signature requests regardless of user notification settings. Notifications are still created in Odoo, preserving in-app visibility for users who rely on it. task-6041834
This update automatically calculates and transmits the necessary commission payments related to employee earnings for Swiss payroll (l10n_ch_hr_payroll). Previously, this calculation was manual, and this change streamlines the process, ensuring accurate and timely reporting to Swiss tax authorities. This improves compliance and reduces the risk of errors.
Original PR description
Forward-Port-Of: odoo/enterprise#111143
This update fixes an issue where DATEV exports were inaccurate when a move line's account was changed. Now, updating a move line's account automatically recalculates the DATEV main account, ensuring the exported data correctly reflects the current financial accounts. This prevents duplicate lines in DATEV reports.
Original PR description
Description of the issue this commit addresses: When the account of a move line is updated (e.g. replacing the suspense account with the actual one), l10n_de_datev_main_account_id was not recomputed which leads to an incorrect DATEV export with duplicate lines. Desired behavior after this commit is merged: Changing the account_id of a move line recomputes l10n_de_datev_main_account_id so that the exported DATEV data reflects the current accounts of the move.
This update resolves an issue where night shift slots (e.g., 20PM - 4AM) were not visible in the weekly planning view. The fix adjusts how the system displays multi-day slots, ensuring all scheduled hours are accurately shown. This improves the planning experience for employees with flexible work arrangements.
Original PR description
**Steps to reproduce** 1. Have an employee using a flexible schedule 2. Create a slot from e.g. 20PM to 4AM for this employee. Make sure this is the only slot that week for the employee. 3. Publish…
**Steps to reproduce** 1. Have an employee using a flexible schedule 2. Create a slot from e.g. 20PM to 4AM for this employee. Make sure this is the only slot that week for the employee. 3. Publish the Schedule and send it to the employee. Open the outgoing mail to access the link to the planning view. Issue: the slot is not visible in the week view. **Cause** https://github.com/odoo/enterprise/blob/04a885dbb6eed96297cb5ce9a155ebf8e169427c/planning/controllers/main.py#L193-L194 The `event_hour_min` and `event_hour_max` returned by `planning_get` and used to control the min/max hours displayed in the week view, didn't account for slots over multiple days. For a slot between 20pm and 4am, the `event_hour_max` should be the end of the day, and the `event_hour_min` should be the start of the day. **Solution** - we change the `event_hour_min` and `event_hour_max` for multi-day slots to display the full days in the week view - the previous point has the drawback of displaying the full days for non-flexible employees even when not necessary. This is because `slots_start_datetime` and `slots_end_datetime` contained the `planning.slot` start and end. Instead, we can look at the actual slot values displayed (by `_get_slots_vals`). For example, a 5 day slot for a non-flexible employee may contain actual slot values corresponding to a typical 8-17 working day. opw-5245985 Forward-Port-Of: odoo/enterprise#99784
This update ensures that payroll payslips with analytic rules are correctly anonymized, preventing individual employee lines from appearing in aggregated accounting moves. The fix addresses a technical issue related to how analytic distributions are processed, enhancing data privacy and compliance. A new test has been added to verify the fix.
Original PR description
The Batch Account Move Lines option in the settings is used to aggregate together the different payslips of a payrun and to create only one move with aggregated lines, per account. This is done to…
The Batch Account Move Lines option in the settings is used to aggregate together the different payslips of a payrun and to create only one move with aggregated lines, per account. This is done to enforce privacy and avoid having lines for each employee in the payrun. If salary rules with analytic distributions are involved, though, the lines are not merged and we lose the anonimity.
This happens because in the _get_existing_lines funciton, that should return the lines to be merged with the input line (line), the condition for the rules that have an analytic distribution is wrong.
In particular, the condition is wrong because the
distribution_analytic_account_ids field is a recordset of the accounts, while line_id['analytic_distribution'] is a dictionary with keys that are comma separated strings of the ids of the accounts, with values reflecting the percentage.
For example, if a rule has one analytic distribution for 40% and involving accounts 13,7 and 12 + another analytic distribution for 60% involving accounts 3 and 5, line_id['analytic_distribution'] will be {'13,7,12': 40.0, '3,5': 60.0} while distribution_analytic_etc will be a recordset containing (13,7,12,3,5). To fix the problem and keep everything inline, we extract the logic to a new function, where we first unravel the ids from the keys of the dictionary and only then try to match them to the values in the recordset.
Task: 6043957