mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-27 19:16:44 +00:00
Schema: Mark nullable fields (#9546)
* Add allow_null to nullable fields * Fix serializer for InfoApi, add nullable flags * Bump api version * Fix incorrectly replaced required tag
This commit is contained in:
parent
bd74044ed9
commit
0de8e61d53
@ -229,11 +229,11 @@ class InfoApiSerializer(serializers.Serializer):
|
||||
|
||||
logo = serializers.CharField()
|
||||
splash = serializers.CharField()
|
||||
login_message = serializers.CharField()
|
||||
navbar_message = serializers
|
||||
login_message = serializers.CharField(allow_null=True)
|
||||
navbar_message = serializers.CharField(allow_null=True)
|
||||
|
||||
server = serializers.CharField(read_only=True)
|
||||
id = serializers.CharField(read_only=True)
|
||||
id = serializers.CharField(read_only=True, allow_null=True)
|
||||
version = serializers.CharField(read_only=True)
|
||||
instance = serializers.CharField(read_only=True)
|
||||
apiVersion = serializers.IntegerField(read_only=True) # noqa: N815
|
||||
@ -246,15 +246,13 @@ class InfoApiSerializer(serializers.Serializer):
|
||||
email_configured = serializers.BooleanField(read_only=True)
|
||||
debug_mode = serializers.BooleanField(read_only=True)
|
||||
docker_mode = serializers.BooleanField(read_only=True)
|
||||
default_locale = serializers.ChoiceField(
|
||||
choices=settings.LOCALE_CODES, read_only=True
|
||||
)
|
||||
default_locale = serializers.CharField(read_only=True)
|
||||
customize = CustomizeSerializer(read_only=True)
|
||||
system_health = serializers.BooleanField(read_only=True)
|
||||
database = serializers.CharField(read_only=True)
|
||||
platform = serializers.CharField(read_only=True)
|
||||
installer = serializers.CharField(read_only=True)
|
||||
target = serializers.CharField(read_only=True)
|
||||
target = serializers.CharField(read_only=True, allow_null=True)
|
||||
django_admin = serializers.CharField(read_only=True)
|
||||
settings = SettingsSerializer(read_only=True, many=False)
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 339
|
||||
INVENTREE_API_VERSION = 340
|
||||
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v340 -> 2025-04-15 : https://github.com/inventree/InvenTree/pull/9546
|
||||
- Add nullable to various fields to make them not required
|
||||
|
||||
v339 -> 2025-04-15 : https://github.com/inventree/InvenTree/pull/9283
|
||||
- Remove need for source in /plugins/ui/features
|
||||
|
||||
|
@ -1431,7 +1431,12 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
pricing=False,
|
||||
)
|
||||
build_detail = BuildSerializer(
|
||||
label=_('Build'), source='build', part_detail=False, many=False, read_only=True
|
||||
label=_('Build'),
|
||||
source='build',
|
||||
part_detail=False,
|
||||
many=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
)
|
||||
|
||||
# Annotated (calculated) fields
|
||||
|
@ -812,6 +812,4 @@ class DataOutputSerializer(InvenTreeModelSerializer):
|
||||
|
||||
user_detail = UserSerializer(source='user', read_only=True, many=False)
|
||||
|
||||
output = InvenTreeAttachmentSerializerField(
|
||||
required=False, allow_null=True, read_only=True
|
||||
)
|
||||
output = InvenTreeAttachmentSerializerField(allow_null=True, read_only=True)
|
||||
|
@ -169,7 +169,7 @@ class CompanySerializer(
|
||||
read_only=True,
|
||||
)
|
||||
|
||||
primary_address = AddressSerializer(required=False, allow_null=True, read_only=True)
|
||||
primary_address = AddressSerializer(allow_null=True, read_only=True)
|
||||
|
||||
image = InvenTreeImageSerializerField(required=False, allow_null=True)
|
||||
|
||||
@ -463,7 +463,7 @@ class SupplierPartSerializer(
|
||||
)
|
||||
|
||||
MPN = serializers.CharField(
|
||||
source='manufacturer_part.MPN', read_only=True, label=_('MPN')
|
||||
source='manufacturer_part.MPN', read_only=True, allow_null=True, label=_('MPN')
|
||||
)
|
||||
|
||||
# Date fields
|
||||
|
@ -65,7 +65,7 @@ class DataImporterModelSerializer(serializers.Serializer):
|
||||
|
||||
serializer = serializers.CharField(read_only=True)
|
||||
model_type = serializers.CharField(read_only=True)
|
||||
api_url = serializers.URLField(read_only=True)
|
||||
api_url = serializers.URLField(read_only=True, allow_null=True)
|
||||
|
||||
|
||||
class DataImporterModelList(APIView):
|
||||
|
@ -112,11 +112,13 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria
|
||||
import_exclude_fields = ['notes', 'duplicate']
|
||||
|
||||
# Number of line items in this order
|
||||
line_items = serializers.IntegerField(read_only=True, label=_('Line Items'))
|
||||
line_items = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Line Items')
|
||||
)
|
||||
|
||||
# Number of completed line items (this is an annotated field)
|
||||
completed_lines = serializers.IntegerField(
|
||||
read_only=True, label=_('Completed Lines')
|
||||
read_only=True, allow_null=True, label=_('Completed Lines')
|
||||
)
|
||||
|
||||
# Human-readable status text (read-only)
|
||||
@ -156,7 +158,7 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria
|
||||
)
|
||||
|
||||
# Boolean field indicating if this order is overdue (Note: must be annotated)
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
overdue = serializers.BooleanField(read_only=True, allow_null=True)
|
||||
|
||||
barcode_hash = serializers.CharField(read_only=True)
|
||||
|
||||
@ -609,7 +611,7 @@ class PurchaseOrderLineItemSerializer(
|
||||
|
||||
received = serializers.FloatField(default=0, read_only=True)
|
||||
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
overdue = serializers.BooleanField(read_only=True, allow_null=True)
|
||||
|
||||
total_price = serializers.FloatField(read_only=True)
|
||||
|
||||
@ -632,7 +634,7 @@ class PurchaseOrderLineItemSerializer(
|
||||
)
|
||||
|
||||
destination_detail = stock.serializers.LocationBriefSerializer(
|
||||
source='get_destination', read_only=True
|
||||
source='get_destination', read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
purchase_price_currency = InvenTreeCurrencySerializer(
|
||||
@ -652,14 +654,22 @@ class PurchaseOrderLineItemSerializer(
|
||||
write_only=True,
|
||||
)
|
||||
|
||||
sku = serializers.CharField(source='part.SKU', read_only=True, label=_('SKU'))
|
||||
sku = serializers.CharField(
|
||||
source='part.SKU', read_only=True, allow_null=True, label=_('SKU')
|
||||
)
|
||||
|
||||
mpn = serializers.CharField(
|
||||
source='part.manufacturer_part.MPN', read_only=True, label=_('MPN')
|
||||
source='part.manufacturer_part.MPN',
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
label=_('MPN'),
|
||||
)
|
||||
|
||||
ipn = serializers.CharField(
|
||||
source='part.part.IPN', read_only=True, label=_('Internal Part Number')
|
||||
source='part.part.IPN',
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
label=_('Internal Part Number'),
|
||||
)
|
||||
|
||||
internal_part = serializers.PrimaryKeyRelatedField(
|
||||
@ -1078,10 +1088,12 @@ class SalesOrderSerializer(
|
||||
source='customer', many=False, read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
shipments_count = serializers.IntegerField(read_only=True, label=_('Shipments'))
|
||||
shipments_count = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Shipments')
|
||||
)
|
||||
|
||||
completed_shipments_count = serializers.IntegerField(
|
||||
read_only=True, label=_('Completed Shipments')
|
||||
read_only=True, allow_null=True, label=_('Completed Shipments')
|
||||
)
|
||||
|
||||
|
||||
@ -1253,7 +1265,7 @@ class SalesOrderLineItemSerializer(
|
||||
)
|
||||
|
||||
# Annotated fields
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
overdue = serializers.BooleanField(read_only=True, allow_null=True)
|
||||
available_stock = serializers.FloatField(read_only=True)
|
||||
available_variant_stock = serializers.FloatField(read_only=True)
|
||||
on_order = serializers.FloatField(label=_('On Order'), read_only=True)
|
||||
@ -1316,7 +1328,7 @@ class SalesOrderShipmentSerializer(NotesFieldMixin, InvenTreeModelSerializer):
|
||||
return queryset
|
||||
|
||||
allocated_items = serializers.IntegerField(
|
||||
read_only=True, label=_('Allocated Items')
|
||||
read_only=True, allow_null=True, label=_('Allocated Items')
|
||||
)
|
||||
|
||||
order_detail = SalesOrderSerializer(
|
||||
@ -1389,7 +1401,7 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
|
||||
order = serializers.PrimaryKeyRelatedField(
|
||||
source='line.order', many=False, read_only=True
|
||||
)
|
||||
serial = serializers.CharField(source='get_serial', read_only=True)
|
||||
serial = serializers.CharField(source='get_serial', read_only=True, allow_null=True)
|
||||
quantity = serializers.FloatField(read_only=False)
|
||||
location = serializers.PrimaryKeyRelatedField(
|
||||
source='item.location', many=False, read_only=True
|
||||
|
@ -126,9 +126,13 @@ class CategorySerializer(
|
||||
help_text=_('Parent part category'),
|
||||
)
|
||||
|
||||
part_count = serializers.IntegerField(read_only=True, label=_('Parts'))
|
||||
part_count = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Parts')
|
||||
)
|
||||
|
||||
subcategories = serializers.IntegerField(read_only=True, label=_('Subcategories'))
|
||||
subcategories = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Subcategories')
|
||||
)
|
||||
|
||||
level = serializers.IntegerField(read_only=True)
|
||||
|
||||
@ -149,7 +153,7 @@ class CategorySerializer(
|
||||
max_length=100,
|
||||
)
|
||||
|
||||
parent_default_location = serializers.IntegerField(read_only=True)
|
||||
parent_default_location = serializers.IntegerField(read_only=True, allow_null=True)
|
||||
|
||||
|
||||
class CategoryTree(InvenTree.serializers.InvenTreeModelSerializer):
|
||||
@ -335,6 +339,7 @@ class PartParameterTemplateSerializer(
|
||||
|
||||
parts = serializers.IntegerField(
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
label=_('Parts'),
|
||||
help_text=_('Number of parts using this template'),
|
||||
)
|
||||
@ -396,7 +401,9 @@ class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
||||
read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
image = InvenTree.serializers.InvenTreeImageSerializerField(read_only=True)
|
||||
image = InvenTree.serializers.InvenTreeImageSerializerField(
|
||||
read_only=True, allow_null=True
|
||||
)
|
||||
thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
|
||||
|
||||
IPN = serializers.CharField(
|
||||
@ -924,25 +931,47 @@ class PartSerializer(
|
||||
)
|
||||
|
||||
# Annotated fields
|
||||
allocated_to_build_orders = serializers.FloatField(read_only=True)
|
||||
allocated_to_sales_orders = serializers.FloatField(read_only=True)
|
||||
building = serializers.FloatField(read_only=True, label=_('Building'))
|
||||
in_stock = serializers.FloatField(read_only=True, label=_('In Stock'))
|
||||
ordering = serializers.FloatField(read_only=True, label=_('On Order'))
|
||||
required_for_build_orders = serializers.IntegerField(read_only=True)
|
||||
required_for_sales_orders = serializers.IntegerField(read_only=True)
|
||||
stock_item_count = serializers.IntegerField(read_only=True, label=_('Stock Items'))
|
||||
revision_count = serializers.IntegerField(read_only=True, label=_('Revisions'))
|
||||
suppliers = serializers.IntegerField(read_only=True, label=_('Suppliers'))
|
||||
total_in_stock = serializers.FloatField(read_only=True, label=_('Total Stock'))
|
||||
external_stock = serializers.FloatField(read_only=True, label=_('External Stock'))
|
||||
allocated_to_build_orders = serializers.FloatField(read_only=True, allow_null=True)
|
||||
allocated_to_sales_orders = serializers.FloatField(read_only=True, allow_null=True)
|
||||
building = serializers.FloatField(
|
||||
read_only=True, allow_null=True, label=_('Building')
|
||||
)
|
||||
in_stock = serializers.FloatField(
|
||||
read_only=True, allow_null=True, label=_('In Stock')
|
||||
)
|
||||
ordering = serializers.FloatField(
|
||||
read_only=True, allow_null=True, label=_('On Order')
|
||||
)
|
||||
required_for_build_orders = serializers.IntegerField(
|
||||
read_only=True, allow_null=True
|
||||
)
|
||||
required_for_sales_orders = serializers.IntegerField(
|
||||
read_only=True, allow_null=True
|
||||
)
|
||||
stock_item_count = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Stock Items')
|
||||
)
|
||||
revision_count = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Revisions')
|
||||
)
|
||||
suppliers = serializers.IntegerField(
|
||||
read_only=True, allow_null=True, label=_('Suppliers')
|
||||
)
|
||||
total_in_stock = serializers.FloatField(
|
||||
read_only=True, allow_null=True, label=_('Total Stock')
|
||||
)
|
||||
external_stock = serializers.FloatField(
|
||||
read_only=True, allow_null=True, label=_('External Stock')
|
||||
)
|
||||
unallocated_stock = serializers.FloatField(
|
||||
read_only=True, label=_('Unallocated Stock')
|
||||
read_only=True, allow_null=True, label=_('Unallocated Stock')
|
||||
)
|
||||
category_default_location = serializers.IntegerField(
|
||||
read_only=True, allow_null=True
|
||||
)
|
||||
variant_stock = serializers.FloatField(read_only=True, label=_('Variant Stock'))
|
||||
variant_stock = serializers.FloatField(
|
||||
read_only=True, allow_null=True, label=_('Variant Stock')
|
||||
)
|
||||
|
||||
minimum_stock = serializers.FloatField(
|
||||
required=False, label=_('Minimum Stock'), default=0
|
||||
@ -1657,11 +1686,17 @@ class BomItemSerializer(
|
||||
allow_null=True,
|
||||
)
|
||||
|
||||
on_order = serializers.FloatField(label=_('On Order'), read_only=True)
|
||||
on_order = serializers.FloatField(
|
||||
label=_('On Order'), read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
building = serializers.FloatField(label=_('In Production'), read_only=True)
|
||||
building = serializers.FloatField(
|
||||
label=_('In Production'), read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
can_build = serializers.FloatField(label=_('Can Build'), read_only=True)
|
||||
can_build = serializers.FloatField(
|
||||
label=_('Can Build'), read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
# Cached pricing fields
|
||||
pricing_min = InvenTree.serializers.InvenTreeMoneySerializer(
|
||||
@ -1684,12 +1719,14 @@ class BomItemSerializer(
|
||||
)
|
||||
|
||||
# Annotated fields for available stock
|
||||
available_stock = serializers.FloatField(label=_('Available Stock'), read_only=True)
|
||||
available_stock = serializers.FloatField(
|
||||
label=_('Available Stock'), read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
available_substitute_stock = serializers.FloatField(read_only=True)
|
||||
available_variant_stock = serializers.FloatField(read_only=True)
|
||||
available_substitute_stock = serializers.FloatField(read_only=True, allow_null=True)
|
||||
available_variant_stock = serializers.FloatField(read_only=True, allow_null=True)
|
||||
|
||||
external_stock = serializers.FloatField(read_only=True)
|
||||
external_stock = serializers.FloatField(read_only=True, allow_null=True)
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
|
@ -655,20 +655,20 @@ class StockItemSerializer(
|
||||
|
||||
# Annotated fields
|
||||
allocated = serializers.FloatField(
|
||||
required=False, read_only=True, label=_('Allocated Quantity')
|
||||
read_only=True, allow_null=True, label=_('Allocated Quantity')
|
||||
)
|
||||
expired = serializers.BooleanField(
|
||||
required=False, read_only=True, label=_('Expired')
|
||||
read_only=True, allow_null=True, label=_('Expired')
|
||||
)
|
||||
installed_items = serializers.IntegerField(
|
||||
read_only=True, required=False, label=_('Installed Items')
|
||||
read_only=True, allow_null=True, label=_('Installed Items')
|
||||
)
|
||||
child_items = serializers.IntegerField(
|
||||
read_only=True, required=False, label=_('Child Items')
|
||||
read_only=True, allow_null=True, label=_('Child Items')
|
||||
)
|
||||
stale = serializers.BooleanField(required=False, read_only=True, label=_('Stale'))
|
||||
stale = serializers.BooleanField(read_only=True, allow_null=True, label=_('Stale'))
|
||||
tracking_items = serializers.IntegerField(
|
||||
read_only=True, required=False, label=_('Tracking Items')
|
||||
read_only=True, allow_null=True, label=_('Tracking Items')
|
||||
)
|
||||
|
||||
purchase_price = InvenTree.serializers.InvenTreeMoneySerializer(
|
||||
@ -1161,7 +1161,7 @@ class StockLocationTypeSerializer(InvenTree.serializers.InvenTreeModelSerializer
|
||||
|
||||
read_only_fields = ['location_count']
|
||||
|
||||
location_count = serializers.IntegerField(read_only=True)
|
||||
location_count = serializers.IntegerField(read_only=True, allow_null=True)
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
@ -1273,7 +1273,7 @@ class LocationSerializer(
|
||||
|
||||
# Detail for location type
|
||||
location_type_detail = StockLocationTypeSerializer(
|
||||
source='location_type', read_only=True, many=False
|
||||
source='location_type', read_only=True, allow_null=True, many=False
|
||||
)
|
||||
|
||||
|
||||
|
@ -283,9 +283,13 @@ class GroupSerializer(InvenTreeModelSerializer):
|
||||
"""Return a list of permissions associated with the group."""
|
||||
return generate_permission_dict(group.permissions.all())
|
||||
|
||||
roles = RuleSetSerializer(source='rule_sets', many=True, read_only=True)
|
||||
roles = RuleSetSerializer(
|
||||
source='rule_sets', many=True, read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
users = UserSerializer(source='user_set', many=True, read_only=True)
|
||||
users = UserSerializer(
|
||||
source='user_set', many=True, read_only=True, allow_null=True
|
||||
)
|
||||
|
||||
|
||||
class ExtendedUserSerializer(UserSerializer):
|
||||
|
Loading…
x
Reference in New Issue
Block a user