2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-08-03 02:21:34 +00:00

[PUI] Details Panel components ()

* Add default_location to part filters

* Add Detail components

* Add Detail Image V1

* Remove piggyback change from different branch

* Remove unused code

* Add remove image modal

* Basic part image selection form

* Add Part Image selector Modal and fix PartThumb API pagination

* imports

* Add Image Upload modal

* Typescript and translation cleanup

* .

* Revert temporary workaround for existing_image

* Start adding fields

* .

* Modre fields and Icon manager

* Add most part detail fields

* .

* Final draft

* Remove unused TS

* More cleanup

* .

* Bump API version

* .

* Docstring oopsie
This commit is contained in:
Lavissa
2024-01-31 00:37:42 +01:00
committed by GitHub
parent 3bfde82394
commit fb71e847bb
18 changed files with 1716 additions and 9 deletions

@@ -1,11 +1,14 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 164
INVENTREE_API_VERSION = 165
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v165 -> 2024-01-28 : https://github.com/inventree/InvenTree/pull/6040
- Adds supplier_part.name, part.creation_user, part.required_for_sales_order
v164 -> 2024-01-24 : https://github.com/inventree/InvenTree/pull/6343
- Adds "building" quantity to BuildLine API serializer

@@ -895,6 +895,11 @@ class SupplierPart(MetadataMixin, InvenTreeBarcodeMixin, common.models.MetaMixin
self.availability_updated = datetime.now()
self.save()
@property
def name(self):
"""Return string representation of own name."""
return str(self)
@property
def manufacturer_string(self):
"""Format a MPN string for this SupplierPart.

@@ -309,6 +309,7 @@ class SupplierPartSerializer(InvenTreeTagModelSerializer):
'manufacturer_part',
'manufacturer_part_detail',
'MPN',
'name',
'note',
'pk',
'barcode_hash',
@@ -395,6 +396,8 @@ class SupplierPartSerializer(InvenTreeTagModelSerializer):
source='manufacturer_part', part_detail=False, read_only=True
)
name = serializers.CharField(read_only=True)
url = serializers.CharField(source='get_absolute_url', read_only=True)
# Date fields

@@ -442,6 +442,15 @@ class PartThumbs(ListAPI):
queryset.values('image').annotate(count=Count('image')).order_by('-count')
)
page = self.paginate_queryset(data)
if page is not None:
serializer = self.get_serializer(page, many=True)
else:
serializer = self.get_serializer(data, many=True)
data = serializer.data
return Response(data)
filter_backends = [InvenTreeSearchFilter]

@@ -169,6 +169,26 @@ def annotate_build_order_allocations(reference: str = ''):
)
def annotate_sales_order_requirements(reference: str = ''):
"""Annotate the total quantity of each part required for sales orders.
- Only interested in 'active' sales orders
- We are looking for any order lines which requires this part
- We are interested in 'quantity'-'shipped'
"""
# Order filter only returns incomplete shipments for open orders
order_filter = Q(order__status__in=SalesOrderStatusGroups.OPEN)
return Coalesce(
SubquerySum(f'{reference}sales_order_line_items__quantity', filter=order_filter)
- SubquerySum(
f'{reference}sales_order_line_items__shipped', filter=order_filter
),
Decimal(0),
output_field=models.DecimalField(),
)
def annotate_sales_order_allocations(reference: str = ''):
"""Annotate the total quantity of each part allocated to sales orders.

@@ -538,6 +538,7 @@ class PartSerializer(
'category_path',
'component',
'creation_date',
'creation_user',
'default_expiry',
'default_location',
'default_supplier',
@@ -575,6 +576,7 @@ class PartSerializer(
'in_stock',
'ordering',
'required_for_build_orders',
'required_for_sales_orders',
'stock_item_count',
'suppliers',
'total_in_stock',
@@ -715,7 +717,8 @@ class PartSerializer(
# Annotate with the total 'required for builds' quantity
queryset = queryset.annotate(
required_for_build_orders=part.filters.annotate_build_order_requirements()
required_for_build_orders=part.filters.annotate_build_order_requirements(),
required_for_sales_orders=part.filters.annotate_sales_order_requirements(),
)
return queryset
@@ -738,6 +741,10 @@ class PartSerializer(
source='responsible_owner',
)
creation_user = serializers.PrimaryKeyRelatedField(
queryset=users.models.User.objects.all(), required=False, allow_null=True
)
# Annotated fields
allocated_to_build_orders = serializers.FloatField(read_only=True)
allocated_to_sales_orders = serializers.FloatField(read_only=True)
@@ -745,6 +752,7 @@ class PartSerializer(
in_stock = serializers.FloatField(read_only=True)
ordering = serializers.FloatField(read_only=True)
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)
suppliers = serializers.IntegerField(read_only=True)
total_in_stock = serializers.FloatField(read_only=True)

@@ -812,7 +812,7 @@ class Owner(models.Model):
self.owner_type.name == 'user'
and common_models.InvenTreeSetting.get_setting('DISPLAY_FULL_NAMES')
):
return self.owner.get_full_name()
return self.owner.get_full_name() or str(self.owner)
return str(self.owner)
def label(self):