Fix currency choices for PartPricing model (#12336)

* Fix currency choices for PartPricing model

- Remove dynamic choices from model definition
- Move validation step to the serializer
- Add validator to ensure only valid currencies can be used

* Add regression test

* Bump API version
This commit is contained in:
Oliver
2026-07-09 06:37:24 +10:00
committed by GitHub
parent 8e555f6b37
commit 6cc356220f
5 changed files with 78 additions and 3 deletions
@@ -1,11 +1,14 @@
"""InvenTree API version information.""" """InvenTree API version information."""
# InvenTree API version # InvenTree API version
INVENTREE_API_VERSION = 516 INVENTREE_API_VERSION = 517
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" """Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """ INVENTREE_API_TEXT = """
v517 -> 2026-07-08 : https://github.com/inventree/InvenTree/pull/12336
- Fix currency code options for the PartPricing model and API endpoints
v516 -> 2026-07-03 : https://github.com/inventree/InvenTree/pull/12295 v516 -> 2026-07-03 : https://github.com/inventree/InvenTree/pull/12295
- Adds "consumable" field to the Part model and API endpoints - Adds "consumable" field to the Part model and API endpoints
@@ -1,5 +1,7 @@
"""Tests for custom InvenTree management commands.""" """Tests for custom InvenTree management commands."""
import os
import subprocess
from pathlib import Path from pathlib import Path
from django.conf import settings from django.conf import settings
@@ -15,6 +17,48 @@ from InvenTree.config import get_testfolder_dir
class CommandTestCase(TestCase): class CommandTestCase(TestCase):
"""Test case for custom management commands.""" """Test case for custom management commands."""
def test_makemigrations_currency_overrides_no_changes(self):
"""Ensure currency list changes do not cause migration drift."""
currency_sets = ['USD,EUR,GBP', 'JPY,CNY,KRW']
for currency_codes in currency_sets:
with self.subTest(currency_codes=currency_codes):
old_value = os.environ.get('INVENTREE_CURRENCY_CODES')
try:
os.environ['INVENTREE_CURRENCY_CODES'] = currency_codes
project_dir = Path(__file__).resolve().parents[1]
result = subprocess.run(
[
'python3',
'manage.py',
'makemigrations',
'--check',
'--dry-run',
'--verbosity',
'0',
],
cwd=project_dir,
env=os.environ.copy(),
capture_output=True,
text=True,
check=False,
)
if result.returncode != 0:
self.fail(
'makemigrations reported schema changes '
f'for INVENTREE_CURRENCY_CODES={currency_codes}\n'
f'stdout:\n{result.stdout}\n'
f'stderr:\n{result.stderr}'
)
finally:
if old_value is None:
os.environ.pop('INVENTREE_CURRENCY_CODES', None)
else:
os.environ['INVENTREE_CURRENCY_CODES'] = old_value
def test_schema(self): def test_schema(self):
"""Test the schema generation command.""" """Test the schema generation command."""
output = call_command('schema', file='schema.yml', verbosity=0) output = call_command('schema', file='schema.yml', verbosity=0)
@@ -0,0 +1,26 @@
# Generated by Django 5.2.15 on 2026-07-08 00:00
import InvenTree.validators
import common.currency
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("part", "0151_part_consumable"),
]
operations = [
migrations.AlterField(
model_name="partpricing",
name="currency",
field=models.CharField(
default=common.currency.currency_code_default,
help_text="Currency used to cache pricing calculations",
max_length=10,
validators=[InvenTree.validators.validate_currency_code],
verbose_name="Currency",
),
),
]
+1 -1
View File
@@ -3378,7 +3378,7 @@ class PartPricing(common.models.MetaMixin):
max_length=10, max_length=10,
verbose_name=_('Currency'), verbose_name=_('Currency'),
help_text=_('Currency used to cache pricing calculations'), help_text=_('Currency used to cache pricing calculations'),
choices=common.currency.currency_code_mappings(), validators=[validators.validate_currency_code],
) )
scheduled_for_update = models.BooleanField(default=False) scheduled_for_update = models.BooleanField(default=False)
+3 -1
View File
@@ -1429,7 +1429,9 @@ class PartPricingSerializer(InvenTree.serializers.InvenTreeModelSerializer):
'update', 'update',
] ]
currency = serializers.CharField(allow_null=True, read_only=True) currency = InvenTree.serializers.InvenTreeCurrencySerializer(
allow_null=True, read_only=True
)
updated = serializers.DateTimeField(allow_null=True, read_only=True) updated = serializers.DateTimeField(allow_null=True, read_only=True)