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:
parent
def5ec1455
commit
ec2051d70a
@ -160,6 +160,7 @@ export enum ApiEndpoints {
|
|||||||
return_order_hold = 'order/ro/:id/hold/',
|
return_order_hold = 'order/ro/:id/hold/',
|
||||||
return_order_cancel = 'order/ro/:id/cancel/',
|
return_order_cancel = 'order/ro/:id/cancel/',
|
||||||
return_order_complete = 'order/ro/:id/complete/',
|
return_order_complete = 'order/ro/:id/complete/',
|
||||||
|
return_order_receive = 'order/ro/:id/receive/',
|
||||||
return_order_line_list = 'order/ro-line/',
|
return_order_line_list = 'order/ro-line/',
|
||||||
return_order_extra_line_list = 'order/ro-extra-line/',
|
return_order_extra_line_list = 'order/ro-extra-line/',
|
||||||
|
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { Flex, Table } from '@mantine/core';
|
||||||
import { IconUsers } from '@tabler/icons-react';
|
import { IconUsers } from '@tabler/icons-react';
|
||||||
import { useMemo } from '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({
|
export function useReturnOrderLineItemFields({
|
||||||
orderId,
|
orderId,
|
||||||
customerId,
|
customerId,
|
||||||
@ -43,3 +53,86 @@ export function useReturnOrderLineItemFields({
|
|||||||
};
|
};
|
||||||
}, [create, orderId, customerId]);
|
}, [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`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -244,6 +244,7 @@ export default function ReturnOrderDetail() {
|
|||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
<ReturnOrderLineItemTable
|
<ReturnOrderLineItemTable
|
||||||
orderId={order.pk}
|
orderId={order.pk}
|
||||||
|
order={order}
|
||||||
customerId={order.customer}
|
customerId={order.customer}
|
||||||
currency={orderCurrency}
|
currency={orderCurrency}
|
||||||
/>
|
/>
|
||||||
|
@ -2,18 +2,22 @@ import { t } from '@lingui/macro';
|
|||||||
import { IconSquareArrowRight } from '@tabler/icons-react';
|
import { IconSquareArrowRight } from '@tabler/icons-react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { ActionButton } from '../../components/buttons/ActionButton';
|
||||||
import { AddItemButton } from '../../components/buttons/AddItemButton';
|
import { AddItemButton } from '../../components/buttons/AddItemButton';
|
||||||
import { formatCurrency } from '../../defaults/formatters';
|
import { formatCurrency } from '../../defaults/formatters';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useReturnOrderLineItemFields } from '../../forms/ReturnOrderForms';
|
import {
|
||||||
import { notYetImplemented } from '../../functions/notifications';
|
useReceiveReturnOrderLineItems,
|
||||||
|
useReturnOrderLineItemFields
|
||||||
|
} from '../../forms/ReturnOrderForms';
|
||||||
import {
|
import {
|
||||||
useCreateApiFormModal,
|
useCreateApiFormModal,
|
||||||
useDeleteApiFormModal,
|
useDeleteApiFormModal,
|
||||||
useEditApiFormModal
|
useEditApiFormModal
|
||||||
} from '../../hooks/UseForm';
|
} from '../../hooks/UseForm';
|
||||||
|
import useStatusCodes from '../../hooks/UseStatusCodes';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
@ -32,18 +36,26 @@ import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
|
|||||||
|
|
||||||
export default function ReturnOrderLineItemTable({
|
export default function ReturnOrderLineItemTable({
|
||||||
orderId,
|
orderId,
|
||||||
|
order,
|
||||||
customerId,
|
customerId,
|
||||||
currency
|
currency
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
orderId: number;
|
orderId: number;
|
||||||
|
order: any;
|
||||||
customerId: number;
|
customerId: number;
|
||||||
currency: string;
|
currency: string;
|
||||||
}>) {
|
}>) {
|
||||||
const table = useTable('return-order-line-item');
|
const table = useTable('return-order-line-item');
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
|
const roStatus = useStatusCodes({ modelType: ModelType.returnorder });
|
||||||
|
|
||||||
const [selectedLine, setSelectedLine] = useState<number>(0);
|
const [selectedLine, setSelectedLine] = useState<number>(0);
|
||||||
|
|
||||||
|
const inProgress: boolean = useMemo(() => {
|
||||||
|
return order.status == roStatus.IN_PROGRESS;
|
||||||
|
}, [order, roStatus]);
|
||||||
|
|
||||||
const newLineFields = useReturnOrderLineItemFields({
|
const newLineFields = useReturnOrderLineItemFields({
|
||||||
orderId: orderId,
|
orderId: orderId,
|
||||||
customerId: customerId,
|
customerId: customerId,
|
||||||
@ -90,10 +102,15 @@ export default function ReturnOrderLineItemTable({
|
|||||||
render: (record: any) => PartColumn(record?.part_detail)
|
render: (record: any) => PartColumn(record?.part_detail)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'item',
|
accessor: 'item_detail.serial',
|
||||||
title: t`Stock Item`,
|
title: t`Serial Number`,
|
||||||
switchable: false
|
switchable: false
|
||||||
},
|
},
|
||||||
|
StatusColumn({
|
||||||
|
model: ModelType.stockitem,
|
||||||
|
sortable: false,
|
||||||
|
accessor: 'item_detail.status'
|
||||||
|
}),
|
||||||
ReferenceColumn({}),
|
ReferenceColumn({}),
|
||||||
StatusColumn({
|
StatusColumn({
|
||||||
model: ModelType.returnorderlineitem,
|
model: ModelType.returnorderlineitem,
|
||||||
@ -145,9 +162,30 @@ export default function ReturnOrderLineItemTable({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
newLine.open();
|
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(
|
const rowActions = useCallback(
|
||||||
(record: any): RowAction[] => {
|
(record: any): RowAction[] => {
|
||||||
@ -158,7 +196,10 @@ export default function ReturnOrderLineItemTable({
|
|||||||
hidden: received || !user.hasChangeRole(UserRoles.return_order),
|
hidden: received || !user.hasChangeRole(UserRoles.return_order),
|
||||||
title: t`Receive Item`,
|
title: t`Receive Item`,
|
||||||
icon: <IconSquareArrowRight />,
|
icon: <IconSquareArrowRight />,
|
||||||
onClick: notYetImplemented
|
onClick: () => {
|
||||||
|
setSelectedItems([record]);
|
||||||
|
receiveLineItems.open();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
RowEditAction({
|
RowEditAction({
|
||||||
hidden: !user.hasChangeRole(UserRoles.return_order),
|
hidden: !user.hasChangeRole(UserRoles.return_order),
|
||||||
@ -184,6 +225,7 @@ export default function ReturnOrderLineItemTable({
|
|||||||
{newLine.modal}
|
{newLine.modal}
|
||||||
{editLine.modal}
|
{editLine.modal}
|
||||||
{deleteLine.modal}
|
{deleteLine.modal}
|
||||||
|
{receiveLineItems.modal}
|
||||||
<InvenTreeTable
|
<InvenTreeTable
|
||||||
url={apiUrl(ApiEndpoints.return_order_line_list)}
|
url={apiUrl(ApiEndpoints.return_order_line_list)}
|
||||||
tableState={table}
|
tableState={table}
|
||||||
@ -195,9 +237,13 @@ export default function ReturnOrderLineItemTable({
|
|||||||
item_detail: true,
|
item_detail: true,
|
||||||
order_detail: true
|
order_detail: true
|
||||||
},
|
},
|
||||||
|
enableSelection:
|
||||||
|
inProgress && user.hasChangeRole(UserRoles.return_order),
|
||||||
tableActions: tableActions,
|
tableActions: tableActions,
|
||||||
tableFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
rowActions: rowActions
|
rowActions: rowActions,
|
||||||
|
modelField: 'item',
|
||||||
|
modelType: ModelType.stockitem
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user