2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 12:35:46 +00:00

[PUI] Stocktake (#7704)

* Adjust playwright test

* Add StocktakeReport table in the "admin" section

* Allow deletion of individual stocktake reports

* Add placeholder buttons

* Adds placeholder panel for stocktake data

* Implement <PartStocktakeTable />

* Add modal to generate a new report

* Generate stocktake report from part table

* Adjust table value

* panel display tweaks

* Improve query efficiency for supplier price breaks

* Refator part stocktake detail panel

* Fix role checks

* Cleanup code

* Fix "double loader" in <InvenTreeTable />

* API efficiency improvements

* Bump API version

* Tweak playwright test

* Update playwright test

---------

Co-authored-by: Matthias Mair <code@mjmair.com>
This commit is contained in:
Oliver
2024-09-21 18:29:59 +10:00
committed by GitHub
parent 0cd493e96e
commit f132970ff3
19 changed files with 479 additions and 42 deletions

View File

@ -1,13 +1,16 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 255
INVENTREE_API_VERSION = 256
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v256 - 2024-09-19 : https://github.com/inventree/InvenTree/pull/7704
- Adjustments for "stocktake" (stock history) API endpoints
v255 - 2024-09-19 : https://github.com/inventree/InvenTree/pull/8145
- Enables copying line items when duplicating an order

View File

@ -436,6 +436,13 @@ class SupplierPriceBreakList(ListCreateAPI):
serializer_class = SupplierPriceBreakSerializer
filterset_class = SupplierPriceBreakFilter
def get_queryset(self):
"""Return annotated queryset for the SupplierPriceBreak list endpoint."""
queryset = super().get_queryset()
queryset = SupplierPriceBreakSerializer.annotate_queryset(queryset)
return queryset
def get_serializer(self, *args, **kwargs):
"""Return serializer instance for this endpoint."""
try:
@ -468,6 +475,13 @@ class SupplierPriceBreakDetail(RetrieveUpdateDestroyAPI):
queryset = SupplierPriceBreak.objects.all()
serializer_class = SupplierPriceBreakSerializer
def get_queryset(self):
"""Return annotated queryset for the SupplierPriceBreak list endpoint."""
queryset = super().get_queryset()
queryset = SupplierPriceBreakSerializer.annotate_queryset(queryset)
return queryset
manufacturer_part_api_urls = [
path(

View File

@ -512,6 +512,13 @@ class SupplierPriceBreakSerializer(
if not part_detail:
self.fields.pop('part_detail', None)
@staticmethod
def annotate_queryset(queryset):
"""Prefetch related fields for the queryset."""
queryset = queryset.select_related('part', 'part__supplier', 'part__part')
return queryset
quantity = InvenTreeDecimalField()
price = InvenTreeMoneySerializer(allow_null=True, required=True, label=_('Price'))

View File

@ -991,11 +991,30 @@ class SalesOrderShipmentFilter(rest_filters.FilterSet):
return queryset.filter(delivery_date=None)
class SalesOrderShipmentList(ListCreateAPI):
"""API list endpoint for SalesOrderShipment model."""
class SalesOrderShipmentMixin:
"""Mixin class for SalesOrderShipment endpoints."""
queryset = models.SalesOrderShipment.objects.all()
serializer_class = serializers.SalesOrderShipmentSerializer
def get_queryset(self, *args, **kwargs):
"""Return annotated queryset for this endpoint."""
queryset = super().get_queryset(*args, **kwargs)
queryset = queryset.prefetch_related(
'order',
'order__customer',
'allocations',
'allocations__item',
'allocations__item__part',
)
return queryset
class SalesOrderShipmentList(SalesOrderShipmentMixin, ListCreateAPI):
"""API list endpoint for SalesOrderShipment model."""
filterset_class = SalesOrderShipmentFilter
filter_backends = SEARCH_ORDER_FILTER_ALIAS
@ -1003,12 +1022,9 @@ class SalesOrderShipmentList(ListCreateAPI):
ordering_fields = ['delivery_date', 'shipment_date']
class SalesOrderShipmentDetail(RetrieveUpdateDestroyAPI):
class SalesOrderShipmentDetail(SalesOrderShipmentMixin, RetrieveUpdateDestroyAPI):
"""API detail endpooint for SalesOrderShipment model."""
queryset = models.SalesOrderShipment.objects.all()
serializer_class = serializers.SalesOrderShipmentSerializer
class SalesOrderShipmentComplete(CreateAPI):
"""API endpoint for completing (shipping) a SalesOrderShipment."""

View File

@ -1715,6 +1715,13 @@ class PartStocktakeReportList(ListAPI):
ordering = '-pk'
class PartStocktakeReportDetail(RetrieveUpdateDestroyAPI):
"""API endpoint for detail view of a single PartStocktakeReport object."""
queryset = PartStocktakeReport.objects.all()
serializer_class = part_serializers.PartStocktakeReportSerializer
class PartStocktakeReportGenerate(CreateAPI):
"""API endpoint for manually generating a new PartStocktakeReport."""
@ -2184,6 +2191,11 @@ part_api_urls = [
PartStocktakeReportGenerate.as_view(),
name='api-part-stocktake-report-generate',
),
path(
'<int:pk>/',
PartStocktakeReportDetail.as_view(),
name='api-part-stocktake-report-detail',
),
path(
'',
PartStocktakeReportList.as_view(),

View File

@ -1193,6 +1193,7 @@ class PartStocktakeReportSerializer(InvenTree.serializers.InvenTreeModelSerializ
model = PartStocktakeReport
fields = ['pk', 'date', 'report', 'part_count', 'user', 'user_detail']
read_only_fields = ['date', 'report', 'part_count', 'user']
user_detail = InvenTree.serializers.UserSerializer(
source='user', read_only=True, many=False