mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 05:22:02 +00:00
refactor(FE): Add initial balance row and normalize empty values
This commit is contained in:
@@ -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(', ')
|
||||
: '-'
|
||||
: '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user