[FIX] product_sale_price_from_pricelist: Clean up old ir_property records
Fixed error: TypeError: float() argument must be a string or a real number, not 'dict' when entering decimal values in product form. Added post-migration to delete ir_property records left over from when fields were company_dependent. These leftover records were causing dict values to be passed to Float fields during onchange operations. Migration checks if ir_property table exists to handle fresh installs gracefully. Version bump: 18.0.2.3.0 -> 18.0.2.4.0
This commit is contained in:
parent
4bb7edfbec
commit
3eae4fa884
3 changed files with 85 additions and 1 deletions
|
|
@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [18.0.2.4.0] - 2026-02-14
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Clean up old ir_property records**
|
||||||
|
- Error: `TypeError: float() argument must be a string or a real number, not 'dict'`
|
||||||
|
- Added post-migration to delete ir_property records left over from company_dependent fields
|
||||||
|
- This prevents dict values from being passed to Float fields during onchange
|
||||||
|
- Migration runs after module load to ensure ir_property table exists
|
||||||
|
|
||||||
## [18.0.2.3.0] - 2026-02-14
|
## [18.0.2.3.0] - 2026-02-14
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
{ # noqa: B018
|
{ # noqa: B018
|
||||||
"name": "Product Sale Price from Pricelist",
|
"name": "Product Sale Price from Pricelist",
|
||||||
"version": "18.0.2.3.0",
|
"version": "18.0.2.4.0",
|
||||||
"category": "product",
|
"category": "product",
|
||||||
"summary": "Set sale price from pricelist based on last purchase price",
|
"summary": "Set sale price from pricelist based on last purchase price",
|
||||||
"author": "Odoo Community Association (OCA), Criptomart",
|
"author": "Odoo Community Association (OCA), Criptomart",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Copyright (C) 2026 Criptomart
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
"""Clean up old ir_property records for fields that are no longer company_dependent.
|
||||||
|
|
||||||
|
This migration removes ir_property records that were created when these fields
|
||||||
|
were company_dependent. These records can cause TypeError: float() argument must
|
||||||
|
be a string or a real number, not 'dict' when Odoo tries to read the fields.
|
||||||
|
|
||||||
|
Fields cleaned up:
|
||||||
|
- last_purchase_price_updated
|
||||||
|
- list_price_theoritical
|
||||||
|
- last_purchase_price_received
|
||||||
|
- last_purchase_price_compute_type
|
||||||
|
"""
|
||||||
|
_logger.info(
|
||||||
|
"Cleaning up ir_property records for product_sale_price_from_pricelist fields"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if ir_property table exists
|
||||||
|
cr.execute("""
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT FROM information_schema.tables
|
||||||
|
WHERE table_name = 'ir_property'
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
table_exists = cr.fetchone()[0]
|
||||||
|
|
||||||
|
if not table_exists:
|
||||||
|
_logger.info(
|
||||||
|
"Table ir_property does not exist yet, skipping cleanup (fresh install)"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Delete all ir_property records for these fields on product.product
|
||||||
|
cr.execute("""
|
||||||
|
DELETE FROM ir_property
|
||||||
|
WHERE name IN (
|
||||||
|
'last_purchase_price_updated',
|
||||||
|
'list_price_theoritical',
|
||||||
|
'last_purchase_price_received',
|
||||||
|
'last_purchase_price_compute_type'
|
||||||
|
)
|
||||||
|
AND res_id LIKE 'product.product,%%'
|
||||||
|
""")
|
||||||
|
deleted_count = cr.rowcount
|
||||||
|
_logger.info("Deleted %s ir_property records for product.product", deleted_count)
|
||||||
|
|
||||||
|
# Also clean up for product.template if any exist
|
||||||
|
cr.execute("""
|
||||||
|
DELETE FROM ir_property
|
||||||
|
WHERE name IN (
|
||||||
|
'last_purchase_price_updated',
|
||||||
|
'list_price_theoritical',
|
||||||
|
'last_purchase_price_received',
|
||||||
|
'last_purchase_price_compute_type'
|
||||||
|
)
|
||||||
|
AND res_id LIKE 'product.template,%%'
|
||||||
|
""")
|
||||||
|
deleted_template_count = cr.rowcount
|
||||||
|
_logger.info(
|
||||||
|
"Deleted %s ir_property records for product.template", deleted_template_count
|
||||||
|
)
|
||||||
|
|
||||||
|
_logger.info(
|
||||||
|
"Migration completed successfully. Total records deleted: %s",
|
||||||
|
deleted_count + deleted_template_count,
|
||||||
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue