diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index d99cd90ef1..1b574a65f4 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -160,6 +160,7 @@ export enum ApiEndpoints { return_order_hold = 'order/ro/:id/hold/', return_order_cancel = 'order/ro/:id/cancel/', return_order_complete = 'order/ro/:id/complete/', + return_order_receive = 'order/ro/:id/receive/', return_order_line_list = 'order/ro-line/', return_order_extra_line_list = 'order/ro-extra-line/', diff --git a/src/frontend/src/forms/ReturnOrderForms.tsx b/src/frontend/src/forms/ReturnOrderForms.tsx index 588b91c479..e7dcedd157 100644 --- a/src/frontend/src/forms/ReturnOrderForms.tsx +++ b/src/frontend/src/forms/ReturnOrderForms.tsx @@ -1,6 +1,16 @@ +import { t } from '@lingui/macro'; +import { Flex, Table } from '@mantine/core'; import { IconUsers } from '@tabler/icons-react'; import { useMemo } from 'react'; +import RemoveRowButton from '../components/buttons/RemoveRowButton'; +import { 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 useReturnOrderLineItemFields({ orderId, customerId, @@ -43,3 +53,86 @@ export function useReturnOrderLineItemFields({ }; }, [create, orderId, customerId]); } + +type ReturnOrderLineItemsProps = { + items: any[]; + orderId: number; + onFormSuccess: (data: any) => void; +}; + +function ReturnOrderLineItemFormRow({ + props, + record +}: Readonly<{ + props: TableFieldRowProps; + record: any; +}>) { + return ( + <> + + + + +
{record.part_detail.name}
+
+
+ {record.item_detail.serial} + + props.removeFn(props.idx)} /> + +
+ + ); +} + +export function useReceiveReturnOrderLineItems( + props: ReturnOrderLineItemsProps +) { + const fields: ApiFormFieldSet = { + id: { + value: props.orderId, + hidden: true + }, + items: { + field_type: 'table', + value: props.items.map((item: any) => { + return { + item: item.pk + }; + }), + modelRenderer: (row: TableFieldRowProps) => { + const record = props.items.find((item) => item.pk == row?.item?.item); + + return ( + + ); + }, + headers: [t`Part`, t`Serial Number`] + }, + location: { + filters: { + structural: false + } + } + }; + + return useCreateApiFormModal({ + url: apiUrl(ApiEndpoints.return_order_receive, props.orderId), + title: t`Receive Items`, + fields: fields, + initialData: { + location: null + }, + size: '80%', + onFormSuccess: props.onFormSuccess, + successMessage: t`Item received into stock` + }); +} diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index f20dcc565e..fd7a7d04e1 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -244,6 +244,7 @@ export default function ReturnOrderDetail() { diff --git a/src/frontend/src/tables/sales/ReturnOrderLineItemTable.tsx b/src/frontend/src/tables/sales/ReturnOrderLineItemTable.tsx index 4b5629a768..eca6bd2ef7 100644 --- a/src/frontend/src/tables/sales/ReturnOrderLineItemTable.tsx +++ b/src/frontend/src/tables/sales/ReturnOrderLineItemTable.tsx @@ -2,18 +2,22 @@ import { t } from '@lingui/macro'; import { IconSquareArrowRight } from '@tabler/icons-react'; import { useCallback, useMemo, useState } from 'react'; +import { ActionButton } from '../../components/buttons/ActionButton'; import { AddItemButton } from '../../components/buttons/AddItemButton'; import { formatCurrency } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; -import { useReturnOrderLineItemFields } from '../../forms/ReturnOrderForms'; -import { notYetImplemented } from '../../functions/notifications'; +import { + useReceiveReturnOrderLineItems, + useReturnOrderLineItemFields +} from '../../forms/ReturnOrderForms'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal } from '../../hooks/UseForm'; +import useStatusCodes from '../../hooks/UseStatusCodes'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; @@ -32,18 +36,26 @@ import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; export default function ReturnOrderLineItemTable({ orderId, + order, customerId, currency }: Readonly<{ orderId: number; + order: any; customerId: number; currency: string; }>) { const table = useTable('return-order-line-item'); const user = useUserState(); + const roStatus = useStatusCodes({ modelType: ModelType.returnorder }); + const [selectedLine, setSelectedLine] = useState(0); + const inProgress: boolean = useMemo(() => { + return order.status == roStatus.IN_PROGRESS; + }, [order, roStatus]); + const newLineFields = useReturnOrderLineItemFields({ orderId: orderId, customerId: customerId, @@ -90,10 +102,15 @@ export default function ReturnOrderLineItemTable({ render: (record: any) => PartColumn(record?.part_detail) }, { - accessor: 'item', - title: t`Stock Item`, + accessor: 'item_detail.serial', + title: t`Serial Number`, switchable: false }, + StatusColumn({ + model: ModelType.stockitem, + sortable: false, + accessor: 'item_detail.status' + }), ReferenceColumn({}), StatusColumn({ model: ModelType.returnorderlineitem, @@ -145,9 +162,30 @@ export default function ReturnOrderLineItemTable({ onClick={() => { newLine.open(); }} + />, + } + hidden={!inProgress || !user.hasChangeRole(UserRoles.return_order)} + onClick={() => { + setSelectedItems( + table.selectedRecords.filter((record: any) => !record.received_date) + ); + receiveLineItems.open(); + }} + disabled={table.selectedRecords.length == 0} /> ]; - }, [user, orderId]); + }, [user, inProgress, orderId, table.selectedRecords]); + + const [selectedItems, setSelectedItems] = useState([]); + + const receiveLineItems = useReceiveReturnOrderLineItems({ + orderId: orderId, + items: selectedItems, + onFormSuccess: (data: any) => table.refreshTable() + }); const rowActions = useCallback( (record: any): RowAction[] => { @@ -158,7 +196,10 @@ export default function ReturnOrderLineItemTable({ hidden: received || !user.hasChangeRole(UserRoles.return_order), title: t`Receive Item`, icon: , - onClick: notYetImplemented + onClick: () => { + setSelectedItems([record]); + receiveLineItems.open(); + } }, RowEditAction({ hidden: !user.hasChangeRole(UserRoles.return_order), @@ -184,6 +225,7 @@ export default function ReturnOrderLineItemTable({ {newLine.modal} {editLine.modal} {deleteLine.modal} + {receiveLineItems.modal}