BuildOrder and SalesOrderShipment
This commit is contained in:
parent
6de4a056c7
commit
763fab2033
|
|
@ -7,8 +7,10 @@ import { PartPreviewComponent } from './models/PartPreview';
|
|||
import { PurchaseOrderPreviewComponent } from './models/PurchaseOrderPreview';
|
||||
import { ReturnOrderPreviewComponent } from './models/ReturnOrderPreview';
|
||||
import { SalesOrderPreviewComponent } from './models/SalesOrderPreview';
|
||||
import { SalesOrderShipmentPreviewComponent } from './models/SalesOrderShipmentPreview';
|
||||
import { StockPreviewComponent } from './models/StockPreview';
|
||||
import { SupplierPartPreviewComponent } from './models/SupplierPartPreview';
|
||||
import { TransferOrderPreviewComponent } from './models/TransferOrderPreview';
|
||||
|
||||
export interface PreviewType {
|
||||
preview: ReactNode;
|
||||
|
|
@ -49,6 +51,10 @@ export function getPreviewComponentForModel({
|
|||
return CompanyPreviewComponent({ instance, modelId });
|
||||
case ModelType.build:
|
||||
return BuildOrderPreviewComponent({ instance, modelId });
|
||||
case ModelType.salesordershipment:
|
||||
return SalesOrderShipmentPreviewComponent({ instance, modelId });
|
||||
case ModelType.transferorder:
|
||||
return TransferOrderPreviewComponent({ instance, modelId });
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { SalesOrderShipmentDetailsPanel } from '../../../pages/sales/SalesOrderShipmentDetailsPanel';
|
||||
import type { PreviewType } from '../PreviewType';
|
||||
|
||||
export function SalesOrderShipmentPreviewComponent({
|
||||
instance,
|
||||
modelId
|
||||
}: Readonly<{
|
||||
instance: any;
|
||||
modelId: number;
|
||||
}>): PreviewType {
|
||||
const order = instance?.order_detail?.reference;
|
||||
const ref = instance?.reference ?? `#${modelId}`;
|
||||
|
||||
let title = `${t`Shipment`} ${ref}`;
|
||||
|
||||
if (order) {
|
||||
title += ` (${order})`;
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
preview: <SalesOrderShipmentDetailsPanel instance={instance} />
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { TransferOrderDetailsPanel } from '../../../pages/stock/TransferOrderDetailsPanel';
|
||||
import type { PreviewType } from '../PreviewType';
|
||||
|
||||
export function TransferOrderPreviewComponent({
|
||||
instance,
|
||||
modelId
|
||||
}: Readonly<{
|
||||
instance: any;
|
||||
modelId: number;
|
||||
}>): PreviewType {
|
||||
const ref = instance?.reference ?? `#${modelId}`;
|
||||
|
||||
return {
|
||||
title: `${t`Transfer Order`} ${ref}`,
|
||||
preview: <TransferOrderDetailsPanel instance={instance} />
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { Grid, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { Stack } from '@mantine/core';
|
||||
import {
|
||||
IconBookmark,
|
||||
IconCircleCheck,
|
||||
|
|
@ -13,18 +13,11 @@ import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
|||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import { getDetailUrl } from '@lib/functions/Navigation';
|
||||
import { TagsList } from '@lib/index';
|
||||
import type { PanelType } from '@lib/types/Panel';
|
||||
import AdminButton from '../../components/buttons/AdminButton';
|
||||
import PrimaryActionButton from '../../components/buttons/PrimaryActionButton';
|
||||
import { PrintingActions } from '../../components/buttons/PrintingActions';
|
||||
import {
|
||||
type 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 {
|
||||
BarcodeActionDropdown,
|
||||
CancelItemAction,
|
||||
|
|
@ -37,9 +30,6 @@ import AttachmentPanel from '../../components/panels/AttachmentPanel';
|
|||
import NotesPanel from '../../components/panels/NotesPanel';
|
||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||
import ParametersPanel from '../../components/panels/ParametersPanel';
|
||||
import { RenderAddress } from '../../components/render/Company';
|
||||
import { RenderUser } from '../../components/render/User';
|
||||
import { formatDate } from '../../defaults/formatters';
|
||||
import {
|
||||
useCheckShipmentForm,
|
||||
useCompleteShipmentForm,
|
||||
|
|
@ -53,6 +43,7 @@ import {
|
|||
import { useInstance } from '../../hooks/UseInstance';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import SalesOrderAllocationTable from '../../tables/sales/SalesOrderAllocationTable';
|
||||
import { SalesOrderShipmentDetailsPanel } from './SalesOrderShipmentDetailsPanel';
|
||||
|
||||
export default function SalesOrderShipmentDetail() {
|
||||
const { id } = useParams();
|
||||
|
|
@ -74,193 +65,21 @@ export default function SalesOrderShipmentDetail() {
|
|||
}
|
||||
});
|
||||
|
||||
const { instance: customer, instanceQuery: customerQuery } = useInstance({
|
||||
endpoint: ApiEndpoints.company_list,
|
||||
pk: shipment.order_detail?.customer,
|
||||
hasPrimaryKey: true
|
||||
});
|
||||
|
||||
const isPending = useMemo(() => !shipment.shipment_date, [shipment]);
|
||||
|
||||
const isChecked = useMemo(() => !!shipment.checked_by, [shipment]);
|
||||
|
||||
const detailsPanel = useMemo(() => {
|
||||
if (shipmentQuery.isFetching || customerQuery.isFetching) {
|
||||
return <Skeleton />;
|
||||
}
|
||||
|
||||
const data: any = {
|
||||
...shipment,
|
||||
customer: customer?.pk,
|
||||
customer_name: customer?.name,
|
||||
customer_reference: shipment.order_detail?.customer_reference
|
||||
};
|
||||
|
||||
// Top Left: Order / customer information
|
||||
const tl: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
model: ModelType.salesorder,
|
||||
name: 'order',
|
||||
label: t`Sales Order`,
|
||||
icon: 'sales_orders',
|
||||
model_field: 'reference'
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'customer',
|
||||
icon: 'customers',
|
||||
label: t`Customer`,
|
||||
model: ModelType.company,
|
||||
model_field: 'name',
|
||||
hidden: !data.customer
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
external: true,
|
||||
name: 'link',
|
||||
label: t`Link`,
|
||||
copy: true,
|
||||
hidden: !shipment.link
|
||||
}
|
||||
];
|
||||
|
||||
// Top right: Shipment information
|
||||
const tr: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'customer_reference',
|
||||
icon: 'serial',
|
||||
label: t`Customer Reference`,
|
||||
hidden: !data.customer_reference,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'reference',
|
||||
icon: 'serial',
|
||||
label: t`Shipment Reference`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'tracking_number',
|
||||
label: t`Tracking Number`,
|
||||
icon: 'trackable',
|
||||
value_formatter: () => shipment.tracking_number || '---',
|
||||
copy: !!shipment.tracking_number
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'invoice_number',
|
||||
label: t`Invoice Number`,
|
||||
icon: 'serial',
|
||||
value_formatter: () => shipment.invoice_number || '---',
|
||||
copy: !!shipment.invoice_number
|
||||
}
|
||||
];
|
||||
|
||||
const address: any =
|
||||
shipment.shipment_address_detail || shipment.order_detail?.address_detail;
|
||||
|
||||
const bl: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'address',
|
||||
label: t`Shipping Address`,
|
||||
icon: 'address',
|
||||
value_formatter: () =>
|
||||
address ? (
|
||||
<RenderAddress
|
||||
instance={
|
||||
shipment.shipment_address_detail ||
|
||||
shipment.order_detail?.address_detail
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Text size='sm' c='red'>{t`Not specified`}</Text>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
const br: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'allocated_items',
|
||||
icon: 'packages',
|
||||
label: t`Allocated Items`
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'checked_by',
|
||||
label: t`Checked By`,
|
||||
icon: 'check',
|
||||
value_formatter: () =>
|
||||
shipment.checked_by_detail ? (
|
||||
<RenderUser instance={shipment.checked_by_detail} />
|
||||
) : (
|
||||
<Text size='sm' c='red'>{t`Not checked`}</Text>
|
||||
)
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'shipment_date',
|
||||
label: t`Shipment Date`,
|
||||
icon: 'calendar',
|
||||
value_formatter: () => formatDate(shipment.shipment_date),
|
||||
hidden: !shipment.shipment_date
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'delivery_date',
|
||||
label: t`Delivery Date`,
|
||||
icon: 'calendar',
|
||||
value_formatter: () => formatDate(shipment.delivery_date),
|
||||
hidden: !shipment.delivery_date
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: data },
|
||||
{ fields: bl, item: data },
|
||||
{ fields: br, item: data }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
appRole={UserRoles.sales_order}
|
||||
apiPath={ApiEndpoints.company_list}
|
||||
src={customer?.image}
|
||||
pk={customer?.pk}
|
||||
imageActions={{
|
||||
selectExisting: false,
|
||||
downloadImage: false,
|
||||
uploadFile: false,
|
||||
deleteFile: false
|
||||
}}
|
||||
/>
|
||||
<Grid.Col span={{ base: 12, sm: 8 }}>
|
||||
<DetailsTable fields={tl} item={data} />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<TagsList tags={shipment.tags} />
|
||||
</Stack>
|
||||
</ItemDetailsGrid>
|
||||
</>
|
||||
);
|
||||
}, [shipment, shipmentQuery, customer, customerQuery]);
|
||||
|
||||
const shipmentPanels: PanelType[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
name: 'detail',
|
||||
label: t`Shipment Details`,
|
||||
icon: <IconInfoCircle />,
|
||||
content: detailsPanel
|
||||
content: (
|
||||
<SalesOrderShipmentDetailsPanel
|
||||
instance={shipment}
|
||||
refreshInstance={refreshShipment}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'items',
|
||||
|
|
@ -291,7 +110,7 @@ export default function SalesOrderShipmentDetail() {
|
|||
has_note: !!shipment.notes
|
||||
})
|
||||
];
|
||||
}, [isPending, shipment, detailsPanel]);
|
||||
}, [isPending, shipment]);
|
||||
|
||||
const editShipmentFields = useSalesOrderShipmentFields({
|
||||
pending: isPending,
|
||||
|
|
@ -457,7 +276,7 @@ export default function SalesOrderShipmentDetail() {
|
|||
}
|
||||
]}
|
||||
badges={shipmentBadges}
|
||||
imageUrl={customer?.image}
|
||||
imageUrl={shipment.order_detail?.customer_detail?.image}
|
||||
editAction={editShipment.open}
|
||||
editEnabled={user.hasChangePermission(ModelType.salesordershipment)}
|
||||
actions={shipmentActions}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,205 @@
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { Grid, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import { TagsList } from '@lib/index';
|
||||
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import { useParameterDetailsGrid } from '../../components/details/ParameterDetailsGrid';
|
||||
import { RenderAddress } from '../../components/render/Company';
|
||||
import { RenderUser } from '../../components/render/User';
|
||||
import { formatDate } from '../../defaults/formatters';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
|
||||
export function SalesOrderShipmentDetailsPanel({
|
||||
instance,
|
||||
refreshInstance
|
||||
}: Readonly<{
|
||||
instance: any;
|
||||
refreshInstance?: () => void;
|
||||
}>) {
|
||||
const { instance: customer } = useInstance({
|
||||
endpoint: ApiEndpoints.company_list,
|
||||
pk: instance?.order_detail?.customer,
|
||||
hasPrimaryKey: true
|
||||
});
|
||||
|
||||
const data = useMemo(
|
||||
() => ({
|
||||
...instance,
|
||||
customer: customer?.pk,
|
||||
customer_name: customer?.name,
|
||||
customer_reference: instance?.order_detail?.customer_reference
|
||||
}),
|
||||
[instance, customer]
|
||||
);
|
||||
|
||||
const address = useMemo(
|
||||
() =>
|
||||
instance?.shipment_address_detail ||
|
||||
instance?.order_detail?.address_detail,
|
||||
[instance]
|
||||
);
|
||||
|
||||
const tl: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
model: ModelType.salesorder,
|
||||
name: 'order',
|
||||
label: t`Sales Order`,
|
||||
icon: 'sales_orders',
|
||||
model_field: 'reference'
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'customer',
|
||||
icon: 'customers',
|
||||
label: t`Customer`,
|
||||
model: ModelType.company,
|
||||
model_field: 'name',
|
||||
hidden: !data.customer
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
external: true,
|
||||
name: 'link',
|
||||
label: t`Link`,
|
||||
copy: true,
|
||||
hidden: !instance?.link
|
||||
}
|
||||
];
|
||||
|
||||
const tr: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'customer_reference',
|
||||
icon: 'serial',
|
||||
label: t`Customer Reference`,
|
||||
hidden: !data.customer_reference,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'reference',
|
||||
icon: 'serial',
|
||||
label: t`Shipment Reference`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'tracking_number',
|
||||
label: t`Tracking Number`,
|
||||
icon: 'trackable',
|
||||
value_formatter: () => instance?.tracking_number || '---',
|
||||
copy: !!instance?.tracking_number
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'invoice_number',
|
||||
label: t`Invoice Number`,
|
||||
icon: 'serial',
|
||||
value_formatter: () => instance?.invoice_number || '---',
|
||||
copy: !!instance?.invoice_number
|
||||
}
|
||||
];
|
||||
|
||||
const bl: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'address',
|
||||
label: t`Shipping Address`,
|
||||
icon: 'address',
|
||||
value_formatter: () =>
|
||||
address ? (
|
||||
<RenderAddress instance={address} />
|
||||
) : (
|
||||
<Text size='sm' c='red'>{t`Not specified`}</Text>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
const br: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'allocated_items',
|
||||
icon: 'packages',
|
||||
label: t`Allocated Items`
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'checked_by',
|
||||
label: t`Checked By`,
|
||||
icon: 'check',
|
||||
value_formatter: () =>
|
||||
instance?.checked_by_detail ? (
|
||||
<RenderUser instance={instance.checked_by_detail} />
|
||||
) : (
|
||||
<Text size='sm' c='red'>{t`Not checked`}</Text>
|
||||
)
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'shipment_date',
|
||||
label: t`Shipment Date`,
|
||||
icon: 'calendar',
|
||||
value_formatter: () => formatDate(instance?.shipment_date),
|
||||
hidden: !instance?.shipment_date
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'delivery_date',
|
||||
label: t`Delivery Date`,
|
||||
icon: 'calendar',
|
||||
value_formatter: () => formatDate(instance?.delivery_date),
|
||||
hidden: !instance?.delivery_date
|
||||
}
|
||||
];
|
||||
|
||||
const parametersTable = useParameterDetailsGrid({
|
||||
model_type: ModelType.salesordershipment,
|
||||
model_id: instance?.pk
|
||||
});
|
||||
|
||||
if (!instance?.pk) return <Skeleton />;
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: data },
|
||||
{ fields: bl, item: data },
|
||||
{ fields: br, item: data },
|
||||
parametersTable
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<DetailsImage
|
||||
appRole={UserRoles.sales_order}
|
||||
apiPath={apiUrl(ApiEndpoints.company_list, customer?.pk)}
|
||||
src={customer?.image}
|
||||
pk={customer?.pk}
|
||||
imageActions={{
|
||||
selectExisting: false,
|
||||
downloadImage: false,
|
||||
uploadFile: false,
|
||||
deleteFile: false
|
||||
}}
|
||||
/>
|
||||
<Grid.Col span={{ base: 12, sm: 8 }}>
|
||||
<DetailsTable fields={tl} item={data} />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<TagsList tags={instance?.tags} />
|
||||
</Stack>
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { Grid, Skeleton, Stack } from '@mantine/core';
|
||||
import { Skeleton, Stack } from '@mantine/core';
|
||||
import { type ReactNode, useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import { type PanelType, TagsList, apiUrl } from '@lib/index';
|
||||
import { type PanelType, apiUrl } from '@lib/index';
|
||||
import {
|
||||
IconBookmark,
|
||||
IconInfoCircle,
|
||||
|
|
@ -16,11 +16,6 @@ import {
|
|||
import AdminButton from '../../components/buttons/AdminButton';
|
||||
import PrimaryActionButton from '../../components/buttons/PrimaryActionButton';
|
||||
import { PrintingActions } from '../../components/buttons/PrintingActions';
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {
|
||||
BarcodeActionDropdown,
|
||||
CancelItemAction,
|
||||
|
|
@ -47,6 +42,7 @@ import { useGlobalSettingsState } from '../../states/SettingsStates';
|
|||
import { useUserState } from '../../states/UserState';
|
||||
import TransferOrderAllocationTable from '../../tables/stock/TransferOrderAllocationTable';
|
||||
import TransferOrderLineItemTable from '../../tables/stock/TransferOrderLineItemTable';
|
||||
import { TransferOrderDetailsPanel } from './TransferOrderDetailsPanel';
|
||||
|
||||
export default function TransferOrderDetail() {
|
||||
const { id } = useParams();
|
||||
|
|
@ -93,172 +89,11 @@ export default function TransferOrderDetail() {
|
|||
);
|
||||
}, [order, toStatus]);
|
||||
|
||||
const detailsPanel = useMemo(() => {
|
||||
if (instanceQuery.isFetching) {
|
||||
return <Skeleton />;
|
||||
}
|
||||
|
||||
const tl: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'reference',
|
||||
label: t`Reference`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'take_from',
|
||||
icon: 'location',
|
||||
label: t`Source Location`,
|
||||
model: ModelType.stocklocation
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'destination',
|
||||
icon: 'location',
|
||||
label: t`Destination Location`,
|
||||
model: ModelType.stocklocation
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'description',
|
||||
label: t`Description`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'status',
|
||||
name: 'status',
|
||||
label: t`Status`,
|
||||
model: ModelType.transferorder
|
||||
},
|
||||
{
|
||||
type: 'status',
|
||||
name: 'status_custom_key',
|
||||
label: t`Custom Status`,
|
||||
model: ModelType.transferorder,
|
||||
icon: 'status',
|
||||
hidden:
|
||||
!order.status_custom_key || order.status_custom_key == order.status
|
||||
}
|
||||
];
|
||||
|
||||
const tr: DetailsField[] = [
|
||||
{
|
||||
type: 'boolean',
|
||||
name: 'consume',
|
||||
icon: 'consume',
|
||||
label: t`Consume Stock`
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'line_items',
|
||||
label: t`Line Items`,
|
||||
icon: 'list'
|
||||
},
|
||||
{
|
||||
type: 'progressbar',
|
||||
name: 'completed',
|
||||
icon: 'progress',
|
||||
label: t`Completed Line Items`,
|
||||
total: order.line_items,
|
||||
progress: order.completed_lines
|
||||
}
|
||||
];
|
||||
|
||||
const bl: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
external: true,
|
||||
name: 'link',
|
||||
label: t`Link`,
|
||||
copy: true,
|
||||
hidden: !order.link
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'project_code_label',
|
||||
label: t`Project Code`,
|
||||
icon: 'reference',
|
||||
copy: true,
|
||||
hidden: !order.project_code
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'responsible',
|
||||
label: t`Responsible`,
|
||||
badge: 'owner',
|
||||
hidden: !order.responsible
|
||||
}
|
||||
];
|
||||
|
||||
const br: DetailsField[] = [
|
||||
{
|
||||
type: 'date',
|
||||
name: 'creation_date',
|
||||
label: t`Creation Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !order.creation_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'issue_date',
|
||||
label: t`Issue Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !order.issue_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'start_date',
|
||||
label: t`Start Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !order.start_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'target_date',
|
||||
label: t`Target Date`,
|
||||
copy: true,
|
||||
hidden: !order.target_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'complete_date',
|
||||
icon: 'calendar_check',
|
||||
label: t`Completion Date`,
|
||||
copy: true,
|
||||
hidden: !order.complete_date
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: order },
|
||||
{ fields: bl, item: order },
|
||||
{ fields: br, item: order }
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
{/* TODO: what image do we show for a Transfer Order? */}
|
||||
{/* <DetailsImage
|
||||
appRole={UserRoles.transfer_order}
|
||||
apiPath={ApiEndpoints.transfer_order_list}
|
||||
src="/static/img/blank_image.png"
|
||||
pk={order.pk}
|
||||
/> */}
|
||||
<Grid.Col span={{ base: 12, sm: 8 }}>
|
||||
<DetailsTable fields={tl} item={order} />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<TagsList tags={order.tags} />
|
||||
</Stack>
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [order, instanceQuery]);
|
||||
const detailsPanel = instanceQuery.isFetching ? (
|
||||
<Skeleton />
|
||||
) : (
|
||||
<TransferOrderDetailsPanel instance={order} />
|
||||
);
|
||||
|
||||
const orderPanels: PanelType[] = useMemo(() => {
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
import { t } from '@lingui/core/macro';
|
||||
import { Grid, Skeleton, Stack } from '@mantine/core';
|
||||
|
||||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { TagsList } from '@lib/index';
|
||||
|
||||
import {
|
||||
type DetailsField,
|
||||
DetailsTable
|
||||
} from '../../components/details/Details';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import { useParameterDetailsGrid } from '../../components/details/ParameterDetailsGrid';
|
||||
|
||||
export function TransferOrderDetailsPanel({
|
||||
instance
|
||||
}: Readonly<{
|
||||
instance: any;
|
||||
}>) {
|
||||
const tl: DetailsField[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'reference',
|
||||
label: t`Reference`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'take_from',
|
||||
icon: 'location',
|
||||
label: t`Source Location`,
|
||||
model: ModelType.stocklocation
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'destination',
|
||||
icon: 'location',
|
||||
label: t`Destination Location`,
|
||||
model: ModelType.stocklocation
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'description',
|
||||
label: t`Description`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'status',
|
||||
name: 'status',
|
||||
label: t`Status`,
|
||||
model: ModelType.transferorder
|
||||
},
|
||||
{
|
||||
type: 'status',
|
||||
name: 'status_custom_key',
|
||||
label: t`Custom Status`,
|
||||
model: ModelType.transferorder,
|
||||
icon: 'status',
|
||||
hidden:
|
||||
!instance?.status_custom_key ||
|
||||
instance?.status_custom_key == instance?.status
|
||||
}
|
||||
];
|
||||
|
||||
const tr: DetailsField[] = [
|
||||
{
|
||||
type: 'boolean',
|
||||
name: 'consume',
|
||||
icon: 'consume',
|
||||
label: t`Consume Stock`
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'line_items',
|
||||
label: t`Line Items`,
|
||||
icon: 'list'
|
||||
},
|
||||
{
|
||||
type: 'progressbar',
|
||||
name: 'completed',
|
||||
icon: 'progress',
|
||||
label: t`Completed Line Items`,
|
||||
total: instance?.line_items,
|
||||
progress: instance?.completed_lines
|
||||
}
|
||||
];
|
||||
|
||||
const bl: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
external: true,
|
||||
name: 'link',
|
||||
label: t`Link`,
|
||||
copy: true,
|
||||
hidden: !instance?.link
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'project_code_label',
|
||||
label: t`Project Code`,
|
||||
icon: 'reference',
|
||||
copy: true,
|
||||
hidden: !instance?.project_code
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'responsible',
|
||||
label: t`Responsible`,
|
||||
badge: 'owner',
|
||||
hidden: !instance?.responsible
|
||||
}
|
||||
];
|
||||
|
||||
const br: DetailsField[] = [
|
||||
{
|
||||
type: 'date',
|
||||
name: 'creation_date',
|
||||
label: t`Creation Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !instance?.creation_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'issue_date',
|
||||
label: t`Issue Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !instance?.issue_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'start_date',
|
||||
label: t`Start Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !instance?.start_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'target_date',
|
||||
label: t`Target Date`,
|
||||
copy: true,
|
||||
hidden: !instance?.target_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'complete_date',
|
||||
icon: 'calendar_check',
|
||||
label: t`Completion Date`,
|
||||
copy: true,
|
||||
hidden: !instance?.complete_date
|
||||
}
|
||||
];
|
||||
|
||||
const parametersTable = useParameterDetailsGrid({
|
||||
model_type: ModelType.transferorder,
|
||||
model_id: instance?.pk
|
||||
});
|
||||
|
||||
if (!instance?.pk) return <Skeleton />;
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid
|
||||
tables={[
|
||||
{ fields: tr, item: instance },
|
||||
{ fields: bl, item: instance },
|
||||
{ fields: br, item: instance },
|
||||
parametersTable
|
||||
]}
|
||||
>
|
||||
<Stack gap='xs'>
|
||||
<Grid grow>
|
||||
<Grid.Col span={{ base: 12, sm: 8 }}>
|
||||
<DetailsTable fields={tl} item={instance} />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<TagsList tags={instance.tags} />
|
||||
</Stack>
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue