mirror of
https://github.com/inventree/InvenTree.git
synced 2025-08-03 02:21:34 +00:00
[PUI] Details Panel components (#6040)
* 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:
InvenTree
InvenTree
company
part
users
src/frontend/src
components
buttons
images
items
nav
tables
enums
functions
pages
part
@@ -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):
|
||||
|
Reference in New Issue
Block a user