mirror of
https://github.com/inventree/InvenTree.git
synced 2025-10-23 09:27:39 +00:00
[UI] Hide actions for completed orders (#10617)
* Adjust error message target * Hide UI actions if order is locked * Refactor salesorderdetail page * Refactor PurchaseOrderDetail page * Refactor ReturnOrderDetail
This commit is contained in:
@@ -1687,7 +1687,7 @@ class OrderLineItem(InvenTree.models.InvenTreeMetadataModel):
|
||||
"""
|
||||
if self.order and self.order.check_locked():
|
||||
raise ValidationError({
|
||||
'reference': _('The order is locked and cannot be modified')
|
||||
'non_field_errors': _('The order is locked and cannot be modified')
|
||||
})
|
||||
|
||||
update_order = kwargs.pop('update_order', True)
|
||||
@@ -1703,7 +1703,7 @@ class OrderLineItem(InvenTree.models.InvenTreeMetadataModel):
|
||||
"""
|
||||
if self.order and self.order.check_locked():
|
||||
raise ValidationError({
|
||||
'reference': _('The order is locked and cannot be modified')
|
||||
'non_field_errors': _('The order is locked and cannot be modified')
|
||||
})
|
||||
|
||||
super().delete(*args, **kwargs)
|
||||
|
@@ -93,6 +93,24 @@ export default function PurchaseOrderDetail() {
|
||||
}
|
||||
});
|
||||
|
||||
const poStatus = useStatusCodes({ modelType: ModelType.purchaseorder });
|
||||
|
||||
const orderOpen: boolean = useMemo(() => {
|
||||
return (
|
||||
order.status == poStatus.PENDING ||
|
||||
order.status == poStatus.PLACED ||
|
||||
order.status == poStatus.ON_HOLD
|
||||
);
|
||||
}, [order, poStatus]);
|
||||
|
||||
const lineItemsEditable: boolean = useMemo(() => {
|
||||
if (orderOpen) {
|
||||
return true;
|
||||
} else {
|
||||
return globalSettings.isSet('PURCHASEORDER_EDIT_COMPLETED_ORDERS');
|
||||
}
|
||||
}, [orderOpen, globalSettings]);
|
||||
|
||||
const duplicatePurchaseOrderInitialData = useMemo(() => {
|
||||
const data = { ...order };
|
||||
// if we set the reference to null/undefined, it will be left blank in the form
|
||||
@@ -335,6 +353,7 @@ export default function PurchaseOrderDetail() {
|
||||
orderDetailRefresh={refreshInstance}
|
||||
currency={orderCurrency}
|
||||
orderId={Number(id)}
|
||||
editable={lineItemsEditable}
|
||||
supplierId={Number(order.supplier)}
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
@@ -349,6 +368,7 @@ export default function PurchaseOrderDetail() {
|
||||
orderId={order.pk}
|
||||
orderDetailRefresh={refreshInstance}
|
||||
currency={orderCurrency}
|
||||
editable={lineItemsEditable}
|
||||
role={UserRoles.purchase_order}
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
@@ -380,8 +400,6 @@ export default function PurchaseOrderDetail() {
|
||||
];
|
||||
}, [order, id, user]);
|
||||
|
||||
const poStatus = useStatusCodes({ modelType: ModelType.purchaseorder });
|
||||
|
||||
const issueOrder = useCreateApiFormModal({
|
||||
url: apiUrl(ApiEndpoints.purchase_order_issue, order.pk),
|
||||
title: t`Issue Purchase Order`,
|
||||
|
@@ -68,6 +68,25 @@ export default function ReturnOrderDetail() {
|
||||
}
|
||||
});
|
||||
|
||||
const roStatus = useStatusCodes({ modelType: ModelType.returnorder });
|
||||
|
||||
const orderOpen = useMemo(() => {
|
||||
return (
|
||||
order.status == roStatus.PENDING ||
|
||||
order.status == roStatus.PLACED ||
|
||||
order.status == roStatus.IN_PROGRESS ||
|
||||
order.status == roStatus.ON_HOLD
|
||||
);
|
||||
}, [order, roStatus]);
|
||||
|
||||
const lineItemsEditable: boolean = useMemo(() => {
|
||||
if (orderOpen) {
|
||||
return true;
|
||||
} else {
|
||||
return globalSettings.isSet('RETURNORDER_EDIT_COMPLETED_ORDERS');
|
||||
}
|
||||
}, [orderOpen, globalSettings]);
|
||||
|
||||
const orderCurrency = useMemo(() => {
|
||||
return (
|
||||
order.order_currency ||
|
||||
@@ -299,6 +318,7 @@ export default function ReturnOrderDetail() {
|
||||
order={order}
|
||||
orderDetailRefresh={refreshInstance}
|
||||
customerId={order.customer}
|
||||
editable={lineItemsEditable}
|
||||
currency={orderCurrency}
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
@@ -313,6 +333,7 @@ export default function ReturnOrderDetail() {
|
||||
orderId={order.pk}
|
||||
orderDetailRefresh={refreshInstance}
|
||||
currency={orderCurrency}
|
||||
editable={lineItemsEditable}
|
||||
role={UserRoles.return_order}
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
@@ -409,8 +430,6 @@ export default function ReturnOrderDetail() {
|
||||
successMessage: t`Order completed`
|
||||
});
|
||||
|
||||
const roStatus = useStatusCodes({ modelType: ModelType.returnorder });
|
||||
|
||||
const orderActions = useMemo(() => {
|
||||
const canEdit: boolean = user.hasChangeRole(UserRoles.return_order);
|
||||
|
||||
@@ -488,7 +507,7 @@ export default function ReturnOrderDetail() {
|
||||
]}
|
||||
/>
|
||||
];
|
||||
}, [user, order, roStatus]);
|
||||
}, [user, order, orderOpen, roStatus]);
|
||||
|
||||
const subtitle: string = useMemo(() => {
|
||||
let t = order.customer_detail?.name || '';
|
||||
|
@@ -284,6 +284,17 @@ export default function SalesOrderDetail() {
|
||||
|
||||
const soStatus = useStatusCodes({ modelType: ModelType.salesorder });
|
||||
|
||||
const lineItemsEditable: boolean = useMemo(() => {
|
||||
const orderOpen: boolean =
|
||||
order.status != soStatus.COMPLETE && order.status != soStatus.CANCELLED;
|
||||
|
||||
if (orderOpen) {
|
||||
return true;
|
||||
} else {
|
||||
return globalSettings.isSet('SALESORDER_EDIT_COMPLETED_ORDERS');
|
||||
}
|
||||
}, [globalSettings, order.status, soStatus]);
|
||||
|
||||
const salesOrderFields = useSalesOrderFields({});
|
||||
|
||||
const editSalesOrder = useEditApiFormModal({
|
||||
@@ -345,10 +356,7 @@ export default function SalesOrderDetail() {
|
||||
orderDetailRefresh={refreshInstance}
|
||||
currency={orderCurrency}
|
||||
customerId={order.customer}
|
||||
editable={
|
||||
order.status != soStatus.COMPLETE &&
|
||||
order.status != soStatus.CANCELLED
|
||||
}
|
||||
editable={lineItemsEditable}
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
@@ -360,6 +368,7 @@ export default function SalesOrderDetail() {
|
||||
<ExtraLineItemTable
|
||||
endpoint={ApiEndpoints.sales_order_extra_line_list}
|
||||
orderId={order.pk}
|
||||
editable={lineItemsEditable}
|
||||
orderDetailRefresh={refreshInstance}
|
||||
currency={orderCurrency}
|
||||
role={UserRoles.sales_order}
|
||||
|
@@ -34,10 +34,12 @@ export default function ExtraLineItemTable({
|
||||
orderId,
|
||||
orderDetailRefresh,
|
||||
currency,
|
||||
editable,
|
||||
role
|
||||
}: Readonly<{
|
||||
endpoint: ApiEndpoints;
|
||||
orderId: number;
|
||||
editable: boolean;
|
||||
orderDetailRefresh: () => void;
|
||||
currency: string;
|
||||
role: UserRoles;
|
||||
@@ -119,21 +121,21 @@ export default function ExtraLineItemTable({
|
||||
(record: any): RowAction[] => {
|
||||
return [
|
||||
RowEditAction({
|
||||
hidden: !user.hasChangeRole(role),
|
||||
hidden: !editable || !user.hasChangeRole(role),
|
||||
onClick: () => {
|
||||
setSelectedLine(record.pk);
|
||||
editLineItem.open();
|
||||
}
|
||||
}),
|
||||
RowDuplicateAction({
|
||||
hidden: !user.hasAddRole(role),
|
||||
hidden: !editable || !user.hasAddRole(role),
|
||||
onClick: () => {
|
||||
setInitialData({ ...record });
|
||||
newLineItem.open();
|
||||
}
|
||||
}),
|
||||
RowDeleteAction({
|
||||
hidden: !user.hasDeleteRole(role),
|
||||
hidden: !editable || !user.hasDeleteRole(role),
|
||||
onClick: () => {
|
||||
setSelectedLine(record.pk);
|
||||
deleteLineItem.open();
|
||||
@@ -141,7 +143,7 @@ export default function ExtraLineItemTable({
|
||||
})
|
||||
];
|
||||
},
|
||||
[user, role]
|
||||
[editable, user, role]
|
||||
);
|
||||
|
||||
const tableActions = useMemo(() => {
|
||||
@@ -149,7 +151,7 @@ export default function ExtraLineItemTable({
|
||||
<AddItemButton
|
||||
key='add-line-item'
|
||||
tooltip={t`Add Extra Line Item`}
|
||||
hidden={!user.hasAddRole(role)}
|
||||
hidden={!editable || !user.hasAddRole(role)}
|
||||
onClick={() => {
|
||||
setInitialData({
|
||||
order: orderId
|
||||
@@ -158,7 +160,7 @@ export default function ExtraLineItemTable({
|
||||
}}
|
||||
/>
|
||||
];
|
||||
}, [user, role]);
|
||||
}, [editable, user, role]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@@ -36,6 +36,7 @@ import {
|
||||
} from '../../hooks/UseForm';
|
||||
import useStatusCodes from '../../hooks/UseStatusCodes';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useGlobalSettingsState } from '../../states/SettingsStates';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import {
|
||||
CurrencyColumn,
|
||||
@@ -59,6 +60,7 @@ export function PurchaseOrderLineItemTable({
|
||||
orderId,
|
||||
currency,
|
||||
supplierId,
|
||||
editable,
|
||||
params
|
||||
}: Readonly<{
|
||||
order: any;
|
||||
@@ -66,10 +68,12 @@ export function PurchaseOrderLineItemTable({
|
||||
orderId: number;
|
||||
currency: string;
|
||||
supplierId?: number;
|
||||
editable: boolean;
|
||||
params?: any;
|
||||
}>) {
|
||||
const table = useTable('purchase-order-line-item');
|
||||
|
||||
const globalSettings = useGlobalSettingsState();
|
||||
const navigate = useNavigate();
|
||||
const user = useUserState();
|
||||
|
||||
@@ -327,14 +331,6 @@ export function PurchaseOrderLineItemTable({
|
||||
|
||||
const poStatus = useStatusCodes({ modelType: ModelType.purchaseorder });
|
||||
|
||||
const orderOpen: boolean = useMemo(() => {
|
||||
return (
|
||||
order.status == poStatus.PENDING ||
|
||||
order.status == poStatus.PLACED ||
|
||||
order.status == poStatus.ON_HOLD
|
||||
);
|
||||
}, [order, poStatus]);
|
||||
|
||||
const orderPlaced: boolean = useMemo(() => {
|
||||
return order.status == poStatus.PLACED;
|
||||
}, [order, poStatus]);
|
||||
@@ -343,6 +339,9 @@ export function PurchaseOrderLineItemTable({
|
||||
(record: any): RowAction[] => {
|
||||
const received = (record?.received ?? 0) >= (record?.quantity ?? 0);
|
||||
|
||||
const canEdit: boolean =
|
||||
editable && user.hasChangeRole(UserRoles.purchase_order);
|
||||
|
||||
return [
|
||||
{
|
||||
hidden: received || !orderPlaced,
|
||||
@@ -362,21 +361,21 @@ export function PurchaseOrderLineItemTable({
|
||||
navigate: navigate
|
||||
}),
|
||||
RowEditAction({
|
||||
hidden: !user.hasChangeRole(UserRoles.purchase_order),
|
||||
hidden: !canEdit,
|
||||
onClick: () => {
|
||||
setSelectedLine(record.pk);
|
||||
editLine.open();
|
||||
}
|
||||
}),
|
||||
RowDuplicateAction({
|
||||
hidden: !orderOpen || !user.hasAddRole(UserRoles.purchase_order),
|
||||
hidden: !canEdit || !user.hasAddRole(UserRoles.purchase_order),
|
||||
onClick: () => {
|
||||
setInitialData({ ...record });
|
||||
newLine.open();
|
||||
}
|
||||
}),
|
||||
RowDeleteAction({
|
||||
hidden: !user.hasDeleteRole(UserRoles.purchase_order),
|
||||
hidden: !canEdit || !user.hasDeleteRole(UserRoles.purchase_order),
|
||||
onClick: () => {
|
||||
setSelectedLine(record.pk);
|
||||
deleteLine.open();
|
||||
@@ -384,7 +383,7 @@ export function PurchaseOrderLineItemTable({
|
||||
})
|
||||
];
|
||||
},
|
||||
[orderId, user, orderOpen, orderPlaced]
|
||||
[orderId, user, editable, orderPlaced]
|
||||
);
|
||||
|
||||
// Custom table actions
|
||||
@@ -392,7 +391,7 @@ export function PurchaseOrderLineItemTable({
|
||||
return [
|
||||
<ActionButton
|
||||
key='import-line-items'
|
||||
hidden={!orderOpen || !user.hasAddRole(UserRoles.purchase_order)}
|
||||
hidden={!editable || !user.hasAddRole(UserRoles.purchase_order)}
|
||||
tooltip={t`Import Line Items`}
|
||||
icon={<IconFileArrowLeft />}
|
||||
onClick={() => importLineItems.open()}
|
||||
@@ -406,7 +405,7 @@ export function PurchaseOrderLineItemTable({
|
||||
});
|
||||
newLine.open();
|
||||
}}
|
||||
hidden={!orderOpen || !user?.hasAddRole(UserRoles.purchase_order)}
|
||||
hidden={!editable || !user?.hasAddRole(UserRoles.purchase_order)}
|
||||
/>,
|
||||
<ActionButton
|
||||
key='receive-items'
|
||||
@@ -417,7 +416,7 @@ export function PurchaseOrderLineItemTable({
|
||||
hidden={!orderPlaced || !user.hasChangeRole(UserRoles.purchase_order)}
|
||||
/>
|
||||
];
|
||||
}, [orderId, user, table, orderOpen, orderPlaced]);
|
||||
}, [orderId, user, table, editable, orderPlaced]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@@ -45,12 +45,14 @@ export default function ReturnOrderLineItemTable({
|
||||
order,
|
||||
orderDetailRefresh,
|
||||
customerId,
|
||||
editable,
|
||||
currency
|
||||
}: Readonly<{
|
||||
orderId: number;
|
||||
order: any;
|
||||
orderDetailRefresh: () => void;
|
||||
customerId: number;
|
||||
editable: boolean;
|
||||
currency: string;
|
||||
}>) {
|
||||
const table = useTable('return-order-line-item');
|
||||
@@ -181,7 +183,7 @@ export default function ReturnOrderLineItemTable({
|
||||
<AddItemButton
|
||||
key='add-line-item'
|
||||
tooltip={t`Add Line Item`}
|
||||
hidden={!user.hasAddRole(UserRoles.return_order)}
|
||||
hidden={!editable || !user.hasAddRole(UserRoles.return_order)}
|
||||
onClick={() => {
|
||||
newLine.open();
|
||||
}}
|
||||
@@ -190,7 +192,9 @@ export default function ReturnOrderLineItemTable({
|
||||
key='receive-items'
|
||||
tooltip={t`Receive selected items`}
|
||||
icon={<IconSquareArrowRight />}
|
||||
hidden={!inProgress || !user.hasChangeRole(UserRoles.return_order)}
|
||||
hidden={
|
||||
!editable || inProgress || !user.hasChangeRole(UserRoles.return_order)
|
||||
}
|
||||
onClick={() => {
|
||||
setSelectedItems(
|
||||
table.selectedRecords.filter((record: any) => !record.received_date)
|
||||
@@ -200,7 +204,7 @@ export default function ReturnOrderLineItemTable({
|
||||
disabled={table.selectedRecords.length == 0}
|
||||
/>
|
||||
];
|
||||
}, [user, inProgress, orderId, table.selectedRecords]);
|
||||
}, [user, editable, inProgress, orderId, table.selectedRecords]);
|
||||
|
||||
const [selectedItems, setSelectedItems] = useState<any[]>([]);
|
||||
|
||||
@@ -218,6 +222,7 @@ export default function ReturnOrderLineItemTable({
|
||||
{
|
||||
hidden:
|
||||
received ||
|
||||
!editable ||
|
||||
!inProgress ||
|
||||
!user.hasChangeRole(UserRoles.return_order),
|
||||
title: t`Receive Item`,
|
||||
@@ -228,14 +233,14 @@ export default function ReturnOrderLineItemTable({
|
||||
}
|
||||
},
|
||||
RowEditAction({
|
||||
hidden: !user.hasChangeRole(UserRoles.return_order),
|
||||
hidden: !editable || !user.hasChangeRole(UserRoles.return_order),
|
||||
onClick: () => {
|
||||
setSelectedLine(record.pk);
|
||||
editLine.open();
|
||||
}
|
||||
}),
|
||||
RowDeleteAction({
|
||||
hidden: !user.hasDeleteRole(UserRoles.return_order),
|
||||
hidden: !editable || !user.hasDeleteRole(UserRoles.return_order),
|
||||
onClick: () => {
|
||||
setSelectedLine(record.pk);
|
||||
deleteLine.open();
|
||||
@@ -243,7 +248,7 @@ export default function ReturnOrderLineItemTable({
|
||||
})
|
||||
];
|
||||
},
|
||||
[user, inProgress]
|
||||
[user, editable, inProgress]
|
||||
);
|
||||
|
||||
return (
|
||||
|
Reference in New Issue
Block a user