From 6a8875a4a6bfd253189d2675bd3f869a2fe10f29 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 19 Sep 2024 13:17:50 +1000 Subject: [PATCH] Duplicate orders via API (#8145) * Refactor API endpoint for duplicating line items from a purchase order - Previously was "hidden" (undocumented) - Cleanup / refactor code - Now matches part duplication options - Generic implementation supports all order types * Update forms * Refactor line item duplication * Implement front-end support for return orders * Enable duplication of sales orders from PUI * Bump API version --- .../InvenTree/InvenTree/api_version.py | 5 +- src/backend/InvenTree/order/api.py | 50 ---------- src/backend/InvenTree/order/models.py | 26 +++++ src/backend/InvenTree/order/serializers.py | 96 ++++++++++++++++++- src/backend/InvenTree/order/test_api.py | 24 +++-- .../templates/js/translated/purchase_order.js | 33 ++----- src/frontend/src/forms/PurchaseOrderForms.tsx | 27 +++++- src/frontend/src/forms/ReturnOrderForms.tsx | 76 ++++++++++++++- src/frontend/src/forms/SalesOrderForms.tsx | 71 +++++--------- .../pages/purchasing/PurchaseOrderDetail.tsx | 8 +- .../src/pages/sales/ReturnOrderDetail.tsx | 10 +- .../src/pages/sales/SalesOrderDetail.tsx | 8 +- .../tables/purchasing/PurchaseOrderTable.tsx | 2 +- .../src/tables/sales/ReturnOrderTable.tsx | 4 +- .../src/tables/sales/SalesOrderTable.tsx | 2 +- 15 files changed, 292 insertions(+), 150 deletions(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index d7f0ffa89b..9dafef844b 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,13 +1,16 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 254 +INVENTREE_API_VERSION = 255 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v255 - 2024-09-19 : https://github.com/inventree/InvenTree/pull/8145 + - Enables copying line items when duplicating an order + v254 - 2024-09-14 : https://github.com/inventree/InvenTree/pull/7470 - Implements new API endpoints for enabling custom UI functionality via plugins diff --git a/src/backend/InvenTree/order/api.py b/src/backend/InvenTree/order/api.py index 374941afbc..c115a4aae4 100644 --- a/src/backend/InvenTree/order/api.py +++ b/src/backend/InvenTree/order/api.py @@ -5,7 +5,6 @@ from typing import cast from django.conf import settings from django.contrib.auth import authenticate, login -from django.db import transaction from django.db.models import F, Q from django.http.response import JsonResponse from django.urls import include, path, re_path @@ -14,7 +13,6 @@ from django.utils.translation import gettext_lazy as _ from django_filters import rest_framework as rest_filters from django_ical.views import ICalFeed from rest_framework import status -from rest_framework.exceptions import ValidationError from rest_framework.response import Response import common.models @@ -214,54 +212,6 @@ class PurchaseOrderList(PurchaseOrderMixin, DataExportViewMixin, ListCreateAPI): filterset_class = PurchaseOrderFilter - def create(self, request, *args, **kwargs): - """Save user information on create.""" - data = self.clean_data(request.data) - - duplicate_order = data.pop('duplicate_order', None) - duplicate_line_items = str2bool(data.pop('duplicate_line_items', False)) - duplicate_extra_lines = str2bool(data.pop('duplicate_extra_lines', False)) - - if duplicate_order is not None: - try: - duplicate_order = models.PurchaseOrder.objects.get(pk=duplicate_order) - except (ValueError, models.PurchaseOrder.DoesNotExist): - raise ValidationError({ - 'duplicate_order': [_('No matching purchase order found')] - }) - - serializer = self.get_serializer(data=data) - serializer.is_valid(raise_exception=True) - - with transaction.atomic(): - order = serializer.save() - order.created_by = request.user - order.save() - - # Duplicate line items from other order if required - if duplicate_order is not None: - if duplicate_line_items: - for line in duplicate_order.lines.all(): - # Copy the line across to the new order - line.pk = None - line.order = order - line.received = 0 - - line.save() - - if duplicate_extra_lines: - for line in duplicate_order.extra_lines.all(): - # Copy the line across to the new order - line.pk = None - line.order = order - - line.save() - - headers = self.get_success_headers(serializer.data) - return Response( - serializer.data, status=status.HTTP_201_CREATED, headers=headers - ) - def filter_queryset(self, queryset): """Custom queryset filtering.""" # Perform basic filtering diff --git a/src/backend/InvenTree/order/models.py b/src/backend/InvenTree/order/models.py index d294eae75c..7c236037e5 100644 --- a/src/backend/InvenTree/order/models.py +++ b/src/backend/InvenTree/order/models.py @@ -247,6 +247,16 @@ class Order( 'contact': _('Contact does not match selected company') }) + def clean_line_item(self, line): + """Clean a line item for this order. + + Used when duplicating an existing line item, + to ensure it is 'fresh'. + """ + line.pk = None + line.target_date = None + line.order = self + def report_context(self): """Generate context data for the reporting interface.""" return { @@ -379,6 +389,11 @@ class PurchaseOrder(TotalPriceMixin, Order): verbose_name = _('Purchase Order') + def clean_line_item(self, line): + """Clean a line item for this PurchaseOrder.""" + super().clean_line_item(line) + line.received = 0 + def report_context(self): """Return report context data for this PurchaseOrder.""" return {**super().report_context(), 'supplier': self.supplier} @@ -892,6 +907,11 @@ class SalesOrder(TotalPriceMixin, Order): verbose_name = _('Sales Order') + def clean_line_item(self, line): + """Clean a line item for this SalesOrder.""" + super().clean_line_item(line) + line.shipped = 0 + def report_context(self): """Generate report context data for this SalesOrder.""" return {**super().report_context(), 'customer': self.customer} @@ -2083,6 +2103,12 @@ class ReturnOrder(TotalPriceMixin, Order): verbose_name = _('Return Order') + def clean_line_item(self, line): + """Clean a line item for this ReturnOrder.""" + super().clean_line_item(line) + line.received_date = None + line.outcome = ReturnOrderLineStatus.PENDING.value + def report_context(self): """Generate report context data for this ReturnOrder.""" return {**super().report_context(), 'customer': self.customer} diff --git a/src/backend/InvenTree/order/serializers.py b/src/backend/InvenTree/order/serializers.py index 2060c7b4b0..769ae3f456 100644 --- a/src/backend/InvenTree/order/serializers.py +++ b/src/backend/InvenTree/order/serializers.py @@ -74,10 +74,39 @@ class TotalPriceMixin(serializers.Serializer): ) +class DuplicateOrderSerializer(serializers.Serializer): + """Serializer for specifying options when duplicating an order.""" + + class Meta: + """Metaclass options.""" + + fields = ['order_id', 'copy_lines', 'copy_extra_lines'] + + order_id = serializers.IntegerField( + required=True, label=_('Order ID'), help_text=_('ID of the order to duplicate') + ) + + copy_lines = serializers.BooleanField( + required=False, + default=True, + label=_('Copy Lines'), + help_text=_('Copy line items from the original order'), + ) + + copy_extra_lines = serializers.BooleanField( + required=False, + default=True, + label=_('Copy Extra Lines'), + help_text=_('Copy extra line items from the original order'), + ) + + class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Serializer): """Abstract serializer class which provides fields common to all order types.""" - export_exclude_fields = ['notes'] + export_exclude_fields = ['notes', 'duplicate'] + + import_exclude_fields = ['notes', 'duplicate'] # Number of line items in this order line_items = serializers.IntegerField(read_only=True, label=_('Line Items')) @@ -127,6 +156,13 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria required=False, allow_null=True, label=_('Creation Date') ) + duplicate = DuplicateOrderSerializer( + label=_('Duplicate Order'), + help_text=_('Specify options for duplicating this order'), + required=False, + write_only=True, + ) + def validate_reference(self, reference): """Custom validation for the reference field.""" self.Meta.model.validate_reference_field(reference) @@ -166,9 +202,49 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria 'notes', 'barcode_hash', 'overdue', + 'duplicate', *extra_fields, ] + def clean_line_item(self, line): + """Clean a line item object (when duplicating).""" + line.pk = None + line.order = self + + @transaction.atomic + def create(self, validated_data): + """Create a new order object. + + Optionally, copy line items from an existing order. + """ + duplicate = validated_data.pop('duplicate', None) + + instance = super().create(validated_data) + + if duplicate: + order_id = duplicate.get('order_id', None) + copy_lines = duplicate.get('copy_lines', True) + copy_extra_lines = duplicate.get('copy_extra_lines', True) + + try: + copy_from = instance.__class__.objects.get(pk=order_id) + except Exception: + # If the order ID is invalid, raise a validation error + raise ValidationError(_('Invalid order ID')) + + if copy_lines: + for line in copy_from.lines.all(): + instance.clean_line_item(line) + line.save() + + if copy_extra_lines: + for line in copy_from.extra_lines.all(): + line.pk = None + line.order = instance + line.save() + + return instance + class AbstractLineItemSerializer: """Abstract serializer for LineItem object.""" @@ -259,6 +335,12 @@ class PurchaseOrderSerializer( if supplier_detail is not True: self.fields.pop('supplier_detail', None) + def skip_create_fields(self): + """Skip these fields when instantiating a new object.""" + fields = super().skip_create_fields() + + return [*fields, 'duplicate'] + @staticmethod def annotate_queryset(queryset): """Add extra information to the queryset. @@ -900,6 +982,12 @@ class SalesOrderSerializer( if customer_detail is not True: self.fields.pop('customer_detail', None) + def skip_create_fields(self): + """Skip these fields when instantiating a new object.""" + fields = super().skip_create_fields() + + return [*fields, 'duplicate'] + @staticmethod def annotate_queryset(queryset): """Add extra information to the queryset. @@ -1692,6 +1780,12 @@ class ReturnOrderSerializer( if customer_detail is not True: self.fields.pop('customer_detail', None) + def skip_create_fields(self): + """Skip these fields when instantiating a new object.""" + fields = super().skip_create_fields() + + return [*fields, 'duplicate'] + @staticmethod def annotate_queryset(queryset): """Custom annotation for the serializer queryset.""" diff --git a/src/backend/InvenTree/order/test_api.py b/src/backend/InvenTree/order/test_api.py index 3dfd6d4737..7599442a84 100644 --- a/src/backend/InvenTree/order/test_api.py +++ b/src/backend/InvenTree/order/test_api.py @@ -439,18 +439,22 @@ class PurchaseOrderTest(OrderTest): del data['reference'] # Duplicate with non-existent PK to provoke error - data['duplicate_order'] = 10000001 - data['duplicate_line_items'] = True - data['duplicate_extra_lines'] = False + data['duplicate'] = { + 'order_id': 10000001, + 'copy_lines': True, + 'copy_extra_lines': False, + } data['reference'] = 'PO-9999' # Duplicate via the API response = self.post(reverse('api-po-list'), data, expected_code=400) - data['duplicate_order'] = 1 - data['duplicate_line_items'] = True - data['duplicate_extra_lines'] = False + data['duplicate'] = { + 'order_id': 1, + 'copy_lines': True, + 'copy_extra_lines': False, + } data['reference'] = 'PO-9999' @@ -466,8 +470,12 @@ class PurchaseOrderTest(OrderTest): self.assertEqual(po_dup.lines.count(), po.lines.count()) data['reference'] = 'PO-9998' - data['duplicate_line_items'] = False - data['duplicate_extra_lines'] = True + + data['duplicate'] = { + 'order_id': 1, + 'copy_lines': False, + 'copy_extra_lines': True, + } response = self.post(reverse('api-po-list'), data, expected_code=201) diff --git a/src/backend/InvenTree/templates/js/translated/purchase_order.js b/src/backend/InvenTree/templates/js/translated/purchase_order.js index d99223256c..4604181e84 100644 --- a/src/backend/InvenTree/templates/js/translated/purchase_order.js +++ b/src/backend/InvenTree/templates/js/translated/purchase_order.js @@ -98,7 +98,8 @@ function purchaseOrderFields(options={}) { return fields; } - } + }, + disabled: !!options.duplicate_order, }, supplier_reference: {}, project_code: { @@ -155,35 +156,13 @@ function purchaseOrderFields(options={}) { // Add fields for order duplication (only if required) if (options.duplicate_order) { - fields.duplicate_order = { + fields.duplicate__order_id = { value: options.duplicate_order, - group: 'duplicate', - required: 'true', - type: 'related field', - model: 'purchaseorder', - filters: { - supplier_detail: true, - }, - api_url: '{% url "api-po-list" %}', - label: '{% trans "Purchase Order" %}', - help_text: '{% trans "Select purchase order to duplicate" %}', + hidden: true, }; - fields.duplicate_line_items = { - value: true, - group: 'duplicate', - type: 'boolean', - label: '{% trans "Duplicate Line Items" %}', - help_text: '{% trans "Duplicate all line items from the selected order" %}', - }; - - fields.duplicate_extra_lines = { - value: true, - group: 'duplicate', - type: 'boolean', - label: '{% trans "Duplicate Extra Lines" %}', - help_text: '{% trans "Duplicate extra line items from the selected order" %}', - }; + fields.duplicate__copy_lines = {}; + fields.duplicate__copy_extra_lines = {}; } if (!global_settings.PROJECT_CODES_ENABLED) { diff --git a/src/frontend/src/forms/PurchaseOrderForms.tsx b/src/frontend/src/forms/PurchaseOrderForms.tsx index 067bb19fb4..4564a16932 100644 --- a/src/frontend/src/forms/PurchaseOrderForms.tsx +++ b/src/frontend/src/forms/PurchaseOrderForms.tsx @@ -138,14 +138,19 @@ export function usePurchaseOrderLineItemFields({ /** * Construct a set of fields for creating / editing a PurchaseOrder instance */ -export function usePurchaseOrderFields(): ApiFormFieldSet { +export function usePurchaseOrderFields({ + duplicateOrderId +}: { + duplicateOrderId?: number; +}): ApiFormFieldSet { return useMemo(() => { - return { + let fields: ApiFormFieldSet = { reference: { icon: }, description: {}, supplier: { + disabled: duplicateOrderId !== undefined, filters: { is_supplier: true, active: true @@ -187,7 +192,23 @@ export function usePurchaseOrderFields(): ApiFormFieldSet { icon: } }; - }, []); + + // Order duplication fields + if (!!duplicateOrderId) { + fields.duplicate = { + children: { + order_id: { + hidden: true, + value: duplicateOrderId + }, + copy_lines: {}, + copy_extra_lines: {} + } + }; + } + + return fields; + }, [duplicateOrderId]); } /** diff --git a/src/frontend/src/forms/ReturnOrderForms.tsx b/src/frontend/src/forms/ReturnOrderForms.tsx index e7dcedd157..a9427dfc67 100644 --- a/src/frontend/src/forms/ReturnOrderForms.tsx +++ b/src/frontend/src/forms/ReturnOrderForms.tsx @@ -1,16 +1,88 @@ import { t } from '@lingui/macro'; import { Flex, Table } from '@mantine/core'; -import { IconUsers } from '@tabler/icons-react'; +import { IconAddressBook, IconUser, IconUsers } from '@tabler/icons-react'; import { useMemo } from 'react'; import RemoveRowButton from '../components/buttons/RemoveRowButton'; -import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; +import { + ApiFormAdjustFilterType, + ApiFormFieldSet +} from '../components/forms/fields/ApiFormField'; import { TableFieldRowProps } from '../components/forms/fields/TableField'; import { Thumbnail } from '../components/images/Thumbnail'; import { ApiEndpoints } from '../enums/ApiEndpoints'; import { useCreateApiFormModal } from '../hooks/UseForm'; import { apiUrl } from '../states/ApiState'; +export function useReturnOrderFields({ + duplicateOrderId +}: { + duplicateOrderId?: number; +}): ApiFormFieldSet { + return useMemo(() => { + let fields: ApiFormFieldSet = { + reference: {}, + description: {}, + customer: { + disabled: duplicateOrderId != undefined, + filters: { + is_customer: true, + active: true + } + }, + customer_reference: {}, + project_code: {}, + order_currency: {}, + target_date: {}, + link: {}, + contact: { + icon: , + adjustFilters: (value: ApiFormAdjustFilterType) => { + return { + ...value.filters, + company: value.data.customer + }; + } + }, + address: { + icon: , + adjustFilters: (value: ApiFormAdjustFilterType) => { + return { + ...value.filters, + company: value.data.customer + }; + } + }, + responsible: { + filters: { + is_active: true + }, + icon: + } + }; + + // Order duplication fields + if (!!duplicateOrderId) { + fields.duplicate = { + children: { + order_id: { + hidden: true, + value: duplicateOrderId + }, + copy_lines: { + // Cannot duplicate lines from a return order! + value: false, + hidden: true + }, + copy_extra_lines: {} + } + }; + } + + return fields; + }, [duplicateOrderId]); +} + export function useReturnOrderLineItemFields({ orderId, customerId, diff --git a/src/frontend/src/forms/SalesOrderForms.tsx b/src/frontend/src/forms/SalesOrderForms.tsx index d67ede312b..649910d0f8 100644 --- a/src/frontend/src/forms/SalesOrderForms.tsx +++ b/src/frontend/src/forms/SalesOrderForms.tsx @@ -6,12 +6,17 @@ import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; -export function useSalesOrderFields(): ApiFormFieldSet { +export function useSalesOrderFields({ + duplicateOrderId +}: { + duplicateOrderId?: number; +}): ApiFormFieldSet { return useMemo(() => { - return { + let fields: ApiFormFieldSet = { reference: {}, description: {}, customer: { + disabled: duplicateOrderId != undefined, filters: { is_customer: true, active: true @@ -44,7 +49,23 @@ export function useSalesOrderFields(): ApiFormFieldSet { icon: } }; - }, []); + + // Order duplication fields + if (!!duplicateOrderId) { + fields.duplicate = { + children: { + order_id: { + hidden: true, + value: duplicateOrderId + }, + copy_lines: {}, + copy_extra_lines: {} + } + }; + } + + return fields; + }, [duplicateOrderId]); } export function useSalesOrderLineItemFields({ @@ -125,47 +146,3 @@ export function useSalesOrderShipmentFields(): ApiFormFieldSet { }; }, []); } - -export function useReturnOrderFields(): ApiFormFieldSet { - return useMemo(() => { - return { - reference: {}, - description: {}, - customer: { - filters: { - is_customer: true, - active: true - } - }, - customer_reference: {}, - project_code: {}, - order_currency: {}, - target_date: {}, - link: {}, - contact: { - icon: , - adjustFilters: (value: ApiFormAdjustFilterType) => { - return { - ...value.filters, - company: value.data.customer - }; - } - }, - address: { - icon: , - adjustFilters: (value: ApiFormAdjustFilterType) => { - return { - ...value.filters, - company: value.data.customer - }; - } - }, - responsible: { - filters: { - is_active: true - }, - icon: - } - }; - }, []); -} diff --git a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx index ef3c177195..6e5d0a36cb 100644 --- a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx +++ b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx @@ -81,7 +81,11 @@ export default function PurchaseOrderDetail() { ); }, [order, globalSettings]); - const purchaseOrderFields = usePurchaseOrderFields(); + const purchaseOrderFields = usePurchaseOrderFields({}); + + const duplicatePurchaseOrderFields = usePurchaseOrderFields({ + duplicateOrderId: order.pk + }); const editPurchaseOrder = useEditApiFormModal({ url: ApiEndpoints.purchase_order_list, @@ -96,7 +100,7 @@ export default function PurchaseOrderDetail() { const duplicatePurchaseOrder = useCreateApiFormModal({ url: ApiEndpoints.purchase_order_list, title: t`Add Purchase Order`, - fields: purchaseOrderFields, + fields: duplicatePurchaseOrderFields, initialData: { ...order, reference: undefined diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index fd7a7d04e1..618d43efbf 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -34,7 +34,7 @@ import { formatCurrency } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; -import { useReturnOrderFields } from '../../forms/SalesOrderForms'; +import { useReturnOrderFields } from '../../forms/ReturnOrderForms'; import { useCreateApiFormModal, useEditApiFormModal @@ -304,7 +304,11 @@ export default function ReturnOrderDetail() { ]; }, [order, instanceQuery]); - const returnOrderFields = useReturnOrderFields(); + const returnOrderFields = useReturnOrderFields({}); + + const duplicateReturnOrderFields = useReturnOrderFields({ + duplicateOrderId: order.pk + }); const editReturnOrder = useEditApiFormModal({ url: ApiEndpoints.return_order_list, @@ -319,7 +323,7 @@ export default function ReturnOrderDetail() { const duplicateReturnOrder = useCreateApiFormModal({ url: ApiEndpoints.return_order_list, title: t`Add Return Order`, - fields: returnOrderFields, + fields: duplicateReturnOrderFields, initialData: { ...order, reference: undefined diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx index 1426a3c5be..7dcd920e97 100644 --- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx @@ -231,7 +231,7 @@ export default function SalesOrderDetail() { const soStatus = useStatusCodes({ modelType: ModelType.salesorder }); - const salesOrderFields = useSalesOrderFields(); + const salesOrderFields = useSalesOrderFields({}); const editSalesOrder = useEditApiFormModal({ url: ApiEndpoints.sales_order_list, @@ -243,10 +243,14 @@ export default function SalesOrderDetail() { } }); + const duplicateOrderFields = useSalesOrderFields({ + duplicateOrderId: order.pk + }); + const duplicateSalesOrder = useCreateApiFormModal({ url: ApiEndpoints.sales_order_list, title: t`Add Sales Order`, - fields: salesOrderFields, + fields: duplicateOrderFields, initialData: { ...order, reference: undefined diff --git a/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx b/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx index 7bed5eb38f..9eba0509b2 100644 --- a/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx +++ b/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx @@ -121,7 +121,7 @@ export function PurchaseOrderTable({ ]; }, []); - const purchaseOrderFields = usePurchaseOrderFields(); + const purchaseOrderFields = usePurchaseOrderFields({}); const newPurchaseOrder = useCreateApiFormModal({ url: ApiEndpoints.purchase_order_list, diff --git a/src/frontend/src/tables/sales/ReturnOrderTable.tsx b/src/frontend/src/tables/sales/ReturnOrderTable.tsx index 8297ff4aa8..889933e805 100644 --- a/src/frontend/src/tables/sales/ReturnOrderTable.tsx +++ b/src/frontend/src/tables/sales/ReturnOrderTable.tsx @@ -7,7 +7,7 @@ import { formatCurrency } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; -import { useReturnOrderFields } from '../../forms/SalesOrderForms'; +import { useReturnOrderFields } from '../../forms/ReturnOrderForms'; import { useOwnerFilters, useProjectCodeFilters } from '../../hooks/UseFilter'; import { useCreateApiFormModal } from '../../hooks/UseForm'; import { useTable } from '../../hooks/UseTable'; @@ -112,7 +112,7 @@ export function ReturnOrderTable({ params }: Readonly<{ params?: any }>) { ]; }, []); - const returnOrderFields = useReturnOrderFields(); + const returnOrderFields = useReturnOrderFields({}); const newReturnOrder = useCreateApiFormModal({ url: ApiEndpoints.return_order_list, diff --git a/src/frontend/src/tables/sales/SalesOrderTable.tsx b/src/frontend/src/tables/sales/SalesOrderTable.tsx index 2de115e3a7..b96aa3f2cc 100644 --- a/src/frontend/src/tables/sales/SalesOrderTable.tsx +++ b/src/frontend/src/tables/sales/SalesOrderTable.tsx @@ -77,7 +77,7 @@ export function SalesOrderTable({ ]; }, [projectCodeFilters.choices, responsibleFilters.choices]); - const salesOrderFields = useSalesOrderFields(); + const salesOrderFields = useSalesOrderFields({}); const newSalesOrder = useCreateApiFormModal({ url: ApiEndpoints.sales_order_list,