mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
BOM pricing table fix (#7044)
* Allow click-through from BOM pricing table * Allow sorting by price in BOM table * Add "Total Price" column to BOM table * Enable part table to be sorted by price range * Enable click-through on VariantPricing table * Update quantity columns for BOM tables * Improve rendering for UsedInTable
This commit is contained in:
parent
860ecc43e9
commit
9d2297da7d
@ -1,5 +1,11 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { SegmentedControl, SimpleGrid, Stack } from '@mantine/core';
|
import {
|
||||||
|
Group,
|
||||||
|
SegmentedControl,
|
||||||
|
SimpleGrid,
|
||||||
|
Stack,
|
||||||
|
Text
|
||||||
|
} from '@mantine/core';
|
||||||
import { ReactNode, useMemo, useState } from 'react';
|
import { ReactNode, useMemo, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Bar,
|
Bar,
|
||||||
@ -17,6 +23,7 @@ import {
|
|||||||
import { CHART_COLORS } from '../../../components/charts/colors';
|
import { CHART_COLORS } from '../../../components/charts/colors';
|
||||||
import { formatDecimal, formatPriceRange } from '../../../defaults/formatters';
|
import { formatDecimal, formatPriceRange } from '../../../defaults/formatters';
|
||||||
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
|
||||||
|
import { ModelType } from '../../../enums/ModelType';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
import { TableColumn } from '../../../tables/Column';
|
import { TableColumn } from '../../../tables/Column';
|
||||||
@ -110,7 +117,17 @@ export default function BomPricingPanel({
|
|||||||
title: t`Quantity`,
|
title: t`Quantity`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: false,
|
switchable: false,
|
||||||
render: (record: any) => formatDecimal(record.quantity)
|
render: (record: any) => {
|
||||||
|
let quantity = formatDecimal(record.quantity);
|
||||||
|
let units = record.sub_part_detail?.units;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Group spacing="apart" grow>
|
||||||
|
<Text>{quantity}</Text>
|
||||||
|
{units && <Text size="xs">[{units}]</Text>}
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'unit_price',
|
accessor: 'unit_price',
|
||||||
@ -178,7 +195,9 @@ export default function BomPricingPanel({
|
|||||||
sub_part_detail: true,
|
sub_part_detail: true,
|
||||||
has_pricing: true
|
has_pricing: true
|
||||||
},
|
},
|
||||||
enableSelection: false
|
enableSelection: false,
|
||||||
|
modelType: ModelType.part,
|
||||||
|
modelField: 'sub_part'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{bomPricingData.length > 0 ? (
|
{bomPricingData.length > 0 ? (
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
import { CHART_COLORS } from '../../../components/charts/colors';
|
import { CHART_COLORS } from '../../../components/charts/colors';
|
||||||
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 { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
import { TableColumn } from '../../../tables/Column';
|
import { TableColumn } from '../../../tables/Column';
|
||||||
@ -37,7 +38,7 @@ export default function VariantPricingPanel({
|
|||||||
title: t`Variant Part`,
|
title: t`Variant Part`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: false,
|
switchable: false,
|
||||||
render: (record: any) => PartColumn(record)
|
render: (record: any) => PartColumn(record, true)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'pricing_min',
|
accessor: 'pricing_min',
|
||||||
@ -90,7 +91,8 @@ export default function VariantPricingPanel({
|
|||||||
ancestor: part?.pk,
|
ancestor: part?.pk,
|
||||||
has_pricing: true
|
has_pricing: true
|
||||||
},
|
},
|
||||||
enablePagination: false
|
enablePagination: true,
|
||||||
|
modelType: ModelType.part
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{variantPricingData.length > 0 ? (
|
{variantPricingData.length > 0 ? (
|
||||||
|
@ -16,8 +16,13 @@ import { TableColumn } from './Column';
|
|||||||
import { ProjectCodeHoverCard } from './TableHoverCard';
|
import { ProjectCodeHoverCard } from './TableHoverCard';
|
||||||
|
|
||||||
// Render a Part instance within a table
|
// Render a Part instance within a table
|
||||||
export function PartColumn(part: any) {
|
export function PartColumn(part: any, full_name?: boolean) {
|
||||||
return <Thumbnail src={part?.thumbnail ?? part.image} text={part.name} />;
|
return (
|
||||||
|
<Thumbnail
|
||||||
|
src={part?.thumbnail ?? part.image}
|
||||||
|
text={full_name ? part.full_name : part.name}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BooleanColumn({
|
export function BooleanColumn({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Text } from '@mantine/core';
|
import { Group, Text } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
IconArrowRight,
|
IconArrowRight,
|
||||||
IconCircleCheck,
|
IconCircleCheck,
|
||||||
@ -10,7 +10,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
|
|
||||||
import { YesNoButton } from '../../components/buttons/YesNoButton';
|
import { YesNoButton } from '../../components/buttons/YesNoButton';
|
||||||
import { Thumbnail } from '../../components/images/Thumbnail';
|
import { Thumbnail } from '../../components/images/Thumbnail';
|
||||||
import { formatPriceRange } from '../../defaults/formatters';
|
import { formatDecimal, formatPriceRange } 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';
|
||||||
@ -98,9 +98,19 @@ export function BomTable({
|
|||||||
{
|
{
|
||||||
accessor: 'quantity',
|
accessor: 'quantity',
|
||||||
switchable: false,
|
switchable: false,
|
||||||
sortable: true
|
sortable: true,
|
||||||
// TODO: Custom quantity renderer
|
render: (record: any) => {
|
||||||
// TODO: see bom.js for existing implementation
|
let quantity = formatDecimal(record.quantity);
|
||||||
|
let units = record.sub_part_detail?.units;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Group position="apart" grow>
|
||||||
|
<Text>{quantity}</Text>
|
||||||
|
{record.overage && <Text size="xs">+{record.overage}</Text>}
|
||||||
|
{units && <Text size="xs">{units}</Text>}
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'substitutes',
|
accessor: 'substitutes',
|
||||||
@ -131,12 +141,22 @@ export function BomTable({
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'price_range',
|
accessor: 'price_range',
|
||||||
title: t`Price Range`,
|
title: t`Unit Price`,
|
||||||
|
ordering: 'pricing_max',
|
||||||
sortable: false,
|
sortable: true,
|
||||||
|
switchable: true,
|
||||||
render: (record: any) =>
|
render: (record: any) =>
|
||||||
formatPriceRange(record.pricing_min, record.pricing_max)
|
formatPriceRange(record.pricing_min, record.pricing_max)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessor: 'total_price',
|
||||||
|
title: t`Total Price`,
|
||||||
|
ordering: 'pricing_max_total',
|
||||||
|
sortable: true,
|
||||||
|
switchable: true,
|
||||||
|
render: (record: any) =>
|
||||||
|
formatPriceRange(record.pricing_min_total, record.pricing_max_total)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessor: 'available_stock',
|
accessor: 'available_stock',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
import { Group, Text } from '@mantine/core';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { PartHoverCard } from '../../components/images/Thumbnail';
|
import { PartHoverCard } from '../../components/images/Thumbnail';
|
||||||
|
import { formatDecimal } from '../../defaults/formatters';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
@ -39,8 +41,15 @@ export function UsedInTable({
|
|||||||
{
|
{
|
||||||
accessor: 'quantity',
|
accessor: 'quantity',
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
// TODO: render units if appropriate
|
let quantity = formatDecimal(record.quantity);
|
||||||
return record.quantity;
|
let units = record.sub_part_detail?.units;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Group position="apart" grow>
|
||||||
|
<Text>{quantity}</Text>
|
||||||
|
{units && <Text size="xs">{units}</Text>}
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ReferenceColumn()
|
ReferenceColumn()
|
||||||
|
@ -158,7 +158,8 @@ function partTableColumns(): TableColumn[] {
|
|||||||
{
|
{
|
||||||
accessor: 'price_range',
|
accessor: 'price_range',
|
||||||
title: t`Price Range`,
|
title: t`Price Range`,
|
||||||
sortable: false,
|
sortable: true,
|
||||||
|
ordering: 'pricing_max',
|
||||||
render: (record: any) =>
|
render: (record: any) =>
|
||||||
formatPriceRange(record.pricing_min, record.pricing_max)
|
formatPriceRange(record.pricing_min, record.pricing_max)
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user