Daily updates from Odoo
Tuesday, August 26, 2025
39 changes · 18.0
Enhancements to existing features
The updated UBL BIS3 electronic invoice generation helpers are now enabled by default, improving consistency with the newer invoice creation process. Businesses can still opt out if needed by changing the related configuration setting.
Original PR description
In 0f3a9dee5cf15 we back-ported the new refactored helpers for UBL BIS3 generation to 18.0. However the new helpers would be used only if the `ir.config.parameter` `account_edi_ubl_cii.use_new_dict_to_xml_helpers` was set to True. This commit switches the new helpers on by default in 18.0 -> 18.3, but they can still be switched off by setting that parameter to False. task-none
SMS message generation can now receive extra contextual information from add-on modules. This makes it easier for businesses to customize automated SMS content without relying on fragile workarounds.
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.
This change speeds up an internal accounting localization test by adding temporary database indexes while test accounts are being deleted. It reduces build and validation time, helping developers and CI systems provide feedback 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.This update expands automated checks for several onboarding tours so issues are caught earlier during validation. It also speeds up tour execution and removes a duplicate sales test, helping keep release checks efficient without changing day-to-day user behavior.
Original PR description
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
The shop floor now remembers the user’s last selected work center when they leave and return using breadcrumbs. This keeps the view consistent while preserving the existing behavior when opening shop floor from Manufacturing work centers.
Original PR description
Description of the issue/feature this PR addresses: Incoherent selection of workcenters when using the breadcrumbs to come back to the shopfloor app:…
Description of the issue/feature this PR addresses: Incoherent selection of workcenters when using the breadcrumbs to come back to the shopfloor app: https://drive.google.com/file/d/1C1nVdDHgCss7s7zyXDOpbMj0k79HlJBH/view?usp=drivesdk Current behavior before PR: When leaving the shopfloor app via a WO (WO setting -> Open MO), we set the a **context flag workcenter_id** in the the currentCaller.action.context to save the selected workcenter for breadcrumb logic. The same **context flag workcenter_id** is used in the Manufacturing/workcenters view, when clicking on a workcenter. However, the intended use of the **workcenter_id flag** is different: - 1 From Manufacturing: Open shop floor with **only** workcenter_id selected + visible (no other workcenters visible). - 2 From Shopfloor breadcrumb : Go to shop floor with all previous workcenters same as when leaving. Additionally the current logic for setting the workcenter_id flag from the MrpDisplay record currently handles only the selection of isMyWO ([PR](https://github.com/odoo/enterprise/pull/52258)) Desired behavior after PR is merged: Keep the same behavior when coming from Manufacturing/workcenters ([PR](https://github.com/odoo/enterprise/pull/67318)) but make sure the user come back to same view when leaving shopfloor and coming back via breadcrumbs. task: [4629641](https://www.odoo.com/odoo/project/966/tasks/4629641) I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
Resolved issues and error corrections
Expanding a meeting creation dialog now keeps the original information, such as the meeting name linked to a task. This prevents users from losing prefilled details when switching to the full form, reducing rework and confusion.
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
Users can now duplicate multiple appointment bookings at the same time without triggering an error. This removes a blocker in calendar appointment workflows and makes bulk booking management more reliable.
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
This change fixes an internal automated test for employee time-off accruals by making it use a fixed date. It helps prevent future date-related test failures, improving reliability of the HR time-off module 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
Sales order line prices now correctly refresh when a quantity change qualifies for a different pricelist rule. This helps businesses avoid incorrect customer pricing and reduces the need for manual price updates or pricelist switching.
Original PR description
> [!Note] > This PR unreverts fc6b9ed22728 with a minor modification to ensure one `res.currency` record to compare amounts. **Steps to reproduce**: 1. Install the `sale` module. 2. Enable…
> [!Note] > This PR unreverts fc6b9ed22728 with a minor modification to ensure one `res.currency` record to compare amounts. **Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: - 0.75 for quantity ≥ 0 - 0.50 for quantity ≥ 1000 - Pricelist B with a -10% discount applied to Pricelist A. 4. Create a Sales Order using Pricelist B. 5. Add a product to the order line. 6. Increase the quantity to 1000. **Observed behavior**: - The unit price does not update according to the pricelist rule for quantity ≥ 1000. - If you switch the pricelist to another and then back again, the `Update prices` button appears and correctly updates the price. **Root cause**: - The price is not recomputed when the quantity changes because the `price_unit` is not updated because it does not match the `technical_price_unit`. - Since e1b22257a714, `price_unit` is rounded (2 decimals), but `technical_price_unit` is not. This causes a mismatch in comparison logic due to rounding differences. **Solution**: - Replace direct float comparison with `currency_id.compare_amounts()` to ensure proper comparison with rounding precision. opw-4944644
This fix ensures that changing a product's unit of measure on a sales quotation recalculates the unit price every time, not just the first time. It prevents incorrect pricing when sales teams adjust units repeatedly, keeping quotation amounts accurate.
Original PR description
Problem: When the user changes the UOM on a product more than once, the unit price no longer recomputes. The technical_price_unit and the price_unit are out of sync in which the uom change gets recognized as a manual change from the user. Thus, it no longer recomputes the unit price. Purpose: The unit price should always recompute when the uom is simply being modified more than once. Steps to reproduce on Runbot 18: 1. Install Sales and accounting 2. Enable Units of Measure in Settings > Sale 3. Create a product, Soda, whose units is L 4. Create a quotation and add the product Soda 5. Change the uom on the line for the first time --> price_unit changes 6. Change the uom on the line for the second time --> price_unit does not change opw-4998017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change reverts an earlier adjustment that hid unit information on point-of-sale order lines. The reverted change is no longer needed because the related certification work moved to a separate module, and it also caused a language-specific display bug.
Original PR description
This commit reverts commit ffdedf9, as the change is no longer required due to the LNE certification being implemented in a separate module. It also had a bug where the hiding of 'Units' only worked in English. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where dropshipped product backorders could record inventory valuation amounts for the full original order instead of only the delivered backorder quantity. Businesses using FIFO or average costing with dropshipping will now see more accurate valuation entries after partial deliveries and vendor bills.
Original PR description
…order dropship **Problem:** when the backorder of the delivery (with a bill) of a dropshipped fifo/avco product is validated, the svl created don't have the right values **Steps to reproduce:** -…
…order dropship **Problem:** when the backorder of the delivery (with a bill) of a dropshipped fifo/avco product is validated, the svl created don't have the right values **Steps to reproduce:** - create a new product, with dropship and buy routes - in the purchase tab select "on ordered quantities" - add a vendor with a price of 10 - create a new quotation for a quantity of 10 - confirm and confirm the purchase order - click on "create bill" and confirm it - go back to the PO and click on the "dropship" smart button - change the quantity to 5, validate and create backorder - go back to the PO, click on the "dropship" smart button and select the picking of the backorder (with status ready) - validate - click on the "valuation smart" button **Current behavior:** the svl created for the backorder have a value of 100 and -100 **Expected behavior:** it should be 50 and -50 **Cause of the issue:** inside _get_dropshipped_svl_vals _get_price_unit is called https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/stock_account/models/stock_move.py#L219 because we created a bill and it's a backorder line.qty_invoiced is higher than received_qty and this condition is true https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/purchase_stock/models/stock_move.py#L51 but because it's a dropship there is as much positive svl as negative svl linked to the move so receipt value is null https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/purchase_stock/models/stock_move.py#L56-L63 and remaining value will be 100 instead of 50 (receipt value should have been 50) https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/purchase_stock/models/stock_move.py#L80 **fix** the negative svl from the dropshipped move should not impact receipt value opw-4888827 Forward-Port-Of: odoo/odoo#216899
A privacy lookup test was updated so it no longer fails when extra optional country-specific modules add more partner references. This improves test reliability without changing 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
The spreadsheet component was updated to the latest version, bringing fixes for menu item alignment and Excel copy-paste behavior. This improves day-to-day spreadsheet usability and reduces formatting or interaction issues for users working with imported Excel data.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/7ad0e33f4 [REL] 18.0.42 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/7ad0e33f4 [REL] 18.0.42 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/95353174b [FIX] menu: Fix menu item alignment [Task: 5028721](https://www.odoo.com/odoo/2328/tasks/5028721) https://github.com/odoo/o-spreadsheet/commit/c3b56522c [FIX] Figure: icon of the menu item is not vertically aligned [Task: 4992687](https://www.odoo.com/odoo/2328/tasks/4992687) https://github.com/odoo/o-spreadsheet/commit/313784f22 [FIX] clipboard: fix copy-paste from Excel [Task: 4730469](https://www.odoo.com/odoo/2328/tasks/4730469) 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: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya <rmbh@odoo.com> Co-authored-by: Florian Damhaut (flda) <flda@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>
This fixes an issue in the website editor where pasting multiple content blocks inside inline text could cause an error. It also prevents extra invisible spacing from being inserted in certain edited text areas, making editing more reliable for users.
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#223229
This fix prevents mobile visitors from scrolling sideways when animated content briefly extends beyond the page during scroll effects. It keeps website pages visually contained and avoids showing off-page content, improving the mobile browsing experience.
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
The website editor now hides the image quality slider for WebP images on Safari and iOS webviews when compression is not supported. This prevents users from seeing a control that has no effect and keeps image editing options accurate when switching between image formats.
Original PR description
Scenario: - select a WebP image in the editor - change the quality with the slider Result: - the size and the image quality doesn't change Cause: Safari doesn't support HTMLCanvasElement.toDataURL() with WebP, so the image is exported in PNG instead which is lossless and doesn't support compression. Other issue: If we select in formats a WebP, then a PNG, we still see the quality option that are meant for the WebP, and inversely if we start with a PNG the quality option is hidden. Fix: Disable the quality for WebP images if this is not supported (in safari + iOS webview), and move the code to ImageTools._computeWidgetVisibility so it is updated when we change image type from/to WebP. opw-4979378 Forward-Port-Of: odoo/odoo#223268
This fixes a point-of-sale restaurant issue where staff could not add or adjust a tip once an order had already been invoiced. Businesses can now record tips correctly in this scenario, helping keep customer payments and accounting entries accurate.
Original PR description
In e3c95b9e34388bd059bbe41665ba3d62de0acab5, we make sure to update the payment_line.amount when tipping, for the accounting line to work properly. However, updating the amount on a payment line is only allowed if the order state is not 'done' or 'invoiced', which means, if a user tries to tip an 'invoiced' order, it doesn't work!! Here, we make an exception that allows updating the amount on the payment line of a tipped order in 'invoiced' state. opw-4736154
The Unsplash image picker now handles cases where Unsplash returns the same image more than once in a search result. This prevents users from seeing a crash when browsing images, making image selection more reliable.
Original PR description
This commit fixes an OwlError when we try to render the images received from Unsplash after a search. The issue is that Unsplash can send duplicate images in the same batch of images. When we render those in a `t-foreach` and use the image `id`s as the keys, we get a duplicate key error. This is fixed by expanding on the previous filtering code, which ignored duplicates over multiple batches. We now ignore duplicates within batches as well. At the time of writing, Unsplash is sending us duplicate images on a search for "Inventory". opw-5027032 Forward-Port-Of: odoo/odoo#223789
Dutch UBL e-invoices now use the required discount reason text instead of a reason code on invoice line discounts. This prevents NLCIUS validation warnings and helps businesses send compliant invoices in the Netherlands.
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
Refunds for lot-valued products in Point of Sale now correctly complete the related stock transfer when the session is closed. This prevents refund operations from leaving inventory documents stuck and helps keep stock and valuation records accurate.
Original PR description
When refunding a product that was lot valuated, the picking would not be validated automatically. Steps to reproduce: ------------------- * Create a product tracked by lot, and valuated by lot * Open PoS and create an order with this product * Validate the order and create a refund for it * Validate the refund * Close the session, and go to the picking of the session > Observation: The picking is not validated automatically. Why the fix: ------------ It was happening because the line that was put to 0 here (https://github.com/odoo/odoo/blob/eab97bed9c55a9057c7af7450ae1a09c6383a7b5/addons/point_of_sale/models/stock_picking.py#L249) has no lot assigned and should be deleted instead of just put to 0 quanity. It would then raise an error here (https://github.com/odoo/odoo/blob/2d933b83613ad52d76ab457201adecac6fcf184b/addons/stock_account/models/stock_move_line.py#L94) and cancel the validation of the picking. opw-4769042
Odoo now avoids reusing archived supplier bank accounts when importing electronic vendor bills with bank details. This prevents duplicate bank account errors that could block bill creation and interrupt accounts payable processing.
Original PR description
### Issue When receiving vendor bills that include bank details, if the partner has archived bank accounts, Odoo may attempt to update them. This leads to a duplicate key violation on…
### Issue
When receiving vendor bills that include bank details, if the partner has archived bank accounts, Odoo may attempt to update them. This leads to a duplicate key violation on `res_partner_bank` when the same account number already exists for the partner.
#### Affected versions
16.0 and later
#### Error example
```bash
2025-07-08 13:36:52,942 204 INFO server-dummy odoo.addons.mail.models.mail_thread: Routing mail from "Client Name" <erp@odoo.com> to "M7- Odoo V17" <purchases@test.odoo.com>,purchases@test.odoo.com with Message-Id <*****.****.*****-****-*****-****.****@******>: direct alias match: ('account.move', 0, {'company_id': 1, 'move_type': 'in_invoice', 'journal_id': 10}, 1, mail.alias(6,))
2025-07-08 13:36:52,946 204 INFO server-dummy odoo.addons.mail.models.mail_thread: Primary email missing on account.move
2025-07-08 13:36:53,576 204 ERROR server-dummy odoo.sql_db: bad query: UPDATE "res_partner_bank" SET "acc_holder_name" = 'M7 GROUP INC.', "company_id" = NULL, "has_iban_warning" = false, "has_money_transfer_warning" = false, "sanitized_acc_number" = '1234567', "write_date" = '2025-07-08T13:36:52.897826'::timestamp, "write_uid" = 1 WHERE id IN (63)
ERROR: duplicate key value violates unique constraint "res_partner_bank_unique_number"
DETAIL: Key (sanitized_acc_number, partner_id)=(1234567, 3524) already exists.
2025-07-08 13:36:53,576 204 ERROR server-dummy odoo.addons.account.models.account_move: Error importing attachment 'factur-x.xml' as invoice (decoder=_import_invoice_ubl_cii)
Traceback (most recent call last):
File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 3219, in _extend_with_attachments
with self.env.cr.savepoint():
File "/home/odoo/src/odoo/odoo/sql_db.py", line 85, in __exit__
self.close(rollback=exc_type is not None)
File "/home/odoo/src/odoo/odoo/sql_db.py", line 89, in close
self._close(rollback)
File "/home/odoo/src/odoo/odoo/sql_db.py", line 113, in _close
self._cr.flush()
File "/home/odoo/src/odoo/odoo/sql_db.py", line 137, in flush
self.transaction.flush()
File "/home/odoo/src/odoo/odoo/api.py", line 879, in flush
env_to_flush.flush_all()
File "/home/odoo/src/odoo/odoo/api.py", line 739, in flush_all
self[model_name].flush_model()
File "/home/odoo/src/odoo/odoo/models.py", line 6362, in flush_model
self._flush(fnames)
File "/home/odoo/src/odoo/odoo/models.py", line 6464, in _flush
model.browse(ids)._write(vals)
File "/home/odoo/src/odoo/odoo/models.py", line 4548, in _write
cr.execute(SQL(
File "/home/odoo/src/odoo/odoo/sql_db.py", line 332, in execute
res = self._obj.execute(query, params)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "res_partner_bank_unique_number"
DETAIL: Key (sanitized_acc_number, partner_id)=(1234567, 3524) already exists.
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#224071
Forward-Port-Of: odoo/odoo#223873Sales order lines now recalculate unit prices correctly when quantity changes trigger a different pricelist rule. This prevents customers from seeing or being charged outdated prices when volume-based pricing should apply.
Original PR description
**Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: -…
**Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: - 0.75 for quantity ≥ 0 - 0.50 for quantity ≥ 1000 - Pricelist B with a -10% discount applied to Pricelist A. 4. Create a Sales Order using Pricelist B. 5. Add a product to the order line. 6. Increase the quantity to 1000. **Observed behavior**: - The unit price does not update according to the pricelist rule for quantity ≥ 1000. - If you switch the pricelist to another and then back again, the `Update prices` button appears and correctly updates the price. **Root cause**: - The price is not recomputed when the quantity changes because the `price_unit` is not updated because it does not match the `technical_price_unit`. - Since PR (https://github.com/odoo/odoo/pull/213912), `price_unit` is rounded (2 decimals), but `technical_price_unit` is not. This causes a mismatch in comparison logic due to rounding differences. **Solution**: - Replace direct float comparison with `currency_id.compare_amounts()` to ensure proper comparison with rounding precision. opw-4944644
Duplicated journal entries no longer keep the original partner at the entry level when users change partners on the copied journal items. This prevents misleading partner names in list views and keeps accounting records consistent after duplication.
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#217755
Point of Sale now keeps automatic receipt printing working when a store is offline but still connected to its local receipt printer. This prevents staff from having to manually print receipts during internet outages and keeps checkout operations consistent.
Original PR description
Steps to reproduce: 1. Configure a POS to use a receipt printer with automatic receipt printing. 2. Confirm that the receipt is printed automatically after a order is made as expected. 3. Disconnect from the internet so that POS continues in Offline mode (but ensure you still have access to the receipt printer on the local network). 4. Make an order in offline mode. EXPECTED: The receipt is printed automatically as before ACTUAL: The receipt is not printed. The fix is to still run the `afterOrderValidation` method in offline mode, as previously it was being bypassed and the receipt screen being shown directly. task-4946305 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Time Off allocation Kanban view now shows the New button on mobile, allowing managers to create allocations from the standard mobile view. This removes a confusing gap in the workflow and aligns the behavior with newer Odoo versions.
Original PR description
On mobile the "new" button in the time off allocation is not present Steps to reproduce: ------------------- * Open Time_off app * Select Management>Allocations * Open Kanban view (If you are on phone it's the standard view) * Issue : "New" button is missing Observation: The create "0" don't allow to create on kanban view https://github.com/odoo/odoo/blob/2b109261bc6e7550b23a0d444a4e7c63496e4c55/addons/hr_holidays/views/hr_leave_allocation_views.xml#L371 Why the fix: ------------ - It's misleading on phone. - Align with the change on 18.3. https://github.com/odoo/odoo/commit/944c11e61abead4f5157a7a7cb7b1f536bc14411 opw-4898359
This fixes a problem where changing the quantity on a subcontracted receipt could block validation when component lots or serial numbers were required. Users are guided to update quantities through the proper wizard and can access related production records when component details need attention.
Original PR description
Issue ----- The problem is when a subcontracted product has a component tracked by lots. Creating a receipt for the subcontractor, marking it as Todo then changing the quantity leads to the reception…
Issue
-----
The problem is when a subcontracted product has a component tracked by lots. Creating a receipt for the subcontractor, marking it as Todo then changing the quantity leads to the reception being impossible to validate because the lots for the components cannot be set from the move.
Steps to reproduce
-----
- Create a product (Comp1)
- Tracked by lots
- Create a product (Prod1)
- Add a BoM - Subcontracted - Flexible consumption - Set Comp1 as consumable
- Create a receipt for 2 Prod1
- Mark as Todo
- Set Quantity to 3
- Save
- Try to validate the receipt
Situation
-----
Before changing the quantity, the user has 2 buttons ("Record components" and the move's hamburger) which open the "Subcontract" wizard. This wizard is where they can set a lot/serial for the products.
When they change the quantity of the move, the inverse method of quantity is called
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/stock/models/stock_move.py#L170-L171
This method is overridden in the mrp_subcontracting module
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/stock_move.py#L75
The part that's important to our use case is
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/stock_move.py#L81-L82
Recording components leads us to create a backorder production
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/mrp_production.py#L90-L91
In our specific use case, this is problematic because the subcontract wizard loads the form of the last production
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/stock_move.py#L245
The user has no way to access the previous production which lacks lot/serial (other than opening the MO itself). Obviously, we don't want to mess with this flow, but there are 2 things we can do:
1. Avoiding weird cases such as this one by forcing the user to change the quantity through the appropriate wizard
2. Providing a link to the mrp.production once some production has been recorded
For the first point, the stock.move model already has a field we can use
https://github.com/odoo/odoo/blob/8c8449f51d5e327ccd2e4bb7c3c4868d51c6d619/addons/stock/models/stock_move.py#L180
We can just override the compute to fit our use case.
For the second point, there is already a button for this. The problem is that its display condition was changed in 9ca1064 to only show once the move is picked. This fix was a bit of an over correction because we also want to show the button for unpicked moves for which a production has been recorded.
-----
Ticket:
opw-4751896This fixes an issue where standard Employee and Department view options could disappear after enabling a new view through Studio. Users can now customize these HR screens without losing access to existing views such as activity, kanban, calendar, or pivot.
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
This update adjusts a website shop test related to zero-priced products. It helps keep automated checks aligned with expected shopping behavior, reducing the risk of unnoticed issues reaching customers.
Original PR description
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
When invoice OCR finds several contacts with the same VAT number, it now chooses the most relevant customer or supplier based on their business activity ranking. This prevents invoices from being linked to the wrong address or related contact, improving accuracy in automated invoice processing.
Original PR description
It's possible that multiple partners are sharing the same VAT number, for example, when multiple addresses are set on it (each address will be a child `res.partner` with the same VAT number). Previously, when the OCR matched such partners from their VAT number, it would select one "at random" (based on the default sort of `res.partner`). Now, it will match the one with the highest supplier/customer rank. opw-[4954057](https://www.odoo.com/odoo/49/tasks/4954057) Forward-Port-Of: odoo/enterprise#92398
Recurring invoices are now created for subscriptions with timesheet-delivered services even when the original sales order quantity or recurring value is zero. This prevents valid billable work from being incorrectly treated as a free renewal and skipped during automated invoicing.
Original PR description
### Steps to reproduce: - Install Helpdesk, Sale Subscription apps - Create a service recurring product and set its invoicing policy as 'Based on Timesheets' - Create a SO with the created product and set the qty to 0 - Create a Helpdesk ticket and link it to the SO - Record some timesheets in this SO - Run the cron for generating recurring invoices - Notice no invoice will be created for the SO and it will be considered as free renewal ### Cause: When trying to create a recurring invoice we check if the invoice that will get generated is free by checking the MRR and the total amount of the SO and if one of them are 0 we will flag this invoice as free so we won't generate it ### Fix: We check if the order lines to be invoiced is invoiced based on delivery and they have delivered quantity already and if so we create the invoice even if the MRR and the total amount is equal 0 opw-4990478
This update prevents an error when several appointment calendar events are processed at the same time. It ensures each event gets the correct video call redirection link, improving reliability for appointment scheduling.
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
Fixed an issue where projects that exceeded an expense budget could still show the budget status in green instead of red. This helps users quickly identify budget overruns from the project dashboard and avoid misleading financial signals.
Original PR description
**Step to reproduce:** - install "project_account_budget" - go to accounting > accounting > Analytic Budget - create a budget of type expense,say test budget - select analytic account `Asustek - Wood…
**Step to reproduce:**
- install "project_account_budget"
- go to accounting > accounting > Analytic Budget
- create a budget of type expense,say test budget
- select analytic account `Asustek - Wood Corner`
- set budget amount => 500. open the budget
- create a new project 'test project"> open setting > Analytic Page
- add `Asustek - Wood Corner` analytic account in project field
- create a PO with amount > 500
- in analytic distribution column, add `Asustek - Wood Corner` in project column
- confirm PO and create Bill
- Go to `test project` settings > Dashboard smart button
**Observation:**
- For exceeding expense budget, we have green color in budget section
- It should be red
**Cause:**
The conditional class for budget progress was incorrectly evaluated due to missing parentheses around the `and` condition.
In expressions like:
`(true and (1 == 1 ? 'a' : 'c')) or (1 == 1 ? 'b' : 'd') → 'a'` ✅
`true and 1 == 1 ? 'a' : 'c' or 1 == 1 ? 'b' : 'd' → 'b'` ❌
Without parenthesis, the `or` clause is evaluated unexpectedly, even when the `and` branch is intended to take precedence.
This commit wraps the `and` condition in parentheses to ensure the correct evaluation order and consistent class assignment.
Budget:
<img width="1203" height="291" alt="budget 4968162" src="https://github.com/user-attachments/assets/2d8223d5-0344-4ad0-b33c-2598ea167f2d" />
Before fix:
<img width="623" height="195" alt="before fix 4968162" src="https://github.com/user-attachments/assets/4ac749bf-fa93-4835-963a-5dfbdd05559d" />
After fix:
<img width="643" height="225" alt="after fix 4968162 " src="https://github.com/user-attachments/assets/4fd228f9-e32f-48d9-b6ef-55251b21d601" />
opw-4968162Swiss payroll ELM transmissions now include contact person details only when all required contact fields are filled in. This helps avoid sending incomplete contact information and reduces the risk of rejected or unclear declarations.
Original PR description
Contact person information should only be transmitted if all 3 fields are filled Forward-Port-Of: odoo/enterprise#93084
Quality IoT setups can now distinguish between multiple connected cameras, allowing more than one camera to be used at the same time. Existing camera configurations are preserved through a temporary compatibility identifier, and camera communication is made more reliable by avoiding websocket errors.
Original PR description
Due to an issue with the `CameraInterface`, the same identifier would be chosen for any connected camera (`camera-2`), meaning only one camera could be used at once. To fix this, the `camera.id`…
Due to an issue with the `CameraInterface`, the same identifier would be chosen for any connected camera (`camera-2`), meaning only one camera could be used at once. To fix this, the `camera.id` property is used as the identifier instead. The `libcamera` documentation says the following: > The camera ID is a free-form string that identifies a camera in the > system. IDs are guaranteed to be unique and stable: the same camera, > when connected to the system in the same way > (e.g. in the same USB port), will have the same ID across both > unplug/replug and system reboots. However, we will also still return the last camera with the `camera-2` identifier, so that existing device configurations in the backend don't get lost. In master we will remove this legacy identifier. You can see the legacy camera with the others in the list below: <img width="801" height="385" alt="image" src="https://github.com/user-attachments/assets/6f3a6408-bcb4-46b0-980e-b5a8881f6df0" /> In addition, another small fix was made to the `CameraDriver` to ensure a string is sent rather than raw bytes, this prevents a traceback when communicating over the websocket. task-4792552 Forward-Port-Of: odoo/enterprise#93076
Users can now duplicate multiple appointment bookings at the same time from the list view without triggering an error. This removes a blocker for staff managing several bookings and makes appointment administration smoother.
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 happened because the `copy()` method in `calendar.event` assumed a single record, but in list view, users can select and duplicate multiple records at once. Reference commit: https://github.com/odoo/enterprise/commit/6e85fff3d9fce23f8591e6bb3340749c889c9934 Done for single record.
The field service report guided tour was adjusted so it waits for the correct action button instead of matching a condition that was always true. This makes the tour more reliable and helps prevent interruptions during guided workflows or automated checks.
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"].
A failing rental point-of-sale test is fixed by ensuring a needed price list is available during the test setup. This helps keep automated checks reliable without changing customer-facing behavior.
Original PR description
The test was failing because available_pricelist_ids was empty although it was not since it is filled in the setup
but this line `self.env['res.config.settings'].create({'group_rental_stock_picking': False}).execute()`,
empty it and the test expected at least one pricelist to be available for the POS configuration.
This caused the test to fail when it tried to access the first element of an empty list.
This change adds a check, and if no pricelist exists, it creates one and links it to the POS config.
build_error-223356Code cleanup and technical improvements
This draft update removes or simplifies parts of the automated onboarding tour checks for Helpdesk and Planning. The change appears to be internal test maintenance, with minimal expected impact on day-to-day business users.