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,12 +320,93 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
<View style={[pdfStyles.tableCellHeader, { flex: 1 }]}> <View style={[pdfStyles.tableCellHeader, { flex: 1 }]}>
<Text>Pengambilan</Text> <Text>Pengambilan</Text>
</View> </View>
<View style={[pdfStyles.tableCellHeader, { flex: 1.5 }]}> <View
style={[
pdfStyles.tableCellHeader,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text>Sales</Text> <Text>Sales</Text>
</View> </View>
</View> </View>
{/* Table Body */} {/* Table Body */}
<>
{/* Initial Balance Row */}
<View style={[pdfStyles.tableRow, pdfStyles.tableBorderBottom]}>
<View style={[pdfStyles.tableCellNo, { flex: 0.5 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 1.2 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellCenter, { flex: 0.8 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
<Text></Text>
</View>
<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 }]}>
<Text></Text>
</View>
<View style={[pdfStyles.tableCell, { flex: 1 }]}>
<Text></Text>
</View>
<View
style={[
pdfStyles.tableCell,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text></Text>
</View>
</View>
{/* Data Rows */}
{customerReport.rows.map((item, index) => ( {customerReport.rows.map((item, index) => (
<View <View
key={index} key={index}
@@ -355,7 +436,9 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
</View> </View>
<View style={[pdfStyles.tableCellCenter, { flex: 0.8 }]}> <View style={[pdfStyles.tableCellCenter, { flex: 0.8 }]}>
<Text> <Text>
{item.aging_day ? formatNumber(item.aging_day) : '-'} hari {item.aging_day != null
? `${formatNumber(item.aging_day)} hari`
: '-'}
</Text> </Text>
</View> </View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}> <View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
@@ -364,8 +447,10 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}> <View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
<Text> <Text>
{Array.isArray(item.vehicle_numbers) {Array.isArray(item.vehicle_numbers)
? item.vehicle_numbers.length > 0
? item.vehicle_numbers.join(', ') ? item.vehicle_numbers.join(', ')
: item.vehicle_numbers || '-'} : '-'
: '-'}
</Text> </Text>
</View> </View>
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}> <View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
@@ -415,15 +500,23 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
<View style={[pdfStyles.tableCell, { flex: 1 }]}> <View style={[pdfStyles.tableCell, { flex: 1 }]}>
<Text> <Text>
{Array.isArray(item.pickup_info) {Array.isArray(item.pickup_info)
? item.pickup_info.length > 0
? item.pickup_info.join(', ') ? item.pickup_info.join(', ')
: item.pickup_info || '-'} : '-'
: '-'}
</Text> </Text>
</View> </View>
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}> <View
style={[
pdfStyles.tableCell,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text>{item.sales_person || '-'}</Text> <Text>{item.sales_person || '-'}</Text>
</View> </View>
</View> </View>
))} ))}
</>
{/* Summary Row */} {/* Summary Row */}
{customerReport.summary && ( {customerReport.summary && (
@@ -488,7 +581,12 @@ const createPDFDocument = (params: CustomerPaymentExportPDFParams) => {
<View style={[pdfStyles.tableCell, { flex: 1 }]}> <View style={[pdfStyles.tableCell, { flex: 1 }]}>
<Text></Text> <Text></Text>
</View> </View>
<View style={[pdfStyles.tableCellLast, { flex: 1.5 }]}> <View
style={[
pdfStyles.tableCell,
{ flex: 1.5, borderRightWidth: 0 },
]}
>
<Text></Text> <Text></Text>
</View> </View>
</View> </View>
@@ -44,20 +44,50 @@ export const generateCustomerPaymentExcel = async (
const worksheet = workbook.addWorksheet(customerName.substring(0, 31)); const worksheet = workbook.addWorksheet(customerName.substring(0, 31));
worksheet.columns = columns; 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) => { customerData.forEach((item, index) => {
const row = worksheet.addRow({ const row = worksheet.addRow({
no: index + 1, no: index + 1,
transDate: item.trans_date transDate: item.trans_date
? formatDate(item.trans_date, 'DD MMM YYYY') ? formatDate(item.trans_date, 'DD MMM YYYY')
: '', : '-',
deliveryDate: item.delivery_date deliveryDate: item.delivery_date
? formatDate(item.delivery_date, 'DD MMM YYYY') ? formatDate(item.delivery_date, 'DD MMM YYYY')
: '', : '-',
aging: formatNumber(item.aging_day || 0), aging: item.aging_day != null ? formatNumber(item.aging_day) : '-',
reference: item.reference || '', reference: item.reference || '-',
vehicleNumbers: Array.isArray(item.vehicle_numbers) vehicleNumbers: Array.isArray(item.vehicle_numbers)
? item.vehicle_numbers.length > 0
? item.vehicle_numbers.join(', ') ? item.vehicle_numbers.join(', ')
: '', : '-'
: '-',
qty: formatNumber(item.qty || 0), qty: formatNumber(item.qty || 0),
weight: formatNumber(item.weight || 0), weight: formatNumber(item.weight || 0),
avgWeight: formatNumber(item.average_weight || 0), avgWeight: formatNumber(item.average_weight || 0),
@@ -66,11 +96,13 @@ export const generateCustomerPaymentExcel = async (
totalPrice: formatCurrency(item.total_price || 0), totalPrice: formatCurrency(item.total_price || 0),
paymentAmount: formatCurrency(item.payment_amount || 0), paymentAmount: formatCurrency(item.payment_amount || 0),
accountsReceivable: formatCurrency(item.accounts_receivable || 0), accountsReceivable: formatCurrency(item.accounts_receivable || 0),
status: item.status || '', status: item.status || '-',
pickupInfo: Array.isArray(item.pickup_info) pickupInfo: Array.isArray(item.pickup_info)
? item.pickup_info.length > 0
? item.pickup_info.join(', ') ? item.pickup_info.join(', ')
: '', : '-'
salesPerson: item.sales_person || '', : '-',
salesPerson: item.sales_person || '-',
}); });
const accountsReceivableCell = row.getCell('accountsReceivable'); const accountsReceivableCell = row.getCell('accountsReceivable');
@@ -364,7 +364,11 @@ const CustomerPaymentTab = () => {
enableSorting: false, enableSorting: false,
cell: (props) => { cell: (props) => {
const value = props.row.original.vehicle_numbers; 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, enableSorting: false,
cell: (props) => { cell: (props) => {
const value = props.row.original.pickup_info; const value = props.row.original.pickup_info;
return Array.isArray(value) ? value.join(', ') : value || '-'; return Array.isArray(value)
? value.length > 0
? value.join(', ')
: '-'
: '-';
}, },
}, },
{ {