2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-27 19:16:44 +00:00

Schema: (Redo) Remove hardcoded enum values from customizable fields (#9452)

* Remove hardcoded currency enum from schema

* Convert schema custom key enums to int to allow customized keys to validate

* Convert stock status key enums to int to allow customizations to
validate in schema

* api version bump

* Restore enumerated help text for currencies

* Remove commented block of old code

* Restore custom key enumerated values to schema documentation

* Restore status key enumeration to schema documentation
This commit is contained in:
Joe Rogers 2025-04-08 07:31:40 +02:00 committed by GitHub
parent f541d76cd1
commit f87f4387ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 98 additions and 37 deletions

View File

@ -1,12 +1,16 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 332
INVENTREE_API_VERSION = 333
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v333 - 2025-04-03 : https://github.com/inventree/InvenTree/pull/9452
- Currency string is no longer restricted to a hardcoded enum
- Customizable status keys are no longer hardcoded enum values
v332 - 2025-04-02 : https://github.com/inventree/InvenTree/pull/9393
- Adds 'search_notes' parameter to all searchable API endpoints

View File

@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _
from djmoney.contrib.django_rest_framework.fields import MoneyField
from djmoney.money import Money
from djmoney.utils import MONEY_CLASSES, get_currency_field_name
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.fields import empty
@ -86,6 +87,7 @@ class InvenTreeMoneySerializer(MoneyField):
return amount
@extend_schema_field(serializers.CharField())
class InvenTreeCurrencySerializer(serializers.ChoiceField):
"""Custom serializers for selecting currency option."""
@ -111,6 +113,14 @@ class InvenTreeCurrencySerializer(serializers.ChoiceField):
if 'help_text' not in kwargs:
kwargs['help_text'] = _('Select currency from available options')
if InvenTree.ready.isGeneratingSchema():
kwargs['help_text'] = (
kwargs['help_text']
+ '\n\n'
+ '\n'.join(f'* `{value}` - {label}' for value, label in choices)
+ "\n\nOther valid currencies may be found in the 'CURRENCY_CODES' global setting."
)
super().__init__(*args, **kwargs)

View File

@ -40,7 +40,11 @@ from InvenTree.serializers import (
)
from stock.generators import generate_batch_code
from stock.models import StockItem, StockLocation
from stock.serializers import LocationBriefSerializer, StockItemSerializerBrief
from stock.serializers import (
LocationBriefSerializer,
StockItemSerializerBrief,
StockStatusCustomSerializer,
)
from stock.status_codes import StockStatus
from users.serializers import OwnerSerializer, UserSerializer
@ -581,11 +585,7 @@ class BuildOutputCompleteSerializer(serializers.Serializer):
help_text=_('Location for completed build outputs'),
)
status_custom_key = serializers.ChoiceField(
choices=StockStatus.items(custom=True),
default=StockStatus.OK.value,
label=_('Status'),
)
status_custom_key = StockStatusCustomSerializer(default=StockStatus.OK.value)
accept_incomplete_allocation = serializers.BooleanField(
default=False,

View File

@ -8,9 +8,13 @@ from django.db import models
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from rest_framework.fields import ChoiceField
import InvenTree.ready
from .custom import get_logical_value
@ -73,6 +77,7 @@ class CustomChoiceField(serializers.ChoiceField):
return field_info
@extend_schema_field(OpenApiTypes.INT)
class ExtraCustomChoiceField(CustomChoiceField):
"""Custom Choice Field that returns value of status if empty.
@ -138,14 +143,27 @@ class InvenTreeCustomStatusModelField(models.PositiveIntegerField):
if self.status_class:
validators.append(CustomStatusCodeValidator(status_class=self.status_class))
help_text = _('Additional status information for this item')
if InvenTree.ready.isGeneratingSchema():
help_text = (
help_text
+ '\n\n'
+ '\n'.join(
f'* `{value}` - {label}'
for value, label in self.status_class.items(custom=True)
)
+ "\n\nAdditional custom status keys may be retrieved from the corresponding 'status_retrieve' call."
)
custom_key_field = ExtraInvenTreeCustomStatusModelField(
default=None,
verbose_name=_('Custom status key'),
help_text=_('Additional status information for this item'),
help_text=help_text,
validators=validators,
blank=True,
null=True,
)
cls.add_to_class(f'{name}_custom_key', custom_key_field)
self._custom_key_field = custom_key_field

View File

@ -795,11 +795,7 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer):
allow_blank=True,
)
status = serializers.ChoiceField(
choices=StockStatus.items(custom=True),
default=StockStatus.OK.value,
label=_('Status'),
)
status = stock.serializers.StockStatusCustomSerializer(default=StockStatus.OK.value)
packaging = serializers.CharField(
label=_('Packaging'),
@ -1981,13 +1977,8 @@ class ReturnOrderLineItemReceiveSerializer(serializers.Serializer):
label=_('Return order line item'),
)
status = serializers.ChoiceField(
choices=stock.status_codes.StockStatus.items(custom=True),
default=None,
label=_('Status'),
help_text=_('Stock item status code'),
required=False,
allow_blank=True,
status = stock.serializers.StockStatusCustomSerializer(
default=None, required=False, allow_blank=True
)
def validate_line_item(self, item):

View File

@ -16,6 +16,7 @@ from django.utils.translation import gettext_lazy as _
import structlog
from djmoney.contrib.exchange.exceptions import MissingRate
from djmoney.contrib.exchange.models import convert_money
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from sql_util.utils import SubqueryCount, SubquerySum
from taggit.serializers import TagListSerializerField
@ -1300,6 +1301,21 @@ class PartStocktakeReportGenerateSerializer(serializers.Serializer):
)
@extend_schema_field(
serializers.CharField(
help_text=_('Select currency from available options')
+ '\n\n'
+ '\n'.join(
f'* `{value}` - {label}'
for value, label in common.currency.currency_code_mappings()
)
+ "\n\nOther valid currencies may be found in the 'CURRENCY_CODES' global setting."
)
)
class PartPricingCurrencySerializer(serializers.ChoiceField):
"""Serializer to allow annotating the schema to use String on currency fields."""
class PartPricingSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""Serializer for Part pricing information."""
@ -1384,7 +1400,7 @@ class PartPricingSerializer(InvenTree.serializers.InvenTreeModelSerializer):
required=False,
)
override_min_currency = serializers.ChoiceField(
override_min_currency = PartPricingCurrencySerializer(
label=_('Minimum price currency'),
read_only=False,
required=False,
@ -1399,7 +1415,7 @@ class PartPricingSerializer(InvenTree.serializers.InvenTreeModelSerializer):
required=False,
)
override_max_currency = serializers.ChoiceField(
override_max_currency = PartPricingCurrencySerializer(
label=_('Maximum price currency'),
read_only=False,
required=False,

View File

@ -10,6 +10,7 @@ from django.db.models.functions import Coalesce
from django.utils.translation import gettext_lazy as _
import structlog
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from rest_framework.serializers import ValidationError
from sql_util.utils import SubqueryCount, SubquerySum
@ -984,6 +985,38 @@ class ConvertStockItemSerializer(serializers.Serializer):
stock_item.convert_to_variant(part, request.user)
@extend_schema_field(
serializers.IntegerField(
help_text='Status key, chosen from the list of StockStatus keys'
)
)
class StockStatusCustomSerializer(serializers.ChoiceField):
"""Serializer to allow annotating the schema to use int where custom values may be entered."""
def __init__(self, *args, **kwargs):
"""Initialize the status selector."""
if 'choices' not in kwargs:
kwargs['choices'] = stock.status_codes.StockStatus.items(custom=True)
if 'label' not in kwargs:
kwargs['label'] = _('Status')
if 'help_text' not in kwargs:
kwargs['help_text'] = _('Stock item status code')
if InvenTree.ready.isGeneratingSchema():
kwargs['help_text'] = (
kwargs['help_text']
+ '\n\n'
+ '\n'.join(
f'* `{value}` - {label}' for value, label in kwargs['choices']
)
+ "\n\nAdditional custom status keys may be retrieved from the 'stock_status_retrieve' call."
)
super().__init__(*args, **kwargs)
class ReturnStockItemSerializer(serializers.Serializer):
"""DRF serializer for returning a stock item from a customer."""
@ -1001,14 +1034,7 @@ class ReturnStockItemSerializer(serializers.Serializer):
help_text=_('Destination location for returned item'),
)
status = serializers.ChoiceField(
choices=stock.status_codes.StockStatus.items(custom=True),
default=None,
label=_('Status'),
help_text=_('Stock item status code'),
required=False,
allow_blank=True,
)
status = StockStatusCustomSerializer(default=None, required=False, allow_blank=True)
notes = serializers.CharField(
label=_('Notes'),
@ -1058,10 +1084,8 @@ class StockChangeStatusSerializer(serializers.Serializer):
return items
status = serializers.ChoiceField(
choices=stock.status_codes.StockStatus.items(custom=True),
default=stock.status_codes.StockStatus.OK.value,
label=_('Status'),
status = StockStatusCustomSerializer(
default=stock.status_codes.StockStatus.OK.value
)
note = serializers.CharField(
@ -1620,11 +1644,9 @@ class StockAdjustmentItemSerializer(serializers.Serializer):
help_text=_('Batch code for this stock item'),
)
status = serializers.ChoiceField(
status = StockStatusCustomSerializer(
choices=stock_item_adjust_status_options(),
default=None,
label=_('Status'),
help_text=_('Stock item status code'),
required=False,
allow_blank=True,
)