diff --git a/docsource/modules190-200.rst b/docsource/modules190-200.rst index 8da46d62bbc..7cc613ca895 100644 --- a/docsource/modules190-200.rst +++ b/docsource/modules190-200.rst @@ -6,7 +6,7 @@ Module coverage 19.0 -> 20.0 +---------------------------------------------------+----------------------+-------------------------------------------------+ | Module | Status + Extra Information | +===================================================+======================+=================================================+ -| account | | | +| account |Done | | +---------------------------------------------------+----------------------+-------------------------------------------------+ | |del| account_add_gln | | | +---------------------------------------------------+----------------------+-------------------------------------------------+ diff --git a/openupgrade_scripts/scripts/account/20.0.1.5/noupdate_changes.xml b/openupgrade_scripts/scripts/account/20.0.1.5/noupdate_changes.xml new file mode 100644 index 00000000000..10dcc32f4e9 --- /dev/null +++ b/openupgrade_scripts/scripts/account/20.0.1.5/noupdate_changes.xml @@ -0,0 +1,129 @@ + + + + + + + + + + {'module': 'general_settings'} + + + mail.mail_notification_layout_with_responsible_signature + + + +
+

+ Dear + Brandon Freeman (Azure Interior), + Azure Interior, + + Brandon Freeman, + +

+ Here is your + + invoice INV/2021/05/0005 + + + invoice + + + (with reference: SUB003) + + amounting in $ 143,750.00 + from YourCompany. + + This invoice is already paid. + + + Please remit payment at your earliest convenience. +

+ Please use the following communication for your payment: INV/2021/05/0005 + + on the account + + . +
+
+

+ Do not hesitate to contact us if you have any questions. +

--
Mitchell Admin
+

+
+
+ mail.mail_notification_layout_with_responsible_signature +
+ + +
+

+ Dear + Brandon Freeman (Azure Interior), + Azure Interior, + + Brandon Freeman, + +

+ Here is your + + self-billing invoice INV/2021/05/0005 + + + self-billing invoice + + + (with reference: SUB003) + + amounting in $ 143,750.00 + from YourCompany. + + This self-billing invoice has already been paid. + +

+ Do not hesitate to contact us if you have any questions. +

--
Mitchell Admin
+

+
+
+
+ + + +
+

+ Dear Azure Interior

+ We have processed your refund of + We have processed your payment of + Thank you for your refund of + Thank you for your payment of $ 10.00. + Please find the payment receipt BNK1-2021-05-0002 from YourCompany. +

+ Do not hesitate to contact us if you have any questions. +

+ Best regards, +

--
Mitchell Admin
+

