From 4864efb9f55a9bea5c85f2febf17d306b3edc732 Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Fri, 20 Sep 2024 15:47:07 +0800 Subject: [PATCH] 1. Update Financial Summary, (Total Cum Expenditure = manhour expenditure + porject expense) 2. Update project expense, align with invoice (add team search, add expense No, and update team to full name code - name) --- src/app/api/projectExpenses/index.ts | 1 + .../ExpenseSearch/CreateExpenseModal.tsx | 12 ++- .../ExpenseSearch/ExpenseSearch.tsx | 20 ++--- .../ExpenseSearch/ExpenseSearchWrapper.tsx | 3 +- .../ProjectFinancialCard.tsx | 21 +++++ .../ProjectFinancialSummary.tsx | 78 +++++++++++++++++-- 6 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/app/api/projectExpenses/index.ts b/src/app/api/projectExpenses/index.ts index 70eaead..805af7b 100644 --- a/src/app/api/projectExpenses/index.ts +++ b/src/app/api/projectExpenses/index.ts @@ -15,6 +15,7 @@ export type ProjectExpensesResult = { issueDate: number[] receiptDate: number[] remarks?: string + team: string } export type ProjectExpensesResultFormatted = Omit & { diff --git a/src/components/ExpenseSearch/CreateExpenseModal.tsx b/src/components/ExpenseSearch/CreateExpenseModal.tsx index 51bfcf2..e864d3a 100644 --- a/src/components/ExpenseSearch/CreateExpenseModal.tsx +++ b/src/components/ExpenseSearch/CreateExpenseModal.tsx @@ -23,6 +23,7 @@ import dayjs from "dayjs"; import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; import { submitDialog, successDialog } from "../Swal/CustomAlerts"; import { useRouter } from 'next/navigation'; +import { ProjectExpensesResultFormatted } from "@/app/api/projectExpenses"; interface Props { isOpen: boolean; @@ -41,9 +42,12 @@ const modalSx: SxProps = { bgcolor: "background.paper", }; + + type postData = { - data: PostExpenseData[]; -}; + data: (PostExpenseData & { _error: any })[]; +} + const CreateExpenseModal: React.FC = ({ isOpen, onClose, projects }) => { const { t } = useTranslation(); const formProps = useForm(); @@ -51,6 +55,10 @@ const CreateExpenseModal: React.FC = ({ isOpen, onClose, projects }) => { const onSubmit = useCallback>((data) => { const _data = data.data; + // console.log(_data.some(data => data._error)) + if(_data.some(data => data._error)){ + return + } try { const postData: PostExpenseData[] = _data.map((item) => { return { diff --git a/src/components/ExpenseSearch/ExpenseSearch.tsx b/src/components/ExpenseSearch/ExpenseSearch.tsx index 69e08d5..8191a63 100644 --- a/src/components/ExpenseSearch/ExpenseSearch.tsx +++ b/src/components/ExpenseSearch/ExpenseSearch.tsx @@ -76,12 +76,12 @@ const ExpenseSearch: React.FC = ({ expenses, projects }) => { // { label: t("Expense No"), paramName: "ExpenseNo", type: "text" }, { label: t("Project Code"), paramName: "projectCode", type: "text" }, { label: t("Project Name"), paramName: "projectName", type: "text" }, - // { - // label: t("Team"), - // paramName: "team", - // type: "select", - // options: uniq(expenses.map((expenses) => expenses.teamCode)), - // }, + { + label: t("Team"), + paramName: "team", + type: "select", + options: uniq(expenses.map((expenses) => `${expenses.teamCode} - ${expenses.teamName}`)), + }, ], [] ); @@ -97,17 +97,18 @@ const ExpenseSearch: React.FC = ({ expenses, projects }) => { buttonIcon: , // disabled: !abilities.includes(MAINTAIN_PROJECT), }, + { name: "expenseNo", label: t("Expense No.")}, { name: "projectCode", label: t("Project Code") }, { name: "projectName", label: t("Project Name") }, { name: "amount", label: t("Amount (HKD)"), type: 'money', needTranslation: true}, - { name: "teamCode", label: t("Team") }, + { name: "team", label: t("Team") }, { name: "issueDate", label: t("Issue Date") }, { name: "remarks", label: t("Remarks")} ], [t] ); const onReset = useCallback(() => { - // setFilteredExpenses(); + setFilteredExpenses(expenses); }, []); /** @@ -287,7 +288,8 @@ const ExpenseSearch: React.FC = ({ expenses, projects }) => { expenses.filter( (e) => e.projectCode.toLowerCase().includes(query.projectCode.toLowerCase()) && - e.projectName.toLowerCase().includes(query.projectName.toLowerCase()) + e.projectName.toLowerCase().includes(query.projectName.toLowerCase()) && + (query.team === "All" || query.team.toLowerCase().includes(e.team.toLowerCase())) ), ); }} diff --git a/src/components/ExpenseSearch/ExpenseSearchWrapper.tsx b/src/components/ExpenseSearch/ExpenseSearchWrapper.tsx index 79236b4..126afea 100644 --- a/src/components/ExpenseSearch/ExpenseSearchWrapper.tsx +++ b/src/components/ExpenseSearch/ExpenseSearchWrapper.tsx @@ -43,7 +43,8 @@ const ExpenseSearchWrapper: React.FC & SubComponents = async () => { ...e, issuedDate: e.issueDate, issueDate: formattedIssueDate, - receiptDate: formattedReceiptDate + receiptDate: formattedReceiptDate, + team: `${e.teamCode} - ${e.teamName}` }) }) return = ({ TotalFees, TotalBudget, TotalCumulative, + TotalProjectExpense, TotalInvoicedAmount, TotalUnInvoicedAmount, TotalReceivedAmount, @@ -138,10 +140,29 @@ const ProjectFinancialCard: React.FC = ({
{"(d) " + t("Total Cumulative Expenditure")}
+
+ {(TotalCumulative + TotalProjectExpense).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +
+
+
+
{"(d) = (d1) + (d2)"}
+
+
+
+
+ {"(d1) " + t("Manpower Expenses")} +
{TotalCumulative.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}

+
+ {"(d2) " + t("Project Expenses")} +
+
+ {TotalProjectExpense.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} +
+
{"(e) " + t("Total Invoiced Amount")}
diff --git a/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx b/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx index 78b834d..1d057dd 100644 --- a/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx +++ b/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx @@ -59,6 +59,7 @@ const ProjectFinancialSummary: React.FC = () => { const fetchData = async () => { const financialSummaryCard = await fetchFinancialSummaryCard(); + console.log(financialSummaryCard) setProjectFinancialData(financialSummaryCard) } const fetchTableData = async (teamId?:any) => { @@ -231,14 +232,38 @@ const ProjectFinancialSummary: React.FC = () => { }, }, { - id: 'cumulativeExpenditure', - field: 'cumulativeExpenditure', + id: 'totalExpenditure', + field: 'totalExpenditure', headerName: t("Total Cumulative Expenditure")+t("HKD"), minWidth:280, type: "number", renderCell: (params:any) => { return ( - ${params.row.cumulativeExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + ${(params.row.totalExpenditure).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + ) + }, + }, + { + id: 'manhoursExpenditure', + field: 'manhoursExpenditure', + headerName: t("Manpower Expenses")+t("HKD"), + minWidth:280, + type: "number", + renderCell: (params:any) => { + return ( + ${params.row.manhoursExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + ) + }, + }, + { + id: 'projectExpense', + field: 'projectExpense', + headerName: t("Project Expense")+t("HKD"), + minWidth:280, + type: "number", + renderCell: (params:any) => { + return ( + ${(params.row.projectExpense ?? 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ) }, }, @@ -453,14 +478,38 @@ const columns2 = [ }, }, { - id: 'totalCumulativeExpenditure', - field: 'totalCumulativeExpenditure', + id: 'totalExpenditure', + field: 'totalExpenditure', headerName: t("Total Cumulative Expenditure")+t("HKD"), minWidth:250, type: "number", renderCell: (params:any) => { return ( - ${params.row.cumulativeExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + ${(params.row.totalExpenditure).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + ) + }, + }, + { + id: 'manhoursExpenditure', + field: 'manhoursExpenditure', + headerName: t("Manpower Expenses")+t("HKD"), + minWidth:280, + type: "number", + renderCell: (params:any) => { + return ( + ${params.row.manhoursExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} + ) + }, + }, + { + id: 'projectExpense', + field: 'projectExpense', + headerName: t("Project Expense")+t("HKD"), + minWidth:280, + type: "number", + renderCell: (params:any) => { + return ( + ${(params.row.projectExpense ?? 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ) }, }, @@ -512,6 +561,7 @@ const columns2 = [ const fetchProjectTableData = async (teamId?:any,customerId?:any) => { const financialSummaryByProject = await searchFinancialSummaryByProject(teamId); setProjectFinancialRows(financialSummaryByProject) + console.log(financialSummaryByProject) setFilteredProjectResult(financialSummaryByProject) } @@ -546,7 +596,21 @@ const columns2 = [
{projectFinancialData.map((record:any, index:any) => (
handleCardClick(record,index)}> - +
))}