diff --git a/src/app/api/invoices/index.ts b/src/app/api/invoices/index.ts index 4b00adb..8d68557 100644 --- a/src/app/api/invoices/index.ts +++ b/src/app/api/invoices/index.ts @@ -142,7 +142,7 @@ export const fetchIssuedInvoices = cache(async () => { }); export const fetchReceivedInvoices = cache(async () => { - return serverFetchJson(`${BASE_API_URL}/invoices/v2/allInvoices/received`, { + return serverFetchJson(`${BASE_API_URL}/invoices/v2/allInvoices/paid`, { next: { tags: ["invoices"] }, }); }); \ No newline at end of file diff --git a/src/components/CompanyHoliday/CompanyHoliday.tsx b/src/components/CompanyHoliday/CompanyHoliday.tsx index 521b172..cdb5ed3 100644 --- a/src/components/CompanyHoliday/CompanyHoliday.tsx +++ b/src/components/CompanyHoliday/CompanyHoliday.tsx @@ -146,7 +146,7 @@ const CompanyHoliday: React.FC = ({ holidays }) => { window.location.reload() setOpen(false); setIsEdit(false); - }, t, {}) + }, t) } catch (e) { console.log(e); setServerError(t("An error has occurred. Please try again later.")); diff --git a/src/components/CustomerSave/CustomerSave.tsx b/src/components/CustomerSave/CustomerSave.tsx index 5673956..acb4ecf 100644 --- a/src/components/CustomerSave/CustomerSave.tsx +++ b/src/components/CustomerSave/CustomerSave.tsx @@ -212,7 +212,7 @@ const CustomerSave: React.FC = ({ return false }) } - }, t, {}) + }, t) } catch (e) { console.log(e) setServerError(t("An error has occurred. Please try again later.")); diff --git a/src/components/InvoiceSearch/InvoiceSearch.tsx b/src/components/InvoiceSearch/InvoiceSearch.tsx index adf1153..6d2a244 100644 --- a/src/components/InvoiceSearch/InvoiceSearch.tsx +++ b/src/components/InvoiceSearch/InvoiceSearch.tsx @@ -55,6 +55,14 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { setFilteredIssuedInvoices(issuedInvoice); }, [issuedInvoice]); + function concatListOfObject(obj: any[]): string { + return obj.map(obj => `Cannot find "${obj.paymentMilestone}" in ${obj.invoiceNo}`).join(", ") + } + + function concatListOfObject2(obj: any[]): string { + return obj.map(obj => `"${obj.projectCode}" does not match with ${obj.invoicesNo}`).join(", ") + } + const handleImportClick = useCallback(async (event:any) => { // console.log(event) try { @@ -99,7 +107,20 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { } else if (response.invoiceList.length >= 1){ errorDialogWithContent(t("Import Fail"), - t(`Please check the corresponding Invoice No.
`)+ `${response.invoiceList.join(", ")}`, t) + t(`Please check the corresponding Invoice No. The invoice is imported.
`)+ `${response.invoiceList.join(", ")}`, t) + .then(() => { + window.location.reload() + }) + } + else if (response.duplicateItem.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`Please check the corresponding Invoice No. The below invoice has duplicated number.
`)+ `${response.duplicateItem.join(", ")}`, t) + .then(() => { + window.location.reload() + }) + }else if (response.paymentMilestones.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`The payment milestone does not match with records. Please check the corresponding Invoice No.
`)+ `${concatListOfObject(response.paymentMilestones)}`, t) .then(() => { window.location.reload() }) @@ -112,7 +133,7 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { } }, []); - const handleExportClick = useCallback(async (event:any) => { + const handleRecImportClick = useCallback(async (event:any) => { try { const file = event.target.files[0]; @@ -131,7 +152,48 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { formData.append('multipartFileList', file); const response = await importReceivedInovice(formData) - + console.log(response) + + if (response.status) { + successDialog(t("Import Success"), t).then(() => { + window.location.reload() + }) + }else{ + if (response.emptyRowList.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`Please fill the mandatory field at Row
${response.emptyRowList.join(", ")}`), t) + .then(() => { + window.location.reload() + }) + } + else if (response.projectList.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`Please check the corresponding project code
${response.projectList.join(", ")}`), t) + .then(() => { + // window.location.reload() + }) + } + else if (response.invoiceList.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`Please check the corresponding Invoice No. The invoice has not yet issued.
`)+ `${response.invoiceList.join(", ")}`, t) + .then(() => { + window.location.reload() + }) + } + else if (response.duplicateItem.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`Please check the corresponding Invoice No. The below invoice has duplicated number.
`)+ `${response.duplicateItem.join(", ")}`, t) + .then(() => { + window.location.reload() + }) + }else if (response.paymentMilestones.length >= 1){ + errorDialogWithContent(t("Import Fail"), + t(`The payment milestone does not match with records. Please check the corresponding Invoice No.
`)+ `${concatListOfObject2(response.paymentMilestones)}`, t) + .then(() => { + window.location.reload() + }) + } + } }catch(error){ console.log(error) } @@ -151,6 +213,18 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { [t], ); + const columns2 = useMemo[]>( + () => [ + { name: "invoiceNo", label: t("Invoice No") }, + { name: "projectCode", label: t("Project Code") }, + { name: "projectName", label: t("Project Name") }, + { name: "team", label: t("Team") }, + { name: "receiptDate", label: t("Receipt Date") }, + { name: "receivedAmount", label: t("Amount (HKD)") }, + ], + [t], + ); + function isDateInRange(dateToCheck: string, startDate: string, endDate: string): boolean { if (!startDate || !endDate) { @@ -197,7 +271,7 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { type='file' accept='.xlsx, .csv' hidden - onChange={(event) => {handleExportClick(event)}} + onChange={(event) => {handleRecImportClick(event)}} /> {t("Import Invoice Amount Receive Summary")} @@ -228,10 +302,10 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { criteria={searchCriteria2} onSearch={(query) => { console.log(query) - setFilteredIssuedInvoices( - issuedInvoice.filter( + setFilteredReceivedInvoices( + receivedInvoice.filter( (s) => - (isDateInRange(s.invoiceDate, query.receiptDate ?? undefined, query.receiptDateTo ?? undefined)) || + (isDateInRange(s.receiptDate, query.receiptDate ?? undefined, query.receiptDateTo ?? undefined)) || (s.invoiceNo === query.invoiceNo) || (s.projectCode === query.projectCode) ), @@ -253,7 +327,10 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { } { tabIndex == 1 && -

Todo

+ + items={filteredReceivedInvoices} + columns={columns2} + /> } diff --git a/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx b/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx index 7a4cfcf..8680599 100644 --- a/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx +++ b/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx @@ -17,7 +17,7 @@ interface SubComponents { const InvoiceSearchWrapper: React.FC & SubComponents = async () => { const issuedInvoices = await fetchIssuedInvoices() - // const receivedInvoices = await fetchReceivedInvoices() + const receivedInvoices = await fetchReceivedInvoices() const convertedIssedInvoices = issuedInvoices.map((invoice)=>{ return{ @@ -33,10 +33,21 @@ const InvoiceSearchWrapper: React.FC & SubComponents = async () => { } }) + const convertedReceivedInvoices = receivedInvoices.map((invoice)=>{ + return{ + id: invoice.id, + invoiceNo: invoice.invoiceNo, + projectCode: invoice.projectCode, + projectName: invoice.projectName, + team: invoice.team, + receiptDate: convertDateArrayToString(invoice.receiptDate, INPUT_DATE_FORMAT, false)!!, + receivedAmount: moneyFormatter.format(invoice.receivedAmount) + } + }) return };