Export Excel Invoice & Imporve Invoice

This commit is contained in:
ivan-sim
2025-12-18 09:53:01 +07:00
parent 9976e8e438
commit e178682fcf
13 changed files with 622 additions and 80 deletions

View File

@@ -440,7 +440,7 @@ import { DatePicker, MobileDatePicker } from '@mui/x-date-pickers';
setIsLoading(false)
enqueueSnackbar(response.data.message, { variant: 'success' });
setTimeout(() => {
window.location.reload();
navigate('/invoice-payment');
}, 1000);
})
.catch(({ response }) => {
@@ -911,7 +911,11 @@ const handleGetClaimDetails = async () => {
// Hitung Grand Total
const grandTotal = dataLogs.reduce((sum, item) => sum + item.totalBilling, 0);
const grandTotal = dataLogs.reduce(
(sum, item) => sum + Number(item.totalBilling),
0
);
const [fileBukti, setFileBukti] = useState<any>([]);
const removeBuktiFiles = (filesState:any, index:any) => {
setFileBukti(
@@ -976,7 +980,7 @@ const handleGetClaimDetails = async () => {
}
}, [invoicePayment]);
const [payments, setPayments] = useState([{ id: Date.now(), amount: "", existingFiles: [], files: [], paymentNumber: 1 }]);
const [payments, setPayments] = useState([{ id: Date.now(), amount: "", existingFiles: [], files: [], noReference: "", paymentNumber: 1 }]);
const fileInputRefs = useRef({});
useEffect(() => {
@@ -986,6 +990,7 @@ const handleGetClaimDetails = async () => {
amount: fCurrency(parseFloat(payment.amount_paid)),
existingFiles: Array.isArray(payment.files) ? payment.files : [],
files: [],
noReference: payment.no_reference,
paymentNumber: payment.payment_number
}));
setPayments(mappedPayments);
@@ -995,7 +1000,7 @@ const handleGetClaimDetails = async () => {
const handleAddPayment = () => {
const newId = Date.now();
setPayments([...payments, { id: newId, amount: "", existingFiles: [], files: [], paymentNumber: payments.length + 1 }]);
setPayments([...payments, { id: newId, amount: "", existingFiles: [], files: [], noReference: "", paymentNumber: payments.length + 1 }]);
fileInputRefs.current[newId] = null;
};
@@ -1005,6 +1010,12 @@ const handleGetClaimDetails = async () => {
setPayments(updatedPayments);
};
const handleReferenceChange = (index, value) => {
const updatedPayments = [...payments];
updatedPayments[index].noReference = value;
setPayments(updatedPayments);
};
const handleFileChange = (index, event) => {
const newFiles = Array.from(event.target.files);
const updatedPayments = [...payments];
@@ -1029,9 +1040,14 @@ const handleGetClaimDetails = async () => {
};
const totalAmount = payments.reduce((sum, payment) => {
const num = parseFloat(payment.amount.replace(/[^\d]/g, "")) || 0;
const num =
parseFloat(
(payment.amount ?? '0').toString().replace(/[^\d]/g, '')
) || 0;
return sum + num;
}, 0);
}, 0);
return (
@@ -1066,7 +1082,7 @@ const handleGetClaimDetails = async () => {
<Stack direction="row" spacing={2} width="100%">
<Stack spacing={2} sx={{ width: '50%' }}>
<Typography variant="subtitle1">Nomor Invoice *</Typography>
<Typography variant="subtitle1">Nomor Invoice <span style={{color: 'red'}}>*</span></Typography>
<TextField
id="nomor_invoice"
variant="outlined"
@@ -1191,7 +1207,7 @@ const handleGetClaimDetails = async () => {
{/* Input Jumlah Bayar */}
<Stack direction="row" spacing={2} width="100%">
<Stack spacing={2} sx={{ width: "50%" }}>
<Stack spacing={2} sx={{ width: "35%" }}>
<Typography variant="subtitle1">Nominal Pembayaran</Typography>
<TextField
variant="outlined"
@@ -1202,7 +1218,7 @@ const handleGetClaimDetails = async () => {
</Stack>
{/* Input File Bukti */}
<Stack spacing={2} sx={{ width: "50%" }}>
<Stack spacing={2} sx={{ width: "35%" }}>
<Typography variant="subtitle1">Upload Bukti Pembayaran</Typography>
<Stack>
<Stack divider={<Divider orientation="horizontal" flexItem />} spacing={1}>
@@ -1262,6 +1278,15 @@ const handleGetClaimDetails = async () => {
/>
</Stack>
</Stack>
<Stack spacing={2} sx={{ width: "30%" }}>
<Typography variant="subtitle1">No. Referensi</Typography>
<TextField
variant="outlined"
placeholder="Nomor Referensi"
value={payment.noReference}
onChange={(e) => handleReferenceChange(index, e.target.value)}
/>
</Stack>
</Stack>
</Stack>
))}

View File

@@ -268,13 +268,13 @@ export default function Detail() {
{/* Input Jumlah Bayar */}
<Stack direction="row" spacing={2} width="100%">
<Stack spacing={2} sx={{ width: "50%" }}>
<Stack spacing={2} sx={{ width: "35%" }}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Nominal Pembayaran</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{fCurrency(parseFloat(file.amount_paid))}</Typography>
</Stack>
{/* Input File Bukti */}
<Stack spacing={2} sx={{ width: "50%" }}>
<Stack spacing={2} sx={{ width: "35%" }}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Bukti Pembayaran</Typography>
<Stack>
<Stack divider={<Divider orientation="horizontal" flexItem />} spacing={1}>
@@ -292,6 +292,10 @@ export default function Detail() {
</Stack>
</Stack>
</Stack>
<Stack spacing={2} sx={{ width: "30%" }}>
<Typography variant='subtitle2' sx={style1} gutterBottom>No. Reference</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{file.no_reference}</Typography>
</Stack>
</Stack>
</Stack>
))}

View File

@@ -146,35 +146,60 @@ import { ClearOutlined, LoopOutlined } from "@mui/icons-material";
var filter = Object.fromEntries([...searchParams.entries()]);
setIsLoading(true)
await axios
.get('/invoice-payment/export',{
params: {
search: searchText,
start_date: formattedDate ? formattedDate : null,
end_date:formattedDate1,
provider: dataProvider,
status: dataStatus,
order: order,
orderBy: orderBy,
page: perPage,
}
})
.then((res) => {
enqueueSnackbar('Data berhasil di Export', {
variant: 'success',
anchorOrigin: { horizontal: 'right', vertical: 'top' },
});
setIsLoading(false)
document.location.href = res.data.data.file_url;
})
.catch((err) =>
enqueueSnackbar('Data Gagal di Export', {
variant: 'error',
anchorOrigin: { horizontal: 'right', vertical: 'top' },
})
const res = await axios.get('/invoice-payment/export', {
params: {
// search: searchText,
start_date: formattedDate ? formattedDate : null,
end_date: formattedDate1,
provider: dataProvider,
status: dataStatus,
order: order,
orderBy: orderBy,
},
responseType: 'blob',
});
);
const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'Report-Vale-Payment.xlsx');
document.body.appendChild(link);
link.click();
setIsLoading(false);
// await axios
// .get('/invoice-payment/export',{
// params: {
// search: searchText,
// start_date: formattedDate ? formattedDate : null,
// end_date:formattedDate1,
// provider: dataProvider,
// status: dataStatus,
// order: order,
// orderBy: orderBy,
// page: perPage,
// }
// })
// .then((res) => {
// enqueueSnackbar('Data berhasil di Export', {
// variant: 'success',
// anchorOrigin: { horizontal: 'right', vertical: 'top' },
// });
// setIsLoading(false)
// document.location.href = res.data.data.file_url;
// })
// .catch((err) =>
// enqueueSnackbar('Data Gagal di Export', {
// variant: 'error',
// anchorOrigin: { horizontal: 'right', vertical: 'top' },
// })
// );
};