mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-17 04:25:42 +00:00
Order table variants (#8295)
* BuildOrderTable: Show variants - Allow filtering of build orders by part variant * Add "include_variants" filter for SalesOrder table - A bit tricker! * Add "include_variants" filter to PartPurchaseOrdersTable * Enable filtering ReturnOrder by "part" attribute * Add similiar functionality for SalesOrderAllocation * Add similar filter for BuildAllocation table * Add migration file
This commit is contained in:
@ -223,8 +223,10 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
|
||||
label: t`Return Orders`,
|
||||
icon: <IconTruckReturn />,
|
||||
hidden: !company?.is_customer,
|
||||
content: company.pk && (
|
||||
<ReturnOrderTable params={{ customer: company.pk }} />
|
||||
content: company.pk ? (
|
||||
<ReturnOrderTable customerId={company.pk} />
|
||||
) : (
|
||||
<Skeleton />
|
||||
)
|
||||
},
|
||||
{
|
||||
|
@ -29,6 +29,7 @@ import {
|
||||
IconTestPipe,
|
||||
IconTools,
|
||||
IconTruckDelivery,
|
||||
IconTruckReturn,
|
||||
IconVersions
|
||||
} from '@tabler/icons-react';
|
||||
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
||||
@ -43,7 +44,6 @@ import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||
import DetailsBadge from '../../components/details/DetailsBadge';
|
||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import NotesEditor from '../../components/editors/NotesEditor';
|
||||
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
|
||||
import { Thumbnail } from '../../components/images/Thumbnail';
|
||||
import {
|
||||
@ -98,6 +98,7 @@ import { PartVariantTable } from '../../tables/part/PartVariantTable';
|
||||
import { RelatedPartTable } from '../../tables/part/RelatedPartTable';
|
||||
import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable';
|
||||
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
|
||||
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
|
||||
import SalesOrderAllocationTable from '../../tables/sales/SalesOrderAllocationTable';
|
||||
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
|
||||
import { StockItemTable } from '../../tables/stock/StockItemTable';
|
||||
@ -606,6 +607,7 @@ export default function PartDetail() {
|
||||
modelField="build"
|
||||
modelTarget={ModelType.build}
|
||||
showBuildInfo
|
||||
showPartInfo
|
||||
allowEdit
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
@ -698,6 +700,13 @@ export default function PartDetail() {
|
||||
hidden: !part.salable,
|
||||
content: part.pk ? <SalesOrderTable partId={part.pk} /> : <Skeleton />
|
||||
},
|
||||
{
|
||||
name: 'return_orders',
|
||||
label: t`Return Orders`,
|
||||
icon: <IconTruckReturn />,
|
||||
hidden: !part.salable || !globalSettings.isSet('RETURNORDER_ENABLED'),
|
||||
content: part.pk ? <ReturnOrderTable partId={part.pk} /> : <Skeleton />
|
||||
},
|
||||
{
|
||||
name: 'stocktake',
|
||||
label: t`Stock History`,
|
||||
@ -1093,7 +1102,7 @@ export default function PartDetail() {
|
||||
badges={badges}
|
||||
breadcrumbs={breadcrumbs}
|
||||
breadcrumbAction={() => {
|
||||
setTreeOpen(true);
|
||||
setTreeOpen(true); // Open the category tree
|
||||
}}
|
||||
editAction={editPart.open}
|
||||
editEnabled={user.hasChangeRole(UserRoles.part)}
|
||||
|
@ -45,17 +45,30 @@ export default function BuildAllocatedStockTable({
|
||||
modelField?: string;
|
||||
}>) {
|
||||
const user = useUserState();
|
||||
const table = useTable('buildallocatedstock');
|
||||
const table = useTable(
|
||||
!!partId ? 'buildallocatedstock-part' : 'buildallocatedstock'
|
||||
);
|
||||
|
||||
const tableFilters: TableFilter[] = useMemo(() => {
|
||||
return [
|
||||
let filters: TableFilter[] = [
|
||||
{
|
||||
name: 'tracked',
|
||||
label: t`Allocated to Output`,
|
||||
description: t`Show items allocated to a build output`
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
|
||||
if (!!partId) {
|
||||
filters.push({
|
||||
name: 'include_variants',
|
||||
type: 'boolean',
|
||||
label: t`Include Variants`,
|
||||
description: t`Include orders for part variants`
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [partId]);
|
||||
|
||||
const tableColumns: TableColumn[] = useMemo(() => {
|
||||
return [
|
||||
|
@ -46,6 +46,8 @@ export function BuildOrderTable({
|
||||
parentBuildId?: number;
|
||||
salesOrderId?: number;
|
||||
}>) {
|
||||
const table = useTable(!!partId ? 'buildorder-part' : 'buildorder-index');
|
||||
|
||||
const tableColumns = useMemo(() => {
|
||||
return [
|
||||
ReferenceColumn({}),
|
||||
@ -110,7 +112,7 @@ export function BuildOrderTable({
|
||||
const ownerFilters = useOwnerFilters();
|
||||
|
||||
const tableFilters: TableFilter[] = useMemo(() => {
|
||||
return [
|
||||
let filters: TableFilter[] = [
|
||||
{
|
||||
name: 'active',
|
||||
type: 'boolean',
|
||||
@ -147,12 +149,22 @@ export function BuildOrderTable({
|
||||
choices: ownerFilters.choices
|
||||
}
|
||||
];
|
||||
}, [parentBuildId, projectCodeFilters.choices, ownerFilters.choices]);
|
||||
|
||||
// If we are filtering on a specific part, we can include the "include variants" filter
|
||||
if (!!partId) {
|
||||
filters.push({
|
||||
name: 'include_variants',
|
||||
type: 'boolean',
|
||||
label: t`Include Variants`,
|
||||
description: t`Include orders for part variants`
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [partId, projectCodeFilters.choices, ownerFilters.choices]);
|
||||
|
||||
const user = useUserState();
|
||||
|
||||
const table = useTable('buildorder');
|
||||
|
||||
const buildOrderFields = useBuildOrderFields({ create: true });
|
||||
|
||||
const newBuild = useCreateApiFormModal({
|
||||
|
@ -123,6 +123,12 @@ export default function PartPurchaseOrdersTable({
|
||||
label: t`Order Status`,
|
||||
description: t`Filter by order status`,
|
||||
choiceFunction: StatusFilterOptions(ModelType.purchaseorder)
|
||||
},
|
||||
{
|
||||
name: 'include_variants',
|
||||
type: 'boolean',
|
||||
label: t`Include Variants`,
|
||||
description: t`Include orders for part variants`
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
|
@ -35,15 +35,21 @@ import {
|
||||
} from '../Filter';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
export function ReturnOrderTable({ params }: Readonly<{ params?: any }>) {
|
||||
const table = useTable('return-orders');
|
||||
export function ReturnOrderTable({
|
||||
partId,
|
||||
customerId
|
||||
}: Readonly<{
|
||||
partId?: number;
|
||||
customerId?: number;
|
||||
}>) {
|
||||
const table = useTable(!!partId ? 'returnorders-part' : 'returnorders-index');
|
||||
const user = useUserState();
|
||||
|
||||
const projectCodeFilters = useProjectCodeFilters();
|
||||
const responsibleFilters = useOwnerFilters();
|
||||
|
||||
const tableFilters: TableFilter[] = useMemo(() => {
|
||||
return [
|
||||
let filters: TableFilter[] = [
|
||||
{
|
||||
name: 'status',
|
||||
label: t`Status`,
|
||||
@ -69,7 +75,18 @@ export function ReturnOrderTable({ params }: Readonly<{ params?: any }>) {
|
||||
choices: responsibleFilters.choices
|
||||
}
|
||||
];
|
||||
}, [projectCodeFilters.choices, responsibleFilters.choices]);
|
||||
|
||||
if (!!partId) {
|
||||
filters.push({
|
||||
name: 'include_variants',
|
||||
type: 'boolean',
|
||||
label: t`Include Variants`,
|
||||
description: t`Include orders for part variants`
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [partId, projectCodeFilters.choices, responsibleFilters.choices]);
|
||||
|
||||
const tableColumns = useMemo(() => {
|
||||
return [
|
||||
@ -143,7 +160,8 @@ export function ReturnOrderTable({ params }: Readonly<{ params?: any }>) {
|
||||
columns={tableColumns}
|
||||
props={{
|
||||
params: {
|
||||
...params,
|
||||
part: partId,
|
||||
customer: customerId,
|
||||
customer_detail: true
|
||||
},
|
||||
tableFilters: tableFilters,
|
||||
|
@ -47,17 +47,30 @@ export default function SalesOrderAllocationTable({
|
||||
modelField?: string;
|
||||
}>) {
|
||||
const user = useUserState();
|
||||
const table = useTable('salesorderallocations');
|
||||
const table = useTable(
|
||||
!!partId ? 'salesorderallocations-part' : 'salesorderallocations'
|
||||
);
|
||||
|
||||
const tableFilters: TableFilter[] = useMemo(() => {
|
||||
return [
|
||||
let filters: TableFilter[] = [
|
||||
{
|
||||
name: 'outstanding',
|
||||
label: t`Outstanding`,
|
||||
description: t`Show outstanding allocations`
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
|
||||
if (!!partId) {
|
||||
filters.push({
|
||||
name: 'include_variants',
|
||||
type: 'boolean',
|
||||
label: t`Include Variants`,
|
||||
description: t`Include orders for part variants`
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [partId]);
|
||||
|
||||
const tableColumns: TableColumn[] = useMemo(() => {
|
||||
return [
|
||||
|
@ -43,14 +43,14 @@ export function SalesOrderTable({
|
||||
partId?: number;
|
||||
customerId?: number;
|
||||
}>) {
|
||||
const table = useTable('sales-order');
|
||||
const table = useTable(!!partId ? 'salesorder-part' : 'salesorder-index');
|
||||
const user = useUserState();
|
||||
|
||||
const projectCodeFilters = useProjectCodeFilters();
|
||||
const responsibleFilters = useOwnerFilters();
|
||||
|
||||
const tableFilters: TableFilter[] = useMemo(() => {
|
||||
return [
|
||||
let filters: TableFilter[] = [
|
||||
{
|
||||
name: 'status',
|
||||
label: t`Status`,
|
||||
@ -76,7 +76,18 @@ export function SalesOrderTable({
|
||||
choices: responsibleFilters.choices
|
||||
}
|
||||
];
|
||||
}, [projectCodeFilters.choices, responsibleFilters.choices]);
|
||||
|
||||
if (!!partId) {
|
||||
filters.push({
|
||||
name: 'include_variants',
|
||||
type: 'boolean',
|
||||
label: t`Include Variants`,
|
||||
description: t`Include orders for part variants`
|
||||
});
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [partId, projectCodeFilters.choices, responsibleFilters.choices]);
|
||||
|
||||
const salesOrderFields = useSalesOrderFields({});
|
||||
|
||||
|
Reference in New Issue
Block a user