mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
Merge branch 'fix/data-refactor-and-ui-adjustment' into 'development'
[FIX/FE] Data Refactor and UI Adjustment (Closing, Biaya, Finance Report, Sales Report, Recording) See merge request mbugroup/lti-web-client!170
This commit is contained in:
@@ -38,9 +38,11 @@ const ExpenseEditPage = () => {
|
|||||||
!isLoadingExpense &&
|
!isLoadingExpense &&
|
||||||
isResponseSuccess(expense) &&
|
isResponseSuccess(expense) &&
|
||||||
expense.data.latest_approval.step_number !== 5 &&
|
expense.data.latest_approval.step_number !== 5 &&
|
||||||
|
expense.data.latest_approval.step_number !== 6 &&
|
||||||
(expense.data.latest_approval.step_number === 1 ||
|
(expense.data.latest_approval.step_number === 1 ||
|
||||||
expense.data.latest_approval.step_number === 2 ||
|
expense.data.latest_approval.step_number === 2 ||
|
||||||
expense.data.latest_approval.step_number === 3);
|
expense.data.latest_approval.step_number === 3 ||
|
||||||
|
expense.data.latest_approval.step_number === 4);
|
||||||
|
|
||||||
if (!isLoadingExpense && !isExpenseCanBeEdited) {
|
if (!isLoadingExpense && !isExpenseCanBeEdited) {
|
||||||
router.back();
|
router.back();
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ const ClosingFinanceTable = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Type',
|
header: 'Jenis',
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
accessorFn: (item) => formatTitleCase(item.type || '-'),
|
accessorFn: (item) => formatTitleCase(item.type || '-'),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -678,12 +678,13 @@ const RecordingTable = () => {
|
|||||||
{
|
{
|
||||||
header: 'Nama Project',
|
header: 'Nama Project',
|
||||||
cell: (props) =>
|
cell: (props) =>
|
||||||
`Project ${props.row.original.project_flock_kandang_id}`,
|
props.row.original.project_flock?.flock_name || '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Kategori',
|
header: 'Kategori',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const category = props.row.original.project_flock_category;
|
const category =
|
||||||
|
props.row.original.project_flock?.project_flock_category;
|
||||||
if (!category) return '-';
|
if (!category) return '-';
|
||||||
const color = category === 'LAYING' ? 'info' : 'warning';
|
const color = category === 'LAYING' ? 'info' : 'warning';
|
||||||
return (
|
return (
|
||||||
@@ -706,7 +707,8 @@ const RecordingTable = () => {
|
|||||||
{
|
{
|
||||||
header: 'Populasi Awal',
|
header: 'Populasi Awal',
|
||||||
cell: (props) =>
|
cell: (props) =>
|
||||||
props.row.original.total_chick_qty?.toLocaleString() || '-',
|
props.row.original.project_flock?.total_chick_qty?.toLocaleString() ||
|
||||||
|
'-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Status Approval',
|
header: 'Status Approval',
|
||||||
|
|||||||
@@ -117,8 +117,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
// ===== PAYLOAD CREATION HELPERS =====
|
// ===== PAYLOAD CREATION HELPERS =====
|
||||||
const createGrowingPayload = useCallback(
|
const createGrowingPayload = useCallback(
|
||||||
(values: RecordingGrowingFormValues) => {
|
(values: RecordingGrowingFormValues) => {
|
||||||
|
const today = new Date().toISOString().split('T')[0];
|
||||||
return {
|
return {
|
||||||
project_flock_kandang_id: values.project_flock_kandang_id,
|
project_flock_kandang_id: values.project_flock_kandang_id,
|
||||||
|
record_date: today,
|
||||||
stocks: (values.stocks ?? []).map((stock) => ({
|
stocks: (values.stocks ?? []).map((stock) => ({
|
||||||
product_warehouse_id: stock.product_warehouse_id,
|
product_warehouse_id: stock.product_warehouse_id,
|
||||||
qty: Number(stock.qty) || 0,
|
qty: Number(stock.qty) || 0,
|
||||||
@@ -134,8 +136,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
const createLayingPayload = useCallback(
|
const createLayingPayload = useCallback(
|
||||||
(values: RecordingLayingFormValues) => {
|
(values: RecordingLayingFormValues) => {
|
||||||
|
const today = new Date().toISOString().split('T')[0];
|
||||||
return {
|
return {
|
||||||
project_flock_kandang_id: values.project_flock_kandang_id,
|
project_flock_kandang_id: values.project_flock_kandang_id,
|
||||||
|
record_date: today,
|
||||||
stocks: (values.stocks ?? []).map((stock) => ({
|
stocks: (values.stocks ?? []).map((stock) => ({
|
||||||
product_warehouse_id: stock.product_warehouse_id,
|
product_warehouse_id: stock.product_warehouse_id,
|
||||||
qty: Number(stock.qty) || 0,
|
qty: Number(stock.qty) || 0,
|
||||||
@@ -252,9 +256,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const projectFlockKandangDetailUrl = useMemo(() => {
|
const projectFlockKandangDetailUrl = useMemo(() => {
|
||||||
if (type === 'add' || !initialValues?.project_flock_kandang_id) return null;
|
if (
|
||||||
return `${ProjectFlockKandangApi.basePath}/${initialValues.project_flock_kandang_id}`;
|
type === 'add' ||
|
||||||
}, [type, initialValues?.project_flock_kandang_id]);
|
!initialValues?.project_flock?.project_flock_kandang_id
|
||||||
|
)
|
||||||
|
return null;
|
||||||
|
return `${ProjectFlockKandangApi.basePath}/${initialValues.project_flock.project_flock_kandang_id}`;
|
||||||
|
}, [type, initialValues?.project_flock?.project_flock_kandang_id]);
|
||||||
|
|
||||||
const { data: projectFlockKandangDetailData } = useSWR(
|
const { data: projectFlockKandangDetailData } = useSWR(
|
||||||
projectFlockKandangDetailUrl,
|
projectFlockKandangDetailUrl,
|
||||||
@@ -404,12 +412,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
}, [approvedProjectFlockKandangsData]);
|
}, [approvedProjectFlockKandangsData]);
|
||||||
|
|
||||||
const isLayingCategory =
|
const isLayingCategory =
|
||||||
initialValues?.project_flock_category === 'LAYING' ||
|
initialValues?.project_flock?.project_flock_category === 'LAYING' ||
|
||||||
projectFlockKandangLookup?.project_flock?.category === 'LAYING' ||
|
projectFlockKandangLookup?.project_flock?.category === 'LAYING' ||
|
||||||
projectFlockKandangDetail?.project_flock?.category === 'LAYING';
|
projectFlockKandangDetail?.project_flock?.category === 'LAYING';
|
||||||
|
|
||||||
const isGrowingCategory =
|
const isGrowingCategory =
|
||||||
initialValues?.project_flock_category === 'GROWING' ||
|
initialValues?.project_flock?.project_flock_category === 'GROWING' ||
|
||||||
projectFlockKandangLookup?.project_flock?.category === 'GROWING' ||
|
projectFlockKandangLookup?.project_flock?.category === 'GROWING' ||
|
||||||
projectFlockKandangDetail?.project_flock?.category === 'GROWING';
|
projectFlockKandangDetail?.project_flock?.category === 'GROWING';
|
||||||
|
|
||||||
@@ -555,7 +563,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
todayRecordings.forEach((recording) => {
|
todayRecordings.forEach((recording) => {
|
||||||
const recordingDate = recording.record_datetime?.split('T')[0];
|
const recordingDate = recording.record_datetime?.split('T')[0];
|
||||||
if (recordingDate === today) {
|
if (recordingDate === today) {
|
||||||
recordedIds.add(recording.project_flock_kandang_id);
|
recordedIds.add(recording.project_flock.project_flock_kandang_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1005,7 +1013,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const hasSameDayRecording = isResponseSuccess(existingRecordings)
|
const hasSameDayRecording = isResponseSuccess(existingRecordings)
|
||||||
? existingRecordings.data?.some(
|
? existingRecordings.data?.some(
|
||||||
(recording: Recording) =>
|
(recording: Recording) =>
|
||||||
recording.project_flock_kandang_id ===
|
recording.project_flock.project_flock_kandang_id ===
|
||||||
projectFlockKandangId &&
|
projectFlockKandangId &&
|
||||||
recording.day === nextDayRecording.next_day
|
recording.day === nextDayRecording.next_day
|
||||||
)
|
)
|
||||||
@@ -1543,13 +1551,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
<Badge
|
<Badge
|
||||||
variant='soft'
|
variant='soft'
|
||||||
color={
|
color={
|
||||||
initialValues.project_flock_category === 'LAYING'
|
initialValues.project_flock
|
||||||
|
?.project_flock_category === 'LAYING'
|
||||||
? 'info'
|
? 'info'
|
||||||
: 'warning'
|
: 'warning'
|
||||||
}
|
}
|
||||||
size='sm'
|
size='sm'
|
||||||
>
|
>
|
||||||
{initialValues.project_flock_category}
|
{initialValues.project_flock?.project_flock_category}
|
||||||
</Badge>
|
</Badge>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -1579,7 +1588,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
{type === 'detail' && initialValues && (
|
{type === 'detail' && initialValues && (
|
||||||
<div
|
<div
|
||||||
className={`grid gap-6 mb-6 grid-cols-1 ${
|
className={`grid gap-6 mb-6 grid-cols-1 ${
|
||||||
initialValues.project_flock_category === 'LAYING'
|
initialValues.project_flock?.project_flock_category === 'LAYING'
|
||||||
? 'xl:grid-cols-3'
|
? 'xl:grid-cols-3'
|
||||||
: 'xl:grid-cols-2'
|
: 'xl:grid-cols-2'
|
||||||
}`}
|
}`}
|
||||||
@@ -1614,8 +1623,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
<td className='text-center py-3 text-gray-600'>
|
||||||
{initialValues.fcr_std && initialValues.fcr_std > 0
|
{initialValues.project_flock?.fcr?.fcr_std &&
|
||||||
? formatNumber(initialValues.fcr_std)
|
initialValues.project_flock?.fcr?.fcr_std > 0
|
||||||
|
? formatNumber(
|
||||||
|
initialValues.project_flock?.fcr?.fcr_std
|
||||||
|
)
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1630,9 +1642,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
<td className='text-center py-3 text-gray-600'>
|
||||||
{initialValues.feed_intake_std &&
|
{initialValues.project_flock?.production_standart
|
||||||
initialValues.feed_intake_std > 0
|
?.feed_intake_std &&
|
||||||
? formatNumber(initialValues.feed_intake_std)
|
initialValues.project_flock?.production_standart
|
||||||
|
?.feed_intake_std > 0
|
||||||
|
? formatNumber(
|
||||||
|
initialValues.project_flock?.production_standart
|
||||||
|
?.feed_intake_std
|
||||||
|
)
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1650,59 +1667,39 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className='p-4'>
|
<div className='p-4'>
|
||||||
<table className='w-full text-sm'>
|
<table className='w-full text-sm'>
|
||||||
<thead>
|
|
||||||
<tr className='border-b border-gray-200'>
|
|
||||||
<th
|
|
||||||
colSpan={2}
|
|
||||||
className='text-center py-2 font-semibold text-gray-600'
|
|
||||||
>
|
|
||||||
DEPLESI KUMULATIF
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr className='border-b border-gray-200'>
|
|
||||||
<th className='text-center py-2 font-semibold text-xs text-gray-500'>
|
|
||||||
Total
|
|
||||||
</th>
|
|
||||||
<th className='text-center py-2 font-semibold text-xs text-gray-500'>
|
|
||||||
(%)
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td className='text-center py-3 border-r border-gray-100'>
|
<td className='py-2 font-medium'>Deplesi Kumulatif</td>
|
||||||
|
<td className='text-right py-2'>
|
||||||
<span className='font-semibold'>
|
<span className='font-semibold'>
|
||||||
{initialValues.total_depletion_qty &&
|
{initialValues.cum_depletion_rate &&
|
||||||
initialValues.total_depletion_qty > 0
|
initialValues.cum_depletion_rate > 0
|
||||||
? formatNumber(initialValues.total_depletion_qty)
|
? `${initialValues.cum_depletion_rate.toFixed(2)}%`
|
||||||
: '-'}
|
: '-'}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
|
||||||
{initialValues.cum_depletion_rate &&
|
|
||||||
initialValues.cum_depletion_rate > 0
|
|
||||||
? initialValues.cum_depletion_rate.toFixed(2)
|
|
||||||
: '-'}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td
|
<td className='py-2 font-medium'>Total Depletion</td>
|
||||||
colSpan={2}
|
<td className='text-right py-2 font-semibold'>
|
||||||
className='text-center py-3 border-r border-gray-200 text-gray-600'
|
{initialValues.total_depletion_qty &&
|
||||||
>
|
initialValues.total_depletion_qty > 0
|
||||||
Total Ayam
|
? formatNumber(initialValues.total_depletion_qty)
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td
|
|
||||||
colSpan={2}
|
|
||||||
className='text-center py-3 font-semibold'
|
|
||||||
>
|
|
||||||
{initialValues.total_chick_qty &&
|
|
||||||
initialValues.total_chick_qty > 0
|
|
||||||
? formatNumber(initialValues.total_chick_qty)
|
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr className='border-t border-gray-200'>
|
||||||
|
<td className='py-2 text-gray-600'>Total Ayam</td>
|
||||||
|
<td className='text-right py-2 font-semibold'>
|
||||||
|
{initialValues.project_flock?.total_chick_qty &&
|
||||||
|
initialValues.project_flock?.total_chick_qty > 0
|
||||||
|
? formatNumber(
|
||||||
|
initialValues.project_flock?.total_chick_qty
|
||||||
|
)
|
||||||
|
: '-'}
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -1712,7 +1709,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
{/* Egg Production Section - Only for LAYING category */}
|
{/* Egg Production Section - Only for LAYING category */}
|
||||||
{type === 'detail' &&
|
{type === 'detail' &&
|
||||||
initialValues &&
|
initialValues &&
|
||||||
initialValues.project_flock_category === 'LAYING' && (
|
initialValues.project_flock?.project_flock_category ===
|
||||||
|
'LAYING' && (
|
||||||
<div className='border border-gray-200 rounded-lg bg-white'>
|
<div className='border border-gray-200 rounded-lg bg-white'>
|
||||||
<div className='px-4 py-3 border-b border-gray-200'>
|
<div className='px-4 py-3 border-b border-gray-200'>
|
||||||
<span className='card-title font-bold text-xl'>
|
<span className='card-title font-bold text-xl'>
|
||||||
@@ -1744,9 +1742,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
<td className='text-center py-3 text-gray-600'>
|
||||||
{initialValues.egg_mass_std &&
|
{initialValues.project_flock?.production_standart
|
||||||
initialValues.egg_mass_std > 0
|
?.egg_mass_std &&
|
||||||
? formatNumber(initialValues.egg_mass_std)
|
initialValues.project_flock?.production_standart
|
||||||
|
?.egg_mass_std > 0
|
||||||
|
? formatNumber(
|
||||||
|
initialValues.project_flock
|
||||||
|
?.production_standart?.egg_mass_std
|
||||||
|
)
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1763,9 +1766,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
<td className='text-center py-3 text-gray-600'>
|
||||||
{initialValues.egg_weight_std &&
|
{initialValues.project_flock?.production_standart
|
||||||
initialValues.egg_weight_std > 0
|
?.egg_weight_std &&
|
||||||
? formatNumber(initialValues.egg_weight_std)
|
initialValues.project_flock?.production_standart
|
||||||
|
?.egg_weight_std > 0
|
||||||
|
? formatNumber(
|
||||||
|
initialValues.project_flock
|
||||||
|
?.production_standart?.egg_weight_std
|
||||||
|
)
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1780,9 +1788,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
<td className='text-center py-3 text-gray-600'>
|
||||||
{initialValues.hen_day_std !== undefined &&
|
{initialValues.project_flock?.production_standart
|
||||||
initialValues.hen_day_std > 0
|
?.hen_day_std !== undefined &&
|
||||||
? `${initialValues.hen_day_std}%`
|
initialValues.project_flock?.production_standart
|
||||||
|
?.hen_day_std > 0
|
||||||
|
? `${initialValues.project_flock?.production_standart?.hen_day_std}%`
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1797,9 +1807,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='text-center py-3 text-gray-600'>
|
<td className='text-center py-3 text-gray-600'>
|
||||||
{initialValues.hen_house_std !== undefined &&
|
{initialValues.project_flock?.production_standart
|
||||||
initialValues.hen_house_std > 0
|
?.hen_house_std !== undefined &&
|
||||||
? `${initialValues.hen_house_std}%`
|
initialValues.project_flock?.production_standart
|
||||||
|
?.hen_house_std > 0
|
||||||
|
? `${initialValues.project_flock?.production_standart?.hen_house_std}%`
|
||||||
: '-'}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const MarketingReportContent = () => {
|
|||||||
const [activeTab, setActiveTab] = useState<string>('daily');
|
const [activeTab, setActiveTab] = useState<string>('daily');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className='w-full max-w-7xl pb-16'>
|
<section className='w-full max-w-full pb-16'>
|
||||||
<Tabs
|
<Tabs
|
||||||
activeTabId={activeTab}
|
activeTabId={activeTab}
|
||||||
onTabChange={setActiveTab}
|
onTabChange={setActiveTab}
|
||||||
|
|||||||
@@ -136,41 +136,132 @@ const pdfStyles = StyleSheet.create({
|
|||||||
backgroundColor: '#F0F0F0',
|
backgroundColor: '#F0F0F0',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
},
|
},
|
||||||
|
badge: {
|
||||||
|
backgroundColor: '#1f74bf',
|
||||||
|
color: '#FFFFFF',
|
||||||
|
padding: 2,
|
||||||
|
borderRadius: 2,
|
||||||
|
fontSize: 7,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
alignSelf: 'center',
|
||||||
|
marginRight: 4,
|
||||||
|
},
|
||||||
|
badgeLunas: {
|
||||||
|
backgroundColor: '#1f74bf',
|
||||||
|
color: '#FFFFFF',
|
||||||
|
},
|
||||||
|
badgeBelumLunas: {
|
||||||
|
backgroundColor: '#F97316',
|
||||||
|
color: '#FFFFFF',
|
||||||
|
},
|
||||||
|
textError: {
|
||||||
|
color: '#DC2626',
|
||||||
|
},
|
||||||
|
parameterBadge: {
|
||||||
|
backgroundColor: '#F5F5F5',
|
||||||
|
color: '#333333',
|
||||||
|
padding: 4,
|
||||||
|
borderRadius: 4,
|
||||||
|
fontSize: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 4,
|
||||||
|
},
|
||||||
|
parameterContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface CustomerPaymentExportPDFParams {
|
interface CustomerPaymentExportPDFParams {
|
||||||
data: CustomerPaymentReport[];
|
data: CustomerPaymentReport[];
|
||||||
|
params?: {
|
||||||
|
customer_name?: string;
|
||||||
|
sales?: string;
|
||||||
|
start_date?: string;
|
||||||
|
end_date?: string;
|
||||||
|
filter_by?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getParameterText = (
|
||||||
|
params?: CustomerPaymentExportPDFParams['params']
|
||||||
|
) => {
|
||||||
|
const paramsText = [];
|
||||||
|
|
||||||
|
if (params?.customer_name) {
|
||||||
|
paramsText.push(`Customer: ${params.customer_name}`);
|
||||||
|
} else {
|
||||||
|
paramsText.push('Semua Customer');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params?.sales) {
|
||||||
|
paramsText.push(`Sales: ${params.sales}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params?.start_date && params?.end_date) {
|
||||||
|
const startDate = formatDate(params.start_date, 'DD MMM YYYY');
|
||||||
|
const endDate = formatDate(params.end_date, 'DD MMM YYYY');
|
||||||
|
paramsText.push(`Periode: ${startDate} - ${endDate}`);
|
||||||
|
} else if (params?.start_date) {
|
||||||
|
const startDate = formatDate(params.start_date, 'DD MMM YYYY');
|
||||||
|
paramsText.push(`Tanggal: ${startDate}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentDate = formatDate(new Date(), 'DD MMM YYYY HH:mm');
|
||||||
|
paramsText.push(`Dicetak: ${currentDate}`);
|
||||||
|
|
||||||
|
return paramsText;
|
||||||
|
};
|
||||||
|
|
||||||
const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
||||||
return (
|
return (
|
||||||
<Document>
|
<Document>
|
||||||
{params.data.map((customerReport, customerIndex) => (
|
{params.data.map((customerReport, customerIndex) => (
|
||||||
<Page
|
<Page
|
||||||
key={customerIndex}
|
key={customerIndex}
|
||||||
size='A4'
|
size='A3'
|
||||||
orientation='landscape'
|
orientation='landscape'
|
||||||
style={pdfStyles.page}
|
style={pdfStyles.page}
|
||||||
>
|
>
|
||||||
{/* Title and Customer Info */}
|
{/* Title and Parameters */}
|
||||||
<View style={pdfStyles.titleSection}>
|
<View style={pdfStyles.titleSection}>
|
||||||
<Text style={pdfStyles.mainTitle}>
|
<Text style={pdfStyles.mainTitle}>
|
||||||
Laporan > Kontrol Pembayaran Customer
|
Laporan > Kontrol Pembayaran Customer
|
||||||
</Text>
|
</Text>
|
||||||
|
<View style={pdfStyles.parameterContainer}>
|
||||||
|
<View style={pdfStyles.parameterBadge}>
|
||||||
|
<Text>
|
||||||
|
Periode:{' '}
|
||||||
|
{params.params?.start_date
|
||||||
|
? formatDate(params.params.start_date, 'DD MMM YYYY')
|
||||||
|
: '-'}{' '}
|
||||||
|
s.d{' '}
|
||||||
|
{params.params?.end_date
|
||||||
|
? formatDate(params.params.end_date, 'DD MMM YYYY')
|
||||||
|
: '-'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={pdfStyles.parameterBadge}>
|
||||||
|
<Text>Filter Tanggal: Tanggal DO</Text>
|
||||||
|
</View>
|
||||||
|
<View style={pdfStyles.parameterBadge}>
|
||||||
|
<Text>
|
||||||
|
Customer: {params.params?.customer_name || 'Semua Customer'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={pdfStyles.parameterBadge}>
|
||||||
|
<Text>
|
||||||
|
Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
<Text style={pdfStyles.supplierTitle}>
|
<Text style={pdfStyles.supplierTitle}>
|
||||||
{customerReport.customer.name}
|
{customerReport.customer.name}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={pdfStyles.supplierInfo}>
|
<Text style={pdfStyles.supplierInfo}>
|
||||||
{customerReport.customer.address || ''}
|
Alamat: {customerReport.customer.address || '-'}
|
||||||
</Text>
|
</Text>
|
||||||
{customerReport.summary && (
|
|
||||||
<Text style={pdfStyles.supplierInfo}>
|
|
||||||
Total Saldo Piutang:{' '}
|
|
||||||
{formatCurrency(
|
|
||||||
customerReport.summary.total_accounts_receivable
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Table */}
|
{/* Table */}
|
||||||
@@ -181,10 +272,10 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
<Text>No</Text>
|
<Text>No</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
||||||
<Text>Tgl DO/Bayar</Text>
|
<Text>Tanggal DO</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
||||||
<Text>Tgl Realisasi</Text>
|
<Text>Tanggal Realisasi</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 0.8 }]}>
|
<View style={[pdfStyles.tableCellHeader, { flex: 0.8 }]}>
|
||||||
<Text>Aging</Text>
|
<Text>Aging</Text>
|
||||||
@@ -193,16 +284,16 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
<Text>Referensi</Text>
|
<Text>Referensi</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.2 }]}>
|
||||||
<Text>No. Polisi</Text>
|
<Text>No Polisi</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
||||||
<Text>Qty</Text>
|
<Text>Qty</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1 }]}>
|
||||||
<Text>Berat (Kg)</Text>
|
<Text>Berat</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
||||||
<Text>AVG</Text>
|
<Text>Rata-Rata</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
<Text>Harga Awal</Text>
|
<Text>Harga Awal</Text>
|
||||||
@@ -214,7 +305,7 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
<Text>Harga Akhir</Text>
|
<Text>Harga Akhir</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 0.8 }]}>
|
||||||
<Text>PPN (%)</Text>
|
<Text>Pajak</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
<Text>Total</Text>
|
<Text>Total</Text>
|
||||||
@@ -223,10 +314,10 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
<Text>Pembayaran</Text>
|
<Text>Pembayaran</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellHeaderRight, { flex: 1.2 }]}>
|
||||||
<Text>Saldo Piutang</Text>
|
<Text>Saldo</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1.5 }]}>
|
<View style={[pdfStyles.tableCellHeader, { flex: 1.5 }]}>
|
||||||
<Text>Ket</Text>
|
<Text>Keterangan</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
|
||||||
<Text>Pengambilan</Text>
|
<Text>Pengambilan</Text>
|
||||||
@@ -301,10 +392,29 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
<Text>{formatCurrency(item.payment)}</Text>
|
<Text>{formatCurrency(item.payment)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>{formatCurrency(item.accounts_receivable)}</Text>
|
<Text style={pdfStyles.textError}>
|
||||||
|
{formatCurrency(item.accounts_receivable)}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
|
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
|
||||||
<Text>{item.notes || '-'}</Text>
|
{item.notes ? (
|
||||||
|
<Text>{item.notes}</Text>
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
pdfStyles.badge,
|
||||||
|
item.accounts_receivable === 0
|
||||||
|
? pdfStyles.badgeLunas
|
||||||
|
: pdfStyles.badgeBelumLunas,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text>
|
||||||
|
{item.accounts_receivable === 0
|
||||||
|
? 'Lunas'
|
||||||
|
: 'Belum Lunas'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
|
||||||
<Text>{item.pickup_info || '-'}</Text>
|
<Text>{item.pickup_info || '-'}</Text>
|
||||||
@@ -378,7 +488,7 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>
|
<Text style={pdfStyles.textError}>
|
||||||
{formatCurrency(
|
{formatCurrency(
|
||||||
customerReport.summary.total_accounts_receivable
|
customerReport.summary.total_accounts_receivable
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useState, useMemo, useCallback } from 'react';
|
|||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
|
import Badge from '@/components/Badge';
|
||||||
import SelectInput, {
|
import SelectInput, {
|
||||||
useSelect,
|
useSelect,
|
||||||
OptionType,
|
OptionType,
|
||||||
@@ -46,7 +47,6 @@ const CustomerPaymentTab = () => {
|
|||||||
const [filterSales, setFilterSales] = useState<OptionType[]>([]);
|
const [filterSales, setFilterSales] = useState<OptionType[]>([]);
|
||||||
const [filterStartDate, setFilterStartDate] = useState('');
|
const [filterStartDate, setFilterStartDate] = useState('');
|
||||||
const [filterEndDate, setFilterEndDate] = useState('');
|
const [filterEndDate, setFilterEndDate] = useState('');
|
||||||
const [filterErrors, setFilterErrors] = useState<Record<string, string>>({});
|
|
||||||
|
|
||||||
const filterModal = useModal();
|
const filterModal = useModal();
|
||||||
|
|
||||||
@@ -68,6 +68,38 @@ const CustomerPaymentTab = () => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getPaymentStatusColor = (notes: string) => {
|
||||||
|
const normalizedValue = notes.toLowerCase();
|
||||||
|
|
||||||
|
if (normalizedValue === 'lunas') {
|
||||||
|
return 'bg-info/10 text-info border-info';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalizedValue.includes('belum')) {
|
||||||
|
return 'bg-warning/10 text-warning border-warning';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'bg-gray-100 text-gray-600 border-gray-300';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPaymentStatusIndicatorColor = (notes: string) => {
|
||||||
|
const normalizedValue = notes.toLowerCase();
|
||||||
|
|
||||||
|
if (normalizedValue === 'lunas') {
|
||||||
|
return 'bg-info';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalizedValue.includes('belum')) {
|
||||||
|
return 'bg-warning';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'bg-gray-400';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPaymentStatusText = (notes: string) => {
|
||||||
|
return notes;
|
||||||
|
};
|
||||||
|
|
||||||
// ===== FILTER HANDLERS =====
|
// ===== FILTER HANDLERS =====
|
||||||
const handleResetFilters = useCallback(() => {
|
const handleResetFilters = useCallback(() => {
|
||||||
setIsSubmitted(false);
|
setIsSubmitted(false);
|
||||||
@@ -75,27 +107,13 @@ const CustomerPaymentTab = () => {
|
|||||||
setFilterSales([]);
|
setFilterSales([]);
|
||||||
setFilterStartDate('');
|
setFilterStartDate('');
|
||||||
setFilterEndDate('');
|
setFilterEndDate('');
|
||||||
setFilterErrors({});
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleApplyFilters = useCallback(() => {
|
const handleApplyFilters = useCallback(() => {
|
||||||
const errors: Record<string, string> = {};
|
setIsSubmitted(true);
|
||||||
|
setCurrentPage(1);
|
||||||
if (!filterStartDate) {
|
filterModal.closeModal();
|
||||||
errors.start_date = 'Tanggal mulai wajib diisi';
|
}, [filterModal]);
|
||||||
}
|
|
||||||
if (!filterEndDate) {
|
|
||||||
errors.end_date = 'Tanggal akhir wajib diisi';
|
|
||||||
}
|
|
||||||
|
|
||||||
setFilterErrors(errors);
|
|
||||||
|
|
||||||
if (Object.keys(errors).length === 0) {
|
|
||||||
setIsSubmitted(true);
|
|
||||||
setCurrentPage(1);
|
|
||||||
filterModal.closeModal();
|
|
||||||
}
|
|
||||||
}, [filterModal, filterStartDate, filterEndDate]);
|
|
||||||
|
|
||||||
// ===== DATA FETCHING =====
|
// ===== DATA FETCHING =====
|
||||||
const { data: customerPayment, isLoading } = useSWR(
|
const { data: customerPayment, isLoading } = useSWR(
|
||||||
@@ -218,7 +236,22 @@ const CustomerPaymentTab = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await generateCustomerPaymentPDF({ data: allDataForExport });
|
await generateCustomerPaymentPDF({
|
||||||
|
data: allDataForExport,
|
||||||
|
params: {
|
||||||
|
customer_name:
|
||||||
|
filterCustomer.length > 0
|
||||||
|
? filterCustomer.map((c) => c.label).join(', ')
|
||||||
|
: undefined,
|
||||||
|
sales:
|
||||||
|
filterSales.length > 0
|
||||||
|
? filterSales.map((s) => s.label).join(', ')
|
||||||
|
: undefined,
|
||||||
|
start_date: filterStartDate || undefined,
|
||||||
|
end_date: filterEndDate || undefined,
|
||||||
|
filter_by: 'do_date',
|
||||||
|
},
|
||||||
|
});
|
||||||
toast.success('PDF berhasil dibuat dan diunduh.');
|
toast.success('PDF berhasil dibuat dan diunduh.');
|
||||||
} catch {
|
} catch {
|
||||||
toast.error('Gagal membuat PDF. Silakan coba lagi.');
|
toast.error('Gagal membuat PDF. Silakan coba lagi.');
|
||||||
@@ -435,7 +468,9 @@ const CustomerPaymentTab = () => {
|
|||||||
accessorKey: 'accounts_receivable',
|
accessorKey: 'accounts_receivable',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.accounts_receivable;
|
const value = props.row.original.accounts_receivable;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return (
|
||||||
|
<div className='text-right text-error'>{formatCurrency(value)}</div>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
<div className='text-right font-semibold text-gray-900'>
|
<div className='text-right font-semibold text-gray-900'>
|
||||||
@@ -449,7 +484,23 @@ const CustomerPaymentTab = () => {
|
|||||||
accessorKey: 'notes',
|
accessorKey: 'notes',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.notes;
|
const value = props.row.original.notes;
|
||||||
return value || '-';
|
|
||||||
|
if (!value) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
statusIndicator={true}
|
||||||
|
variant='soft'
|
||||||
|
className={{
|
||||||
|
badge: `rounded-xl justify-start border border-gray-200 ${getPaymentStatusColor(value)}`,
|
||||||
|
status: getPaymentStatusIndicatorColor(value),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getPaymentStatusText(value)}
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -538,15 +589,9 @@ const CustomerPaymentTab = () => {
|
|||||||
value={filterStartDate}
|
value={filterStartDate}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setFilterStartDate(e.target.value);
|
setFilterStartDate(e.target.value);
|
||||||
setFilterErrors((prev) => ({ ...prev, start_date: '' }));
|
|
||||||
}}
|
}}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
{filterErrors.start_date && (
|
|
||||||
<p className='text-red-500 text-sm mt-1'>
|
|
||||||
{filterErrors.start_date}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -556,15 +601,9 @@ const CustomerPaymentTab = () => {
|
|||||||
value={filterEndDate}
|
value={filterEndDate}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setFilterEndDate(e.target.value);
|
setFilterEndDate(e.target.value);
|
||||||
setFilterErrors((prev) => ({ ...prev, end_date: '' }));
|
|
||||||
}}
|
}}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
{filterErrors.end_date && (
|
|
||||||
<p className='text-red-500 text-sm mt-1'>
|
|
||||||
{filterErrors.end_date}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -659,14 +698,13 @@ const CustomerPaymentTab = () => {
|
|||||||
total_accounts_receivable: 0,
|
total_accounts_receivable: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const totalAccountsReceivable = summary.total_accounts_receivable;
|
|
||||||
const tableColumns = getTableColumns(summary);
|
const tableColumns = getTableColumns(summary);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={customerReport.customer.id}
|
key={customerReport.customer.id}
|
||||||
title={customerReport.customer.name}
|
title={customerReport.customer.name}
|
||||||
subtitle={`${customerReport.customer.address || ''}\nSaldo Piutang: ${formatCurrency(totalAccountsReceivable)}`}
|
subtitle={`${customerReport.customer.address || ''}`}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
variant='bordered'
|
variant='bordered'
|
||||||
collapsible={true}
|
collapsible={true}
|
||||||
|
|||||||
@@ -44,9 +44,7 @@ export class MarketingSaleReportService extends BaseApiService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SaleReportApi = new MarketingSaleReportService(
|
export const SaleReportApi = new MarketingSaleReportService('reports');
|
||||||
'reports/marketings'
|
|
||||||
);
|
|
||||||
|
|
||||||
// export const SaleReportApi = new MarketingSaleReportService(
|
// export const SaleReportApi = new MarketingSaleReportService(
|
||||||
// 'http://localhost:4010/api/reports/marketings'
|
// 'http://localhost:4010/api/reports/marketings'
|
||||||
|
|||||||
+33
-12
@@ -1,34 +1,52 @@
|
|||||||
import { BaseApproval, BaseMetadata, User } from '@/types/api/api-general';
|
import { BaseApproval, BaseMetadata, User } from '@/types/api/api-general';
|
||||||
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
||||||
|
import { Warehouse } from '@/types/api/master-data/warehouse';
|
||||||
|
|
||||||
|
export type ProductionStandard = {
|
||||||
|
id: number;
|
||||||
|
week: number;
|
||||||
|
name: string;
|
||||||
|
hen_day_std: number;
|
||||||
|
hen_house_std: number;
|
||||||
|
feed_intake_std: number;
|
||||||
|
max_depletion_std: number;
|
||||||
|
egg_mass_std: number;
|
||||||
|
egg_weight_std: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FCR = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
fcr_std: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProjectFlock = {
|
||||||
|
project_flock_kandang_id: number;
|
||||||
|
flock_name: string;
|
||||||
|
project_flock_category: 'GROWING' | 'LAYING';
|
||||||
|
period: number;
|
||||||
|
production_standart: ProductionStandard;
|
||||||
|
fcr: FCR;
|
||||||
|
total_chick_qty: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type ProductionMetrics = {
|
export type ProductionMetrics = {
|
||||||
total_depletion_qty: number;
|
total_depletion_qty: number;
|
||||||
cum_depletion_rate: number;
|
cum_depletion_rate: number;
|
||||||
cum_intake: number;
|
cum_intake: number;
|
||||||
fcr_value: number;
|
fcr_value: number;
|
||||||
fcr_std?: number;
|
|
||||||
total_chick_qty: number;
|
|
||||||
hen_day?: number;
|
hen_day?: number;
|
||||||
hen_house?: number;
|
hen_house?: number;
|
||||||
feed_intake?: number;
|
feed_intake?: number;
|
||||||
feed_intake_std?: number;
|
|
||||||
egg_mass?: number;
|
egg_mass?: number;
|
||||||
egg_weight?: number;
|
egg_weight?: number;
|
||||||
hen_day_std?: number;
|
|
||||||
hen_house_std?: number;
|
|
||||||
egg_mass_std?: number;
|
|
||||||
egg_weight_std?: number;
|
|
||||||
daily_gain?: number;
|
|
||||||
avg_daily_gain?: number;
|
|
||||||
cum_depletion?: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BaseRecording = {
|
export type BaseRecording = {
|
||||||
id: number;
|
id: number;
|
||||||
project_flock_kandang_id: number;
|
project_flock: ProjectFlock;
|
||||||
record_datetime: string;
|
record_datetime: string;
|
||||||
day: number;
|
day: number;
|
||||||
project_flock_category?: 'GROWING' | 'LAYING';
|
|
||||||
} & ProductionMetrics;
|
} & ProductionMetrics;
|
||||||
|
|
||||||
export type RecordingDepletion = {
|
export type RecordingDepletion = {
|
||||||
@@ -68,6 +86,8 @@ export type Recording = BaseMetadata &
|
|||||||
BaseRecording & {
|
BaseRecording & {
|
||||||
approval?: BaseApproval;
|
approval?: BaseApproval;
|
||||||
created_user: User;
|
created_user: User;
|
||||||
|
warehouse?: Warehouse;
|
||||||
|
product_category?: 'GROWING' | 'LAYING';
|
||||||
depletions?: RecordingDepletion[];
|
depletions?: RecordingDepletion[];
|
||||||
stocks?: RecordingStock[];
|
stocks?: RecordingStock[];
|
||||||
eggs?: RecordingEgg[];
|
eggs?: RecordingEgg[];
|
||||||
@@ -81,6 +101,7 @@ export type NextDayRecording = {
|
|||||||
|
|
||||||
export type CreateGrowingRecordingPayload = {
|
export type CreateGrowingRecordingPayload = {
|
||||||
project_flock_kandang_id: number;
|
project_flock_kandang_id: number;
|
||||||
|
record_date: string;
|
||||||
stocks?: {
|
stocks?: {
|
||||||
product_warehouse_id: number;
|
product_warehouse_id: number;
|
||||||
qty: number;
|
qty: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user