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

Merge pull request #2329 from SchrodingersGat/bom-quantity-fix

Bom quantity fix
This commit is contained in:
Oliver 2021-11-18 23:24:44 +11:00 committed by GitHub
commit 7d80387f3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 23 deletions

View File

@ -118,7 +118,9 @@ class InvenTreeMetadata(SimpleMetadata):
# Iterate through simple fields # Iterate through simple fields
for name, field in model_fields.fields.items(): for name, field in model_fields.fields.items():
if field.has_default() and name in serializer_info.keys(): if name in serializer_info.keys():
if field.has_default():
default = field.default default = field.default
@ -133,6 +135,15 @@ class InvenTreeMetadata(SimpleMetadata):
elif name in model_default_values: elif name in model_default_values:
serializer_info[name]['default'] = model_default_values[name] serializer_info[name]['default'] = model_default_values[name]
# Attributes to copy from the model to the field (if they don't exist)
attributes = ['help_text']
for attr in attributes:
if attr not in serializer_info[name]:
if hasattr(field, attr):
serializer_info[name][attr] = getattr(field, attr)
# Iterate through relations # Iterate through relations
for name, relation in model_fields.relations.items(): for name, relation in model_fields.relations.items():

View File

@ -296,3 +296,17 @@ class InvenTreeImageSerializerField(serializers.ImageField):
return None return None
return os.path.join(str(settings.MEDIA_URL), str(value)) return os.path.join(str(settings.MEDIA_URL), str(value))
class InvenTreeDecimalField(serializers.FloatField):
"""
Custom serializer for decimal fields. Solves the following issues:
- The normal DRF DecimalField renders values with trailing zeros
- Using a FloatField can result in rounding issues: https://code.djangoproject.com/ticket/30290
"""
def to_internal_value(self, data):
# Convert the value to a string, and then a decimal
return Decimal(str(data))

View File

@ -18,8 +18,9 @@ from rest_framework.serializers import ValidationError
from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializer from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializer
from InvenTree.serializers import InvenTreeAttachmentSerializerField, UserSerializerBrief from InvenTree.serializers import InvenTreeAttachmentSerializerField, UserSerializerBrief
from InvenTree.status_codes import StockStatus
import InvenTree.helpers import InvenTree.helpers
from InvenTree.serializers import InvenTreeDecimalField
from InvenTree.status_codes import StockStatus
from stock.models import StockItem, StockLocation from stock.models import StockItem, StockLocation
from stock.serializers import StockItemSerializerBrief, LocationSerializer from stock.serializers import StockItemSerializerBrief, LocationSerializer
@ -41,7 +42,7 @@ class BuildSerializer(InvenTreeModelSerializer):
part_detail = PartBriefSerializer(source='part', many=False, read_only=True) part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
overdue = serializers.BooleanField(required=False, read_only=True) overdue = serializers.BooleanField(required=False, read_only=True)
@ -473,7 +474,7 @@ class BuildItemSerializer(InvenTreeModelSerializer):
stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True) stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True)
location_detail = LocationSerializer(source='stock_item.location', read_only=True) location_detail = LocationSerializer(source='stock_item.location', read_only=True)
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -8,9 +8,10 @@ from rest_framework import serializers
from sql_util.utils import SubqueryCount from sql_util.utils import SubqueryCount
from InvenTree.serializers import InvenTreeDecimalField
from InvenTree.serializers import InvenTreeImageSerializerField
from InvenTree.serializers import InvenTreeModelSerializer from InvenTree.serializers import InvenTreeModelSerializer
from InvenTree.serializers import InvenTreeMoneySerializer from InvenTree.serializers import InvenTreeMoneySerializer
from InvenTree.serializers import InvenTreeImageSerializerField
from part.serializers import PartBriefSerializer from part.serializers import PartBriefSerializer
@ -255,7 +256,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
class SupplierPriceBreakSerializer(InvenTreeModelSerializer): class SupplierPriceBreakSerializer(InvenTreeModelSerializer):
""" Serializer for SupplierPriceBreak object """ """ Serializer for SupplierPriceBreak object """
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer( price = InvenTreeMoneySerializer(
allow_null=True, allow_null=True,

View File

@ -17,8 +17,9 @@ from rest_framework.serializers import ValidationError
from sql_util.utils import SubqueryCount from sql_util.utils import SubqueryCount
from InvenTree.serializers import InvenTreeModelSerializer
from InvenTree.serializers import InvenTreeAttachmentSerializer from InvenTree.serializers import InvenTreeAttachmentSerializer
from InvenTree.serializers import InvenTreeModelSerializer
from InvenTree.serializers import InvenTreeDecimalField
from InvenTree.serializers import InvenTreeMoneySerializer from InvenTree.serializers import InvenTreeMoneySerializer
from InvenTree.serializers import InvenTreeAttachmentSerializerField from InvenTree.serializers import InvenTreeAttachmentSerializerField
@ -551,7 +552,7 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
part_detail = PartBriefSerializer(source='part', many=False, read_only=True) part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True) allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True)
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
allocated = serializers.FloatField(source='allocated_quantity', read_only=True) allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True) fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True)

