2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 19:46:46 +00:00

PUI: Receive items against return order (#8142)

- Implement existing functionality in PUI
- Frontend changes / enhancements
This commit is contained in:
Oliver 2024-09-18 13:11:17 +10:00 committed by GitHub
parent def5ec1455
commit ec2051d70a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 148 additions and 7 deletions

View File

@ -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/',

View File

@ -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 (
<>
<Table.Tr>
<Table.Td>
<Flex gap="sm" align="center">
<Thumbnail
size={40}
src={record.part_detail.thumbnail}
align="center"
/>
<div>{record.part_detail.name}</div>
</Flex>
</Table.Td>
<Table.Td>{record.item_detail.serial}</Table.Td>
<Table.Td>
<RemoveRowButton onClick={() => props.removeFn(props.idx)} />
</Table.Td>
</Table.Tr>
</>
);
}
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 (
<ReturnOrderLineItemFormRow
props={row}
record={record}
key={record.pk}
/>
);
},
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`
});
}

View File

@ -244,6 +244,7 @@ export default function ReturnOrderDetail() {
<Accordion.Panel>
<ReturnOrderLineItemTable
orderId={order.pk}
order={order}
customerId={order.customer}
currency={orderCurrency}
/>

View File

@ -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<number>(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();
}}
/>,
<ActionButton
key="receive-items"
tooltip={t`Receive selected items`}
icon={<IconSquareArrowRight />}
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<any[]>([]);
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: <IconSquareArrowRight />,
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}
<InvenTreeTable
url={apiUrl(ApiEndpoints.return_order_line_list)}
tableState={table}
@ -195,9 +237,13 @@ export default function ReturnOrderLineItemTable({
item_detail: true,
order_detail: true
},
enableSelection:
inProgress && user.hasChangeRole(UserRoles.return_order),
tableActions: tableActions,
tableFilters: tableFilters,
rowActions: rowActions
rowActions: rowActions,
modelField: 'item',
modelType: ModelType.stockitem
}}
/>
</>