Wednesday, March 18, 2026
11 changes · saas-18.2
New functionality added to Odoo
This update introduces a new report for Polish businesses that still need to generate JPK_FA XML reports even when using the KSeF online invoicing system. This report ensures compliance with Polish tax regulations by detailing invoices and lines not yet validated by KSeF, aligning with JPK-FA(4) standards.
Original PR description
In Poland, if a business chooses to keep B2C invoicing outside of KSeF (online platform), the JPK_FA obligation remains. It is a XML report that lists all the invoices and the invoice lines that have not been validated by KSeF during a desired period of time. The report follows the JPK-FA(4) norms. task-5166047 Forward-Port-Of: odoo/enterprise#103000
Resolved issues and error corrections
This update ensures that NACHA payment files use the correct bank account holder's name instead of the customer's name in Odoo. Prioritizing the account holder name improves payment accuracy and compliance with NACHA regulations, preventing potential payment processing issues.
Original PR description
The NACHA entry detail was using the partner's name (res.partner.name) for the Individual Name field. This should instead prioritize the Account Holder Name (acc_holder_name) from the bank account, as this reflects the actual name on the bank account which may differ from the partner's name in Odoo. The code now uses bank.acc_holder_name if set, and falls back to payment.partner_id.name if not set. Forward-Port-Of: odoo/enterprise#108414 Forward-Port-Of: odoo/enterprise#105582
This update resolves an issue where night shift slots (e.g., 20PM - 4AM) weren't visible in the weekly planning view. The fix adjusts how the system calculates display hours for multi-day shifts, ensuring all scheduled time is accurately represented. 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 fixes a bug where project timesheets didn't accurately reflect changes in employee costs when switching workers on a manufacturing order. The fix ensures that the AAL (analytic accounting line) associated with the work center is updated correctly, accurately tracking labor costs in the project dashboard. This ensures accurate project costing and reporting.
Original PR description
### Steps to reproduce: - Create an MTO product and another Service product that create a project and task - Create a quotation with both products - Create two employees with different hourly cost - Go to Manufacturing order - Configure an employee to manufacture the product at a work station. - Observe the project dashboard - Go back to the MO and change the employee on the work station - Notice the project dashboard Timesheets section doesn't have any change on the amount ### Cause: This is happening because when changing the employee we don't modify anything in the AAL linked to the work station. As we only modify the AAL when the duration change. ### Fix: We call _create_analytic_entry when we change the employee on the work station to change the amount and the employee_id for the AAL. opw-5939321 Forward-Port-Of: odoo/enterprise#109695
This update ensures that shift notifications are automatically sent to employees in their preferred language, regardless of the user's language settings. Previously, emails were defaulted to the current user's language, causing confusion. This fix improves communication and user experience for international teams.
Original PR description
Steps to reproduce: ------------------------- 1. Install Planning and Contacts. 2. Install any language other than English (e.g., Arabic). 3. Change an employee's contact language to that language.…
Steps to reproduce: ------------------------- 1. Install Planning and Contacts. 2. Install any language other than English (e.g., Arabic). 3. Change an employee's contact language to that language. 4. Create a shift for that employee and click "Send". 5. Check the message in Settings > Technical > Discuss > Messages. Issue: --------- The email is sent in the language of the current user rather than the language of the employee receiving the shift. Cause: --------- The mail template rendering logic ([_render_lang](https://github.com/odoo/odoo/blob/0dbfa8b99d5c28a7d84e781a7f23b226fd964e95/addons/mail/models/mail_render_mixin.py#L549-L566)) fails to determine a valid language on the planning slot record because it is not directly linked to a `partner_id`. As a result, it falls back to the current user's language. Solution: ------------ Explicitly pass the employee partner's language in the mail context so that the email is sent in the correct language. opw-5928676 Forward-Port-Of: odoo/enterprise#110778 Forward-Port-Of: odoo/enterprise#109619
This update resolves an issue preventing new employee creation when generating the BVG-LLP Basis Declaration report. The fix addresses a technical problem with how Odoo compares report records, ensuring the system correctly handles multiple reports with the same month.
Original PR description
Steps to reproduce: ---------------------------------- 1. Install `l10n_ch_hr_payroll_elm_transmission` module 2. Switch to Swiss company 3. Navigate to Payroll > Transmission > BVG-LLP Basis…
Steps to reproduce:
----------------------------------
1. Install `l10n_ch_hr_payroll_elm_transmission` module
2. Switch to Swiss company
3. Navigate to Payroll > Transmission > BVG-LLP Basis Declaration
4. Create two Reports with same Year and Month
5. Now try to create new Employee from the employee app
Observation:
----------------------------------
Tracaback Occurs:
```
File '/home/odoo/src/enterprise/19.0/l10n_ch_hr_payroll/models/l10n_ch_employee_monthly_values.py', line 319, in _compute_bvg_lpp_annual_basis
existing_declaration = max(existing_declaration, key=lambda r: r.month) if existing_declaration else False
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/src/odoo/19.0/odoo/orm/models.py', line 5934, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: l10n.ch.lpp.basis.report(1, 2)
```
Issue:
----------------------------------
In the following code:
https://github.com/odoo/enterprise/blob/44a26539093f9313d9cd5f823c11866e3c98ec97/l10n_ch_hr_payroll_elm_transmission/models/l10n_ch_employee_monthly_values.py#L319-L320
Python's max() function doesn't just call the key function once per item. When there are ties (equal key values), it may need to compare the original objects, and during this process, Odoo's recordset operations combine records, causing the lambda receives `r` as a combined recordset. To access `.month` on a multi-record recordset it gives singleton error.
Solution:
----------------------------------
Creates tuples of (month, recordset) pairs and uses max() to compare month integers directly, avoiding the singleton error.
opw-5391742
Forward-Port-Of: odoo/enterprise#102335This update ensures that all attendees of appointments – internal users and organizers – receive booking notifications, regardless of whether the booking syncs with Google or Outlook. Previously, notifications were limited, but this change ensures consistent communication for all involved parties.
Original PR description
In [1] we prevented cancelation emails from being sent when the booking was synced via google or outlook calendar. However this means even followers who would not be notified by the mail provider (not assisting to the meeting) would not be notified. As well as the organizer who is doing to booking/cancelling from the perspective of the mail provider, as the meeting is created from their account. Instead we should keep sending the "appointment booked" template in all cases as it is only followed by internal users to whom it is always relevant. As for cancelation templates, it should stil be sent to internal users. Partners of the meeting however need not be notified and may be unsubscribed if syncing is enabled, as cancellation typically only happens once. task-5152917 [1]: https://github.com/odoo/enterprise/pull/60913 Forward-Port-Of: odoo/enterprise#96638
This update resolves an issue where tax calculations were incorrect during the reconciliation process for certain journal entries, specifically those involving reverse charges. The fix ensures that tax amounts are accurately reflected in the reconciled entries, improving financial reporting accuracy. This impacts users utilizing the reconciliation feature within the Enterprise edition.
Original PR description
## ISSUE 1: **Steps to reproduce [l10n_be easier]:** - Create a journal entry: ``` 440 : supplier 0 300 False 499 : suspense account 300 0 False ``` - Accounting > Reconcile: select the entry and in…
## ISSUE 1: **Steps to reproduce [l10n_be easier]:** - Create a journal entry: ``` 440 : supplier 0 300 False 499 : suspense account 300 0 False ``` - Accounting > Reconcile: select the entry and in the wizard > account 600 tax 12% (purchase) - Validate - Check the last entry created **Issue:** There is no invert tag set on the tax line **Cause:** The tax repartition line was not propagated in the rec wizard, therefore in https://github.com/odoo/odoo/blob/a456d9c7cbdf17edb5db2c73306b62150e46a7a7/addons/account/models/account_move_line.py#L814-L815 The line was never set to properly (same of is_refund) ## ISSUE2: **Steps to reproduce:** - create a journal entry ``` 440 : supplier 0 300 False 499 : suspense account 300 0 False ``` - Accounting > Reconcile: select the entry and in the wizard > account 600 tax 21% EU M (Purchases) - Validate - Check the last entry created **Issue:** No issue in 17.0. But we added the test to cover the flow. A fix for this issue will be applied as of 18.0. opw-4976780 Forward-Port-Of: odoo/enterprise#93839 Forward-Port-Of: odoo/enterprise#92556
This update corrects a problem causing incorrect stock synchronization for Amazon listings, leading to phantom orders. The fix allows users to manually specify the fulfillment channel (FBA or FBM) for listings, resolving a known 'ghost listing' issue. This ensures accurate stock management and order fulfillment.
Original PR description
When configuring a listing on Amazon Seller Central, the user must choose **one** of the available fulfillment channels that Amazon offers. We distinguish two kinds: Fulfillment by Amazon (FBA) and…
When configuring a listing on Amazon Seller Central, the user must choose **one** of the available fulfillment channels that Amazon offers. We distinguish two kinds: Fulfillment by Amazon (FBA) and Fulfillment by Merchant (FBM). However, Amazon suffers from a known issue of ghost listings. A ghost listing occurs when an offer is presumably sold via FBA, but in fact stores stock information for both FBM and FBA creating unwanted FBM orders. To avoid ghost listings, the first solution was to disable stock synchronization as soon as an offer contained stock in the Amazon location of Odoo. However, if a merchant decided to change the fulfillment channel, it became impossible to sync the stock anymore. See also e7c01c7097d90e731c5408cee4d3595ed810c8fa. To resolve this issue, we decided to use the Amazon API to fetch information about the fulfillment channel of a listing. However, Amazon doesn't give a clear answer for a given listing. Therefore, after some research, the assumption was that an offer was FBM if the listing contained a `merchant_shipping_group`, as the merchant shipping group is a setting specific to FBM listings. See also e6d620e4b200cadabb00ce37ab03289cfeb4ae58. However, this assumption was flawed because Amazon can keep the shipping group even if the listing switches to FBA. This in turn enabled stock synchronization, leading to ghost listings. To fix this issue we give the possibility to users to manually set the correct fulfillment channel of an offer when it becomes ambiguous. opw-5480254 See also: - https://github.com/odoo/upgrade/pull/9692 Forward-Port-Of: odoo/enterprise#106662
This update corrects an issue where incorrect folio numbering occurred when a Chilean Accounting (l10n_cl_edi) configuration was not set up. The fix ensures that folios are generated correctly, avoiding potential errors and disruptions in accounting processes. This improves data accuracy and reliability for Chilean clients.
Original PR description
`l10n_cl_edi` overrides `account.move._get_last_sequence()` to ensure the folio belongs to an available in-use CAF. When no CAF exists at all, `l10n_latam.document.type._get_start_number()` returns 0 and the fallback builds a previous sequence using start_nb - 1. Formatting -1 as `:06d` yields “-00001”, which then propagates to “FAC -00002”, “-00003” and corrupts the sequence chain. In addition, returning an invalid “last sequence” may force `sequence.mixin` to search for a free number under the UNIQUE constraint by retrying increments inside a savepoint and rolling back on UniqueViolation, which is costly when many values are already taken see [ _locked_increment()](https://github.com/odoo/odoo/blob/18.0/addons/account/models/sequence_mixin.py#L352). Now we only reset to the CAF start when an in-use CAF actually exists (start_nb > 0). opw-5918758 Forward-Port-Of: odoo/enterprise#108909
This update resolves an issue where Odoo generated invalid UBL/QR invoices for foreign customers. Specifically, it ensures the receiver identification type defaults to '0' when a Peruvian company invoices a customer with a foreign identification type, preventing errors from the Peruvian tax authority (SUNAT). This ensures proper invoice generation and compliance for multi-country operations.
Original PR description
In multi-country databases, a Peruvian company can invoice a foreign customer (e.g., a Colombian company) whose identification type is defined by another localization. Those records typically have an…
In multi-country databases, a Peruvian company can invoice a foreign customer (e.g., a Colombian company) whose identification type is defined by another localization. Those records typically have an empty l10n_pe_vat_code, since there are no cross-country dependencies between LATAM identification types. In that case, the generated UBL leaves the receiver identity type empty and SUNAT returns an error like: ``` 2015/2015 - El XML no contiene el tag o no existe informacion del tipo de documento de identidad del receptor... (missing schemeID value). ``` Odoo already defines schemeID = 0 for some foreign identification types in l10n_pe data, but it cannot cover identification types coming from other countries’ localizations (e.g. Colombia): https://github.com/odoo/odoo/blob/18.0/addons/l10n_pe/data/l10n_latam_identification_type_data.xml#L4 This change ensures that, when the partner is not from Peru and the PE VAT code is missing, we fallback the receiver identification type to "0" in: - PartyIdentification/ID/@schemeID - AccountingCustomerParty/AdditionalAccountID - the QR payload identification type field This prevents generating invalid UBL/QR content for foreign customers in multi-country setups. Forward-Port-Of: odoo/enterprise#105115