Daily updates from Odoo
Tuesday, June 30, 2026
13 changes · 19.0
Enhancements to existing features
This update improves how Australian payroll handles superannuation corrections after a payslip has already been submitted and paid. If an underpayment needs to be fixed, the system can now create the right update action and report the adjustment more accurately through STP, helping reduce manual work and compliance risk.
Original PR description
Amending STP creates an update action if full file replacement is not available. Amended STPs create delta superannuation stream lines. task-6245415
Resolved issues and error corrections
Bank reconciliation now correctly matches statement lines even when the invoice payment reference has extra leading or trailing symbols such as + or *. This restores automatic matching for cases like Belgian structured references, reducing manual work and missed matches.
Original PR description
### Issue: In 19.0, bank reconciliation stopped automatically matching statement lines against moves when the payment reference contains leading/trailing `+` or `*` characters For example, a…
### Issue: In 19.0, bank reconciliation stopped automatically matching statement lines against moves when the payment reference contains leading/trailing `+` or `*` characters For example, a statement line with communication `000/0000/00123` would not auto-match an invoice with `payment_reference` `+++000/0000/00123+++` This affects Belgian structured references, where QR codes are generated without the surrounding `+++` ### Cause: The reconciliation SQL builds a list of words from `aml.ref` and `move.payment_reference` and compares them against the statement line's `payment_ref` using ILIKE Before the fix, `+++000/0000/00123+++` was used as-is, so it never matched `000/0000/00123` The regex delimiter pattern in the Python match also did not account for `+` and `*` as valid word boundaries ### Steps to reproduce: - Install `account_accountant` and `l10n_be` - Switch to the BE company - Create and confirm at least 2 invoices for the same partner with the same total (to avoid single-match shortcuts) - Note the Payment Reference of the first invoice (e.g. +++000/0000/00123+++) - In Bank Reconciliation, create a statement line for that partner and total, using the reference without the `+++` (e.g. 000/0000/00123) Before the fix, no automatic match was suggested opw-6095533
This change prevents the Intrastat report from failing when a company has no country set. It corrects how the SQL query is built so the report can generate normally instead of stopping with a database error.
Original PR description
When there is no `country_id` on the company we get `False`. The generated query then fail at: ``` ... CASE WHEN (code.country_id IS NULL OR code.country_id = false) THEN code.code ELSE NULL END AS commodity_code, ... ``` with: ``` ERROR: operator does not exist: integer = boolean LINE 12: ... WHEN (code.country_id IS NULL OR code.country_id = false) T... ``` Forward-Port-Of: odoo/enterprise#121798 Forward-Port-Of: odoo/enterprise#121608
Users can now select accounts of type Other Expenses when creating or editing financial budget lines. This fixes a gap that prevented some profit and loss accounts from being included in budgets, making budget setup more complete and accurate.
Original PR description
Currently, accounts with the `Other Expenses` account type cannot be selected in financial budget lines. **Steps to reproduce:** - Install the `accountant` module. - Go to `Chart of Accounts` and…
Currently, accounts with the `Other Expenses` account type cannot be selected in financial budget lines. **Steps to reproduce:** - Install the `accountant` module. - Go to `Chart of Accounts` and create a new account with `Type: Other Expenses`. - Go to Accounting > Configuration > Financial Budgets. - Create a new budget and add a budget line. - Try to select the newly created account. **Observation:** Accounts with the `Other Expenses` type are not available for selection in budget lines. **Root Cause:** At [1], the `expense_other` account type is missing from the `account_id` domain. **Expected Behavior:** Financial budgets should allow all Profit & Loss accounts, since the feature relies on P&L reporting. **Reference**: https://www.odoo.com/odoo/project/49/tasks/4314709 **Fix:** This commit ensures that users can add `Other Expenses` accounts to budget lines. [1]: https://github.com/odoo/enterprise/blob/41b66ba081f3938f7e55da209506c637850ae4ec/account_reports/models/budget.py#L114-L120 opw-6313835 Forward-Port-Of: odoo/enterprise#121735
This fix ensures that when an invoice linked to a batch payment is changed, all related payments move back to the correct status. It prevents one grouped payment from being left in the wrong state, which could cause problems when reconciling bank statements again.
Original PR description
**Steps to reproduce:** - Install Accounting - Create an invoice: * Customer: Partner A * Total: 30.00 - Confirm the invoice - Create a second invoice for the same customer: * Customer: Partner A *…
**Steps to reproduce:** - Install Accounting - Create an invoice: * Customer: Partner A * Total: 30.00 - Confirm the invoice - Create a second invoice for the same customer: * Customer: Partner A * Total; 10.00 - Confirm the invoice - From the invoice list, select both invoice - Create payment: * Journal: Bank * Group Payments: [checked] * Group Payments: [checked] * Amount: 40.00 - Create a third invoice for another customer: * Customer: Partner B * Total: 25.00 - Confirm the invoice - Register payment from the invoice - Install Accounting - Create an invoice: * Customer: Partner A * Total: 30.00 - Confirm the invoice - Create a second invoice for the same customer: * Customer: Partner A * Total; 10.00 - Confirm the invoice - From the invoice list, select both invoice - Create payment: * Journal: Bank * Group Payments: [checked] * Amount: 40.00 - Create a third invoice for another customer: * Customer: Partner B * Total: 25.00 - Confirm the invoice - Register payment from the invoice - Create a fourth invoice for another customer: * Customer: Partner C * Total; 40.00 - Confirm the invoice - Register payment from the invoice - From the payment list, select all 3 payments and create batch payment - Validate the batch payment - From Accounting dashboard, open Bank journal - Create a new bank statement line of 105.00 - Match it with the batch payment At that point, the statement line is reconciled with the 4 invoices and the 3 payments are marked as paid. - Go to the fourth invoice - Reset it to draft - Change the price - Save When the amount of the invoice is changed, the statement line is unreconciled and all the payments should change state from "Paid" to "In Process". **Issue:** All the single payments have their state correctly changed to "In Process", except for the group payment for the 2 first invoices, which leads to undesired values when trying to reconcile the statement line with the batch payment again. **Cause:** When the statement is unreconciled, all the partial reconcile records are deleted and the state of the linked payments are updated to "In Process". The payments are retrieved by checking if there are linked to an account move present in the partial reconcile record and if the amount of the payment matches the amount of the partial reconcile record. In case of a group payment, there are 2 partial reconcile records for each invoice linked to the payment. Therefore, in that case, the amount doesn't match the amount of the payment because it matches the amount of one of the invoice. opw-6141089 Forward-Port-Of: odoo/enterprise#121988 Forward-Port-Of: odoo/enterprise#120210
This fix lets managers create an appraisal even when the employee’s next appraisal date is already in the past. It prevents an unnecessary error from blocking the request, especially in cases where the user cannot edit the employee’s appraisal date themselves.
Original PR description
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings,…
# How to reproduce You need to simulate the fact that you are creating an appraisal late so either : A) Directly edit the `next_appraisal_date` in SQL B) Go to Employee App > any Employee > Settings, set Next Appraisal Date to tomorrow and wait for 2 days Then : - Click on Request Appraisal - Save # The problem An error is shown saying "You cannot set 'Next Appraisal Date' in the past.". You can workaround this by changing the Next Appraisal Date to a date in the future, but the problem is not every user has the right to do this. # Cause `next_appraisal_date` is also defined in hr.appraisal as a relate field of hr.employee : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_appraisal.py#L56-L57 When creating an hr.appraisal, `next_appraisal_date` is present in `vals_list` because it is defined in the view since : https://github.com/odoo/enterprise/commit/58fba3098f33db82dfbccca2db229550402ed3ab https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/views/hr_appraisal_views.xml#L92 This triggers a write on `next_appraisal_date` of hr.employee which triggers a constraint : https://github.com/odoo/enterprise/blob/0226ad15abc8db70f8e379fddec3d83d15749c85/hr_appraisal/models/hr_employee.py#L81-L85 opw-6147865
This update fixes a problem where DHL shipping requests could be rejected for addresses in regions that use one-character province codes. The system now converts those codes into the longer format DHL requires, helping shipments validate successfully for affected countries and regions.
Original PR description
Steps:
- Install delivery_dhl_rest
- Create a new customer with barcelona as address
- Create a new Delivery
- Set DHL
- Validate de delivery
- Validation error #/customerDetails/receiverDetails/postalAddress/provinceCode: expected minLength: 2, actual: 1
DHL requires `provinceCode` to be at least 2 characters. Several countries in `res.country.state` data use single-character codes (e.g. ES: B, M, A…; AR: C, B, S…; CN: 京, 沪…). This caused API validation errors when shipping from or to addresses in those regions.
Add `PROVINCE_CODE_MAP`, a dict keyed by `(country_ISO2, state_code)`, mapping each offending code to its ISO 3166-2 form (e.g. ('ES', 'B') -> 'ES-B'). Both `_get_consignee_vals` and `_get_shipper_vals` now look up the map before sending `provinceCode`, falling back to the raw code for countries not in the map.
links: https://developer.dhl.com/api-reference/mydhl-api-dhl-express#shipments
opw-6341745This update fixes how payroll deduction attachments are matched to payroll lines. It prevents partial code matches from being treated as valid, which helps ensure the correct deductions are applied to employee payslips.
Original PR description
Currently we have for deduction_codes, attachments in slip.salary_attachment_ids.grouped( lambda x: x.other_input_type_id.code ) salary_lines = slip.line_ids.filtered( lambda r: r.code in deduction_codes ) I believe the intent in the second line is to check either r.code is in deduction_codes. This assumes deduction codes is an array. the issue is that it is not an array. The return of "grouped" on the first line implies that deduction_code will always have a string that describe which is the deduction_code, and attachment_ids will be an array Now the bug happens on the comparison "in" on the second line. Since we are matching against a string, suposing we had 2 codes like TEST_CODE and TEST, both would match positively using "in" changing "in" to "==" will ensure we match codes properly opw-6206134 Forward-Port-Of: odoo/enterprise#121022
This fix removes an access error that prevented users from creating rental orders when they did not have inventory permissions. It also keeps the rental pickup process working by granting the needed access to the rental picking role instead of requiring broader stock access.
Original PR description
Issue: --- It's not possible to create rental orders without stock.lot access. Steps to reproduce: 1- Change demo user access: - All inventory accesses: No 2- Enable `Rental Transfers`. 3- Login Demo user. 4- Create a rental order. You will get access error. Cause and Fix: --- `stock.lot` model is in only accessed by `group_stock_user`. As a result fields such as `reserved_lot_ids` will be problematic when we don't have stock access. We initially tried to fix the issue by limiting the problematic fields to group stock user. However that limits the user from rental pickup. Instead we are giving the required access to group rental picking user. opw-6281154
Folders connected to a project will no longer be removed by the automatic trash cleanup, preventing errors during cleanup jobs. This keeps project documents safe and ensures the trash can be emptied normally without breaking linked records.
Original PR description
## Problem
When a folder linked to a project gets archived, the documents trash autovacuum unlinks it along with regular trash. That triggers the constrains . This happens whether the project is still active or also archived.
## Fix
Add one leaf on the GC domain: `('project_ids', '=', False)`. so the document is not deleted if linked to a projectThis fix prevents Auto Plan from assigning a worker just because they previously worked on the same project. The system now checks the role on the slot first, so only resources assigned to that role can be selected. This avoids incorrect scheduling and makes planning results more reliable.
Original PR description
## Issue When using the *Auto Plan* feature on a planning slot with a Role and a Project set, a resource which operated on the same project will be chosen if available, without taking into account…
## Issue
When using the *Auto Plan* feature on a planning slot with a Role and a Project set, a resource which operated on the same project will be chosen if available, without taking into account the Role set on the slot.
## Steps to reproduce
1. Install Project Planning (`project_forecast`)
2. In Planning > Configuration > Roles, create two planning roles A and B
- Role A: Assign a resource R
- Role B: No resource
3. Open Planning (Schedule by Resource), and go back a few weeks (to prevent overlaps with potential demo data)
4. Create two new slots:
1. Set Role B and a random Project P, then click Auto Plan: there should be no available resource (because we didn't set any resource for Role B)
2. Set Role A and the same Project P, then click Auto Plan: it should assign the resource R assigned to Role A
5. After assigning a resource to the slot for Role A, edit the Open Shift for Role B again and click Auto Plan: **it assigns the same resource R, even though that resource is not assigned to Role B.**
## Cause
The `_get_open_shifts_resources` override in `project_forecast` looks for resources that were assigned to slots related to the same project. It does not filter resources based on the requested role.
https://github.com/odoo/enterprise/blob/885edbc270a86ab76e0a6eff4acb5767c0fe29d1/project_forecast/models/planning_slot.py#L104-L116
This means that resources that are not part of the requested role can be assigned to the slot, as long as the resource operated on another slot for the same project.
opw-6325744The GSTR-1 spreadsheet now shows the Invoice Value for SEZ invoices in company currency (INR) instead of the foreign invoice currency. This ensures the export matches the expected tax return format and avoids incorrect values in the report.
Original PR description
Currently, when generatign GSTR-1 return spreadshee, SEZ invoices issued in a foreign currency are exported with their totals in the foreign currency rather than the company currency (INR) Steps to reproduce: - Create a B2B SEZ invoice in foreign currency - Go to Accounting > Reporting > [India] GST Return periods - Generate the GSTR-1 report for the period Issue: In the resulting spreadsheet, the "Invoice Value" column takes the invoice total in USD rather then INR opw-6292913 Forward-Port-Of: odoo/enterprise#121864 Forward-Port-Of: odoo/enterprise#121157
We fixed an issue in Kenyan PoS orders where selling a combo could wrongly trigger an eTIMS registration warning and block payment. The combo itself is now ignored for eTIMS checks, so only the actual products inside the combo need to be registered, allowing the order to be completed normally.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5.…
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306 Forward-Port-Of: odoo/enterprise#121991 Forward-Port-Of: odoo/enterprise#119362