refactor(FE): Add initial balance row and normalize empty values

This commit is contained in:
rstubryan
2026-01-23 10:34:53 +07:00
parent c012f39a38
commit a82860cb68
3 changed files with 216 additions and 78 deletions
@@ -320,110 +320,203 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
<Text>Pengambilan</Text>
</View>
<View style={[pdfStyles.tableCellHeader, { flex: 1.5 }]}>
<View
style={[
pdfStyles.tableCellHeader,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text>Sales</Text>
</View>
</View>
{/* Table Body */}
{customerReport.rows.map((item, index) => (
<View
key={index}
style={[
pdfStyles.tableRow,
index < customerReport.rows.length - 1
? pdfStyles.tableBorderBottom
: {},
]}
>
<>
{/* Initial Balance Row */}
<View style={[pdfStyles.tableRow, pdfStyles.tableBorderBottom]}>
<View style={[pdfStyles.tableCellNo, { flex: 0.5 }]}>
<Text>{index + 1}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
<Text>
{item.trans_date
? formatDate(item.trans_date, 'DD MMM YY')
: '-'}
</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
<Text>
{item.delivery_date
? formatDate(item.delivery_date, 'DD MMM YY')
: '-'}
</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 0.8 }]}>
<Text>
{item.aging_day ? formatNumber(item.aging_day) : '-'} hari
</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
<Text>{item.reference || '-'}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
<Text>
{Array.isArray(item.vehicle_numbers)
? item.vehicle_numbers.join(', ')
: item.vehicle_numbers || '-'}
</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
<Text>{formatNumber(item.qty)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
<Text>{formatNumber(item.weight)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
<Text>{formatNumber(item.average_weight)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.unit_price)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.final_price)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.total_price)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.payment_amount)}</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text style={pdfStyles.textError}>
{formatCurrency(item.accounts_receivable)}
<View
style={[
pdfStyles.tableCellRight,
{
flex: 1.2,
color:
typeof customerReport.initial_balance === 'number' &&
customerReport.initial_balance < 0
? 'red'
: 'black',
},
]}
>
<Text>
{formatCurrency(customerReport.initial_balance || 0)}
</Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
{item.status ? (
<View
style={[
pdfStyles.badge,
item.status === 'LUNAS'
? pdfStyles.badgeLunas
: pdfStyles.badgeBelumLunas,
]}
>
<Text>
{item.status === 'LUNAS' ? 'Lunas' : 'Belum Lunas'}
</Text>
</View>
) : (
<Text>-</Text>
)}
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
<Text>
{Array.isArray(item.pickup_info)
? item.pickup_info.join(', ')
: item.pickup_info || '-'}
</Text>
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
<Text>{item.sales_person || '-'}</Text>
<View
style={[
pdfStyles.tableCell,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text></Text>
</View>
</View>
))}
{/* Data Rows */}
{customerReport.rows.map((item, index) => (
<View
key={index}
style={[
pdfStyles.tableRow,
index < customerReport.rows.length - 1
? pdfStyles.tableBorderBottom
: {},
]}
>
<View style={[pdfStyles.tableCellNo, { flex: 0.5 }]}>
<Text>{index + 1}</Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
<Text>
{item.trans_date
? formatDate(item.trans_date, 'DD MMM YY')
: '-'}
</Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
<Text>
{item.delivery_date
? formatDate(item.delivery_date, 'DD MMM YY')
: '-'}
</Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 0.8 }]}>
<Text>
{item.aging_day != null
? `${formatNumber(item.aging_day)} hari`
: '-'}
</Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
<Text>{item.reference || '-'}</Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
<Text>
{Array.isArray(item.vehicle_numbers)
? item.vehicle_numbers.length > 0
? item.vehicle_numbers.join(', ')
: '-'
: '-'}
</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
<Text>{formatNumber(item.qty)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
<Text>{formatNumber(item.weight)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
<Text>{formatNumber(item.average_weight)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.unit_price)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.final_price)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.total_price)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text>{formatCurrency(item.payment_amount)}</Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text style={pdfStyles.textError}>
{formatCurrency(item.accounts_receivable)}
</Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
{item.status ? (
<View
style={[
pdfStyles.badge,
item.status === 'LUNAS'
? pdfStyles.badgeLunas
: pdfStyles.badgeBelumLunas,
]}
>
<Text>
{item.status === 'LUNAS' ? 'Lunas' : 'Belum Lunas'}
</Text>
</View>
) : (
<Text>-</Text>
)}
</View>
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
<Text>
{Array.isArray(item.pickup_info)
? item.pickup_info.length > 0
? item.pickup_info.join(', ')
: '-'
: '-'}
</Text>
</View>
<View
style={[
pdfStyles.tableCell,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text>{item.sales_person || '-'}</Text>
</View>
</View>
))}
</>
{/* Summary Row */}
{customerReport.summary && (
@@ -488,7 +581,12 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellLast, { flex: 1.5 }]}>
<View
style={[
pdfStyles.tableCell,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text></Text>
</View>
</View>
@@ -44,20 +44,50 @@ export const generateCustomerPaymentExcel = async (
const worksheet = workbook.addWorksheet(customerName.substring(0, 31));
worksheet.columns = columns;
const initialRow = worksheet.addRow({
no: '',
transDate: '',
deliveryDate: '',
aging: '',
reference: '',
vehicleNumbers: '',
qty: '',
weight: '',
avgWeight: '',
unitPrice: '',
finalPrice: '',
totalPrice: '',
paymentAmount: '',
accountsReceivable: formatCurrency(customerReport.initial_balance || 0),
status: '',
pickupInfo: '',
salesPerson: '',
});
const initialBalanceCell = initialRow.getCell('accountsReceivable');
if (
typeof customerReport.initial_balance === 'number' &&
customerReport.initial_balance < 0
) {
initialBalanceCell.font = { color: { argb: 'FFFF0000' } };
}
customerData.forEach((item, index) => {
const row = worksheet.addRow({
no: index + 1,
transDate: item.trans_date
? formatDate(item.trans_date, 'DD MMM YYYY')
: '',
: '-',
deliveryDate: item.delivery_date
? formatDate(item.delivery_date, 'DD MMM YYYY')
: '',
aging: formatNumber(item.aging_day || 0),
reference: item.reference || '',
: '-',
aging: item.aging_day != null ? formatNumber(item.aging_day) : '-',
reference: item.reference || '-',
vehicleNumbers: Array.isArray(item.vehicle_numbers)
? item.vehicle_numbers.join(', ')
: '',
? item.vehicle_numbers.length > 0
? item.vehicle_numbers.join(', ')
: '-'
: '-',
qty: formatNumber(item.qty || 0),
weight: formatNumber(item.weight || 0),
avgWeight: formatNumber(item.average_weight || 0),
@@ -66,11 +96,13 @@ export const generateCustomerPaymentExcel = async (
totalPrice: formatCurrency(item.total_price || 0),
paymentAmount: formatCurrency(item.payment_amount || 0),
accountsReceivable: formatCurrency(item.accounts_receivable || 0),
status: item.status || '',
status: item.status || '-',
pickupInfo: Array.isArray(item.pickup_info)
? item.pickup_info.join(', ')
: '',
salesPerson: item.sales_person || '',
? item.pickup_info.length > 0
? item.pickup_info.join(', ')
: '-'
: '-',
salesPerson: item.sales_person || '-',
});
const accountsReceivableCell = row.getCell('accountsReceivable');
@@ -364,7 +364,11 @@ const CustomerPaymentTab = () => {
enableSorting: false,
cell: (props) => {
const value = props.row.original.vehicle_numbers;
return Array.isArray(value) ? value.join(', ') : value || '-';
return Array.isArray(value)
? value.length > 0
? value.join(', ')
: '-'
: '-';
},
},
{
@@ -528,7 +532,11 @@ const CustomerPaymentTab = () => {
enableSorting: false,
cell: (props) => {
const value = props.row.original.pickup_info;
return Array.isArray(value) ? value.join(', ') : value || '-';
return Array.isArray(value)
? value.length > 0
? value.join(', ')
: '-'
: '-';
},
},
{