From 3b126c870af24973d4f5322b1860a624900392d1 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Wed, 23 Sep 2026 17:06:23 -0400 Subject: [PATCH] [20.0][OU-ADD] pos_sale: migration scripts ### post-migration.py Point existing points of sale at the default product 20.0 ships. pos.config.default_product_id is new in 20.0 and defaults to `pos_sale.default_sol_product`, a product the module itself loads. A default only runs for rows created after it exists, so every point of sale that predates the upgrade comes out with none and cannot price a productless sale order line -- while one created a minute later can. This is the case the OCA retrospective records us getting wrong last cycle: a default is not automatically safe, and the question is what it means on a row that already existed. Here it means the same as on a new one, so the rows are brought into line with what a fresh install would have. Only the empty ones: a point of sale that already names a product chose it. Assisted-by: Claude Opus 5 --- docsource/modules190-200.rst | 2 +- .../pos_sale/20.0.1.1/post-migration.py | 32 +++++++++++++++++++ .../pos_sale/20.0.1.1/upgrade_analysis.txt | 15 +++++++++ .../20.0.1.1/upgrade_analysis_work.txt | 26 +++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 openupgrade_scripts/scripts/pos_sale/20.0.1.1/post-migration.py create mode 100644 openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis.txt create mode 100644 openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis_work.txt diff --git a/docsource/modules190-200.rst b/docsource/modules190-200.rst index 8da46d62bbc..6e4b85e8a0b 100644 --- a/docsource/modules190-200.rst +++ b/docsource/modules190-200.rst @@ -862,7 +862,7 @@ Module coverage 19.0 -> 20.0 +---------------------------------------------------+----------------------+-------------------------------------------------+ | |del| pos_restaurant_stripe | | | +---------------------------------------------------+----------------------+-------------------------------------------------+ -| pos_sale | | | +| pos_sale |Done | | +---------------------------------------------------+----------------------+-------------------------------------------------+ | |new| pos_sale_delivery | |No DB layout changes. | +---------------------------------------------------+----------------------+-------------------------------------------------+ diff --git a/openupgrade_scripts/scripts/pos_sale/20.0.1.1/post-migration.py b/openupgrade_scripts/scripts/pos_sale/20.0.1.1/post-migration.py new file mode 100644 index 00000000000..5752288990d --- /dev/null +++ b/openupgrade_scripts/scripts/pos_sale/20.0.1.1/post-migration.py @@ -0,0 +1,32 @@ +# Copyright 2026 Don Kendall +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + """Point existing points of sale at the default product 20.0 ships. + + pos.config.default_product_id is new in 20.0 and defaults to + `pos_sale.default_sol_product`, a product the module itself loads. A default + only runs for rows created after it exists, so every point of sale that + predates the upgrade comes out with none and cannot price a productless + sale order line -- while one created a minute later can. + + This is the case the OCA retrospective records us getting wrong last cycle: + a default is not automatically safe, and the question is what it means on a + row that already existed. Here it means the same as on a new one, so the + rows are brought into line with what a fresh install would have. + + Only the empty ones: a point of sale that already names a product chose it. + """ + product = env.ref("pos_sale.default_sol_product", raise_if_not_found=False) + if not product: + return + openupgrade.logged_query( + env.cr, + "UPDATE pos_config SET default_product_id = %s " + "WHERE default_product_id IS NULL", + (product.id,), + ) diff --git a/openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis.txt b/openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis.txt new file mode 100644 index 00000000000..6e25000fedf --- /dev/null +++ b/openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis.txt @@ -0,0 +1,15 @@ +---Models in module 'pos_sale'--- +---Fields in module 'pos_sale'--- +pos_sale / pos.config / default_product_id (many2one) : NEW relation: product.product, hasdefault: default +pos_sale / sale.order / amount_unpaid (float) : module is now 'sale' ('pos_sale') +---XML records in module 'pos_sale'--- +crm.team: sales_team.pos_sales_team (noupdate switched) +NEW ir.access: pos_sale.pos_sale_rule_pos_channel_pos_manager +NEW ir.access: pos_sale.rule_pos_sale_order +NEW ir.access: pos_sale.rule_pos_sale_order_line +DEL ir.model.access: pos_sale.access_crm_team_pos_manager +DEL ir.rule: pos_sale.pos_sale_rule_pos_channel_pos_manager (noupdate) +NEW ir.ui.view: pos_sale.pos_orderline_receipt_information +DEL ir.ui.view: pos_sale.message_body +product.product: pos_sale.default_downpayment_product (noupdate switched) +NEW product.product: pos_sale.default_sol_product diff --git a/openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis_work.txt b/openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis_work.txt new file mode 100644 index 00000000000..b45fc765674 --- /dev/null +++ b/openupgrade_scripts/scripts/pos_sale/20.0.1.1/upgrade_analysis_work.txt @@ -0,0 +1,26 @@ +---Models in module 'pos_sale'--- +---Fields in module 'pos_sale'--- +pos_sale / pos.config / default_product_id (many2one) : NEW relation: product.product, hasdefault: default +# NOTHING TO DO: a new field whose default is falsy -- False, or an empty +# list -- so a NULL left on an existing row already means what the default +# would have written. The one flagged field whose default names a record, +# pos.config.default_product_id, has a script instead +pos_sale / sale.order / amount_unpaid (float) : module is now 'sale' ('pos_sale') +# NOTHING TO DO: the field only changed owning module, the column is the same +---XML records in module 'pos_sale'--- +crm.team: sales_team.pos_sales_team (noupdate switched) +# NOTHING TO DO: only the noupdate flag changed, the definition is the same +NEW ir.access: pos_sale.pos_sale_rule_pos_channel_pos_manager +NEW ir.access: pos_sale.rule_pos_sale_order +NEW ir.access: pos_sale.rule_pos_sale_order_line +DEL ir.model.access: pos_sale.access_crm_team_pos_manager +DEL ir.rule: pos_sale.pos_sale_rule_pos_channel_pos_manager (noupdate) +# NOTHING TO DO: base folds ir.model.access and ir.rule into ir.access, keeping the xml_ids +NEW ir.ui.view: pos_sale.pos_orderline_receipt_information +# NOTHING TO DO: the record is not noupdate, so the module update creates it +DEL ir.ui.view: pos_sale.message_body +# NOTHING TO DO: the record is not noupdate, so the module update removes it +product.product: pos_sale.default_downpayment_product (noupdate switched) +# NOTHING TO DO: only the noupdate flag changed, the definition is the same +NEW product.product: pos_sale.default_sol_product +# NOTHING TO DO: the record is not noupdate, so the module update creates it