Daily updates from Odoo
Wednesday, August 12, 2026
32 changes · saas-19.2
Resolved issues and error corrections
This update adds a safeguard to verify that Indian GSTR-1 reports choose the correct tax rate group when GST and CESS taxes are used together. It helps reduce the risk of incorrect tax reporting in scenarios involving combined Indian indirect taxes.
Original PR description
This PR adds a test case to ensure that the correct tax rate group is selected in the GSTR-1 report when a combination of GST and CESS taxes is used. Community PR - https://github.com/odoo/odoo/pull/280571
Fixed an error that could occur when users turned the No Follow-Up option on or off for invoices with multiple payment installments. This keeps the Follow-Up Report usable when some installments are already paid and others remain open.
Original PR description
Steps to Reproduce: 1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments. 2. Create a Customer Invoice with this Payment Term. 3. Post the invoice.…
Steps to Reproduce:
1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments.
2. Create a Customer Invoice with this Payment Term.
3. Post the invoice.
4. Register a payment and fully reconcile one of the installments.
5. Navigate to the customer's Follow-Up Report (Accounting > Reporting > Partner Ledger > Report: Follow-Up Report).
6. Navigate to remaining open installment/account move line for that invoice.
7. Turn On or Off the No Follow-Up toggle for the invoice.
An error occurs when enabling or disabling the No Follow-Up toggle.
Issue:
Enabling or disabling the No Follow-Up toggle on a remaining open installment in the Follow-Up Report raises a server error when the invoice contains multiple installments and one or more installments are already fully reconciled.
Root Cause:
The Follow-Up Report only loads and sends non-fully reconciled account move lines from the JavaScript side through all_line_ids. In action_toggle_no_followup(), when the selected line belongs to an invoice, the code retrieves all receivable/payable lines of the invoice, including fully reconciled installments:
```
move.line_ids.filtered(
lambda line: line.account_type in ('asset_receivable', 'liability_payable'),
)
```
The method then attempts to map every receivable/payable line to a report line ID using aml_id_to_line_id. Since fully reconciled installments are not present in all_line_ids, they are missing from the mapping dictionary, causing a KeyError when accessing:
`aml_id_to_line_id[line.id]
`
Fix:
Restricted the impacted lines to those present in the report by adding a check that the account move line exists in aml_id_to_line_id before performing the mapping:
```
lambda line: line.account_type in ('asset_receivable', 'liability_payable')
and line.id in aml_id_to_line_id
```
opw-6245448
Forward-Port-Of: odoo/enterprise#126785
Forward-Port-Of: odoo/enterprise#126156Users can now open Bank Matching from a working file return even when no bank journal is selected. This prevents an error screen and lets staff continue reconciling bank statement lines from that workflow.
Original PR description
When accessing the reconciliation widget from the working file check, there is no journal to be selected, hence no journal in the context. This was tracebacking since we were trying to send a read query to the server with an undefined id. To reproduce: * create a bank statement line without reconciling * set up the return on the misc journal * open the return, then "Bank Matching" Forward-Port-Of: odoo/enterprise#127421
This update corrects a small issue in the Swiss payroll transmission process where the current date could be calculated without the proper context. It helps avoid errors during payroll-related submissions and keeps Swiss payroll workflows running reliably.
Original PR description
Fix https://github.com/odoo/enterprise/pull/126718 Forward-Port-Of: odoo/enterprise#127535
This fix ensures Mexican payroll CFDI payslips are included when Odoo checks their official SAT status. Businesses will now see the correct validation or cancellation status instead of an undefined status, improving payroll compliance visibility.
Original PR description
l10n_mx_hr_payroll_account_edi introduces new l10n_mx_edi.document states (payslip_sent, payslip_sent_failed, payslip_cancel, payslip_cancel_failed) but never extends the two hooks the base l10n_mx_edi module relies on to keep sat_state in sync: - _get_update_sat_status_domains(), which builds the domain used by the SAT-status cron (and manual refresh) to pick documents to poll. Payslip states were missing from it, so their SAT status was never fetched at all. - _update_document_sat_state(), which routes a fetched SAT status to a per-source-document handler. It has no branch for the payslip states, so even a manual poll would silently do nothing. As a result, payslip CFDIs validated in the SAT always appeared as "not_defined" in Odoo. opw-6192651 Forward-Port-Of: odoo/enterprise#126104 Forward-Port-Of: odoo/enterprise#124006
Tax closing entries now correctly include VAT credit carried over from the previous period. This prevents overstated tax payable amounts and ensures tax return journal entries match the expected carryover without extra user configuration.
Original PR description
### Issue before this commit: When generating a tax closing entry, the VAT credit carryover from the previous period is missing from the journal entry lines. This results in an incorrect net payable…
### Issue before this commit: When generating a tax closing entry, the VAT credit carryover from the previous period is missing from the journal entry lines. This results in an incorrect net payable amount. ### Steps to reproduce the issue: 1. Download Accounting 2. Go to Vendor > Bills 3. Create a vendor bill with date in June and price > 0 (ex. 1000$) and the 15% tax that produce a 150$ VAT tax 4. Go to Customers > Invoices 5. Create an invoice with price > 0 (ex. 9000$), the date in July and the 15% tax that will produce a 1350$ VAT tax 6. Go to Tax Return and validate all opened months up to July and see that for June the balance is -150$ 9. Then go to View Entries of July using the 3 dots next to the "submit" button and see that there is no mentioning of the 150$ carry over of credit from the month before ### Cause of the issue: During a forward-port merge conflict resolution, the code block responsible for retrieving the historical balance from the receivable_account_id was wrongly removed ([diff](https://github.com/odoo/enterprise/compare/b760c1dbee6bfb628bae32041c5b5c7dcaa623a4..4ea95b0c15f5f791d088330596c64ece58effa44)). Consequently, the system only checked the advance_account_id for previous balances, completely ignoring existing credits parked in the standard receivable account. ### Reason to introduce the fix: Restore the dropped logic and the _create_tax_receivable_current_line function. This ensures the tax closing process automatically factors in previous VAT credits from the receivable account, providing accurate closing entries out-of-the-box without requiring extra configuration from the user. opw-6438648
Australian payroll now correctly matches unused leave allocations to each employee when processing multiple payslips at once. This prevents unused leave from being skipped, helping ensure final pay calculations are accurate.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
Fixed an issue where rental returns could fail after using stock transfers for serialized rental products. The system now keeps the pickup and return serial number history correctly, so users can complete later returns without manual errors or blocked workflows.
Original PR description
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return…
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return wizard. **Steps to reproduce** - Activate "Rental Transfers" in the settings - Create a rental product P, tracked by serial number - Create two serial numbers for P - Create and confirm a rental order for 2 units of P - Validate the pickup transfer - Partially validate the return transfer without creating a backorder - Open the rental order and click on "Return" -> The return wizard opens without any available serial number and validation fails with a serial number-related error. **Cause** When clicking on "Return", if there is no pending pickup/return transfer: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/models/sale_order.py#L62-L68 the rental return wizard is opened directly: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/models/sale_order.py#L316 No serial number is prefilled in the wizard because `returned_lot_ids` is empty: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L122-L124 This is because `returnable_lot_ids` is empty as well. `returnable_lot_ids` is computed while generating the wizard lines: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L38 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L47-L48 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L99-L106 and `returnable_lots` is empty because both `pickedup_lots` and `returned_lots` are. Those fields are currently only populated through the rental wizard flow: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L42-L43 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L160-L161 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L166-L167 Since this flow uses stock pickings instead of the rental wizard, those fields are never updated, preventing the wizard from determining any returnable serial number. opw-6150305 Forward-Port-Of: odoo/enterprise#126594 Forward-Port-Of: odoo/enterprise#119257
Refunding a POS order linked to Ecuador's generic "Consumidor Final" customer now shows the intended business error message instead of crashing. This helps cashiers understand why the refund cannot be validated and avoids an unexpected interruption at checkout.
Original PR description
When attempting to refund orders that were created with the "Consumidor Final" customer. The refund validation would crash with a TypeError instead of showing the proper error message. Steps to…
When attempting to refund orders that were created with the "Consumidor Final" customer. The refund validation would crash with a TypeError instead of showing the proper error message. Steps to reproduce: ------------------- In POS with l10n_ec_edi module activated: * Create a new order with "Consumidor Final" as customer * Add products and pay the order * Validate the order * Attempt to refund this order > Observation: The refund validation would crash with: TypeError: Cannot read properties of undefined (reading 'add') at OrderPaymentValidation.isOrderValid Why the fix: ------------ The code was trying to access `this.dialog` which is undefined in the OrderPaymentValidation class context. The dialog service should be accessed via `this.pos.dialog`, which is the correct pattern used throughout the base OrderPaymentValidation class. This fix ensures the error dialog is properly displayed when attempting to refund orders for the anonymous final consumer, instead of crashing with a TypeError. opw-6427113 Forward-Port-Of: odoo/enterprise#126308
This fix prevents an error when a product on a confirmed delivery is later changed into a kit. Kenyan OSCU stock reporting now uses the actual component moves processed, so deliveries can be completed without interruption.
Original PR description
When a stock move's product is turned into a kit after the transfer was confirmed, it explodes it into its component moves and unlinks the original one: https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L358-L363 https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L400 The `_action_done()` override of `l10n_ke_edi_oscu` localisation called `super()` first and then used `self.filtered(...)` on the pre-explosion recordset, which could still reference the now-deleted move, raising a `MissingError`: https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_stock/models/stock_move.py#L96-L99 Use the `super()` return value instead, which reflects the moves that were actually processed. runbot-243291 Forward-Port-Of: odoo/enterprise#127027
This fixes an issue where Swiss payroll settings could assign a Swiss contract type to employees outside Switzerland. The change prevents incorrect contract information from appearing and keeps automated checks stable across versions.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#126520Currently, the is_base_affected condition is only checked on the group tax. However, this condition should also be checked on the child taxes to ensure proper matching. Without checking the child taxes, incorrect matches can occur when the parent tax has is_base_affected set to True, while one of its child taxes has it set to False. Since the parent and child tax configurations are not necessarily synchronized, relying only on the parent tax can lead to incorrect matching. This fix ensures
Original PR description
Currently, the is_base_affected condition is only checked on the group tax. However, this condition should also be checked on the child taxes to ensure proper matching. Without checking the child taxes, incorrect matches can occur when the parent tax has is_base_affected set to True, while one of its child taxes has it set to False. Since the parent and child tax configurations are not necessarily synchronized, relying only on the parent tax can lead to incorrect matching. This fix ensures that is_base_affected is validated at both the parent and child tax levels, preventing such incorrect matches. Enterprise PR - https://github.com/odoo/enterprise/pull/126770
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281686 Forward-Port-Of:
Original PR description
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281686 Forward-Port-Of: odoo/odoo#277818
Steps to reproduce: 0. Create an employee with a fixed working schedule and an overtime ruleset, then enable Absence Management in attendances 1. Go to Attendances and make sure that the employee has no attendances recorded for the previous working day 2. Run the "Attendance: Detect Absences for employees" scheduled action 3. Observe the absence attendance created on the previous working day, along with the amount of overtime hours calculated 4. Create an attendance on the day that the ab
Original PR description
Steps to reproduce: 0. Create an employee with a fixed working schedule and an overtime ruleset, then enable Absence Management in attendances 1. Go to Attendances and make sure that the employee has…
Steps to reproduce: 0. Create an employee with a fixed working schedule and an overtime ruleset, then enable Absence Management in attendances 1. Go to Attendances and make sure that the employee has no attendances recorded for the previous working day 2. Run the "Attendance: Detect Absences for employees" scheduled action 3. Observe the absence attendance created on the previous working day, along with the amount of overtime hours calculated 4. Create an attendance on the day that the absence was recorded 5. Observe that the overtime hours on the absence attendance are not updated 5a. If a full day attendance is recorded on that day, the overtime hours on the absence attendance should change to 0, since we've now recorded hours worked for the day When an absence attendance is created from the Absence Management feature, overtime hours are calculated to represent the time the employee was unjustifiably absent on a given day. If an attendance is later created on the day the absence was recorded, the overtime hours should update to reflect the hours the employee actually worked. Changes were introduced in [this PR](https://github.com/odoo/odoo/pull/272447) that broke this functionality due to the use of `pytz`, which incorrectly calculated timezone offsets. This caused absence attendances to not be picked up by `_get_overtimes_to_update_domain()`, and overtime was not correctly updated. This commit ensures that we get proper time calculations with respect to the employees timezone. [opw-6380343](https://www.odoo.com/odoo/my-tasks/6380343?debug=assets) Forward-Port-Of: odoo/odoo#281613 Forward-Port-Of: odoo/odoo#279556
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Before this commit it was possible to assign an arbitrary account_move to a pos.order by sending it in the order data. This commit prevents that by removing the account_move from the order data before creating the pos.order. Forward-Port-Of: odoo/odoo#280279
Original PR description
Before this commit it was possible to assign an arbitrary account_move to a pos.order by sending it in the order data. This commit prevents that by removing the account_move from the order data before creating the pos.order. Forward-Port-Of: odoo/odoo#280279
`#right-elements` (tax totals block) is floated (`float-end`). Per CSS spec, an `auto` margin on a floated element always resolves to 0, so the `ms-auto` class added by 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 is a no-op, leaving no gutter before adjacent content such as the legal notes paragraph. Partial revert of 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 Steps to reproduce: ------------------- * On a tax, set a multi-line paragraph in Legal Notes (Advanced Options tab) * Apply it on an
Original PR description
`#right-elements` (tax totals block) is floated (`float-end`). Per CSS spec, an `auto` margin on a floated element always resolves to 0, so the `ms-auto` class added by…
`#right-elements` (tax totals block) is floated (`float-end`). Per CSS spec, an `auto` margin on a floated element always resolves to 0, so the `ms-auto` class added by 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 is a no-op, leaving no gutter before adjacent content such as the legal notes paragraph. Partial revert of 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 Steps to reproduce: ------------------- * On a tax, set a multi-line paragraph in Legal Notes (Advanced Options tab) * Apply it on an invoice line and print/preview the invoice PDF > Observation: the legal notes text touches/overlaps the tax totals table, with no spacing. Why the fix: ------------ `ms-5` gives `#right-elements` a real left margin, restoring the spacing lost when `ms-auto` (a no-op on floats) replaced it. BEFORE: <img width="596" height="753" alt="Screenshot 2026-08-05 at 10 52 00" src="https://github.com/user-attachments/assets/c596d6e9-4b61-434c-9b38-3ff0797e7fa7" /> AFTER: <img width="494" height="596" alt="Screenshot 2026-08-05 at 10 51 44" src="https://github.com/user-attachments/assets/f9a1792d-22c2-4586-9a75-53c4695f17e4" /> opw-6384085 Forward-Port-Of: odoo/odoo#280654
Description of the issue/feature this PR addresses: the contents of _t() calls in our data are extracted by the translation process. Having _t squished means that a part of the unsquishing logic would need to be implemented in the translation extraction process, which would be tedious to maintain. Task-6452075 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Description of the issue/feature this PR addresses: the contents of _t() calls in our data are extracted by the translation process. Having _t squished means that a part of the unsquishing logic would need to be implemented in the translation extraction process, which would be tedious to maintain. Task-6452075 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
l10n_vn_pos_symbol carries groups='base.group_system,point_of_sale.group_pos_manager', but _prepare_invoice_vals reads it while an ORDINARY salesperson closes an order: _process_saved_order calls _generate_pos_order_invoice as the acting user, with no sudo anywhere on the way. So on a Vietnamese POS with auto-send to SInvoice enabled, a user in point_of_sale.group_pos_user alone hit Access Denied by ACLs for operation: read, model: pos.config, fields: l10n_vn_pos_symbol and the order nev
Original PR description
l10n_vn_pos_symbol carries groups='base.group_system,point_of_sale.group_pos_manager', but _prepare_invoice_vals reads it while an ORDINARY salesperson closes an order: _process_saved_order calls…
l10n_vn_pos_symbol carries groups='base.group_system,point_of_sale.group_pos_manager', but _prepare_invoice_vals reads it while an ORDINARY salesperson closes an order: _process_saved_order calls _generate_pos_order_invoice as the acting user, with no sudo anywhere on the way. So on a Vietnamese POS with auto-send to SInvoice enabled, a user in point_of_sale.group_pos_user alone hit
Access Denied by ACLs for operation: read, model: pos.config, fields: l10n_vn_pos_symbol
and the order never finished syncing - the receipt screen's Done button stayed disabled and the checkout dead-ended.
This is reachable from the module's own test suite, which is what makes it more than theoretical: point_of_sale's start_pos_tour logs in as `pos_user` (group_pos_user, NOT group_pos_manager - that is `pos_admin`), so test_l10n_vn_edi_pos_refund_reason_tour exercises exactly the unprivileged path.
Reading the config as sudo is the right resolution rather than widening the field's groups: the salesperson is never shown the symbol or allowed to change it, it is only stamped onto the invoice their own sale produces, which is what a per-POS configuration field is for. Both symbols are read through the same sudo recordset so the company-level fallback keeps working identically.
Reproduced and verified on v18_full (5-repo addons path):
before - FAILED: [13/36] Tour L10nVnEdiPosRefundReasonTour -> "go to next screen from
receipt"; 1 failed, 0 error(s) of 1 tests
after - tour succeeded for both tours in the class; 0 failed, 0 error(s) of 2 tests,
and no ACL line left in the log
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281621
Forward-Port-Of: odoo/odoo#281119Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device Issue: The second order is rejected by TicketBAI with the error 5040, the invoice number is already registered for that issuer, series and year. Cause: The invoice number sent to TicketBAI is the pos.order name. That name is built by _get_order_name_from_pos_reference out of the last part of
Original PR description
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device…
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device Issue: The second order is rejected by TicketBAI with the error 5040, the invoice number is already registered for that issuer, series and year. Cause: The invoice number sent to TicketBAI is the pos.order name. That name is built by _get_order_name_from_pos_reference out of the last part of pos_reference only, which is the receipt counter each device keeps in its own browser local storage and which restarts at 1. Both devices therefore name their first order "<config> - 000001", and _get_tbai_seq_from_name derives the same SerieFactura and NumFactura for the two of them. Fix: Send pos_reference instead. It is the number printed on the customer receipt and it also holds the device identifier, allocated by the device sequence of the config, which is what makes it unique. The device part ends up as the series and the counter as the number, so the numbering stays sequential inside the series of each device, and the series still starts with the year the duplicate check is made on. Both stay well below the 20 characters SerieFactura and NumFactura are limited to. The name of the refunded document is taken from the same helper, so a credit note cannot reference a number that was never registered. The pos.order name itself is not unique on any version from 19.0 on, but it cannot be changed in stable. opw-6442837 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280621
The test "Image cropper Enter saves and Escape closes in website builder" fails indeterministically on runbot. The error seems to have appeared just after the merging of [1], which introduced a speed-up in test execution. The failure is caused by an image being "invisible" when queried by `contains()`. The most likely cause is that the image is not yet fetched by the time the test runs. The image source is replaced with a `base64` `data:` URL, so that no fetching is required for this
Original PR description
The test "Image cropper Enter saves and Escape closes in website builder" fails indeterministically on runbot. The error seems to have appeared just after the merging of [1], which introduced a speed-up in test execution. The failure is caused by an image being "invisible" when queried by `contains()`. The most likely cause is that the image is not yet fetched by the time the test runs. The image source is replaced with a `base64` `data:` URL, so that no fetching is required for this test. [1]: https://github.com/odoo/odoo/pull/279584 runbot-944664 Forward-Port-Of: odoo/odoo#280333
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/685ffdada8 [REL] 19.2.25 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/9e09359384 [FIX] functions: omit functions from the squisher [Task: 6452075](https://www.odoo.com/odoo/2328/tasks/6452075) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authore
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/685ffdada8 [REL] 19.2.25 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/9e09359384 [FIX] functions: omit functions from the squisher [Task: 6452075](https://www.odoo.com/odoo/2328/tasks/6452075) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Automatically update the ruff config to the latest version generated on runbot
Original PR description
Automatically update the ruff config to the latest version generated on runbot
Before this commit, the default einvoice format was changed only when the partner was french and had a vat number, but we want to ease that condition and do it only if the partner is french. task-6303174 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278158 Forward-Port-Of: odoo/odoo#270720
Original PR description
Before this commit, the default einvoice format was changed only when the partner was french and had a vat number, but we want to ease that condition and do it only if the partner is french. task-6303174 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278158 Forward-Port-Of: odoo/odoo#270720
We now dpkg configure before every upgrade to ensure the IoT Box is ready to upgrade properly and `apt` commands won't fail. Forward-Port-Of: odoo/odoo#281693
Original PR description
We now dpkg configure before every upgrade to ensure the IoT Box is ready to upgrade properly and `apt` commands won't fail. Forward-Port-Of: odoo/odoo#281693
Steps to reproduce the bug: - Enable 2-step delivery (pick + ship) on a warehouse. - Set both rules on the delivery route to "Pull" (instead of the default Pull + Push): - Pick rule (Stock -> Output): action = Pull, procure_method = make_to_stock - Ship rule (Output -> Customers): action = Pull, procure_method = make_to_order - Create a sale order for qty 1 and confirm it. - Validate the Pick transfer. - Return the Pick transfer. - Cancel the sale order. - Set it back to quotati
Original PR description
Steps to reproduce the bug: - Enable 2-step delivery (pick + ship) on a warehouse. - Set both rules on the delivery route to "Pull" (instead of the default Pull + Push): - Pick rule (Stock ->…
Steps to reproduce the bug:
- Enable 2-step delivery (pick + ship) on a warehouse.
- Set both rules on the delivery route to "Pull" (instead of the default Pull + Push):
- Pick rule (Stock -> Output): action = Pull, procure_method = make_to_stock
- Ship rule (Output -> Customers): action = Pull, procure_method = make_to_order
- Create a sale order for qty 1 and confirm it.
- Validate the Pick transfer.
- Return the Pick transfer.
- Cancel the sale order.
- Set it back to quotation and confirm it again.
Problem:
The newly created delivery (ship) move ends up asking for a wrong, inflated quantity instead of the ordered one (e.g. 3 times the ordered qty for the scenario above; the multiplier depends on the number of prior confirm/cancel/return cycles).
`_action_cancel` (addons/sale_stock/models/sale_order.py) only cancels pickings that are not `done`, so after the pick is validated and returned, cancelling the SO only cancels the still-pending ship move. The pick move and its return stay `done` and linked to the sale order line.
`SaleOrderLine._get_outgoing_incoming_moves` determines which rule "started" the pull/push chain by picking the rule of the first surviving (non-cancelled) move, grouped by warehouse: https://github.com/odoo/odoo/blob/d7bad3dc6c068ffe8643ecb01da1865d743bfb8f/addons/sale_stock/models/sale_order_line.py#L338-L347
Once the ship move is cancelled, it is excluded from that computation, so the Pick rule is wrongly identified as the "triggering" rule instead of the Ship rule. The done pick move and its return share that rule, so they both end up wrongly classified as incoming (returned) quantities instead of being excluded from the computation like before the cancellation, corrupting `_get_qty_procurement`. On reconfirm, `_action_launch_stock_rule` computes
`product_qty = product_uom_qty - qty`, inflating the quantity requested on the new ship move.
Solution:
Identify the triggering rule from the sale order line's full move history, including cancelled moves, so cancelling a move later doesn't change which rule is considered to have started the chain.
opw-6364113
Forward-Port-Of: odoo/odoo#280280Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions 3. Create invoice with ar_001 partner 4. Confirm the invoice 5. Try to create credit note → Error: KeyError: 'en_US' Root Cause: The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB di
Original PR description
Steps to Reproduce the Error (Odoo SaaS 19.2): 1. Install l10n_gcc_invoice localization & Accounting 2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings >…
Steps to Reproduce the Error (Odoo SaaS 19.2):
1. Install l10n_gcc_invoice localization & Accounting
2. Activate Arabic language (ar_001) and add Default Terms and Conditions in Settings > Configuration > Customer Invoices > Default Terms and Conditions
3. Create invoice with ar_001 partner
4. Confirm the invoice
5. Try to create credit note → Error: KeyError: 'en_US'
Root Cause:
The _load_narration_translation() workaround reads raw invoice_terms from DB and injects the entire JSONB dict directly into cache, bypassing ORM field conversion. When Odoo 19.2's improved ORM conversion runs, it creates nested JSON in narration instead of a flat structure.
Timeline:
- bedf1cb66fbb: Workaround added to prevent T&C duplication in preview
- 75f050b9650d: Root cause fixed in report template (conditional display) → Made _load_narration_translation() redundant
- 4e4156536bc9: Odoo 19.2 improved ORM conversion → Now conflicts with the redundant workaround, causing nested JSON
How It Breaks:
1. Invoice creation: _load_narration_translation() injects raw dict into cache
2. ORM writes: nested JSON stored: {ar_001: {en_US: ., ar_001: Arabic}}
3. Credit note creation: copy_translations() expects flat structure → Crashes: KeyError: 'en_US'
Why It's Safe to Remove:
Report template already prevents T&C duplication (commit 75f050b9650d). Removing the workaround restores proper credit note creation without breaking T&C display.
Changes:
- Remove moves._load_narration_translation() in create()
- Remove out self.filtered('id')._load_narration_translation() in _compute_narration()
opw : 6284943
Forward-Port-Of: odoo/odoo#271037Before this commit, a call test where a participant card appears while in a call fails with: Unimplemented server route: /mail/rtc/channel/upgrade_connection The client sends that request a few seconds later, so only a test still running by then fails, as `Adjust view: switching between Tiled and Spotlight` does on master under load. This happens because the other participants of a test call are only records, so their peer connection negotiates no transceiver, and asking it to downl
Original PR description
Before this commit, a call test where a participant card appears while in a call fails with:
Unimplemented server route: /mail/rtc/channel/upgrade_connection
The client sends that request a few seconds later, so only a test still running by then fails, as `Adjust view: switching between Tiled and Spotlight` does on master under load.
This happens because the other participants of a test call are only records, so their peer connection negotiates no transceiver, and asking it to download the video of the card schedules a connection recovery instead. Recovering without a TURN server, which a test never has, asks the server to move the call to an SFU with that route, and the mock server implements join_call and leave_call only.
This commit registers the route with an empty handler, as no test has an SFU server to join.
Forward-Port-Of: odoo/odoo#281736Previously, refreshing the PoS caused categories with sequence = 0 to fall back to ID-based sorting from IndexedDB. Sequence-based ordering was already fixed in this [pr](https://github.com/odoo/odoo/pull/207172), but the fallback for sequence 0 still sorted by ID. This change ensures categories with sequence = 0 follow the expected ordering when refreshing. Task-6185359 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merge
Original PR description
Previously, refreshing the PoS caused categories with sequence = 0 to fall back to ID-based sorting from IndexedDB. Sequence-based ordering was already fixed in this [pr](https://github.com/odoo/odoo/pull/207172), but the fallback for sequence 0 still sorted by ID. This change ensures categories with sequence = 0 follow the expected ordering when refreshing. Task-6185359 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273954
Before this commit, some layouts had the customer address on the right (light, boxed, bold, striped) and some had it on the left (bubble, wave, folder). For the latter, when an information_block with the address existed, it would be inserted before the address pushing it further right. This was inconsistent since the address position should not depend on whether an information_block is present or not. The customer address must stay in a fixed place to match the transparent window of the
Original PR description
Before this commit, some layouts had the customer address on the right (light, boxed, bold, striped) and some had it on the left (bubble, wave, folder). For the latter, when an information_block with…
Before this commit, some layouts had the customer address on the right (light, boxed, bold, striped) and some had it on the left (bubble, wave, folder). For the latter, when an information_block with the address existed, it would be inserted before the address pushing it further right. This was inconsistent since the address position should not depend on whether an information_block is present or not. The customer address must stay in a fixed place to match the transparent window of the envelope when sending a physical letter by snailmail. This commit fixes this issue by ensuring that in all cases the customer address position stays fixed regardless of the presence or absence of the information_block and regardless of the layout used for the letter. It also fixes the addresses displayed on the sale order report: 1) If invoicing address = partner address != shipping address or invoicing address != partner address = shipping address then the three addresses would be printed, even though 2 addresses are identical. 2) The shipping address and the invoicing address are now printed horizontally rather than vertically to get rid of the resulting large blank block under the partner address in that case. backport of: https://github.com/odoo/odoo/pull/276622 task-6340467 Forward-Port-Of: odoo/odoo#273640
Steps to reproduce: ------------------- 1. Install `hr` module 2. Create two employees (e.g., emp1 and emp2) and assign emp1 as the manager of emp2 → emp2 is now a direct subordinate of emp1 3. In the employee list view, apply the custom filter "Direct subordinates is set" (child_ids != False) → emp1 appears in the results as expected 4. Archive emp2 5. Apply the same filter again → emp1 still appears in the results even though it has no active subordinates Issue
Original PR description
Steps to reproduce: ------------------- 1. Install `hr` module 2. Create two employees (e.g., emp1 and emp2) and assign emp1 as the manager of emp2 → emp2 is now a direct subordinate of emp1 3. In…
Steps to reproduce: ------------------- 1. Install `hr` module 2. Create two employees (e.g., emp1 and emp2) and assign emp1 as the manager of emp2 → emp2 is now a direct subordinate of emp1 3. In the employee list view, apply the custom filter "Direct subordinates is set" (child_ids != False) → emp1 appears in the results as expected 4. Archive emp2 5. Apply the same filter again → emp1 still appears in the results even though it has no active subordinates Issue: ------ When an employee (e.g., `emp2`) is archived, their manager (`emp1`) should no longer appear in the "Direct subordinates is set" (child_ids != False) filter — since `emp1` no longer has any active subordinates. However, `emp1` still appears in the search results after `emp2` is archived, because the underlying EXISTS subquery checks all subordinates regardless of their active state. Cause: -------- Before this commit 5ef007a, `osv.expression`, filtering on a One2many field would automatically search against [active co-records ](https://github.com/odoo/odoo/blob/5f65e92d7fa341193df53f5aba1620b596f9a1ec/odoo/osv/expression.py#L1260-L1265)only by default. After that commit, the `condition_to_sql` method in `_RelationalMulti` constructs the comodel with [active_test=False](https://github.com/odoo/odoo/blob/463ca4cf867812890c17d1e1abf7640b04f70ad0/odoo/orm/fields_relational.py#L672-L686) when resolving relational field conditions. This causes the EXISTS subquery generated for `child_ids != False` to compare against all subordinates. (including archived ones rather than active ones only). Solution: --------- Added a callable `domain` attribute on the `child_ids` field definition so that only active subordinates are considered by default. This ensures [get_comodel_domain()](https://github.com/odoo/odoo/blob/2d8b24a791b6fe6bb214c32d4fb58b3d46eca70b/odoo/orm/fields_relational.py#L75-L85) returns a server-side domain that filters out archived subordinates, making the `child_ids != False` filter behave as expected. **NOTE:** > The ORM uses the **active_test** flag when doing searches. Having in [1, 2, 3] in domains bypasses the search method because we suppose that we already searched to find these ids. For hierarchical resolution, we bypass rights and active_test. The result is that inactive records are considered in the result. confirmed with the framework team, and it is intended behaviour. However, this is not the expected behaviour for the direct subordinates case in `hr`. The fix is therefore applied at the field level by explicitly declaring a domain on `child_ids` to filter out archived subordinates. ORM commit: https://github.com/odoo-dev/odoo/commit/12eae5c85fa7facb299f0f1bf1fdd62e3ff82aa5 opw-6193104 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281222 Forward-Port-Of: odoo/odoo#266658
During the backport we discovered a programming error in `_get_peppol_document_params`. The super function can return `None` values for both `edi_user` and `document`. This can lead to a traceback when the variables are used. We do not have any known issues in 18.0 or higher versions. (Probably because the move send was heavily refactored.) But better safe than sorry. It could maybe happen with the batch sending or in case the "surrounding" logic is refactored in the future. task-None
Original PR description
During the backport we discovered a programming error in `_get_peppol_document_params`. The super function can return `None` values for both `edi_user` and `document`. This can lead to a traceback when the variables are used. We do not have any known issues in 18.0 or higher versions. (Probably because the move send was heavily refactored.) But better safe than sorry. It could maybe happen with the batch sending or in case the "surrounding" logic is refactored in the future. task-None Forward-Port-Of: odoo/odoo#279317