diff --git a/InvenTree/InvenTree/api_version.py b/InvenTree/InvenTree/api_version.py index 01e2fda972..0867ef8b0c 100644 --- a/InvenTree/InvenTree/api_version.py +++ b/InvenTree/InvenTree/api_version.py @@ -2,11 +2,15 @@ # InvenTree API version -INVENTREE_API_VERSION = 145 +INVENTREE_API_VERSION = 147 """ Increment this API version number whenever there is a significant change to the API that any clients need to know about +v147 -> 2023-11-04: https://github.com/inventree/InvenTree/pull/5860 + - Adds "completed_lines" field to SalesOrder API endpoint + - Adds "completed_lines" field to PurchaseOrder API endpoint + v146 -> 2023-11-02: https://github.com/inventree/InvenTree/pull/5822 - Extended SSO Provider endpoint to contain if a provider is configured - Adds API endpoints for Email Address model diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index b4825ce1a9..939123b660 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -29,8 +29,8 @@ from InvenTree.serializers import (InvenTreeAttachmentSerializer, InvenTreeModelSerializer, InvenTreeMoneySerializer) from InvenTree.status_codes import (PurchaseOrderStatusGroups, - ReturnOrderStatus, SalesOrderStatusGroups, - StockStatus) + ReturnOrderLineStatus, ReturnOrderStatus, + SalesOrderStatusGroups, StockStatus) from part.serializers import PartBriefSerializer from users.serializers import OwnerSerializer @@ -58,6 +58,9 @@ class AbstractOrderSerializer(serializers.Serializer): # Number of line items in this order line_items = serializers.IntegerField(read_only=True) + # Number of completed line items (this is an annotated field) + completed_lines = serializers.IntegerField(read_only=True) + # Human-readable status text (read-only) status_text = serializers.CharField(source='get_status_display', read_only=True) @@ -107,6 +110,7 @@ class AbstractOrderSerializer(serializers.Serializer): 'target_date', 'description', 'line_items', + 'completed_lines', 'link', 'project_code', 'project_code_detail', @@ -211,6 +215,10 @@ class PurchaseOrderSerializer(TotalPriceMixin, AbstractOrderSerializer, InvenTre """ queryset = AbstractOrderSerializer.annotate_queryset(queryset) + queryset = queryset.annotate( + completed_lines=SubqueryCount('lines', filter=Q(quantity__lte=F('received'))) + ) + queryset = queryset.annotate( overdue=Case( When( @@ -743,10 +751,15 @@ class SalesOrderSerializer(TotalPriceMixin, AbstractOrderSerializer, InvenTreeMo """Add extra information to the queryset. - Number of line items in the SalesOrder + - Number of completed line items in the SalesOrder - Overdue status of the SalesOrder """ queryset = AbstractOrderSerializer.annotate_queryset(queryset) + queryset = queryset.annotate( + completed_lines=SubqueryCount('lines', filter=Q(quantity__lte=F('shipped'))) + ) + queryset = queryset.annotate( overdue=Case( When( @@ -1503,6 +1516,10 @@ class ReturnOrderSerializer(AbstractOrderSerializer, TotalPriceMixin, InvenTreeM """Custom annotation for the serializer queryset""" queryset = AbstractOrderSerializer.annotate_queryset(queryset) + queryset = queryset.annotate( + completed_lines=SubqueryCount('lines', filter=~Q(outcome=ReturnOrderLineStatus.PENDING.value)) + ) + queryset = queryset.annotate( overdue=Case( When( diff --git a/src/frontend/src/components/renderers/StatusRenderer.tsx b/src/frontend/src/components/renderers/StatusRenderer.tsx index f3a97ccf5d..bcd1359f8a 100644 --- a/src/frontend/src/components/renderers/StatusRenderer.tsx +++ b/src/frontend/src/components/renderers/StatusRenderer.tsx @@ -1,4 +1,4 @@ -import { Badge, MantineSize } from '@mantine/core'; +import { Badge, Center, MantineSize } from '@mantine/core'; import { colorMap } from '../../defaults/backendMappings'; import { useServerApiState } from '../../states/ApiState'; @@ -99,5 +99,8 @@ export const StatusRenderer = ({ export function TableStatusRenderer( type: ModelType ): ((record: any) => any) | undefined { - return (record: any) => StatusRenderer({ status: record.status, type: type }); + return (record: any) => + record.status && ( +
{StatusRenderer({ status: record.status, type: type })}
+ ); } diff --git a/src/frontend/src/components/tables/ColumnRenderers.tsx b/src/frontend/src/components/tables/ColumnRenderers.tsx new file mode 100644 index 0000000000..bad1d3621b --- /dev/null +++ b/src/frontend/src/components/tables/ColumnRenderers.tsx @@ -0,0 +1,134 @@ +/** + * Common rendering functions for table column data. + */ +import { t } from '@lingui/macro'; + +import { ProgressBar } from '../items/ProgressBar'; +import { ModelType } from '../render/ModelType'; +import { RenderOwner } from '../render/User'; +import { TableStatusRenderer } from '../renderers/StatusRenderer'; +import { TableColumn } from './Column'; +import { ProjectCodeHoverCard } from './TableHoverCard'; + +export function DescriptionColumn(): TableColumn { + return { + accessor: 'description', + title: t`Description`, + sortable: false, + switchable: true + }; +} + +export function LinkColumn(): TableColumn { + return { + accessor: 'link', + title: t`Link`, + sortable: false + // TODO: Custom URL hyperlink renderer? + }; +} + +export function LineItemsProgressColumn(): TableColumn { + return { + accessor: 'line_items', + title: t`Line Items`, + sortable: true, + render: (record: any) => ( + + ) + }; +} + +export function ProjectCodeColumn(): TableColumn { + return { + accessor: 'project_code', + title: t`Project Code`, + sortable: true, + render: (record: any) => ( + + ) + }; +} + +export function StatusColumn(model: ModelType) { + return { + accessor: 'status', + sortable: true, + title: t`Status`, + render: TableStatusRenderer(model) + }; +} + +export function ResponsibleColumn(): TableColumn { + return { + accessor: 'responsible', + title: t`Responsible`, + sortable: true, + render: (record: any) => + record.responsible && RenderOwner({ instance: record.responsible_detail }) + }; +} + +export function TargetDateColumn(): TableColumn { + return { + accessor: 'target_date', + title: t`Target Date`, + sortable: true + // TODO: custom renderer which alerts user if target date is overdue + }; +} + +export function CreationDateColumn(): TableColumn { + return { + accessor: 'creation_date', + title: t`Creation Date`, + sortable: true + }; +} + +export function ShipmentDateColumn(): TableColumn { + return { + accessor: 'shipment_date', + title: t`Shipment Date`, + sortable: true + }; +} + +export function CurrencyColumn({ + accessor, + title, + currency, + currency_accessor, + sortable +}: { + accessor: string; + title?: string; + currency?: string; + currency_accessor?: string; + sortable?: boolean; +}): TableColumn { + return { + accessor: accessor, + title: title ?? t`Currency`, + sortable: sortable ?? true, + render: (record: any) => { + let value = record[accessor]; + let currency_key = currency_accessor ?? `${accessor}_currency`; + currency = currency ?? record[currency_key]; + + // TODO: A better render which correctly formats money values + return `${value} ${currency}`; + } + }; +} + +export function TotalPriceColumn(): TableColumn { + return CurrencyColumn({ + accessor: 'total_price', + title: t`Total Price` + }); +} diff --git a/src/frontend/src/components/tables/TableHoverCard.tsx b/src/frontend/src/components/tables/TableHoverCard.tsx index 03499f585d..b43f134e7a 100644 --- a/src/frontend/src/components/tables/TableHoverCard.tsx +++ b/src/frontend/src/components/tables/TableHoverCard.tsx @@ -1,3 +1,4 @@ +import { t } from '@lingui/macro'; import { Divider, Group, HoverCard, Stack, Text } from '@mantine/core'; import { IconInfoCircle } from '@tabler/icons-react'; import { ReactNode } from 'react'; @@ -21,6 +22,10 @@ export function TableHoverCard({ return value; } + if (Array.isArray(extra) && extra.length == 0) { + return value; + } + return ( @@ -42,3 +47,18 @@ export function TableHoverCard({ ); } + +/** + * Custom hovercard for displaying projectcode detail in a table + */ +export function ProjectCodeHoverCard({ projectCode }: { projectCode: any }) { + return projectCode ? ( + + ) : ( + '-' + ); +} diff --git a/src/frontend/src/components/tables/build/BuildOrderTable.tsx b/src/frontend/src/components/tables/build/BuildOrderTable.tsx index b39b2a85c3..950961e81d 100644 --- a/src/frontend/src/components/tables/build/BuildOrderTable.tsx +++ b/src/frontend/src/components/tables/build/BuildOrderTable.tsx @@ -1,22 +1,22 @@ import { t } from '@lingui/macro'; -import { Text } from '@mantine/core'; -import { useCallback, useMemo } from 'react'; +import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { buildOrderFields } from '../../../forms/BuildForms'; -import { openCreateApiForm } from '../../../functions/forms'; import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; -import { AddItemButton } from '../../buttons/AddItemButton'; import { ThumbnailHoverCard } from '../../images/Thumbnail'; import { ProgressBar } from '../../items/ProgressBar'; import { ModelType } from '../../render/ModelType'; -import { RenderOwner, RenderUser } from '../../render/User'; -import { TableStatusRenderer } from '../../renderers/StatusRenderer'; +import { RenderUser } from '../../render/User'; import { TableColumn } from '../Column'; -import { TableFilter } from '../Filter'; +import { + CreationDateColumn, + ProjectCodeColumn, + ResponsibleColumn, + StatusColumn, + TargetDateColumn +} from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; -import { TableHoverCard } from '../TableHoverCard'; /** * Construct a list of columns for the build order table @@ -66,47 +66,15 @@ function buildOrderTableColumns(): TableColumn[] { /> ) }, - { - accessor: 'status', - sortable: true, - title: t`Status`, - - render: TableStatusRenderer(ModelType.build) - }, - { - accessor: 'project_code', - title: t`Project Code`, - sortable: true, - // TODO: Hide this if project code is not enabled - render: (record: any) => { - let project = record.project_code_detail; - - return project ? ( - {project.description}} - /> - ) : ( - '-' - ); - } - }, + StatusColumn(ModelType.build), + ProjectCodeColumn(), { accessor: 'priority', title: t`Priority`, sortable: true }, - { - accessor: 'creation_date', - sortable: true, - title: t`Created` - }, - { - accessor: 'target_date', - sortable: true, - title: t`Target Date` - }, + CreationDateColumn(), + TargetDateColumn(), { accessor: 'completion_date', sortable: true, @@ -120,14 +88,7 @@ function buildOrderTableColumns(): TableColumn[] { ) }, - { - accessor: 'responsible', - sortable: true, - title: t`Responsible`, - render: (record: any) => ( - - ) - } + ResponsibleColumn() ]; } diff --git a/src/frontend/src/components/tables/general/CompanyTable.tsx b/src/frontend/src/components/tables/general/CompanyTable.tsx index 77908caea4..97ec95c5c7 100644 --- a/src/frontend/src/components/tables/general/CompanyTable.tsx +++ b/src/frontend/src/components/tables/general/CompanyTable.tsx @@ -6,6 +6,7 @@ import { useNavigate } from 'react-router-dom'; import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { Thumbnail } from '../../images/Thumbnail'; +import { DescriptionColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; /** @@ -42,11 +43,7 @@ export function CompanyTable({ ); } }, - { - accessor: 'description', - title: t`Description`, - sortable: false - }, + DescriptionColumn(), { accessor: 'website', title: t`Website`, diff --git a/src/frontend/src/components/tables/part/PartCategoryTable.tsx b/src/frontend/src/components/tables/part/PartCategoryTable.tsx index c2c7ad55ed..4688ea498d 100644 --- a/src/frontend/src/components/tables/part/PartCategoryTable.tsx +++ b/src/frontend/src/components/tables/part/PartCategoryTable.tsx @@ -5,6 +5,7 @@ import { useNavigate } from 'react-router-dom'; import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { TableColumn } from '../Column'; +import { DescriptionColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; /** @@ -23,11 +24,7 @@ export function PartCategoryTable({ params = {} }: { params?: any }) { sortable: true, switchable: false }, - { - accessor: 'description', - title: t`Description`, - sortable: false - }, + DescriptionColumn(), { accessor: 'pathstring', title: t`Path`, diff --git a/src/frontend/src/components/tables/part/PartTable.tsx b/src/frontend/src/components/tables/part/PartTable.tsx index 49221ce43a..fe35844af9 100644 --- a/src/frontend/src/components/tables/part/PartTable.tsx +++ b/src/frontend/src/components/tables/part/PartTable.tsx @@ -8,6 +8,7 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { Thumbnail } from '../../images/Thumbnail'; import { TableColumn } from '../Column'; +import { DescriptionColumn, LinkColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; import { TableHoverCard } from '../TableHoverCard'; @@ -42,11 +43,7 @@ function partTableColumns(): TableColumn[] { sortable: true, title: t`Units` }, - { - accessor: 'description', - title: t`Description`, - sortable: true - }, + DescriptionColumn(), { accessor: 'category', title: t`Category`, @@ -155,10 +152,7 @@ function partTableColumns(): TableColumn[] { return '-- price --'; } }, - { - accessor: 'link', - title: t`Link` - } + LinkColumn() ]; } diff --git a/src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx b/src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx index bd264a1ba8..c3d2746172 100644 --- a/src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx +++ b/src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx @@ -12,6 +12,13 @@ import { useUserState } from '../../../states/UserState'; import { ActionButton } from '../../buttons/ActionButton'; import { AddItemButton } from '../../buttons/AddItemButton'; import { Thumbnail } from '../../images/Thumbnail'; +import { RenderStockLocation } from '../../render/Stock'; +import { + CurrencyColumn, + LinkColumn, + TargetDateColumn, + TotalPriceColumn +} from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, @@ -112,8 +119,8 @@ export function PurchaseOrderLineItemTable({ sortable: true, switchable: false, render: (record: any) => { - let part = record?.part_detail; let supplier_part = record?.supplier_part_detail ?? {}; + let part = record?.part_detail ?? supplier_part?.part_detail ?? {}; let extra = []; if (supplier_part.pack_quantity_native != 1) { @@ -127,8 +134,7 @@ export function PurchaseOrderLineItemTable({ extra.push( - {t`Total Quantity`}: {total} - {part.units} + {t`Total Quantity`}: {total} {part?.units} ); } @@ -158,7 +164,6 @@ export function PurchaseOrderLineItemTable({ { accessor: 'pack_quantity', sortable: false, - title: t`Pack Quantity`, render: (record: any) => record?.supplier_part_detail?.pack_quantity }, @@ -166,7 +171,8 @@ export function PurchaseOrderLineItemTable({ accessor: 'SKU', title: t`Supplier Code`, switchable: false, - sortable: true + sortable: true, + render: (record: any) => record?.supplier_part_detail?.SKU }, { accessor: 'supplier_link', @@ -183,43 +189,26 @@ export function PurchaseOrderLineItemTable({ render: (record: any) => record?.supplier_part_detail?.manufacturer_part_detail?.MPN }, - - { + CurrencyColumn({ accessor: 'purchase_price', - title: t`Unit Price`, - sortable: true - - // TODO: custom renderer - }, - { - accessor: 'total_price', - title: t`Total Price`, - sortable: true - - // TODO: custom renderer - }, - { - accessor: 'target_date', - title: t`Target Date`, - sortable: true - }, + title: t`Unit Price` + }), + TotalPriceColumn(), + TargetDateColumn(), { accessor: 'destination', title: t`Destination`, - sortable: false - - // TODO: Custom renderer + sortable: false, + render: (record: any) => + record.destination + ? RenderStockLocation({ instance: record.destination_detail }) + : '-' }, { accessor: 'notes', title: t`Notes` }, - { - accessor: 'link', - title: t`Link` - - // TODO: custom renderer - } + LinkColumn() ]; }, [orderId, user]); diff --git a/src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx b/src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx index a0343358c1..63c0c60faa 100644 --- a/src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx +++ b/src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx @@ -6,7 +6,16 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { Thumbnail } from '../../images/Thumbnail'; import { ModelType } from '../../render/ModelType'; -import { StatusRenderer } from '../../renderers/StatusRenderer'; +import { + CreationDateColumn, + DescriptionColumn, + LineItemsProgressColumn, + ProjectCodeColumn, + ResponsibleColumn, + StatusColumn, + TargetDateColumn, + TotalPriceColumn +} from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; /** @@ -30,11 +39,9 @@ export function PurchaseOrderTable({ params }: { params?: any }) { title: t`Reference`, sortable: true, switchable: false + // TODO: Display extra information if order is overdue }, - { - accessor: 'description', - title: t`Description` - }, + DescriptionColumn(), { accessor: 'supplier__name', title: t`Supplier`, @@ -55,54 +62,13 @@ export function PurchaseOrderTable({ params }: { params?: any }) { accessor: 'supplier_reference', title: t`Supplier Reference` }, - { - accessor: 'project_code', - title: t`Project Code` - - // TODO: Custom project code formatter - }, - { - accessor: 'status', - title: t`Status`, - sortable: true, - - render: (record: any) => - StatusRenderer({ - status: record.status, - type: ModelType.purchaseorder - }) - }, - { - accessor: 'creation_date', - title: t`Created` - - // TODO: Custom date formatter - }, - { - accessor: 'target_date', - title: t`Target Date` - - // TODO: Custom date formatter - }, - { - accessor: 'line_items', - title: t`Line Items`, - sortable: true - }, - { - accessor: 'total_price', - title: t`Total Price`, - sortable: true - - // TODO: Custom money formatter - }, - { - accessor: 'responsible', - title: t`Responsible`, - sortable: true - - // TODO: custom 'owner' formatter - } + LineItemsProgressColumn(), + StatusColumn(ModelType.purchaseorder), + ProjectCodeColumn(), + CreationDateColumn(), + TargetDateColumn(), + TotalPriceColumn(), + ResponsibleColumn() ]; }, []); diff --git a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx b/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx index be206a9400..e3e1276885 100644 --- a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx +++ b/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx @@ -14,6 +14,7 @@ import { useUserState } from '../../../states/UserState'; import { AddItemButton } from '../../buttons/AddItemButton'; import { Thumbnail } from '../../images/Thumbnail'; import { TableColumn } from '../Column'; +import { DescriptionColumn, LinkColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, RowEditAction } from '../RowActions'; import { TableHoverCard } from '../TableHoverCard'; @@ -63,11 +64,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { title: t`Supplier Part`, sortable: true }, - { - accessor: 'description', - title: t`Description`, - sortable: false - }, + DescriptionColumn(), { accessor: 'manufacturer', @@ -128,13 +125,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { ); } }, - { - accessor: 'link', - title: t`Link`, - sortable: false - - // TODO: custom link renderer? - }, + LinkColumn(), { accessor: 'note', title: t`Notes`, diff --git a/src/frontend/src/components/tables/sales/ReturnOrderTable.tsx b/src/frontend/src/components/tables/sales/ReturnOrderTable.tsx index 18f298d8ba..41bf78762a 100644 --- a/src/frontend/src/components/tables/sales/ReturnOrderTable.tsx +++ b/src/frontend/src/components/tables/sales/ReturnOrderTable.tsx @@ -6,7 +6,15 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { Thumbnail } from '../../images/Thumbnail'; import { ModelType } from '../../render/ModelType'; -import { TableStatusRenderer } from '../../renderers/StatusRenderer'; +import { + CreationDateColumn, + DescriptionColumn, + LineItemsProgressColumn, + ProjectCodeColumn, + ResponsibleColumn, + StatusColumn, + TargetDateColumn +} from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; export function ReturnOrderTable({ params }: { params?: any }) { @@ -26,10 +34,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { accessor: 'reference', title: t`Return Order`, sortable: true - }, - { - accessor: 'description', - title: t`Description` + // TODO: Display extra information if order is overdue }, { accessor: 'customer__name', @@ -51,24 +56,17 @@ export function ReturnOrderTable({ params }: { params?: any }) { accessor: 'customer_reference', title: t`Customer Reference` }, + DescriptionColumn(), + LineItemsProgressColumn(), + StatusColumn(ModelType.returnorder), + ProjectCodeColumn(), + CreationDateColumn(), + TargetDateColumn(), + ResponsibleColumn(), { - accessor: 'project_code', - title: t`Project Code` - - // TODO: Custom formatter - }, - { - accessor: 'status', - title: t`Status`, - sortable: true, - - render: TableStatusRenderer(ModelType.returnorder) + accessor: 'total_cost', + title: t`Total Cost` } - // TODO: Creation date - // TODO: Target date - // TODO: Line items - // TODO: Responsible - // TODO: Total cost ]; }, []); diff --git a/src/frontend/src/components/tables/sales/SalesOrderTable.tsx b/src/frontend/src/components/tables/sales/SalesOrderTable.tsx index 48cce5cc95..fdda8670d7 100644 --- a/src/frontend/src/components/tables/sales/SalesOrderTable.tsx +++ b/src/frontend/src/components/tables/sales/SalesOrderTable.tsx @@ -6,7 +6,16 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { Thumbnail } from '../../images/Thumbnail'; import { ModelType } from '../../render/ModelType'; -import { TableStatusRenderer } from '../../renderers/StatusRenderer'; +import { + CreationDateColumn, + DescriptionColumn, + LineItemsProgressColumn, + ProjectCodeColumn, + ShipmentDateColumn, + StatusColumn, + TargetDateColumn, + TotalPriceColumn +} from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; export function SalesOrderTable({ params }: { params?: any }) { @@ -27,10 +36,7 @@ export function SalesOrderTable({ params }: { params?: any }) { title: t`Sales Order`, sortable: true, switchable: false - }, - { - accessor: 'description', - title: t`Description` + // TODO: Display extra information if order is overdue }, { accessor: 'customer__name', @@ -52,25 +58,14 @@ export function SalesOrderTable({ params }: { params?: any }) { accessor: 'customer_reference', title: t`Customer Reference` }, - { - accessor: 'project_code', - title: t`Project Code` - - // TODO: Custom formatter - }, - { - accessor: 'status', - title: t`Status`, - sortable: true, - - render: TableStatusRenderer(ModelType.salesorder) - } - - // TODO: Creation date - // TODO: Target date - // TODO: Shipment date - // TODO: Line items - // TODO: Total price + DescriptionColumn(), + LineItemsProgressColumn(), + StatusColumn(ModelType.salesorder), + ProjectCodeColumn(), + CreationDateColumn(), + TargetDateColumn(), + ShipmentDateColumn(), + TotalPriceColumn() ]; }, []); diff --git a/src/frontend/src/components/tables/settings/ProjectCodeTable.tsx b/src/frontend/src/components/tables/settings/ProjectCodeTable.tsx index 7715b938b8..8b7270828f 100644 --- a/src/frontend/src/components/tables/settings/ProjectCodeTable.tsx +++ b/src/frontend/src/components/tables/settings/ProjectCodeTable.tsx @@ -11,6 +11,7 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { AddItemButton } from '../../buttons/AddItemButton'; import { TableColumn } from '../Column'; +import { DescriptionColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; @@ -27,11 +28,7 @@ export function ProjectCodeTable() { sortable: true, title: t`Project Code` }, - { - accessor: 'description', - sortable: false, - title: t`Description` - } + DescriptionColumn() ]; }, []); diff --git a/src/frontend/src/components/tables/stock/StockItemTable.tsx b/src/frontend/src/components/tables/stock/StockItemTable.tsx index 397d40a480..1e15bf3b10 100644 --- a/src/frontend/src/components/tables/stock/StockItemTable.tsx +++ b/src/frontend/src/components/tables/stock/StockItemTable.tsx @@ -7,8 +7,8 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { Thumbnail } from '../../images/Thumbnail'; import { ModelType } from '../../render/ModelType'; -import { TableStatusRenderer } from '../../renderers/StatusRenderer'; import { TableColumn } from '../Column'; +import { StatusColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; import { RowAction } from '../RowActions'; import { TableHoverCard } from '../TableHoverCard'; @@ -150,14 +150,7 @@ function stockItemTableColumns(): TableColumn[] { ); } }, - { - accessor: 'status', - sortable: true, - - filter: true, - title: t`Status`, - render: TableStatusRenderer(ModelType.stockitem) - }, + StatusColumn(ModelType.stockitem), { accessor: 'batch', sortable: true, diff --git a/src/frontend/src/components/tables/stock/StockLocationTable.tsx b/src/frontend/src/components/tables/stock/StockLocationTable.tsx index 06ee99cd5a..52f2299b03 100644 --- a/src/frontend/src/components/tables/stock/StockLocationTable.tsx +++ b/src/frontend/src/components/tables/stock/StockLocationTable.tsx @@ -6,6 +6,7 @@ import { useTableRefresh } from '../../../hooks/TableRefresh'; import { ApiPaths, apiUrl } from '../../../states/ApiState'; import { YesNoButton } from '../../items/YesNoButton'; import { TableColumn } from '../Column'; +import { DescriptionColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; /** @@ -23,10 +24,7 @@ export function StockLocationTable({ params = {} }: { params?: any }) { title: t`Name`, switchable: false }, - { - accessor: 'description', - title: t`Description` - }, + DescriptionColumn(), { accessor: 'pathstring', title: t`Path`,