View File

@ -15,6 +15,7 @@ from sql_util.utils import SubqueryCount, SubquerySum
from djmoney.contrib.django_rest_framework import MoneyField from djmoney.contrib.django_rest_framework import MoneyField
from InvenTree.serializers import (InvenTreeAttachmentSerializerField, from InvenTree.serializers import (InvenTreeAttachmentSerializerField,
InvenTreeDecimalField,
InvenTreeImageSerializerField, InvenTreeImageSerializerField,
InvenTreeModelSerializer, InvenTreeModelSerializer,
InvenTreeAttachmentSerializer, InvenTreeAttachmentSerializer,
@ -120,7 +121,7 @@ class PartSalePriceSerializer(InvenTreeModelSerializer):
Serializer for sale prices for Part model. Serializer for sale prices for Part model.
""" """
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer( price = InvenTreeMoneySerializer(
allow_null=True allow_null=True
@ -144,7 +145,7 @@ class PartInternalPriceSerializer(InvenTreeModelSerializer):
Serializer for internal prices for Part model. Serializer for internal prices for Part model.
""" """
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer( price = InvenTreeMoneySerializer(
allow_null=True allow_null=True
@ -428,7 +429,7 @@ class BomItemSerializer(InvenTreeModelSerializer):
price_range = serializers.CharField(read_only=True) price_range = serializers.CharField(read_only=True)
quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(assembly=True)) part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(assembly=True))

View File

@ -32,6 +32,7 @@ from company.serializers import SupplierPartSerializer
import InvenTree.helpers import InvenTree.helpers
import InvenTree.serializers import InvenTree.serializers
from InvenTree.serializers import InvenTreeDecimalField
from part.serializers import PartBriefSerializer from part.serializers import PartBriefSerializer
@ -55,7 +56,8 @@ class StockItemSerializerBrief(InvenTree.serializers.InvenTreeModelSerializer):
location_name = serializers.CharField(source='location', read_only=True) location_name = serializers.CharField(source='location', read_only=True)
part_name = serializers.CharField(source='part.full_name', read_only=True) part_name = serializers.CharField(source='part.full_name', read_only=True)
quantity = serializers.FloatField()
quantity = InvenTreeDecimalField()
class Meta: class Meta:
model = StockItem model = StockItem
@ -136,7 +138,7 @@ class StockItemSerializer(InvenTree.serializers.InvenTreeModelSerializer):
tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False) tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False)
# quantity = serializers.FloatField() quantity = InvenTreeDecimalField()
allocated = serializers.FloatField(source='allocation_count', required=False) allocated = serializers.FloatField(source='allocation_count', required=False)