mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 07:15:44 +00:00
refactor(FE): Add sales/actual price fields and summary
This commit is contained in:
@@ -6,7 +6,11 @@ import Table from '@/components/Table';
|
|||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import Badge from '@/components/Badge';
|
import Badge from '@/components/Badge';
|
||||||
import { formatCurrency, formatNumber, formatDate } from '@/lib/helper';
|
import { formatCurrency, formatNumber, formatDate } from '@/lib/helper';
|
||||||
import { BaseClosingSales, BaseSales } from '@/types/api/closing';
|
import {
|
||||||
|
BaseClosingSales,
|
||||||
|
BaseSales,
|
||||||
|
ClosingSalesSummary,
|
||||||
|
} from '@/types/api/closing';
|
||||||
import { Product } from '@/types/api/master-data/product';
|
import { Product } from '@/types/api/master-data/product';
|
||||||
import { Customer } from '@/types/api/master-data/customer';
|
import { Customer } from '@/types/api/master-data/customer';
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
@@ -24,14 +28,20 @@ const SalesReportTable = ({
|
|||||||
return initialValues?.sales || [];
|
return initialValues?.sales || [];
|
||||||
}, [initialValues]);
|
}, [initialValues]);
|
||||||
|
|
||||||
|
const summary: ClosingSalesSummary | undefined = useMemo(() => {
|
||||||
|
return initialValues?.summary;
|
||||||
|
}, [initialValues]);
|
||||||
|
|
||||||
const totals = useMemo(() => {
|
const totals = useMemo(() => {
|
||||||
if (salesData.length === 0) {
|
if (salesData.length === 0) {
|
||||||
return {
|
return {
|
||||||
totalQuantity: 0,
|
totalQuantity: 0,
|
||||||
totalWeight: 0,
|
totalWeight: 0,
|
||||||
avgWeight: 0,
|
avgWeight: 0,
|
||||||
avgPricePartner: 0,
|
avgSalesPrice: 0,
|
||||||
totalPartner: 0,
|
totalSalesPrice: 0,
|
||||||
|
avgActualPrice: 0,
|
||||||
|
totalActualPrice: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,26 +55,46 @@ const SalesReportTable = ({
|
|||||||
);
|
);
|
||||||
const avgWeight = totalQuantity > 0 ? totalWeight / totalQuantity : 0;
|
const avgWeight = totalQuantity > 0 ? totalWeight / totalQuantity : 0;
|
||||||
|
|
||||||
const validPriceItems = salesData.filter(
|
const totalSalesPrice = salesData.reduce(
|
||||||
(item) => item.price != null && item.price > 0
|
(sum, item) => sum + (item.total_sales_price || 0),
|
||||||
);
|
|
||||||
const avgPricePartner =
|
|
||||||
validPriceItems.length > 0
|
|
||||||
? validPriceItems.reduce((sum, item) => sum + item.price, 0) /
|
|
||||||
validPriceItems.length
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
const totalPartner = salesData.reduce(
|
|
||||||
(sum, item) => sum + (item.total_price || 0),
|
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const validSalesPriceItems = salesData.filter(
|
||||||
|
(item) => item.sales_price != null && item.sales_price > 0
|
||||||
|
);
|
||||||
|
const avgSalesPrice =
|
||||||
|
validSalesPriceItems.length > 0
|
||||||
|
? validSalesPriceItems.reduce(
|
||||||
|
(sum, item) => sum + item.sales_price,
|
||||||
|
0
|
||||||
|
) / validSalesPriceItems.length
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
const totalActualPrice = salesData.reduce(
|
||||||
|
(sum, item) => sum + (item.total_actual_price || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
const validActualPriceItems = salesData.filter(
|
||||||
|
(item) => item.actual_price != null && item.actual_price > 0
|
||||||
|
);
|
||||||
|
const avgActualPrice =
|
||||||
|
validActualPriceItems.length > 0
|
||||||
|
? validActualPriceItems.reduce(
|
||||||
|
(sum, item) => sum + item.actual_price,
|
||||||
|
0
|
||||||
|
) / validActualPriceItems.length
|
||||||
|
: 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalQuantity,
|
totalQuantity,
|
||||||
totalWeight,
|
totalWeight,
|
||||||
avgWeight,
|
avgWeight,
|
||||||
avgPricePartner,
|
avgSalesPrice,
|
||||||
totalPartner,
|
totalSalesPrice,
|
||||||
|
avgActualPrice,
|
||||||
|
totalActualPrice,
|
||||||
};
|
};
|
||||||
}, [salesData]);
|
}, [salesData]);
|
||||||
|
|
||||||
@@ -161,50 +191,68 @@ const SalesReportTable = ({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'price_partner',
|
id: 'sales_price',
|
||||||
accessorKey: 'price',
|
accessorKey: 'sales_price',
|
||||||
header: 'Harga Mitra (Rp)',
|
header: 'Harga Sales (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
<div className='text-right font-semibold text-gray-900'>
|
<div className='text-right font-semibold text-gray-900'>
|
||||||
{formatCurrency(totals.avgPricePartner)}
|
{summary
|
||||||
|
? formatCurrency(summary.avg_sales_price)
|
||||||
|
: formatCurrency(totals.avgSalesPrice)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'total_mitra',
|
id: 'total_sales_price',
|
||||||
accessorKey: 'total_price',
|
accessorKey: 'total_sales_price',
|
||||||
header: 'Total Mitra (Rp)',
|
header: 'Total Sales (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
<div className='text-right font-semibold text-gray-900'>
|
<div className='text-right font-semibold text-gray-900'>
|
||||||
{formatCurrency(totals.totalPartner)}
|
{summary
|
||||||
|
? formatCurrency(summary.total_sales_price)
|
||||||
|
: formatCurrency(totals.totalSalesPrice)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'price_act',
|
id: 'actual_price',
|
||||||
accessorKey: 'price',
|
accessorKey: 'actual_price',
|
||||||
header: 'Harga Act (Rp)',
|
header: 'Harga Act (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
|
footer: () => (
|
||||||
|
<div className='text-right font-semibold text-gray-900'>
|
||||||
|
{summary
|
||||||
|
? formatCurrency(summary.avg_actual_price)
|
||||||
|
: formatCurrency(totals.avgActualPrice)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'total_act',
|
id: 'total_actual_price',
|
||||||
accessorKey: 'total_price',
|
accessorKey: 'total_actual_price',
|
||||||
header: 'Total Act (Rp)',
|
header: 'Total Act (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
|
footer: () => (
|
||||||
|
<div className='text-right font-semibold text-gray-900'>
|
||||||
|
{summary
|
||||||
|
? formatCurrency(summary.total_actual_price)
|
||||||
|
: formatCurrency(totals.totalActualPrice)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'kandang',
|
id: 'kandang',
|
||||||
|
|||||||
Vendored
+12
-26
@@ -23,33 +23,18 @@ export type BaseSales = {
|
|||||||
qty: number;
|
qty: number;
|
||||||
weight: number;
|
weight: number;
|
||||||
avg_weight: number;
|
avg_weight: number;
|
||||||
price: number;
|
sales_price: number;
|
||||||
total_price: number;
|
total_sales_price: number;
|
||||||
|
actual_price: number;
|
||||||
|
total_actual_price: number;
|
||||||
kandang: Kandang;
|
kandang: Kandang;
|
||||||
payment_status: string;
|
};
|
||||||
};
|
|
||||||
|
export type ClosingSalesSummary = {
|
||||||
export type BaseClosingSales = {
|
total_sales_price: number;
|
||||||
project_type: string;
|
avg_sales_price: number;
|
||||||
flock_id: number;
|
total_actual_price: number;
|
||||||
period: number;
|
avg_actual_price: number;
|
||||||
sales: BaseSales[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BaseSales = {
|
|
||||||
id: number;
|
|
||||||
realization_date: string;
|
|
||||||
age: number;
|
|
||||||
do_number: string;
|
|
||||||
product: Product;
|
|
||||||
customer: Customer;
|
|
||||||
qty: number;
|
|
||||||
weight: number;
|
|
||||||
avg_weight: number;
|
|
||||||
price: number;
|
|
||||||
total_price: number;
|
|
||||||
kandang: Kandang;
|
|
||||||
payment_status: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BaseClosingSales = {
|
export type BaseClosingSales = {
|
||||||
@@ -57,6 +42,7 @@ export type BaseClosingSales = {
|
|||||||
flock_id: number;
|
flock_id: number;
|
||||||
period: number;
|
period: number;
|
||||||
sales: BaseSales[];
|
sales: BaseSales[];
|
||||||
|
summary: ClosingSalesSummary;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BaseClosing = {
|
export type BaseClosing = {
|
||||||
|
|||||||
Reference in New Issue
Block a user