Wednesday, August 27, 2025
49 changes · saas-18.4
Enhancements to existing features
SMS message rendering can now receive extra contextual information through a dedicated extension point. This makes it easier for added modules to customize generated SMS content without overriding broader composer logic, reducing maintenance risk.
Original PR description
In add-ons may need to pass additional context to body render function, both `_render_field`, and `_render_template` support this but the `sms.composer` didn't implement a proper way to pass additional context to them. overwrite `_prepare_body_values` for just passing `add_context` to render functions is not a good practice. In this PR I add a `_get_body_additional_context` to it, so any module can overwrite that function to pass additional context to render functions. Forward-Port-Of: odoo/odoo#208355
This change speeds up internal accounting localization tests by adding temporary database indexes while the tests run, then removing them afterward. It reduces wasted test time and helps build systems finish validation faster without changing customer-facing accounting behavior.
Original PR description
During the second half of `test_all_l10n`, we keep deleting `account.account` records (hundreds to low thousand every iteration). This deletion turns out to account (heh) for about 15% of the test's…
During the second half of `test_all_l10n`, we keep deleting `account.account` records (hundreds to low thousand every iteration). This deletion turns out to account (heh) for about 15% of the test's run time running locally (5mn out of 30). And per the explain, this is largely from executing `ON DELETE` constraints: since accounts are rarely deleted, the forward-only M2Os (used to go from a record to an account) are not generally indexes, which causes a full scan of the non-account table on deletion of accounts, which... can be quite slow if the non-account table is large, e.g. sample `EXPLAIN ANALYZE` for one of the `DELETE FROM account_account`:
Trigger for constraint account_fiscal_position_account_account_src_id_fkey on account_account: time=30.040 calls=1000
Trigger for constraint account_fiscal_position_account_account_dest_id_fkey on account_account: time=20.977 calls=1000
Trigger for constraint account_account_tax_default_rel_account_id_fkey on account_account: time=16.423 calls=1000
Trigger for constraint account_account_res_company_rel_account_account_id_fkey on account_account: time=18.848 calls=1000
Trigger for constraint account_account_account_tag_account_account_id_fkey on account_account: time=12.396 calls=1000
Trigger for constraint account_journal_default_account_id_fkey on account_account: time=207.759 calls=1000
Trigger for constraint account_journal_suspense_account_id_fkey on account_account: time=131.019 calls=1000
Trigger for constraint account_journal_non_deductible_account_id_fkey on account_account: time=126.656 calls=1000
Trigger for constraint account_journal_profit_account_id_fkey on account_account: time=128.753 calls=1000
Trigger for constraint account_journal_loss_account_id_fkey on account_account: time=125.281 calls=1000
Trigger for constraint res_company_transfer_account_id_fkey on account_account: time=85.604 calls=1000
Trigger for constraint res_company_default_cash_difference_income_account_id_fkey on account_account: time=75.154 calls=1000
Trigger for constraint res_company_default_cash_difference_expense_account_id_fkey on account_account: time=73.173 calls=1000
Trigger for constraint res_company_account_journal_suspense_account_id_fkey on account_account: time=73.336 calls=1000
Trigger for constraint res_company_account_journal_early_pay_discount_gain_accoun_fkey on account_account: time=73.741 calls=1000
Trigger for constraint res_company_account_journal_early_pay_discount_loss_accoun_fkey on account_account: time=73.402 calls=1000
Trigger for constraint res_company_income_currency_exchange_account_id_fkey on account_account: time=74.586 calls=1000
Trigger for constraint res_company_expense_currency_exchange_account_id_fkey on account_account: time=74.678 calls=1000
Trigger for constraint res_company_account_default_pos_receivable_account_id_fkey on account_account: time=77.105 calls=1000
Trigger for constraint res_company_expense_accrual_account_id_fkey on account_account: time=77.000 calls=1000
Trigger for constraint res_company_revenue_accrual_account_id_fkey on account_account: time=76.399 calls=1000
Trigger for constraint res_company_account_cash_basis_base_account_id_fkey on account_account: time=77.996 calls=1000
Trigger for constraint res_company_account_discount_income_allocation_id_fkey on account_account: time=77.799 calls=1000
Trigger for constraint res_company_account_discount_expense_allocation_id_fkey on account_account: time=78.145 calls=1000
Trigger for constraint res_company_income_account_id_fkey on account_account: time=79.625 calls=1000
Trigger for constraint res_company_expense_account_id_fkey on account_account: time=79.421 calls=1000
Trigger for constraint account_tax_group_tax_payable_account_id_fkey on account_account: time=103.659 calls=1000
Trigger for constraint account_tax_group_tax_receivable_account_id_fkey on account_account: time=75.211 calls=1000
Trigger for constraint account_tax_group_advance_tax_payment_account_id_fkey on account_account: time=72.384 calls=1000
Trigger for constraint account_tax_cash_basis_transition_account_id_fkey on account_account: time=954.139 calls=1000
Trigger for constraint account_tax_repartition_line_account_id_fkey on account_account: time=1445.578 calls=1000
Trigger for constraint account_reconcile_model_line_account_id_fkey on account_account: time=71.619 calls=1000
Trigger for constraint account_move_line_account_id_fkey on account_account: time=140.720 calls=1000
Trigger for constraint account_payment_outstanding_account_id_fkey on account_account: time=17.682 calls=1000
Trigger for constraint account_payment_destination_account_id_fkey on account_account: time=6.791 calls=1000
Trigger for constraint account_payment_method_line_payment_account_id_fkey on account_account: time=75.530 calls=1000
Trigger for constraint account_analytic_line_general_account_id_fkey on account_account: time=81.989 calls=1000
Trigger for constraint account_automatic_entry_wizard_destination_account_id_fkey on account_account: time=8.967 calls=1000
Trigger for constraint account_payment_register_writeoff_account_id_fkey on account_account: time=9.166 calls=1000
Trigger for constraint account_accrued_orders_wizard_account_id_fkey on account_account: time=7.863 calls=1000
Trigger for constraint account_account_account_merge_wizard_re_account_account_id_fkey on account_account: time=7.338 calls=1000
Trigger for constraint account_merge_wizard_line_account_id_fkey on account_account: time=7.706 calls=1000
Trigger for constraint res_company_deferred_expense_account_id_fkey on account_account: time=126.271 calls=1000
Trigger for constraint res_company_deferred_revenue_account_id_fkey on account_account: time=98.607 calls=1000
Trigger for constraint account_account_account_auto_reconcile__account_account_id_fkey on account_account: time=8.921 calls=1000
Trigger for constraint account_reconcile_wizard_account_id_fkey on account_account: time=8.330 calls=1000
Trigger for constraint account_model_rel_account_account_id_fkey on account_account: time=27.264 calls=1000
Trigger for constraint account_transfer_model_line_account_id_fkey on account_account: time=39.033 calls=1000
Trigger for constraint account_fiscal_position_avatax_invoice_account_id_fkey on account_account: time=83.360 calls=1000
Trigger for constraint account_fiscal_position_avatax_refund_account_id_fkey on account_account: time=60.023 calls=1000
Trigger for constraint account_account_account_import_summary__account_account_id_fkey on account_account: time=8.251 calls=1000
Trigger for constraint res_company_account_revaluation_expense_provision_account__fkey on account_account: time=107.339 calls=1000
Trigger for constraint res_company_account_revaluation_income_provision_account_i_fkey on account_account: time=100.037 calls=1000
Trigger for constraint account_account_exclude_res_currency_pr_account_account_id_fkey on account_account: time=9.025 calls=1000
Trigger for constraint account_report_budget_item_account_id_fkey on account_account: time=7.600 calls=1000
Trigger for constraint account_payment_withholding_line_account_id_fkey on account_account: time=7.814 calls=1000
Trigger for constraint res_company_withholding_tax_base_account_id_fkey on account_account: time=116.893 calls=1000
Trigger for constraint account_payment_register_withholding_outstanding_account_i_fkey on account_account: time=8.580 calls=1000
Trigger for constraint account_payment_register_withholding_line_account_id_fkey on account_account: time=8.799 calls=1000
Trigger for constraint res_company_l10n_ee_rounding_difference_loss_account_id_fkey on account_account: time=115.461 calls=1000
Trigger for constraint res_company_l10n_ee_rounding_difference_profit_account_id_fkey on account_account: time=114.827 calls=1000
Trigger for constraint account_journal_l10n_tr_default_sales_return_account_id_fkey on account_account: time=305.506 calls=1000
Trigger for constraint res_company_account_production_wip_account_id_fkey on account_account: time=125.388 calls=1000
Trigger for constraint res_company_account_production_wip_overhead_account_id_fkey on account_account: time=117.769 calls=1000
Trigger for constraint stock_location_valuation_in_account_id_fkey on account_account: time=104.378 calls=1000
Trigger for constraint stock_location_valuation_out_account_id_fkey on account_account: time=67.309 calls=1000
Trigger for constraint stock_valuation_layer_revaluation_account_id_fkey on account_account: time=8.817 calls=1000
Trigger for constraint res_company_l10n_fr_rounding_difference_loss_account_id_fkey on account_account: time=127.732 calls=1000
Trigger for constraint res_company_l10n_fr_rounding_difference_profit_account_id_fkey on account_account: time=124.773 calls=1000
Trigger for constraint res_company_l10n_in_withholding_account_id_fkey on account_account: time=124.847 calls=1000
Trigger for constraint res_company_l10n_nl_rounding_difference_loss_account_id_fkey on account_account: time=131.094 calls=1000
Trigger for constraint res_company_l10n_nl_rounding_difference_profit_account_id_fkey on account_account: time=132.013 calls=1000
Trigger for constraint mrp_workcenter_expense_account_id_fkey on account_account: time=14.578 calls=1000
Trigger for constraint mrp_account_wip_accounting_line_account_id_fkey on account_account: time=8.530 calls=1000
Trigger for constraint account_payment_force_outstanding_account_id_fkey on account_account: time=11.336 calls=1000
Trigger for constraint pos_payment_method_outstanding_account_id_fkey on account_account: time=11.554 calls=1000
Trigger for constraint pos_payment_method_receivable_account_id_fkey on account_account: time=6.654 calls=1000
Trigger for constraint pos_close_session_wizard_account_id_fkey on account_account: time=7.825 calls=1000
Trigger for constraint res_company_downpayment_account_id_fkey on account_account: time=137.312 calls=1000
Trigger for constraint res_company_l10n_bd_corporate_tax_liability_fkey on account_account: time=143.026 calls=1000
Trigger for constraint res_company_l10n_bd_corporate_tax_expense_fkey on account_account: time=141.801 calls=1000
Trigger for constraint account_move_l10n_de_datev_main_account_id_fkey on account_account: time=3874.682 calls=1000
Trigger for constraint stock_landed_cost_lines_account_id_fkey on account_account: time=14.898 calls=1000
Trigger for constraint account_account_account_asset_rel_account_account_id_fkey on account_account: time=9.640 calls=1000
Trigger for constraint account_asset_account_asset_id_fkey on account_account: time=11.687 calls=1000
Trigger for constraint account_asset_account_depreciation_id_fkey on account_account: time=6.551 calls=1000
Trigger for constraint account_asset_account_depreciation_expense_id_fkey on account_account: time=6.300 calls=1000
Trigger for constraint res_company_gain_account_id_fkey on account_account: time=210.699 calls=1000
Trigger for constraint res_company_loss_account_id_fkey on account_account: time=180.965 calls=1000
Trigger for constraint asset_modify_account_asset_id_fkey on account_account: time=10.665 calls=1000
Trigger for constraint asset_modify_account_asset_counterpart_id_fkey on account_account: time=5.466 calls=1000
Trigger for constraint asset_modify_account_depreciation_id_fkey on account_account: time=5.353 calls=1000
Trigger for constraint asset_modify_account_depreciation_expense_id_fkey on account_account: time=5.438 calls=1000
Trigger for constraint res_company_l10n_ae_tax_report_liabilities_account_fkey on account_account: time=176.808 calls=1000
Trigger for constraint res_company_l10n_ae_tax_report_expenses_account_fkey on account_account: time=172.302 calls=1000
Trigger for constraint res_company_l10n_ae_tax_report_asset_account_fkey on account_account: time=170.480 calls=1000
Trigger for constraint res_company_l10n_ar_tax_base_account_id_fkey on account_account: time=171.774 calls=1000
Trigger for constraint soda_account_mapping_account_id_fkey on account_account: time=9.239 calls=1000
Trigger for constraint res_company_l10n_ec_tax_base_sale_account_id_fkey on account_account: time=176.779 calls=1000
Trigger for constraint res_company_l10n_ec_tax_base_purchase_account_id_fkey on account_account: time=175.159 calls=1000
Trigger for constraint account_loan_long_term_account_id_fkey on account_account: time=13.823 calls=1000
Trigger for constraint account_loan_short_term_account_id_fkey on account_account: time=7.044 calls=1000
Trigger for constraint account_loan_expense_account_id_fkey on account_account: time=5.934 calls=1000
Trigger for constraint res_company_l10n_cl_factoring_counterpart_account_id_fkey on account_account: time=193.722 calls=1000
Trigger for constraint res_company_exemption_doctor_master_account_id_fkey on account_account: time=201.309 calls=1000
Trigger for constraint res_company_exemption_bachelor_account_id_fkey on account_account: time=200.476 calls=1000
Trigger for constraint res_company_exemption_bachelor_capping_account_id_fkey on account_account: time=200.465 calls=1000
Trigger for constraint res_company_partner_id_fkey on res_company: time=0.208 calls=10
Trigger for constraint res_company_currency_id_fkey on res_company: time=0.018 calls=10
Trigger for constraint res_company_paperformat_id_fkey on res_company: time=0.014 calls=10
Trigger for constraint res_company_create_uid_fkey on res_company: time=0.015 calls=10
Trigger for constraint res_company_write_uid_fkey on res_company: time=0.009 calls=10
Trigger for constraint res_company_resource_calendar_id_fkey on res_company: time=0.023 calls=10
Trigger for constraint res_company_transfer_account_id_fkey on res_company: time=0.002 calls=9
Trigger for constraint res_company_default_cash_difference_income_account_id_fkey on res_company: time=0.055 calls=10
Trigger for constraint res_company_default_cash_difference_expense_account_id_fkey on res_company: time=0.030 calls=10
Trigger for constraint res_company_account_journal_suspense_account_id_fkey on res_company: time=0.002 calls=8
Trigger for constraint res_company_account_journal_early_pay_discount_gain_accoun_fkey on res_company: time=0.002 calls=7
Trigger for constraint res_company_account_journal_early_pay_discount_loss_accoun_fkey on res_company: time=0.001 calls=4
Trigger for constraint res_company_income_currency_exchange_account_id_fkey on res_company: time=0.029 calls=10
Trigger for constraint res_company_expense_currency_exchange_account_id_fkey on res_company: time=0.001 calls=5
Trigger for constraint res_company_batch_payment_sequence_id_fkey on res_company: time=0.016 calls=10
Trigger for constraint res_company_account_default_pos_receivable_account_id_fkey on res_company: time=0.001 calls=2
Trigger for constraint res_company_account_fiscal_country_id_fkey on res_company: time=0.015 calls=10
Trigger for constraint res_company_income_account_id_fkey on res_company: time=0.002 calls=6
Trigger for constraint res_company_expense_account_id_fkey on res_company: time=0.001 calls=3
Trigger for constraint res_company_deferred_expense_account_id_fkey on res_company: time=0.000 calls=1
Trigger for constraint res_company_nomenclature_id_fkey on res_company: time=0.012 calls=10
Trigger for constraint res_company_internal_transit_location_id_fkey on res_company: time=0.014 calls=10
Trigger for constraint res_company_stock_mail_confirmation_template_id_fkey on res_company: time=0.013 calls=10
Trigger for constraint res_company_documents_fleet_folder_fkey on res_company: time=0.016 calls=10
Trigger for constraint res_company_documents_hr_folder_fkey on res_company: time=0.010 calls=10
Trigger for constraint res_company_documents_employee_folder_id_fkey on res_company: time=0.011 calls=10
Trigger for constraint res_company_documents_project_folder_id_fkey on res_company: time=0.009 calls=10
Trigger for constraint res_company_stock_sms_confirmation_template_id_fkey on res_company: time=0.012 calls=10
Trigger for constraint res_company_recruitment_folder_id_fkey on res_company: time=0.010 calls=10
Trigger for constraint res_company_project_time_mode_id_fkey on res_company: time=0.019 calls=10
Trigger for constraint res_company_timesheet_encode_uom_id_fkey on res_company: time=0.011 calls=10
Trigger for constraint res_company_internal_project_id_fkey on res_company: time=0.015 calls=10
Trigger for constraint res_company_leave_timesheet_task_id_fkey on res_company: time=0.015 calls=10
Trigger for constraint res_company_rental_loc_id_fkey on res_company: time=0.011 calls=10
Trigger for constraint res_company_l10n_ch_delegate_country_id_fkey on res_company: time=0.013 calls=10
Trigger for constraint res_company_l10n_eg_annual_leave_type_id_fkey on res_company: time=0.014 calls=10
Accumulated across the entire test:
account_account_account_asset_rel_account_account_id_fkey: 367.89
account_account_account_auto_reconcile__account_account_id_fkey: 369.314
account_account_account_import_summary__account_account_id_fkey: 308.894
account_account_account_merge_wizard_re_account_account_id_fkey: 258.345
account_account_account_tag_account_account_id_fkey: 437.58
account_account_exclude_res_currency_pr_account_account_id_fkey: 364.079
account_account_res_company_rel_account_account_id_fkey: 676.195
account_account_tax_default_rel_account_id_fkey: 616.155
account_accrued_orders_wizard_account_id_fkey: 281.117
account_analytic_line_general_account_id_fkey: 2920.52
account_asset_account_asset_id_fkey: 435.021
account_asset_account_depreciation_expense_id_fkey: 225.966
account_asset_account_depreciation_id_fkey: 243.045
account_automatic_entry_wizard_destination_account_id_fkey: 333.281
account_fiscal_position_account_account_dest_id_fkey: 764.004
account_fiscal_position_account_account_src_id_fkey: 1127.7
account_fiscal_position_avatax_invoice_account_id_fkey: 2903.72
account_fiscal_position_avatax_refund_account_id_fkey: 2243.92
account_journal_default_account_id_fkey: 8123.53
account_journal_l10n_tr_default_sales_return_account_id_fkey: 13035
account_journal_loss_account_id_fkey: 4810.37
account_journal_non_deductible_account_id_fkey: 5057.85
account_journal_profit_account_id_fkey: 5063.26
account_journal_suspense_account_id_fkey: 5492.64
account_loan_expense_account_id_fkey: 222.776
account_loan_long_term_account_id_fkey: 553.955
account_loan_short_term_account_id_fkey: 259.905
account_merge_wizard_line_account_id_fkey: 265.135
account_model_rel_account_account_id_fkey: 927.993
account_move_l10n_de_datev_main_account_id_fkey: 122923
account_move_line_account_id_fkey: 4000.68
account_payment_destination_account_id_fkey: 265.653
account_payment_force_outstanding_account_id_fkey: 459.209
account_payment_method_line_payment_account_id_fkey: 2660.46
account_payment_outstanding_account_id_fkey: 575.21
account_payment_register_withholding_line_account_id_fkey: 319.363
account_payment_register_withholding_outstanding_account_i_fkey: 383.508
account_payment_register_writeoff_account_id_fkey: 341.615
account_payment_withholding_line_account_id_fkey: 286.658
account_reconcile_model_line_account_id_fkey: 2608.16
account_reconcile_wizard_account_id_fkey: 309.389
account_report_budget_item_account_id_fkey: 300.099
account_tax_cash_basis_transition_account_id_fkey: 31329.6
account_tax_group_advance_tax_payment_account_id_fkey: 2629.35
account_tax_group_tax_payable_account_id_fkey: 3554.27
account_tax_group_tax_receivable_account_id_fkey: 2772.1
account_tax_repartition_line_account_id_fkey: 47923.3
account_transfer_model_line_account_id_fkey: 1309.84
asset_modify_account_asset_counterpart_id_fkey: 207.683
asset_modify_account_asset_id_fkey: 454.126
asset_modify_account_depreciation_expense_id_fkey: 189.258
asset_modify_account_depreciation_id_fkey: 192.029
mrp_account_wip_accounting_line_account_id_fkey: 305.605
mrp_workcenter_expense_account_id_fkey: 565.317
pos_close_session_wizard_account_id_fkey: 285.536
pos_payment_method_outstanding_account_id_fkey: 432.131
pos_payment_method_receivable_account_id_fkey: 249.401
res_company_account_cash_basis_base_account_id_fkey: 5195.51
res_company_account_default_pos_receivable_account_id_fkey: 5357.29
res_company_account_discount_expense_allocation_id_fkey: 5113.98
res_company_account_discount_income_allocation_id_fkey: 5151.48
res_company_account_fiscal_country_id_fkey: 1
res_company_account_journal_early_pay_discount_gain_accoun_fkey: 5640.61
res_company_account_journal_early_pay_discount_loss_accoun_fkey: 5489.35
res_company_account_journal_suspense_account_id_fkey: 5811.88
res_company_account_production_wip_account_id_fkey: 8351.27
res_company_account_production_wip_overhead_account_id_fkey: 7914.54
res_company_account_revaluation_expense_provision_account__fkey: 8858.1
res_company_account_revaluation_income_provision_account_i_fkey: 8169.02
res_company_batch_payment_sequence_id_fkey: 0.995
res_company_create_uid_fkey: 2.96
res_company_currency_id_fkey: 1.081
res_company_default_cash_difference_expense_account_id_fkey: 6060.06
res_company_default_cash_difference_income_account_id_fkey: 6404.5
res_company_deferred_expense_account_id_fkey: 10447.3
res_company_deferred_revenue_account_id_fkey: 8923.24
res_company_documents_employee_folder_id_fkey: 0.875
res_company_documents_fleet_folder_fkey: 1.374
res_company_documents_hr_folder_fkey: 0.829
res_company_documents_project_folder_id_fkey: 0.779
res_company_downpayment_account_id_fkey: 8009.08
res_company_exemption_bachelor_account_id_fkey: 10964.3
res_company_exemption_bachelor_capping_account_id_fkey: 10860.6
res_company_exemption_doctor_master_account_id_fkey: 11117
res_company_expense_account_id_fkey: 5124.13
res_company_expense_accrual_account_id_fkey: 5246.67
res_company_expense_currency_exchange_account_id_fkey: 5352.77
res_company_external_report_layout_id_fkey: 0.308
res_company_gain_account_id_fkey: 14196.4
res_company_income_account_id_fkey: 5136.8
res_company_income_currency_exchange_account_id_fkey: 5441.56
res_company_internal_project_id_fkey: 1.151
res_company_internal_transit_location_id_fkey: 1.019
res_company_l10n_ae_tax_report_asset_account_fkey: 10908.2
res_company_l10n_ae_tax_report_expenses_account_fkey: 11365.8
res_company_l10n_ae_tax_report_liabilities_account_fkey: 11898.4
res_company_l10n_ar_tax_base_account_id_fkey: 10648.4
res_company_l10n_bd_corporate_tax_expense_fkey: 8098.52
res_company_l10n_bd_corporate_tax_liability_fkey: 8176.24
res_company_l10n_ch_delegate_country_id_fkey: 0.864
res_company_l10n_cl_factoring_counterpart_account_id_fkey: 10872.3
res_company_l10n_ec_tax_base_purchase_account_id_fkey: 10358.2
res_company_l10n_ec_tax_base_sale_account_id_fkey: 10547
res_company_l10n_ee_rounding_difference_loss_account_id_fkey: 8158.92
res_company_l10n_ee_rounding_difference_profit_account_id_fkey: 7896.55
res_company_l10n_eg_annual_leave_type_id_fkey: 0.887
res_company_l10n_fr_rounding_difference_loss_account_id_fkey: 8227.23
res_company_l10n_fr_rounding_difference_profit_account_id_fkey: 7965.89
res_company_l10n_in_withholding_account_id_fkey: 7820.82
res_company_l10n_nl_rounding_difference_loss_account_id_fkey: 7982.45
res_company_l10n_nl_rounding_difference_profit_account_id_fkey: 7874.47
res_company_leave_timesheet_task_id_fkey: 1.153
res_company_loss_account_id_fkey: 12688.6
res_company_nomenclature_id_fkey: 0.828
res_company_paperformat_id_fkey: 0.941
res_company_partner_id_fkey: 5.739
res_company_project_time_mode_id_fkey: 1.273
res_company_recruitment_folder_id_fkey: 0.816
res_company_rental_loc_id_fkey: 0.851
res_company_resource_calendar_id_fkey: 1.515
res_company_revenue_accrual_account_id_fkey: 5175.54
res_company_stock_mail_confirmation_template_id_fkey: 0.9
res_company_stock_sms_confirmation_template_id_fkey: 0.861
res_company_timesheet_encode_uom_id_fkey: 0.78
res_company_transfer_account_id_fkey: 7072.12
res_company_withholding_tax_base_account_id_fkey: 8502.05
res_company_write_uid_fkey: 0.743
soda_account_mapping_account_id_fkey: 398.04
stock_landed_cost_lines_account_id_fkey: 658.493
stock_location_valuation_in_account_id_fkey: 3940.27
stock_location_valuation_out_account_id_fkey: 2818.23
stock_valuation_layer_revaluation_account_id_fkey: 340.648
for a total of 661283ms = 11mn[^0].
This commit adds temporary indexes for every m2o field to account which is not already indexed[^1][^2] after all the l10n modules are installed, those indexes are then deleted at the end of the test to avoid polluting the database for the split tests.
This removes most of the cost of deleting accounts (not going to bother with the detail, the entire thing comes out at under a second), at a very minor cost (a few seconds) to create the indices though an increased overall load (due to having to update indexes).
Saves around 5mn on an unloaded 30mn build, and because it avoids a significant amount of parallelized seq scans it saves even more when running on a loaded runbot where parallel postgres workers are CPU starved (10~15mn out of 50~55).
Note: patched `load_file` because `l10n_tr` enables `tr_TR`, and then the tx subsystem complains about pretty much every module being installed because few to none of them have a tr_TR po file.
Backport of #217690
[^0]: `EXPLAIN ANALYZE`-ing everything slows down the test by a factor
of 2x, which is why this takes 11mn instead of the original 5, and
the test itself takes 1h instead of the original 30mn
[^1]: Kinda, currently it just checks if the field is `index` on the
Odoo side, so it's going to miss things like manual partial
indexes, or compound index (though in that case we should only
take in account cases where the account field is the first one),
etc...
[^2]: The specific missing indexes could have been enumerated and
created specifically but it doesn't seem worth the hassle, the
gain from trimming down the list would only be a fraction of a
second from creating a few less indexes, with the risk of missing
new missing indexes. A blacklist might make sense to avoid
creating indexes for constraints with extremely low costs (either
empty tables or already indexed) e.g. constraints with under 250ms
total runtime[^3].
[^3]: Note that the numbers above are full dumps of the trigger times,
a fair number of triggers in the dumps are *not* on accounts but
are due to ancillary deletions or deletion cascades. Pretty much
every trigger below triple digit (ms) runtime is a non-account
trigger, and this PR is not creating indexes for any of those.
Forward-Port-Of: odoo/odoo#224075The Belgian point-of-sale blackbox detection now retries checks and records clearer diagnostic information. This helps reduce cases where a required fiscal device is not recognized correctly, improving reliability for businesses using Belgian POS compliance hardware.
Original PR description
This PR adds a retry mechanism and a logger to better identify and prevent cases where a blackbox isn't correctly identified as such Forward-Port-Of: odoo/enterprise#92489
Resolved issues and error corrections
The Point of Sale now reuses an existing empty order when staff start a new order from the receipt screen. This prevents clutter from unnecessary blank orders and keeps the checkout workflow cleaner.
Original PR description
- When clicking `New order` on the receipt screen, we now want to reuse an empty order (not finalized and no order lines) before creating a new one. This avoids creating many useless empty orders. task-id: 5003010 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222891 Forward-Port-Of: odoo/odoo#222276
Expanding a meeting form from a pop-up now keeps the information already provided, such as the meeting name linked to a task. This prevents users from losing context when switching to the full form view and makes scheduling activities more reliable.
Original PR description
### Steps to reproduce: - Go to any task in project module - Create a new meeting activity - Open Calendar and drag to create a slot - Notice the name of the meeting in the pop-up is the same as the…
### Steps to reproduce: - Go to any task in project module - Create a new meeting activity - Open Calendar and drag to create a slot - Notice the name of the meeting in the pop-up is the same as the task - Click on the expand button top-right of the dialog - Notice the calendar.event form opened but without a name ### Cause: When expanding the view using 'More options' button we are keeping the context in the new request. https://github.com/odoo/odoo/blob/d9c63a85955c2321bae1a705cc09b2554155f826/addons/calendar/static/src/views/attendee_calendar/attendee_calendar_controller.js#L45-L49 But when doing the same through the expand button we don't pass the current context so it will be lost. https://github.com/odoo/odoo/blob/3dde420665257c63885e891f1ec366568df5007b/addons/web/static/src/views/view_dialogs/form_view_dialog.js#L106-L116 ### Fix: Backporting the commit https://github.com/odoo/odoo/commit/4f71fbbd26b428e57943d974e8441bef295cdef1 to pass the context while expanding the form view opw-4966486 Forward-Port-Of: odoo/odoo#221422
Duplicated journal entries no longer keep the original partner at the entry level when users change the partner on the journal items. This prevents list views from showing an outdated partner name and keeps accounting records consistent with the user's edits.
Original PR description
When changing `partner_id` on the `account.move.line`s of a duplicated journal entry if this journal entry already had a partner_id, it will stay the same (possible to see from list view) but the…
When changing `partner_id` on the `account.move.line`s of a duplicated journal entry if this journal entry already had a partner_id, it will stay the same (possible to see from list view) but the move line will be correctly changed. Step to reproduce: - Select a journal entry of type PBNK - Duplicate the journal entry - Change the partner on the journal items and save - Go back to the list view, the partner name displayed is from the original journal entry When clicking on duplicate it will call the function copy and super.copy() will call copy_data from account_move; This line allow to copy the partner_id (which is needed since invoices revert goes through copy) Since there is no condition on the type of entry, it will also copy the partner_id in our case: https://github.com/odoo/odoo/blob/22c333d0ed7eba1165f6462e668998d37fcabb73/addons/account/models/account_move.py#L2424-L2426 The introduction of this change introduced our issue, It allow for all duplication to copy the partner_id. Original fix : https://github.com/odoo/odoo/commit/e1d18960b57b36b8bf69bc787ef6078dcba8c855 opw-4907648 Forward-Port-Of: odoo/odoo#223959 Forward-Port-Of: odoo/odoo#217755
Corrects an invalid ending command in stock product label templates used for ZPL printers. This helps ensure barcode labels print reliably without printer command errors.
Original PR description
In the ZPL, the `^XZ` command indicates the end of a label. For an unknown reason (a typo ?), the PR [1] replaces some of them by `^XZj` which is not a valid ZPL command. [1]: https://github.com/odoo/odoo/pull/187225 Forward-Port-Of: odoo/odoo#220518
This update fixes an internal test for employee time off accruals by making it use a fixed date. It helps ensure the test remains reliable over time and avoids false failures in future test runs, without changing user-facing behavior.
Original PR description
The test is failing when run one year in the future as it depends on the date but we don't freeze the time. runbot-error-230721 Forward-Port-Of: odoo/odoo#224240
This fix prevents a CRM interface test from failing when the system runs tests with simulated dates. It improves test reliability without changing the CRM experience for users.
Original PR description
When using the faketime mode for testing, the crm_rainbowman tour fails because the underlying SQL query is using `CURRENT_DATE`. Unfortunately, this SQL keyword cannot be replaced globally by a function easyly (like it was done for the NOW function in faketime mode). ~~With this commit, the SQL query is adapted to use the SQL NOW function instead.~~ With this commit, the tour will be skipped in faketime mode Forward-Port-Of: odoo/odoo#223909
This fix keeps mobile website pages from scrolling sideways when animated content briefly moves outside the visible page area. It improves the browsing experience by ensuring pages stay within the expected screen width during scroll animations.
Original PR description
Scenario: - add a 2 columns content widget - set the right column text to "On Scroll" animation with "Slide" effect and "From Right" direction so the content may be out of the page - save and reload…
Scenario: - add a 2 columns content widget - set the right column text to "On Scroll" animation with "Slide" effect and "From Right" direction so the content may be out of the page - save and reload the page on mobile - scroll down get in middle of animation with some content out of page - try to scroll to the right Result: we can scroll to the right and see the overflowing animated content outside of the expected page limit. History: During an animation, a fix prevent the horizontal scrollbar by setting "overflow-x: hidden" (or crop depending on version) on a given element: - in odoo/design-themes@51abb093c77993363b170b12be134c95b3009895 (14.0: 2021) it was added to $().getScrollingElement() - in 189a7c96e6e26825dc05c0c6466576fe63aa091e (18.0: 2022) the main page scroll was moved from #wrapwrap to html - in fece9cb85761e6cb3fe3642f947661464402363b (18.0: 2024) the "overflow-x: hidden" was moved to the body element Cause: the "overflow-x: hidden" is ignored by mobile browser on html and body tags ([example of report]), so in 18.0 and over the possible horizontal scrollbar caused by an animation is not hidden. Fix: apply the "overflow-x: clip/hidden" on #wrapwrap element. [example of report]: https://stackoverflow.com/questions/14270084 opw-4575726 Forward-Port-Of: odoo/odoo#213802
Website editors can once again change the thickness of a website header border from the header options. This restores expected visual customization control and prevents confusion when styling site headers.
Original PR description
Since [1], the header border width option no longer had any effect. This commit restores the ability to change the border width from the header options. Steps to reproduce: - Go to Website in edit mode - Select the header to display its options - Change the border width (e.g., set to `10px`) - Bug: no visible change [1]: https://github.com/odoo/odoo/commit/d0daf3990079477ef7552d769b944b55d9be4366
The privacy lookup test was updated so it no longer fails when optional localization modules add extra partner references. This is an internal test-only fix and does not change how the product works for users.
Original PR description
The test `test_wizard_indirect_reference` failed when modules like `l10n_gt_edi` were installed. This was due to additional Many2one fields (e.g., `l10n_gt_edi_consignatory_partner` on `account.move`) referencing `res.partner`, which were picked up by the privacy lookup wizard. This commit updates the test to avoid assuming a fixed number of reference lines and instead asserts the presence of the expected ones (the partner and the company). No change in functional behavior. RB-[230449](https://runbot.odoo.com/odoo/error/230449) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222105
Users can now duplicate multiple appointment bookings at the same time without triggering an error. This makes managing repeated or copied bookings smoother and avoids interruptions in appointment workflows.
Original PR description
This error occurs when users attempt to duplicate multiple bookings within an appointment. Steps to reproduce: --- - Install `appointment` module - Select an appointment (ie. Dental Care) - Click on New and make 2 new bookings - Go to list view > Select both records > Duplicate Traceback: --- `ValueError: Expected singleton: calendar.event(5, 8)` This occurred because we called `default_get` with a non-empty recordset at the beginning of the `create` method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224188
Fixes the Job Position form so Recruiter and Interviewers fields are populated even when no company is selected. This helps hiring teams assign the right people without needing to set a company first, while still respecting company-specific user lists when a company is chosen.
Original PR description
In the Job Position form, the 'Recruiter' and 'Interviewers' fields were empty when no company was selected. This was due to the static domain using 'company_id' directly without taking into consideration that company_id can be False. This fix introduces computed domain fields (, ) that dynamically adapt based on the selected company. If a company is set, users belonging to that company are shown. If not, only internal users are listed regardless their companies. Related task: 4926154. 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#224114 Forward-Port-Of: odoo/odoo#217884
When users turn formatted text into a button in the HTML editor, the button now keeps the original font size. This prevents unexpected visual changes and helps website content look as intended after editing.
Original PR description
### Steps to reproduce: - Type some text and apply a large font-size. - Select the text and apply the button style. - Notice that the font-size is not reflected on the button. ### Description of the…
### Steps to reproduce: - Type some text and apply a large font-size. - Select the text and apply the button style. - Notice that the font-size is not reflected on the button. ### Description of the issue/feature this PR addresses: - The `<a class=btn>` element was placed inside a font-size `<span>`. - However, the `.btn` class defined its own font-size, causing the original styling to be overridden. ### Desired behavior after PR is merged: - Improved the splitAroundUntil utility to correctly handle cases where the target node has no previous or next sibling. In such edge cases, the function now recursively splits up the inline ancestry until the specified limitAncestor, ensuring that the target node is fully isolated. - The font-size `<span>` is moved inside `<a>` tag when applying a button style. - This ensures the original font-size is preserved and correctly displayed. task-4731416 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223640 Forward-Port-Of: odoo/odoo#216300
This fix prevents the website editor from crashing when users paste multiple content blocks inside inline text areas. It improves editing reliability and also corrects an issue where empty inline content could be filled twice, avoiding unwanted extra spacing or line breaks.
Original PR description
Problem: When pasting two blocks inside an inline element, a traceback occurs. Cause: During `insert`, when `insertBefore` is `true` and `isEmptyBlock(right)` after `splitElement`, `currentNode` is set to `right`. But `right` may already have been deleted, leading to an invalid reference. Solution: Delete `right` if empty, but do not set `currentNode` to `right` in that case. Steps to reproduce: It is tricky to reproduce manually (you must copy two blocks and paste them in an inline element). A test has been added to cover the case. opw-4972695 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224029 Forward-Port-Of: odoo/odoo#223229
This fix restores the intended rule for showing QR codes on Saudi Arabia invoices after it was missed during a forward port. It helps ensure compliant invoice reports display the QR code when expected.
Original PR description
In this commit: https://github.com/odoo/odoo/commit/fdb37c9aa3d2c6002b42e87ebd14afd280ebd03f We changed the condition to display the qr code, but the change was lost in the forward port task-5039596 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224051
This fix ensures the Threads social media icon displays correctly when used in email marketing snippets. Recipients will now see the intended icon in delivered emails, improving the consistency of branded marketing content.
Original PR description
Problem: When adding the Threads icon to an email marketing snippet and sending the email, the icon does not appear in the received email. Solution: Add support for the newly added icons from commit 21db1065aee9b403a316389f306c865cc47354ed (same fix as commit 7e9466e27d61fa8ece43d2238e1570dc3e65337a). Steps to reproduce: - Add the Threads icon to an email marketing snippet. - Send a test email. - Observe that the icon is not visible in the received email. opw-5024970 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224189
Creating a child menu on a website now keeps it under the menu chosen by the user instead of moving it to the main website menu. This prevents confusing website navigation changes and helps administrators manage menu structures reliably.
Original PR description
Steps to reproduce: - Have a database with only the website module installed --> Turn on the developer mode. - Go to Configuration ---> Menus - Create a Menu (Parent) and a child menu (Child) in that. - Upon saving, the following behaviour is observed: the child menu is converted to the main menu. Issue: Before this commit, when we create a child menu for single website then it takes the website.menu_id.id as the parent_id. Which is wrong because it gives the parent_id of the websites' top menu. Solution: With this commit, we have passed the correct parent_id from vals to solve this issue. task-4231974 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222615
This update improves how Odoo handles cases where an automated browser test unexpectedly loses its connection. Instead of waiting for timeouts or reporting a misleading cleanup error, the system now fails the test promptly and records the real connection issue for investigation.
Original PR description
As far as I can tell this can occur if the ws connection gets closed while we're in a `recv`: in that case `recv` will mark the connection as closed (`connected=False` and `sock=None`) and raise…
As far as I can tell this can occur if the ws connection gets closed while we're in a `recv`: in that case `recv` will mark the connection as closed (`connected=False` and `sock=None`) and raise `WebSocketConnectionClosedException`, then any attempt to `send` will fail with `WebSocketConnectionClosedException`. Here this likely is an issue because in `_receive` `WebSocketConnectionClosedException` goes through the generic exception handler, which sees that: - it's not a `ConnectionResetError` - the result is not set - and the ws is not connected So `_receive` just cancels the result and `return`s, and when whatever's waiting on a future finally times out it tries to cleanly shut down and hits a connection that's already closed. Handle a connection closed in that context more properly: - unset `ws` so we don't try to clean it up, as we know it's closed - set the result as being in error - cancel every future in order to immediately go to the tour failure step rather than wait for timeouts Note that this will not really *fix* any error per se, because every time this happens it means the browser abruptly closed the WS connection (possibly straight up died), so this should mostly properly attribute the error so we can investigate it. https://runbot.odoo.com/odoo/error/229793 Forward-Port-Of: odoo/odoo#224023
This fixes an issue where standard Employee and Department views could disappear after enabling a Calendar view through Studio. Users can now customize HR screens while keeping the usual view options such as activity, kanban, and pivot available.
Original PR description
**Steps to reproduce:** - Install `hr` and `web_studio`. - Go to Employees → click Studio icon. - Views → activate Calendar view. **Observation:** - Existing views (activity, kanban, pivot, etc.) disappear from the view types. **Issue:** - After commit https://github.com/odoo/odoo/pull/160280/commits/e67ed24320c555c0cc63d59aa4921267e10a472d, view_mode in actions was removed, so only default (list, form) and Studio-added views remain. **Solution:** - Add view_mode to the action to preserve standard views after customisation. opw-4967654 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222485
This fix ensures Canary Islands withholding taxes are classified under the proper Spanish tax type instead of the default taxable category. It improves accuracy in tax reporting and grouping for businesses using Spanish localization.
Original PR description
Steps to reproduce: - Install `l10n_es' - Go to accounting -> settings and load any package for the Canary Islands - Go to Accounting → Configuration → Taxes - Group by “Tax Type (Spain)” Observation: - 'Withholding' taxes should have type 'retencion' instead of 'Sujeto' Issue: - After this commit, https://github.com/odoo-dev/odoo/commit/643496b337c2edc9c56c76f72aec12021358f631 withholding taxes brings back but not set a l10n_es_type(Tax Type(Spain)), so it's default type to 'Sujeto' Solution: - Add `l10n_es_type` column in the data file and assign 'retencion' to withholding taxes. opw-5000677 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#223546
Removing a bank account from a customer or partner record no longer triggers an unexpected error. This helps accounting users manage customer banking details smoothly and avoids disruption during routine data cleanup.
Original PR description
Currently an error occurs when we try to remove bank accounts from a partner. **Steps to reproduce:** - Install `accountant` (with demo), Go to customers and create a new one with random name. -…
Currently an error occurs when we try to remove bank accounts from a partner.
**Steps to reproduce:**
- Install `accountant` (with demo), Go to customers and create a new one with random name.
- Under accounting tab add a new bank account with an acc number, bank and save.
- Now remove the bank account record.
**Error:**
`AttributeError: 'NoneType' object has no attribute 'origin'`
**Cause:**
- The error occurs because of the SQL query [1] returning None values in the `id2duplicates` dict, somewhat like `{1: [None]}`, this caused the browse [2] to assign `None` to the `duplicate_bank_partner_ids`.
- While recording snapshots for diff checking in onchange system the none value will be stored like`None: {display_name:{}}` and when the line [3] tries to access `id_.origin` where `id_` is None and causes the error.
**Solution:**
- Added a condition which makes sure null values are not accounted. (The Join is added to makes sure that the correct `partner_id` is fetched.)
[1]: https://github.com/odoo/odoo/blob/04ba4e4a51843701dd42a3f0243add50b3ac0c79/addons/account/models/res_partner_bank.py#L71-L85
[2]: https://github.com/odoo/odoo/blob/04ba4e4a51843701dd42a3f0243add50b3ac0c79/addons/account/models/res_partner_bank.py#L88
[3]: https://github.com/odoo/odoo/blob/04ba4e4a51843701dd42a3f0243add50b3ac0c79/addons/web/models/models.py#L1173
sentry-6748249363
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#224111
Forward-Port-Of: odoo/odoo#219455The website editor no longer records the temporary background grid in undo history. This prevents errors when users edit links and resize or move grid-based banner content at the same time, making page editing more reliable.
Original PR description
The background grid of the grid layout is recorded by the history. Because of this if some feature modifies the history while a grid resize or drag'n'drop is in progress, it might generate an error. This commit excludes the background grid from the history to avoid accidental history manipulations from impacting it. Steps to reproduce: - Drop a "Banner" block - Select a word - Press Ctrl+K to open the link popover - Resize the block that contains the word from the bottom => An error was produced because the grid was removed by the link popver which reverts to the history state it observed when it was opened. task-4367641
After an employee signs a contract and is assigned as the future driver of a company car or bike, the vehicle is no longer incorrectly shown as available. This helps HR and fleet teams avoid double-booking vehicles and keeps availability records accurate.
Original PR description
Issue: When a contract was signed and a future driver was assigned to a vehicle, the car still remained marked as available. Fix: Once the first signature is completed and the future driver is assigned, the vehicle is correctly marked with plan_to_change_car = False (same for the bike). Related task: 4926335. 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#218809
The project portal now sends users back to the project that actually contains the task they were editing. This avoids confusion when teams work with multiple shared projects and ensures users return to the right task list.
Original PR description
Steps to Reproduce: ------------- 1. Install project and create two projects and tasks. 2. Share both projects with edit access. 3. Edit a task from the portal view (Back to edit mode) then click the (back to tasks) button. 4. Instead of the correct project the page redirects to the another project kanban view. Issue: -------------- - When redirecting to a task from project sharing (edit mode – task form view) it redirects to a different project’s kanban view instead of the actual project. Cause: ------------- - In the portal view the URL is hardcoded with `id=1` instead of dynamically using the correct project ID. Fix: --------------- - pass the correct `project_id` in the URL instead of using a hardcoded value. The issue occurred from this PR-https://github.com/odoo/odoo/pull/174648 task-5031632 Forward-Port-Of: odoo/odoo#224092 Forward-Port-Of: odoo/odoo#224005
The website builder now correctly shows the text animation tool as active when animated text is selected, even if that text also has a highlight effect. This removes confusion for editors by making the toolbar reflect the current styling more reliably.
Original PR description
The commit e80a2a20d4ba49b51f31f8ed06a5a0d3d1fa2e6d added the text animation in the toolbar as part of the website builder refactor The tool in the toolbar was shown as active when the animated node was fully selected (or selection collapsed). But if the text inside is highlighted, extra nodes with no text are added with the highlight's svg, and these are not selected. With this commit, the comparison checks if the text content of the selection is the same as the text content of the animated span, thus empty dom nodes are ignored. Steps to reproduce: - Open website builder - Select some text (for example in the footer) - Add an animation - Add an highlight - Select the same text again - Bug: the animate text tool is not shown as active task-4367641
This fix makes an automated two-factor authentication test wait until the web client is fully ready before continuing. It reduces false test failures in validation runs, helping keep releases stable without changing customer-facing behavior.
Original PR description
Code and issue at hand are very similar to odoo/odoo#212102 so implement the same "fix" to synchronise the tour on the web client being ready, though technically the first two calls are just "wait a bit" then "wait a bit more" (wait until DOMContentLoaded, then until next frame, then until next event loop). At which point we wait until the event bus has fully connected to the server before moving on to interact with the client for real. It does seem to reliably wait sufficiently long for the issue to go away so works for me... Backport of #224066 https://runbot.odoo.com/odoo/error/181862 Forward-Port-Of: odoo/odoo#224161
This fix makes the automated website menu editing checks more stable by ensuring pages are fully ready before test actions run. It reduces false failures in internal validation, helping teams trust release testing results without changing customer-facing behavior.
Original PR description
The `edit_menus` tour was occasionally failing on runbot due to race conditions affecting certain steps. Issue: 1. Following the [PR [1]](https://github.com/odoo/odoo/pull/198596), the tour system…
The `edit_menus` tour was occasionally failing on runbot due to race conditions affecting certain steps. Issue: 1. Following the [PR [1]](https://github.com/odoo/odoo/pull/198596), the tour system has a safeguard where steps wait for iframe readiness, determined by the `is-ready="true"` attribute on the iframe body. However, the `parentFrameIsReady` function had a bug: when called before the `is-ready` attribute was set, it defaulted to `true` instead of waiting. This caused tour steps to execute prematurely while the iframe was still loading, creating race conditions. 2. Entering edit mode causes the builder sidebar to open, triggering multiple iframe resize events. Each resize rebuilds (i.e., removes and recreates) the extra menu items dropdown (see auto_hide_menu.js [2]). The tour tried to open a link popover inside this dropdown immediately after entering edit mode. This caused a race condition where, if the step ran before all resize events had completed, the dropdown could be rebuilt mid-process, and our target element could be lost, causing the step to fail to open the popover. Fix: 1. Set `is-ready="false"` as the initial value on iframe body load. This ensures the readiness check waits for the attribute to be explicitly set to "true" when publicRoot is ready, eliminating false positives. 2. After the builder sidebar fully opens, we now wait briefly before interacting with the link in the extra menu items dropdown. This delay ensures all recalculations (triggered by iframe resizes) are complete before proceeding, avoiding race conditions. [1] - https://github.com/odoo/odoo/pull/198596 [2] - [website/static/src/js/content/auto_hide_menu.js#L92](https://github.com/odoo/odoo/blob/saas-18.4/addons/website/static/src/js/content/auto_hide_menu.js#L92) [runbot-226308](https://runbot.odoo.com/odoo/error/226308) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Incoming email fetching now avoids a timing conflict that could cause the process to fail while saving progress. This helps keep automated email retrieval running smoothly and reduces interruptions for users relying on mail synchronization.
Original PR description
The process of fetching run in a transaction t1 and for each message we do it in a transaction tm. tm commits and updates the progress for each message found on the server. t1 was started before tm and since tm changed the progress, t1 may result in a serialization error. By adding the commit, t1 commits all changes and starts a new transaction to update the progress (at that point tm is committed). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The website builder highlight picker now previews the selected color and thickness instead of always showing a black default style. Highlights also default to the primary theme color, making the editing experience more consistent and easier for users.
Original PR description
The hightlight picker is always shown with default black color and default thickness. This commit adapts the preview to use the currently set color and thickness. It also defaults the color to primary. task-4367641
This update fixes an automated test for home working presence status so it remains reliable across different Odoo editions. It reduces false test failures caused by visual styling differences, helping maintain confidence in HR homeworking functionality.
Original PR description
The test `Home Location (away)` was failing because the text-danger value is not the same when enterprise is installed. To avoid this kinf of erros, we will check the classes instead of the style 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
Employee skill records can now keep extra information, such as appraisal justifications, when a skill is copied or updated. This prevents important context from being lost during skill level changes.
Original PR description
Allow models that inherit the hr_individual_skill mixin to specify additional fields to be included/preserved/carried-over when writing/creating new skill records. This was already an issue in the `hr_appraisal_skill` module where the `Justification` field was not included when copying/creating new skills. As a result, the field was "erased" on every skill level change task-4984689 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The media dialog now disables the Add button while selected media is being saved. This prevents users from accidentally triggering duplicate save actions and reduces the chance of repeated media entries or unnecessary processing.
Original PR description
Problem: `this.props.save` is awaited, which might take a while to process. During that time, the user can click "Add" multiple times. Cause: Multiple clicks trigger multiple calls to the same RPC, leading to duplicate saves. Solution: Disable the "Add" button while saving to prevent multiple calls. Steps to reproduce: - Open website/shop. - Open a product page. - Add extra media to the product to open the media dialog. - Select multiple images and click "Add" multiple times. - The save is called multiple times, triggering the same RPC several times. opw-4937004 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Products used as loyalty rewards can no longer be hidden from the Point of Sale. This helps ensure loyalty programs work reliably at checkout and prevents missing reward items during sales.
Original PR description
Before this commit, a product used as a loyalty reward could be hidden in the PoS. opw-5005934 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222451
Dutch e-invoices now use the expected discount reason text instead of a reason code on invoice lines. This prevents validation warnings under Dutch NLCIUS rules and helps invoices process more smoothly.
Original PR description
NLCIUS rule BR-NL-32 triggers a warning if the AllowanceChargeReasonCode rather than the AllowanceChargeReason is present on an invoice line AllowanceCharge. We don't handle this correctly at the moment for discounts, because in that case the UBL 2.0 builder adds an reason code but not a reason. This commit ensures that the reason rather than the reason code is specified in NLCIUS in the case of a discount. opw-4997704 Forward-Port-Of: odoo/odoo#223072
This change updates an automated Point of Sale test so it handles page unloads consistently. It helps reduce unpredictable test failures, supporting more reliable releases without changing the user-facing Point of Sale experience.
Original PR description
Use expectUnloadPage key in tour to fix undeterministic behavior. 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#224176
This fix makes an automated Point of Sale test wait until menu buttons are ready before selecting them. It reduces false build failures caused by timing issues, helping keep development and release checks stable.
Original PR description
steps to reproduce: 1. in multi enterprise 2. run the tour `test_02_others` added a wait step for the menu buttons before clicking the menu button in the `chrome_util.js` file. build_error-229618 Forward-Port-Of: odoo/odoo#217939
Point of Sale now handles product searches correctly when the system is offline. Instead of showing an unexpected crash, users see the expected connection error, making offline behavior clearer and more stable.
Original PR description
- Fix issue that was causing a traceback when searching for products in offline mode. Now when we search a product in offline mode, we get the `ConnectionLostError` as before instead of a traceback. task-id: 5008058 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222761
This update fixes an internal website test that could fail after a system component refresh during module upgrades. It helps keep automated checks reliable, reducing false failures during development and release validation.
Original PR description
Since [1] the `test_02_copy_ids_views_unlink_on_module_update` standalone test fails because it cannot find the `is_seo_optimized` field. This happens because the `env`'s registry is changed when `button_immediate_upgrade` is called: the types of the used records do not belong to the correct registry after the first call. This commit re-obtains the records used in the second part of the test to avoid this issue. [1]: https://github.com/odoo/odoo/commit/7f36a94a548f728aa89feb1a4facd59c91fc47bf task-4422810 runbot-227670
This update adds test coverage to ensure bank statement reconciliation keeps working when no payment account is configured. It helps prevent regressions in accounting workflows that could disrupt finance teams reconciling bank statements.
Original PR description
Add a test to previous fix: https://github.com/odoo/enterprise/commit/582e3ee22cba404ff38782534e76569bc93a44ef opw-5039931 opw-5039807 Forward-Port-Of: odoo/enterprise#93182
This fix prevents the Point of Sale from showing an error when an order is unavailable or has not been loaded. It helps keep payment settlement workflows stable and avoids disruptions for staff using POS.
Original PR description
Before this commit, accessing the order amount caused an error if the order was not defined. opw-5027426 Forward-Port-Of: odoo/enterprise#92928 Forward-Port-Of: odoo/enterprise#92736
This fix ensures negative Swiss payroll lines are posted to the correct opposite accounts. It helps keep payroll accounting entries accurate, reducing manual corrections and improving financial reporting reliability.
Original PR description
…r 2050 Invert accounts for negative payslip line Forward-Port-Of: odoo/enterprise#93074
This update fixes an automated guided tour used in the Field Service reporting area so it waits for the correct button before continuing. This helps keep quality checks reliable and reduces false failures during testing, with no expected impact on day-to-day users.
Original PR description
In this commit, we fix the tour industry_fsm_tour by removing "body:not(.modal-open) nav.o_main_navbar" (this trigger is always true) from trigger to let only button[name="action_generate_new_template"]. Forward-Port-Of: odoo/enterprise#93169 Forward-Port-Of: odoo/enterprise#91771
When an employee signs a salary contract and is assigned as a future driver, the related car or bike is no longer incorrectly shown as available. This helps HR and fleet teams avoid double-booking vehicles and keeps fleet planning accurate.
Original PR description
Issue: When a contract was signed and a future driver was assigned to a vehicle, the car still remained marked as available. Fix: Once the first signature is completed and the future driver is assigned, the vehicle is correctly marked with plan_to_change_car = False (the same applies to the bike). Related task: 4926335. Forward-Port-Of: odoo/enterprise#89774
This fix prevents appointment video call links from failing when several calendar events are processed at once. It helps ensure users are redirected correctly to their video appointments without interruption.
Original PR description
When computing `videocall_redirection`, the method `get_base_url()` was called directly on a recordset containing multiple `calendar.event` records. Since `get_base_url()` expects a singleton, this raised the error: Traceback: --- `ValueError: Expected singleton or no record: calendar.event(4, 6, 1, 5)` This commit ensures the computation is done per record, avoiding the singleton issue and allowing correct videocall redirection values to be set on multiple events. Reference review: https://github.com/odoo/enterprise/pull/53569#discussion_r1543135425 sentry-6819406171 Forward-Port-Of: odoo/enterprise#92717
Employee appraisal skill records now keep extra information, such as justification notes, when a skill level is updated or copied. This prevents important context from being accidentally erased during normal appraisal updates.
Original PR description
Allow models that inherit the hr_individual_skill mixin to specify additional fields to be included/preserved/carried-over when writing/creating new skill records. This was already an issue in the `hr_appraisal_skill` module where the `Justification` field was not included when copying/creating new skills. As a result, the field was "erased" on every skill level change task-4984689
A missing setup field was added to Point of Sale enterprise tests so they run correctly when the module is installed. This helps keep automated checks reliable and prevents false build failures without changing customer-facing behavior.
Original PR description
steps to reproduce: 1. install pos_enterprise 2. run the test `test_should_not_affect_other_pos_config` or `test_is_header_or_footer_to_false` this commit adds the missing_field `account_tax_return_journal_id` to the test build_error-230301 Forward-Port-Of: odoo/enterprise#90995
This fix prevents users from seeing an error when they complete a scheduled activity linked to an approval rule that has since been deleted. It keeps the activity workflow stable in Web Studio by safely handling cases where no approval rules remain.
Original PR description
An error occurs when a user attempts to mark a scheduled activity as done after the associated approval rule has been deleted. **Steps to Reproduce:** 1) Install Sales and Web Studio modules. 2) Log…
An error occurs when a user attempts to mark a scheduled activity as done after the associated approval rule has been deleted. **Steps to Reproduce:** 1) Install Sales and Web Studio modules. 2) Log in as Admin and use Studio to add an approval rule to the Sale Order’s Preview button. >- Set Allowed Group to Access Rights. >- Set Responsible User to Mitchell Admin. 3) In the Incognito Tab, login as Demo, open the same sale order and click on preview to create activity in chatter. 4) Delete the Approval Rule in the original tab. 5) Switch back to Demo and click Mark Done under Planned Activity in chatter. **Error:** `SyntaxError: syntax error at or near ')'` `LINE 1: SELECT id FROM studio_approval_rule WHERE id IN () FOR UPDAT. ^` **Root Cause:** The error occurs because the SQL query at [1] includes an empty tuple of rule IDs `(all_rule_ids)`. An empty `IN ()` clause in SQL results in a syntax error. [1]- https://github.com/odoo/enterprise/blob/7ea45724e7689a0df11d20ace9c562788f5d19e3/web_studio/models/studio_approval.py#L366 **Solution:** This commit avoids the error by ensuring that the SQL query only runs when `all_rule_ids` is not empty. sentry-6306636466 Forward-Port-Of: odoo/enterprise#86982