+
+
+ {{ object.company_id.name }} {{ object.payment_receipt_title }} (Ref {{ object.name or 'n/a' }}) + mail.mail_notification_light +
+ + + +
diff --git a/openupgrade_scripts/scripts/account/20.0.1.5/post-migration.py b/openupgrade_scripts/scripts/account/20.0.1.5/post-migration.py new file mode 100644 index 00000000000..c6fd166ddef --- /dev/null +++ b/openupgrade_scripts/scripts/account/20.0.1.5/post-migration.py @@ -0,0 +1,100 @@ +# Copyright 2026 Don Kendall +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from openupgradelib import openupgrade + + +def _settle_in_process_payments(env): + """19.0's payment state had an "In Process" step that 20.0 does not. + + 19.0 ran draft -> in_process -> paid; 20.0 runs draft -> paid -> + reconciled. The middle step is gone, and because the column already holds a + value the stored compute leaves it there: the payment reads as blank in the + interface and matches no branch of a domain over the state. + + 'paid' is the honest landing point. It states only what is certainly true -- + the payment was made -- and 20.0's own _compute_state takes it from there: + for a payment already in 'paid' or 'reconciled' it re-derives which of the + two applies from the liquidity lines' residual. Writing 'reconciled' + directly would assert a bank match this migration has no evidence for. + """ + openupgrade.logged_query( + env.cr, + "UPDATE account_payment SET state = 'paid' WHERE state = 'in_process'", + ) + + +def _carry_a_deliberate_not_reviewed_into_the_review_queue(env): + """19.0's `checked` becomes 20.0's review_state, and only part of it is real. + + 19.0 carried a boolean "Reviewed". It was a stored COMPUTE with the value + written by:: + + move.checked = move.state == 'posted' and ( + move.journal_id.type == 'general' or move._is_user_able_to_review()) + + and `readonly=False`, so a user could tick or untick it afterwards. + + 20.0 replaces it with `review_state`, a plain stored selection of no_review + / todo / reviewed / supervised / anomaly defaulting to 'no_review', and + keeps an index named after the field it replaced:: + + _checked_idx = models.Index( + "(journal_id) WHERE (review_state IN ('todo', 'anomaly'))") + + which is what makes it a work queue rather than a label. + + **Only the deviation is carried.** A True that merely reproduces the compute + records nothing a reader could not derive, and writing 'reviewed' for it + would assert a review of every posted invoice in the database -- 3206 of the + seed's 3223 moves, on the strength of a value that is really just "posted". + A posted move whose `checked` is FALSE is the opposite: the compute would + have set it True, so False is there because somebody put it there, and + 'todo' is what 20.0 calls that. + + Nothing is written for a draft move. 19.0 left those unchecked by the same + formula, which says "not posted yet", not "waiting to be reviewed". + + **This seed contains no such row** -- `checked` equals `state = 'posted'` on + all 3223 of its moves -- so the branch is unreachable here and the migration + test builds the row that reaches it. The count is reported either way, so a + database where it does fire says so in the log rather than only in the data. + """ + openupgrade.logged_query( + env.cr, + """ + UPDATE account_move + SET review_state = 'todo' + WHERE state = 'posted' AND NOT checked AND review_state = 'no_review' + """, + ) + if env.cr.rowcount: + openupgrade.message( + env.cr, + "account", + False, + False, + "%s posted journal entr(ies) had been marked as NOT reviewed by hand " + "in 19.0 and are now in 20.0's review queue as 'todo'; entries that " + "merely carried the computed default were left on 'no_review'", + env.cr.rowcount, + ) + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.load_data(env, "account", "20.0.1.5/noupdate_changes.xml") + openupgrade.delete_record_translations( + env.cr, + "account", + ["email_template_edi_invoice", "email_template_edi_self_billing_invoice"], + ["body_html"], + ) + openupgrade.delete_record_translations( + env.cr, + "account", + ["mail_template_data_payment_receipt"], + ["body_html", "subject"], + ) + _settle_in_process_payments(env) + _carry_a_deliberate_not_reviewed_into_the_review_queue(env) diff --git a/openupgrade_scripts/scripts/account/20.0.1.5/pre-migration.py b/openupgrade_scripts/scripts/account/20.0.1.5/pre-migration.py new file mode 100644 index 00000000000..a1a55ad57f4 --- /dev/null +++ b/openupgrade_scripts/scripts/account/20.0.1.5/pre-migration.py @@ -0,0 +1,20 @@ +# Copyright 2026 Don Kendall +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from openupgradelib import openupgrade + +_renamed_xmlids = [ + # the stock valuation report moved from stock_account into account + ( + "stock_account.action_report_stock_valuation", + "account.action_report_stock_valuation", + ), +] + + +@openupgrade.migrate() +def migrate(env, version): + # The client action keeps its path, which is unique, so account's copy of + # the record has to land on the existing row instead of inserting a second + # one and tripping ir_act_client_path_unique. + openupgrade.rename_xmlids(env.cr, _renamed_xmlids) diff --git a/openupgrade_scripts/scripts/account/20.0.1.5/upgrade_analysis.txt b/openupgrade_scripts/scripts/account/20.0.1.5/upgrade_analysis.txt new file mode 100644 index 00000000000..af5e5efb645 --- /dev/null +++ b/openupgrade_scripts/scripts/account/20.0.1.5/upgrade_analysis.txt @@ -0,0 +1,564 @@ +---Models in module 'account'--- +obsolete model account.group +new model account.stock.valuation.report (renamed from stock_account.stock.valuation.report in module stock_account) [abstract] +new model res.currency.rate.consolidation.mixin [abstract] +---Fields in module 'account'--- +account / account.account / _order : _order is now 'code_path, account_type, name_path' ('code, placeholder_code') +account / account.account / account_stock_expense_id (many2one): previously in module stock_account +account / account.account / account_stock_variation_id (many2one): previously in module stock_account +account / account.account / parent_id (many2one) : NEW relation: account.account +account / account.account / parent_path (char) : NEW +account / account.account / website_message_ids (one2many): DEL relation: mail.message +account / account.bank.statement / is_statement_posted (boolean) : NEW hasdefault: default +account / account.bank.statement.line / invoice_outstanding_credits_debits_widget (binary): type is now 'json' ('binary') +account / account.bank.statement.line / invoice_payments_widget (binary): type is now 'json' ('binary') +account / account.bank.statement.line / needed_terms (binary) : type is now 'json' ('binary') +account / account.bank.statement.line / payment_term_details (binary) : type is now 'json' ('binary') +account / account.bank.statement.line / tax_totals (binary) : type is now 'json' ('binary') +account / account.cash.rounding / _order : _order is now 'sequence, id' ('id') +account / account.cash.rounding / active (boolean) : NEW hasdefault: default +account / account.cash.rounding / company_id (many2one) : NEW relation: res.company +account / account.cash.rounding / currency_ids (many2many) : NEW relation: res.currency +account / account.cash.rounding / partner_category_ids (many2many): NEW relation: res.partner.category +account / account.cash.rounding / payment_method_line_ids (many2many): NEW relation: account.payment.method.line +account / account.cash.rounding / sequence (integer) : NEW required, hasdefault: default +account / account.fiscal.position / account_map (binary) : type is now 'json' ('binary') +account / account.fiscal.position / tax_map (binary) : type is now 'json' ('binary') +account / account.group / code_prefix_end (char) : DEL +account / account.group / code_prefix_start (char) : DEL +account / account.group / company_id (many2one) : DEL relation: res.company, required +account / account.group / name (char) : DEL required +account / account.group / parent_id (many2one) : DEL relation: account.group +account / account.journal / disable_dashboard_graph (boolean): NEW +account / account.journal / display_invoice_template_pdf_report_id (boolean): now a function +account / account.journal / journal_group_id (many2one) : NEW relation: account.journal.group +account / account.journal / journal_group_ids (many2many) : DEL relation: account.journal.group +account / account.journal / website_message_ids (one2many): DEL relation: mail.message +account / account.journal.group / company_id (many2one) : DEL relation: res.company +account / account.journal.group / excluded_journal_ids (many2many): DEL relation: account.journal +account / account.journal.group / included_journal_ids (one2many): NEW relation: account.journal +account / account.move / checked (boolean) : DEL +account / account.move / document_tax_mode (selection) : NEW selection_keys: ['tax_excluded', 'tax_included'], hasdefault: compute +account / account.move / import_source_attachment_id (many2one): NEW relation: ir.attachment +account / account.move / inventory_closing (boolean) : NEW hasdefault: default +account / account.move / invoice_outstanding_credits_debits_widget (binary): type is now 'json' ('binary') +account / account.move / invoice_payments_widget (binary): type is now 'json' ('binary') +account / account.move / journal_group_id (many2one) : now related +account / account.move / journal_line_ids (one2many) : DEL relation: account.move.line +account / account.move / narration (html) : now a function +account / account.move / needed_terms (binary) : type is now 'json' ('binary') +account / account.move / payment_term_details (binary) : type is now 'json' ('binary') +account / account.move / review_state (selection) : NEW required, selection_keys: ['anomaly', 'no_review', 'reviewed', 'supervised', 'todo'], hasdefault: default +account / account.move / tax_totals (binary) : type is now 'json' ('binary') +account / account.move / website_message_ids (one2many): DEL relation: mail.message +account / account.move.line / cogs_origin_id (many2one) : previously in module stock_account +account / account.move.line / deductible_amount (float) : DEL +account / account.move.line / deductible_percentage (float) : NEW hasdefault: default +account / account.move.line / discount_allocation_key (binary): type is now 'json' ('binary') +account / account.move.line / discount_allocation_needed (binary): type is now 'json' ('binary') +account / account.move.line / epd_key (binary) : type is now 'json' ('binary') +account / account.move.line / epd_needed (binary) : type is now 'json' ('binary') +account / account.move.line / journal_group_id (many2one) : now related +account / account.move.line / name (char) : type is now 'text' ('char') +account / account.move.line / open_on (date) : NEW stored: False +account / account.move.line / term_key (binary) : type is now 'json' ('binary') +account / account.payment / commercial_partner_id (many2one): NEW relation: res.partner, isfunction: function, stored +account / account.payment / return_partner_bank_id (many2one): NEW relation: res.partner.bank, hasdefault: compute +account / account.payment / state (selection) : selection_keys added: [reconciled], removed: [in_process] +account / account.payment / transaction_uuid (char) : NEW isfunction: function, stored +account / account.payment / website_message_ids (one2many): DEL relation: mail.message +account / account.reconcile.model / matching_order (selection) : NEW required, selection_keys: ['new_first', 'old_first'], hasdefault: default +account / account.reconcile.model / payment_tolerance (float) : NEW required, hasdefault: default +account / account.reconcile.model / payment_tolerance_type (selection): NEW required, selection_keys: ['amount', 'percentage'], hasdefault: default +account / account.reconcile.model / rule_type (selection) : NEW selection_keys: ['matching_rule', 'reco_model'], hasdefault: default +account / account.reconcile.model / website_message_ids (one2many): DEL relation: mail.message +account / account.report / active (boolean) : not stored anymore +account / account.report / active (boolean) : now a function +account / account.report / active_fallback (boolean) : NEW hasdefault: default +account / account.report / active_selection (selection) : NEW selection_keys: ['False', 'True'] +account / account.report / availability_condition (selection): selection_keys added: [consolidation] (most likely nothing to do) +account / account.report / enable_snapshots (boolean) : NEW hasdefault: compute +account / account.report / filter_analytic (boolean) : DEL +account / account.report / filter_line_comparison (boolean): NEW hasdefault: compute +account / account.report / groupby (char) : NEW +account / account.report / prefix_groups_threshold (integer): DEL +account / account.report / use_fiscal_periods (boolean) : NEW hasdefault: compute +account / account.report / user_groupby (char) : NEW hasdefault: compute +account / account.report.column / figure_type (selection) : selection_keys added: [many2one] (most likely nothing to do) +account / account.report.column / report_id (many2one) : now required +account / account.report.expression / engine (selection) : selection_keys added: [reference, text] (most likely nothing to do) +account / account.report.expression / figure_type (selection) : selection_keys added: [many2one] (most likely nothing to do) +account / account.report.expression / formula (char) : type is now 'text' ('char') +account / account.report.expression / subformula (char) : type is now 'text' ('char') +account / account.report.line / foldability (selection) : NEW selection_keys: ['always_unfolded', 'foldable', 'never_unfolded'], hasdefault: compute +account / account.report.line / foldable (boolean) : DEL +account / account.tax / website_message_ids (one2many): DEL relation: mail.message +account / account.tax.group / advance_tax_payment_account_id (many2one): DEL relation: account.account +account / account.tax.group / tax_payable_account_id (many2one): DEL relation: account.account +account / account.tax.group / tax_receivable_account_id (many2one): DEL relation: account.account +account / account.tax.repartition.line / tag_ids_domain (binary) : type is now 'json' ('binary') +account / ir.module.module / account_templates (binary) : type is now 'json' ('binary') +account / product.category / account_stock_variation_id (many2one): previously in module stock_account +account / product.category / property_cost_method (selection): previously in module stock_account +account / product.category / property_price_difference_account_id (many2one): previously in module stock_account +account / product.category / property_stock_journal (many2one): previously in module stock_account +account / product.category / property_stock_valuation_account_id (many2one): previously in module stock_account +account / product.category / property_valuation (selection): previously in module stock_account +account / product.product / catalog_is_in_selected_section (boolean): NEW stored: False +account / product.product / cost_method (selection) : previously in module stock_account +account / product.product / valuation (selection) : previously in module stock_account +account / product.template / cost_method (selection) : previously in module stock_account +account / product.template / valuation (selection) : previously in module stock_account +account / res.company / account_stock_journal_id (many2one): previously in module stock_account +account / res.company / account_stock_valuation_id (many2one): previously in module stock_account +account / res.company / cost_method (selection) : previously in module stock_account +account / res.company / document_sequence_editable (boolean): NEW +account / res.company / expense_account_id (many2one) : not stored anymore +account / res.company / expense_account_id (many2one) : now a function +account / res.company / income_account_id (many2one) : not stored anymore +account / res.company / income_account_id (many2one) : now a function +account / res.company / inventory_period (selection) : previously in module stock_account +account / res.company / inventory_valuation (selection): previously in module stock_account +account / res.company / quick_edit_mode_enabled (boolean): NEW +account / res.company / set_to_review_documents (boolean): NEW +account / res.company / vat_check_vies (boolean) : previously in module base_vat +account / res.company / vat_disabled (boolean) : NEW isfunction: function, stored +account / res.company / website_message_ids (one2many): DEL relation: mail.message +account / res.partner / display_invoice_template_pdf_report_id (boolean): now a function +account / res.partner / duplicate_bank_partner_ids (many2many): not related anymore +account / res.partner / duplicate_bank_partner_ids (many2many): now a function +account / res.partner / qr_code_method (selection) : NEW selection_keys: function +account / res.partner.bank / account_type (False) : NEW selection_keys: ['bank', 'clabe', 'iban'], mode: modify +account / res.partner.bank / has_iban_warning (boolean) : DEL +account / res.partner.bank / has_money_transfer_warning (boolean): DEL +account / res.partner.bank / has_phishing_warnings (boolean): NEW isfunction: function, stored +account / res.partner.bank / website_message_ids (one2many): DEL relation: mail.message +account_add_gln / res.partner / global_location_number (char) : not stored anymore +account_add_gln / res.partner / global_location_number (char) : now a function +stock_account / product.category / property_cost_method (selection): selection_keys removed: [fifo] +stock_account / product.template / cost_method (selection) : selection_keys removed: [fifo] +stock_account / res.company / account_stock_journal_id (many2one): not stored anymore +stock_account / res.company / account_stock_journal_id (many2one): now a function +stock_account / res.company / account_stock_valuation_id (many2one): not stored anymore +stock_account / res.company / account_stock_valuation_id (many2one): now a function +stock_account / res.company / cost_method (selection) : not stored anymore +stock_account / res.company / cost_method (selection) : now a function +stock_account / res.company / cost_method (selection) : selection_keys removed: [fifo] +stock_account / res.company / inventory_valuation (selection): not stored anymore +stock_account / res.company / inventory_valuation (selection): now a function +---XML records in module 'account'--- +account.account.tag: account.account_tag_financing (noupdate switched) +account.account.tag: account.account_tag_investing (noupdate switched) +account.account.tag: account.account_tag_operating (noupdate switched) +account.payment.method: account.account_payment_method_manual_in (noupdate switched) +account.payment.method: account.account_payment_method_manual_out (noupdate switched) +account.payment.term: account.account_payment_term_15days (noupdate switched) +account.payment.term: account.account_payment_term_21days (noupdate switched) +account.payment.term: account.account_payment_term_30_days_end_month_the_10 (noupdate switched) +account.payment.term: account.account_payment_term_30days (noupdate switched) +account.payment.term: account.account_payment_term_30days_early_discount (noupdate switched) +account.payment.term: account.account_payment_term_45days (noupdate switched) +account.payment.term: account.account_payment_term_90days_on_the_10th (noupdate switched) +account.payment.term: account.account_payment_term_advance_60days (noupdate switched) +account.payment.term: account.account_payment_term_end_following_month (noupdate switched) +account.payment.term: account.account_payment_term_immediate (noupdate switched) +decimal.precision: account.decimal_payment (noupdate switched) +digest.digest: digest.digest_digest_default (noupdate switched) +DEL digest.tip: account.digest_tip_account_0 +NEW ir.access: account.access_account_account_manager +NEW ir.access: account.access_account_account_tax +NEW ir.access: account.access_account_account_user +NEW ir.access: account.access_account_accrued_orders_wizard +NEW ir.access: account.access_account_analytic_account +NEW ir.access: account.access_account_analytic_accountant +NEW ir.access: account.access_account_analytic_applicability_accountant +NEW ir.access: account.access_account_analytic_distribution_invoice +NEW ir.access: account.access_account_analytic_distribution_readonly +NEW ir.access: account.access_account_analytic_plan_accountant +NEW ir.access: account.access_account_automatic_entry_wizard +NEW ir.access: account.access_account_autopost_bills_wizard +NEW ir.access: account.access_account_bank_statement +NEW ir.access: account.access_account_bank_statement_group_invoice +NEW ir.access: account.access_account_bank_statement_group_readonly +NEW ir.access: account.access_account_cash_rounding_readonly +NEW ir.access: account.access_account_cash_rounding_uinvoice +NEW ir.access: account.access_account_code_mapping +NEW ir.access: account.access_account_code_mapping_manager +NEW ir.access: account.access_account_financial_year_op +NEW ir.access: account.access_account_fiscal_position +NEW ir.access: account.access_account_fiscal_position_account +NEW ir.access: account.access_account_fiscal_position_account_product_manager +NEW ir.access: account.access_account_fiscal_position_product_manager +NEW ir.access: account.access_account_full_reconcile_group_invoice +NEW ir.access: account.access_account_full_reconcile_group_readonly +NEW ir.access: account.access_account_incoterms_all +NEW ir.access: account.access_account_incoterms_manager +NEW ir.access: account.access_account_journal_group_invoice +NEW ir.access: account.access_account_journal_group_manager +NEW ir.access: account.access_account_journal_group_readonly +NEW ir.access: account.access_account_journal_invoice +NEW ir.access: account.access_account_journal_manager +NEW ir.access: account.access_account_journal_readonly +NEW ir.access: account.access_account_lock_exception +NEW ir.access: account.access_account_lock_exception_manager +NEW ir.access: account.access_account_merge_wizard_line_manager +NEW ir.access: account.access_account_merge_wizard_manager +NEW ir.access: account.access_account_move_reversal +NEW ir.access: account.access_account_partial_reconcile_group_invoice +NEW ir.access: account.access_account_partial_reconcile_readonly +NEW ir.access: account.access_account_payment +NEW ir.access: account.access_account_payment_method +NEW ir.access: account.access_account_payment_method_line +NEW ir.access: account.access_account_payment_method_line_readonly +NEW ir.access: account.access_account_payment_method_readonly +NEW ir.access: account.access_account_payment_readonly +NEW ir.access: account.access_account_payment_register +NEW ir.access: account.access_account_payment_term_line_manager +NEW ir.access: account.access_account_payment_term_line_partner_manager +NEW ir.access: account.access_account_payment_term_manager +NEW ir.access: account.access_account_payment_term_partner_manager +NEW ir.access: account.access_account_payment_term_portal +NEW ir.access: account.access_account_reconcile_model +NEW ir.access: account.access_account_reconcile_model_billing +NEW ir.access: account.access_account_reconcile_model_line +NEW ir.access: account.access_account_reconcile_model_line_billing +NEW ir.access: account.access_account_reconcile_model_line_readonly +NEW ir.access: account.access_account_reconcile_model_readonly +NEW ir.access: account.access_account_report_ac_user +NEW ir.access: account.access_account_report_column_ac_user +NEW ir.access: account.access_account_report_column_readonly +NEW ir.access: account.access_account_report_expression_ac_user +NEW ir.access: account.access_account_report_expression_readonly +NEW ir.access: account.access_account_report_external_value_ac_user +NEW ir.access: account.access_account_report_external_value_readonly +NEW ir.access: account.access_account_report_line_ac_user +NEW ir.access: account.access_account_report_line_readonly +NEW ir.access: account.access_account_report_readonly +NEW ir.access: account.access_account_resequence +NEW ir.access: account.access_account_root +NEW ir.access: account.access_account_secure_entries_wizard +NEW ir.access: account.access_account_setup_bank_manual_config +NEW ir.access: account.access_account_tag_internal_user +NEW ir.access: account.access_account_tax_group_internal_user +NEW ir.access: account.access_account_tax_group_manager +NEW ir.access: account.access_account_tax_internal_user +NEW ir.access: account.access_account_tax_manager +NEW ir.access: account.access_account_tax_repartition_line_manager +NEW ir.access: account.access_account_tax_repartition_line_user +NEW ir.access: account.access_base_document_layout_account_user +NEW ir.access: account.access_ir_model_account_reports +NEW ir.access: account.access_product_product_account_user +NEW ir.access: account.access_res_currency_account_manager +NEW ir.access: account.access_res_currency_rate_account_manager +NEW ir.access: account.access_validate_account_move +NEW ir.access: account.account_analytic_line_rule_billing_user +NEW ir.access: account.account_analytic_line_rule_readonly_user +NEW ir.access: account.account_bank_statement_comp_rule +NEW ir.access: account.account_bank_statement_line_comp_rule +NEW ir.access: account.account_bank_statement_line_rule_basic_user +NEW ir.access: account.account_bank_statement_line_rule_invoice_user +NEW ir.access: account.account_bank_statement_line_rule_readonly_user +NEW ir.access: account.account_cash_rounding_comp_rule +NEW ir.access: account.account_comp_rule +NEW ir.access: account.account_fiscal_position_comp_rule +NEW ir.access: account.account_invoice_line_rule_portal +NEW ir.access: account.account_invoice_report_rule_invoice +NEW ir.access: account.account_invoice_report_rule_readonly +NEW ir.access: account.account_invoice_rule_portal +NEW ir.access: account.account_move_comp_rule +NEW ir.access: account.account_move_line_comp_rule +NEW ir.access: account.account_move_line_rule_group_readonly +NEW ir.access: account.account_move_line_see_all +NEW ir.access: account.account_move_rule_group_readonly +NEW ir.access: account.account_move_see_all +NEW ir.access: account.account_move_send_batch_rule_group_invoice +NEW ir.access: account.account_move_send_single_rule_group_invoice +NEW ir.access: account.account_payment_comp_rule +NEW ir.access: account.account_payment_term_comp_rule +NEW ir.access: account.account_reconcile_model_line_template_comp_rule +NEW ir.access: account.account_reconcile_model_template_comp_rule +NEW ir.access: account.invoice_analysis_comp_rule +NEW ir.access: account.ir_rule_res_partner_bank_billing_officers +NEW ir.access: account.journal_comp_rule +NEW ir.access: account.report_external_value_comp_rule +NEW ir.access: account.res_partner_rule_user +NEW ir.access: account.tax_comp_rule +NEW ir.access: account.tax_group_comp_rule +NEW ir.access: account.tax_rep_comp_rule +ir.actions.act_window: account.account_send_payment_receipt_by_email_action (noupdate switched) +ir.actions.act_window: account.account_send_payment_receipt_by_email_action_multi (noupdate switched) +ir.actions.act_window: account.action_account_audit_trail_report (deleted domain) +NEW ir.actions.act_window: account.action_account_cashflow_analysis +NEW ir.actions.act_window: account.action_account_matching_rules +ir.actions.act_window: account.action_account_moves_all (deleted domain) +ir.actions.act_window: account.action_account_moves_all_a (deleted domain) +ir.actions.act_window: account.action_account_moves_all_grouped_matching (deleted domain) +ir.actions.act_window: account.action_account_moves_all_tree (deleted domain) +ir.actions.act_window: account.action_account_moves_email_preview (deleted domain) +ir.actions.act_window: account.action_account_moves_journal_bank_cash (deleted domain) +ir.actions.act_window: account.action_account_moves_journal_misc (deleted domain) +ir.actions.act_window: account.action_account_moves_journal_purchase (deleted domain) +ir.actions.act_window: account.action_account_moves_journal_sales (deleted domain) +ir.actions.act_window: account.action_account_moves_ledger_partner (deleted domain) +ir.actions.act_window: account.action_account_resequence (noupdate switched) +ir.actions.act_window: account.action_amounts_to_settle (deleted domain) +ir.actions.act_window: account.action_bank_statement_tree (deleted domain) +ir.actions.act_window: account.action_credit_statement_tree (deleted domain) +ir.actions.act_window: account.action_move_in_invoice (deleted domain) +ir.actions.act_window: account.action_move_in_invoice_type (deleted domain) +ir.actions.act_window: account.action_move_in_refund_type (deleted domain) +ir.actions.act_window: account.action_move_out_invoice (deleted domain) +ir.actions.act_window: account.action_move_out_invoice_type (deleted domain) +ir.actions.act_window: account.action_move_out_refund_type (deleted domain) +ir.actions.act_window: account.action_move_out_refund_type_non_legacy (deleted domain) +ir.actions.act_window: account.action_open_settings (noupdate switched) +ir.actions.act_window: account.action_view_bank_statement_tree (deleted domain) +ir.actions.act_window: account.res_partner_action_supplier_bills (deleted domain) +NEW ir.actions.client: account.action_report_stock_valuation [renamed from stock_account module] +NEW ir.actions.server: account.accountant_reset_to_draft_entries_action +NEW ir.actions.server: account.action_mark_payment_as_reconciled +NEW ir.actions.server: account.action_server_payment_receipt +ir.actions.server: account.model_account_move_action_share (noupdate switched) +DEL ir.actions.server: account.accountant_confirm_entries_action +NEW ir.config_parameter: account.disable_dashboard_kpis +ir.config_parameter: account.product_name_similarity_threshold (noupdate switched) +NEW ir.cron: account.ir_cron_post_stock_valuation [renamed from stock_account module] (noupdate switched) +DEL ir.model.access: account.access_account_account +DEL ir.model.access: account.access_account_account_invoice +DEL ir.model.access: account.access_account_account_manager +DEL ir.model.access: account.access_account_account_partner_manager +DEL ir.model.access: account.access_account_account_tax +DEL ir.model.access: account.access_account_account_tax_readonly +DEL ir.model.access: account.access_account_account_tax_user +DEL ir.model.access: account.access_account_account_user +DEL ir.model.access: account.access_account_accrued_orders_wizard +DEL ir.model.access: account.access_account_analytic_account +DEL ir.model.access: account.access_account_analytic_accountant +DEL ir.model.access: account.access_account_analytic_applicability_accountant +DEL ir.model.access: account.access_account_analytic_distribution_invoice +DEL ir.model.access: account.access_account_analytic_distribution_readonly +DEL ir.model.access: account.access_account_analytic_line_invoice +DEL ir.model.access: account.access_account_analytic_line_manager +DEL ir.model.access: account.access_account_analytic_line_readonly +DEL ir.model.access: account.access_account_analytic_plan_accountant +DEL ir.model.access: account.access_account_automatic_entry_wizard +DEL ir.model.access: account.access_account_autopost_bills_wizard +DEL ir.model.access: account.access_account_bank_statement +DEL ir.model.access: account.access_account_bank_statement_group_invoice +DEL ir.model.access: account.access_account_bank_statement_group_readonly +DEL ir.model.access: account.access_account_bank_statement_line +DEL ir.model.access: account.access_account_bank_statement_line_group_invoice +DEL ir.model.access: account.access_account_bank_statement_line_group_readonly +DEL ir.model.access: account.access_account_cash_rounding_readonly +DEL ir.model.access: account.access_account_cash_rounding_uinvoice +DEL ir.model.access: account.access_account_code_mapping +DEL ir.model.access: account.access_account_code_mapping_manager +DEL ir.model.access: account.access_account_financial_year_op +DEL ir.model.access: account.access_account_fiscal_position +DEL ir.model.access: account.access_account_fiscal_position_account +DEL ir.model.access: account.access_account_fiscal_position_account_product_manager +DEL ir.model.access: account.access_account_fiscal_position_product_manager +DEL ir.model.access: account.access_account_full_reconcile +DEL ir.model.access: account.access_account_full_reconcile_group_invoice +DEL ir.model.access: account.access_account_full_reconcile_group_readonly +DEL ir.model.access: account.access_account_group +DEL ir.model.access: account.access_account_group_basic +DEL ir.model.access: account.access_account_group_manager +DEL ir.model.access: account.access_account_incoterms_all +DEL ir.model.access: account.access_account_incoterms_manager +DEL ir.model.access: account.access_account_invoice_line_portal +DEL ir.model.access: account.access_account_invoice_portal +DEL ir.model.access: account.access_account_invoice_report +DEL ir.model.access: account.access_account_invoice_report_billing +DEL ir.model.access: account.access_account_invoice_report_readonly +DEL ir.model.access: account.access_account_journal_group_invoice +DEL ir.model.access: account.access_account_journal_group_manager +DEL ir.model.access: account.access_account_journal_group_readonly +DEL ir.model.access: account.access_account_journal_invoice +DEL ir.model.access: account.access_account_journal_manager +DEL ir.model.access: account.access_account_journal_readonly +DEL ir.model.access: account.access_account_lock_exception +DEL ir.model.access: account.access_account_lock_exception_manager +DEL ir.model.access: account.access_account_merge_wizard_line_manager +DEL ir.model.access: account.access_account_merge_wizard_manager +DEL ir.model.access: account.access_account_move_line_manager +DEL ir.model.access: account.access_account_move_line_readonly +DEL ir.model.access: account.access_account_move_line_uinvoice +DEL ir.model.access: account.access_account_move_manager +DEL ir.model.access: account.access_account_move_readonly +DEL ir.model.access: account.access_account_move_reversal +DEL ir.model.access: account.access_account_move_send_batch_wizard +DEL ir.model.access: account.access_account_move_send_wizard +DEL ir.model.access: account.access_account_move_uinvoice +DEL ir.model.access: account.access_account_partial_reconcile +DEL ir.model.access: account.access_account_partial_reconcile_group_invoice +DEL ir.model.access: account.access_account_partial_reconcile_readonly +DEL ir.model.access: account.access_account_payment +DEL ir.model.access: account.access_account_payment_method +DEL ir.model.access: account.access_account_payment_method_line +DEL ir.model.access: account.access_account_payment_method_line_readonly +DEL ir.model.access: account.access_account_payment_method_readonly +DEL ir.model.access: account.access_account_payment_readonly +DEL ir.model.access: account.access_account_payment_register +DEL ir.model.access: account.access_account_payment_term_line_manager +DEL ir.model.access: account.access_account_payment_term_line_partner_manager +DEL ir.model.access: account.access_account_payment_term_manager +DEL ir.model.access: account.access_account_payment_term_partner_manager +DEL ir.model.access: account.access_account_payment_term_portal +DEL ir.model.access: account.access_account_reconcile_model +DEL ir.model.access: account.access_account_reconcile_model_billing +DEL ir.model.access: account.access_account_reconcile_model_line +DEL ir.model.access: account.access_account_reconcile_model_line_billing +DEL ir.model.access: account.access_account_reconcile_model_line_readonly +DEL ir.model.access: account.access_account_reconcile_model_readonly +DEL ir.model.access: account.access_account_report_ac_user +DEL ir.model.access: account.access_account_report_basic +DEL ir.model.access: account.access_account_report_column_ac_user +DEL ir.model.access: account.access_account_report_column_basic +DEL ir.model.access: account.access_account_report_column_readonly +DEL ir.model.access: account.access_account_report_expression_ac_user +DEL ir.model.access: account.access_account_report_expression_basic +DEL ir.model.access: account.access_account_report_expression_readonly +DEL ir.model.access: account.access_account_report_external_value_ac_user +DEL ir.model.access: account.access_account_report_external_value_readonly +DEL ir.model.access: account.access_account_report_line_ac_user +DEL ir.model.access: account.access_account_report_line_basic +DEL ir.model.access: account.access_account_report_line_readonly +DEL ir.model.access: account.access_account_report_readonly +DEL ir.model.access: account.access_account_resequence +DEL ir.model.access: account.access_account_root +DEL ir.model.access: account.access_account_root_manager +DEL ir.model.access: account.access_account_secure_entries_wizard +DEL ir.model.access: account.access_account_setup_bank_manual_config +DEL ir.model.access: account.access_account_tag_internal_user +DEL ir.model.access: account.access_account_tax_group +DEL ir.model.access: account.access_account_tax_group_internal_user +DEL ir.model.access: account.access_account_tax_group_manager +DEL ir.model.access: account.access_account_tax_group_readonly +DEL ir.model.access: account.access_account_tax_internal_user +DEL ir.model.access: account.access_account_tax_invoice +DEL ir.model.access: account.access_account_tax_manager +DEL ir.model.access: account.access_account_tax_readonly +DEL ir.model.access: account.access_account_tax_repartition_line_invoice +DEL ir.model.access: account.access_account_tax_repartition_line_manager +DEL ir.model.access: account.access_account_tax_repartition_line_readonly +DEL ir.model.access: account.access_account_tax_repartition_line_user +DEL ir.model.access: account.access_product_product_account_user +DEL ir.model.access: account.access_res_currency_account_manager +DEL ir.model.access: account.access_res_currency_rate_account_manager +DEL ir.model.access: account.access_res_partner_group_account_manager +DEL ir.model.access: account.access_validate_account_move +ir.model.constraint: account.constraint_account_account_tag_name_uniq (changed definition: is now 'False' ('unique(name, applicability, country_id)')) +ir.model.constraint: account.constraint_account_bank_statement_first_line_index_idx (changed definition: is now 'False' ('INDEX (journal_id, first_line_index)')) +ir.model.constraint: account.constraint_account_bank_statement_journal_id_date_desc_id_desc_idx (changed definition: is now 'False' ('INDEX (journal_id, date DESC, id DESC)')) +ir.model.constraint: account.constraint_account_bank_statement_line_main_idx (changed definition: is now 'False' ('INDEX (journal_id, company_id, internal_index)')) +ir.model.constraint: account.constraint_account_bank_statement_line_orphan_idx (changed definition: is now 'False' ('INDEX (journal_id, company_id, internal_index) WHERE statement_id IS NULL')) +ir.model.constraint: account.constraint_account_bank_statement_line_unreconciled_idx (changed definition: is now 'False' ('INDEX (journal_id, company_id, internal_index) WHERE is_reconciled IS NOT TRUE')) +ir.model.constraint: account.constraint_account_fiscal_position_account_account_src_dest_uniq (changed definition: is now 'False' ('unique (position_id,account_src_id,account_dest_id)')) +ir.model.constraint: account.constraint_account_journal_code_company_uniq (changed definition: is now 'False' ('unique (company_id, code)')) +ir.model.constraint: account.constraint_account_journal_group_uniq_name (changed definition: is now 'False' ('unique(company_id, name)')) +ir.model.constraint: account.constraint_account_lock_exception_company_id_end_datetime_idx (changed definition: is now 'False' ('INDEX (company_id, user_id, end_datetime) WHERE active IS TRUE')) +ir.model.constraint: account.constraint_account_move_account_move_sanitize_payment_ref_idx (changed definition: is now 'False' ('INDEX (regexp_replace(COALESCE(payment_reference, ''), '[^a-zA-Z0-9]', '', 'g'))')) +NEW ir.model.constraint: account.constraint_account_move_check_document_tax_mode_set +ir.model.constraint: account.constraint_account_move_checked_idx (changed definition: is now 'False' ('INDEX (journal_id) WHERE (checked IS NOT TRUE)')) +ir.model.constraint: account.constraint_account_move_duplicate_bills_idx (changed definition: is now 'False' ('INDEX (ref) WHERE (move_type IN ('in_invoice', 'in_refund'))')) +ir.model.constraint: account.constraint_account_move_journal_id_company_id_idx (changed definition: is now 'False' ('INDEX (journal_id, company_id, date)')) +ir.model.constraint: account.constraint_account_move_journal_id_date_idx (changed definition: is now 'False' ('INDEX (journal_id, date)')) +ir.model.constraint: account.constraint_account_move_line_account_id_date_idx (changed definition: is now 'False' ('INDEX (account_id, date)')) +ir.model.constraint: account.constraint_account_move_line_check_accountable_required_fields (changed definition: is now 'False' ('CHECK(display_type IN ('line_section', 'line_subsection', 'line_note') OR account_id IS NOT NULL)')) +ir.model.constraint: account.constraint_account_move_line_check_amount_currency_balance_sign (changed definition: is now 'False' ('CHECK( display_type IN ('line_section', 'line_subsection', 'line_note') OR ( (balance <= 0 AND amount_currency <= 0) OR (balance >= 0 AND amount_currency >= 0) ) )')) +ir.model.constraint: account.constraint_account_move_line_check_credit_debit (changed definition: is now 'False' ('CHECK(display_type IN ('line_section', 'line_subsection', 'line_note') OR credit * debit=0)')) +ir.model.constraint: account.constraint_account_move_line_check_non_accountable_fields_null (changed definition: is now 'False' ('CHECK(display_type NOT IN ('line_section', 'line_subsection', 'line_note') OR (amount_currency = 0 AND debit = 0 AND credit = 0 AND account_id IS NULL))')) +ir.model.constraint: account.constraint_account_move_line_date_name_id_idx (changed definition: is now 'False' ('INDEX (date desc, move_name desc, id)')) +ir.model.constraint: account.constraint_account_move_line_journal_id_neg_amnt_residual_idx (changed definition: is now 'False' ('INDEX (journal_id) WHERE amount_residual < 0')) +ir.model.constraint: account.constraint_account_move_line_partner_id_ref_idx (changed definition: is now 'False' ('INDEX (partner_id, ref)')) +ir.model.constraint: account.constraint_account_move_line_unreconciled_index (changed definition: is now 'False' ('INDEX (account_id, partner_id) WHERE reconciled IS NOT TRUE')) +ir.model.constraint: account.constraint_account_move_made_gaps (changed definition: is now 'False' ('INDEX (journal_id, state, payment_state, move_type, date) WHERE (made_sequence_gap IS TRUE)')) +ir.model.constraint: account.constraint_account_move_payment_idx (changed definition: is now 'False' ('INDEX (journal_id, state, payment_state, move_type, date)')) +ir.model.constraint: account.constraint_account_move_unique_name (changed definition: is now 'False' ('UNIQUE INDEX (name, journal_id) WHERE (state = 'posted'AND name != '/')')) +ir.model.constraint: account.constraint_account_payment_check_amount_not_negative (changed definition: is now 'False' ('CHECK(amount >= 0.0)')) +ir.model.constraint: account.constraint_account_payment_journal_id_company_id_idx (changed definition: is now 'False' ('INDEX (journal_id, company_id)')) +ir.model.constraint: account.constraint_account_payment_method_name_code_unique (changed definition: is now 'False' ('unique (code, payment_type)')) +ir.model.constraint: account.constraint_account_payment_unmatched_idx (changed definition: is now 'False' ('INDEX (journal_id, company_id) WHERE is_matched IS NOT TRUE')) +NEW ir.model.constraint: account.constraint_account_report_column_expression_label_uniq +ir.model.constraint: account.constraint_account_report_expression_domain_engine_subformula_required (changed definition: is now 'False' ('CHECK(engine != 'domain' OR subformula IS NOT NULL)')) +ir.model.constraint: account.constraint_account_report_expression_line_label_uniq (changed definition: is now 'False' ('UNIQUE(report_line_id,label)')) +ir.model.constraint: account.constraint_account_report_line_code_uniq (changed definition: is now 'False' ('unique (report_id, code)')) +DEL ir.model.constraint: account.constraint_account_group_check_length_prefix +DEL ir.rule: account.account_analytic_line_rule_billing_user (noupdate) +DEL ir.rule: account.account_analytic_line_rule_readonly_user (noupdate) +DEL ir.rule: account.account_bank_statement_comp_rule (noupdate) +DEL ir.rule: account.account_bank_statement_line_comp_rule (noupdate) +DEL ir.rule: account.account_comp_rule (noupdate) +DEL ir.rule: account.account_fiscal_position_comp_rule (noupdate) +DEL ir.rule: account.account_group_comp_rule (noupdate) +DEL ir.rule: account.account_invoice_line_rule_portal (noupdate) +DEL ir.rule: account.account_invoice_rule_portal (noupdate) +DEL ir.rule: account.account_move_comp_rule (noupdate) +DEL ir.rule: account.account_move_line_comp_rule (noupdate) +DEL ir.rule: account.account_move_line_rule_group_invoice (noupdate) +DEL ir.rule: account.account_move_line_rule_group_readonly (noupdate) +DEL ir.rule: account.account_move_line_see_all (noupdate) +DEL ir.rule: account.account_move_rule_group_invoice (noupdate) +DEL ir.rule: account.account_move_rule_group_readonly (noupdate) +DEL ir.rule: account.account_move_see_all (noupdate) +DEL ir.rule: account.account_move_send_batch_rule_group_invoice (noupdate) +DEL ir.rule: account.account_move_send_single_rule_group_invoice (noupdate) +DEL ir.rule: account.account_payment_comp_rule (noupdate) +DEL ir.rule: account.account_payment_term_comp_rule (noupdate) +DEL ir.rule: account.account_reconcile_model_line_template_comp_rule (noupdate) +DEL ir.rule: account.account_reconcile_model_template_comp_rule (noupdate) +DEL ir.rule: account.invoice_analysis_comp_rule (noupdate) +DEL ir.rule: account.ir_rule_res_partner_bank_billing_officers (noupdate) +DEL ir.rule: account.journal_comp_rule (noupdate) +DEL ir.rule: account.journal_group_comp_rule (noupdate) +DEL ir.rule: account.report_external_value_comp_rule (noupdate) +DEL ir.rule: account.tax_comp_rule (noupdate) +DEL ir.rule: account.tax_group_comp_rule (noupdate) +DEL ir.rule: account.tax_rep_comp_rule (noupdate) +ir.sequence: account.seq_account_payment (noupdate switched) +NEW ir.ui.menu: account.menu_action_account_cashflow_analysis +DEL ir.ui.menu: account.account_logs_menu +DEL ir.ui.menu: account.root_payment_menu +NEW ir.ui.view: account.account_bank_statement_line_view_graph_cashflow +NEW ir.ui.view: account.account_bank_statement_line_view_pivot_cashflow +NEW ir.ui.view: account.account_bank_statement_line_view_search_cashflow +NEW ir.ui.view: account.address_form_additional_identifiers +ir.ui.view: account.email_template_mail_gateway_failed (noupdate switched) +NEW ir.ui.view: account.tax_repartition_line_form +NEW ir.ui.view: account.tax_repartition_line_kanban +NEW ir.ui.view: account.uom_uom_view_form +NEW ir.ui.view: account.view_account_list_from_entry +NEW ir.ui.view: account.view_account_move_graph_invoice +NEW ir.ui.view: account.view_account_move_pivot_invoice +NEW ir.ui.view: account.view_bank_statement_kanban +NEW ir.ui.view: account.view_move_line_tree_open_on +NEW ir.ui.view: account.view_partner_bank_kanban_account +DEL ir.ui.view: account.portal_my_home_invoice +DEL ir.ui.view: account.product_uom_form_view_inherit +DEL ir.ui.view: account.product_view_search_catalog +DEL ir.ui.view: account.view_account_group_form +DEL ir.ui.view: account.view_account_group_search +DEL ir.ui.view: account.view_account_group_tree +DEL ir.ui.view: account_add_gln.view_partner_form_inherit +mail.message.subtype: account.mt_invoice_created (noupdate switched) +mail.message.subtype: account.mt_invoice_paid (noupdate switched) +mail.message.subtype: account.mt_invoice_validated (noupdate switched) +mail.template: account.email_template_edi_credit_note (noupdate switched) +mail.template: account.email_template_edi_invoice (noupdate switched) +mail.template: account.email_template_edi_self_billing_credit_note (noupdate switched) +mail.template: account.email_template_edi_self_billing_invoice (noupdate switched) +mail.template: account.mail_template_data_payment_receipt (noupdate switched) +mail.template: account.mail_template_einvoice_notification (noupdate switched) +mail.template: account.mail_template_invoice_subscriber (noupdate switched) +onboarding.onboarding: account.onboarding_onboarding_account_dashboard (noupdate switched) +NEW onboarding.onboarding: account.onboarding_onboarding_account_return_dashboard +onboarding.onboarding.step: account.onboarding_onboarding_step_base_document_layout (noupdate switched) +onboarding.onboarding.step: account.onboarding_onboarding_step_chart_of_accounts (noupdate switched) +onboarding.onboarding.step: account.onboarding_onboarding_step_company_data (noupdate switched) +onboarding.onboarding.step: account.onboarding_onboarding_step_fiscal_year (noupdate switched) +onboarding.onboarding.step: account.onboarding_onboarding_step_sales_tax (noupdate switched) +NEW portal.entry: account.portal_invoice_client +NEW portal.entry: account.portal_invoice_vendor +res.country.group: account.europe_vat (noupdate switched) +res.country.group: account.intrastat (noupdate switched) diff --git a/openupgrade_scripts/scripts/account/tests/data_account_migration.py b/openupgrade_scripts/scripts/account/tests/data_account_migration.py new file mode 100644 index 00000000000..014848eb1d3 --- /dev/null +++ b/openupgrade_scripts/scripts/account/tests/data_account_migration.py @@ -0,0 +1,44 @@ +env = locals().get("env") + +# 19.0's `checked` ("Reviewed") becomes 20.0's review_state, and only a posted +# move whose checked is FALSE carries information: 19.0's compute would have set +# it True, so a False there was put there by hand. +# +# This seed contains no such row -- `checked` equals `state = 'posted'` on all +# 3223 of its moves -- so the branch that writes 'todo' is unreachable without +# this, and a test over the seed alone would pass against a migration that does +# nothing at all. +# +# An existing move is unticked rather than a new one built: posting a journal +# entry from a shell needs a journal, balanced lines and an open period, none of +# which is what is under test, and each of which is a way for the fixture to +# fail for its own reasons. +move = env["account.move"].search([("state", "=", "posted")], order="id", limit=1) +assert move, "the seed has no posted move to untick" + +# Written straight to the column. `checked` is a stored compute in 19.0, so +# assigning it through the ORM invites the compute to put it back; and the field +# does not exist in 20.0, so nothing recomputes it during the upgrade either. +env.cr.execute("UPDATE account_move SET checked = false WHERE id = %s", (move.id,)) + +# A second, untouched posted move, so the test can say the rule discriminates +# rather than sweeping every posted entry into the review queue. +other = env["account.move"].search( + [("state", "=", "posted"), ("id", "!=", move.id)], order="id", limit=1 +) +assert other, "the seed has only one posted move, so nothing can be left alone" + +for record, name in ( + (move, "ou19_move_unreviewed_by_hand"), + (other, "ou19_move_left_alone"), +): + env["ir.model.data"].create( + { + "module": "__ou19__", + "name": name, + "model": "account.move", + "res_id": record.id, + } + ) + +env.cr.commit() diff --git a/openupgrade_scripts/scripts/account/tests/test_account_migration.py b/openupgrade_scripts/scripts/account/tests/test_account_migration.py new file mode 100644 index 00000000000..de7ab4f06e0 --- /dev/null +++ b/openupgrade_scripts/scripts/account/tests/test_account_migration.py @@ -0,0 +1,76 @@ +from odoo.tests import TransactionCase + +from odoo.addons.openupgrade_framework import openupgrade_test + + +@openupgrade_test +class TestAccountMigration(TransactionCase): + """Assertions on 19.0's Reviewed flag reaching 20.0's review queue. + + Every method opens by resolving its fixture. The data snippet runs in a + separate process through the 19.0 shell, and if its commit were lost it + would exit 0 having written nothing -- an assertion whose empty case is a + pass would then report success for a migration that never happened. + """ + + def _move(self, name): + record = self.env.ref(f"__ou19__.{name}", raise_if_not_found=False) + self.assertTrue( + record, f"{name} is missing: the 19.0 fixture never reached the database" + ) + return record + + def test_a_move_unreviewed_by_hand_lands_in_the_review_queue(self): + """The branch the seed cannot reach on its own. + + 19.0's compute sets checked True for a posted move, so a posted move + carrying False was unticked by somebody. 20.0 calls that 'todo'. + """ + move = self._move("ou19_move_unreviewed_by_hand") + self.env.cr.execute( + "SELECT checked, state FROM account_move WHERE id = %s", (move.id,) + ) + checked, state = self.env.cr.fetchone() + self.assertFalse(checked, "the fixture's 19.0 answer did not survive") + self.assertEqual(state, "posted") + self.assertEqual( + move.review_state, + "todo", + "a move somebody had marked as not reviewed came out indistinguishable " + "from one nobody ever looked at", + ) + + def test_a_move_that_only_carried_the_computed_default_is_left_alone(self): + """The half that says the rule discriminates. + + Mapping checked=True to 'reviewed' would assert a review of every posted + invoice in the database on the strength of a value that is really just + "posted", so nothing is written for those. + """ + move = self._move("ou19_move_left_alone") + self.env.cr.execute( + "SELECT checked FROM account_move WHERE id = %s", (move.id,) + ) + self.assertTrue(self.env.cr.fetchone()[0], "the fixture is no longer checked") + self.assertEqual( + move.review_state, + "no_review", + "a posted entry was put into the review queue on the strength of the " + "computed default", + ) + + def test_no_posted_move_was_swept_into_the_queue_wholesale(self): + """3206 of the seed's moves are posted; one of them is the fixture.""" + self.env.cr.execute( + "SELECT count(*) FROM account_move WHERE review_state = 'todo'" + ) + in_queue = self.env.cr.fetchone()[0] + self.env.cr.execute( + "SELECT count(*) FROM account_move WHERE state = 'posted' AND NOT checked" + ) + self.assertEqual( + in_queue, + self.env.cr.fetchone()[0], + "the review queue holds more than the posted moves that were " + "explicitly unticked in 19.0", + )