| @@ -56,6 +56,14 @@ export interface CashFlowAnticipatedChartResult { | |||
| AverageManhours: number; | |||
| teamLead: number; | |||
| totalManhour: number; | |||
| aniticipateExpenditure: number; | |||
| } | |||
| export interface CashFlowLedgerResult { | |||
| date: string; | |||
| income: number; | |||
| expenditure: number; | |||
| balance: number; | |||
| remarks: string; | |||
| } | |||
| export const preloadProjects = () => { | |||
| @@ -98,3 +106,14 @@ export const fetchProjectsCashFlowAnticipate = cache(async (projectIdList: numbe | |||
| } | |||
| }); | |||
| export const fetchProjectsCashFlowLedger = cache(async (projectIdList: number[]) => { | |||
| if (projectIdList.length !== 0) { | |||
| const queryParams = new URLSearchParams(); | |||
| queryParams.append('projectIdList', projectIdList.join(',')); | |||
| return serverFetchJson<CashFlowLedgerResult[]>(`${BASE_API_URL}/dashboard/searchCashFlowLedger?${queryParams.toString()}`); | |||
| } else { | |||
| return []; | |||
| } | |||
| }); | |||
| @@ -0,0 +1,36 @@ | |||
| "use server"; | |||
| import { cache } from "react"; | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface teamCombo { | |||
| records: comboProp[]; | |||
| } | |||
| export interface teamCashFlow { | |||
| monthInvoice: string; | |||
| invoiceMonth: string; | |||
| income: number; | |||
| cumulativeIncome: number; | |||
| monthExpenditure: string; | |||
| recordMonth: string; | |||
| expenditure: number; | |||
| cumulativeExpenditure: number; | |||
| } | |||
| export const fetchTeamCombo = cache(async () => { | |||
| return serverFetchJson<teamCombo>(`${BASE_API_URL}/team/combo`); | |||
| }); | |||
| export const fetchTeamCashFlowChartData = cache(async (year:number,teamId?:number,) => { | |||
| if (teamId === null) { | |||
| return serverFetchJson<teamCashFlow>(`${BASE_API_URL}/dashboard/searchTeamCashFlow?year=${year}`); | |||
| } else { | |||
| return serverFetchJson<teamCashFlow>(`${BASE_API_URL}/dashboard/searchTeamCashFlow?teamId=${teamId}&year=${year}`); | |||
| } | |||
| }); | |||
| @@ -14,6 +14,13 @@ const pathToLabelMap: { [path: string]: string } = { | |||
| "": "Overview", | |||
| "/home": "User Workspace", | |||
| "/dashboard": "Dashboard", | |||
| "/dashboard/CompanyTeamCashFlow": "Company Team Cash Flow", | |||
| "/dashboard/ProjectCashFlow": "Project Cash Flow", | |||
| "/dashboard/ProjectFinancialSummary": "Project Finanical Summary", | |||
| "/dashboard/ProjectResourceSummary": "Project Resource Summary", | |||
| "/dashboard/ProjectStatusByClient": "Project Status by Client", | |||
| "/dashboard/ProjectStatusByTeam": "Project Status by Team", | |||
| "/dashboard/StaffUtilization": "Staff Utilization", | |||
| "/projects": "Projects", | |||
| "/projects/create": "Create Project", | |||
| "/projects/createSub": "Sub Project", | |||
| @@ -21,19 +21,77 @@ import { Suspense } from "react"; | |||
| import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | |||
| import { Input, Label } from "reactstrap"; | |||
| import Select, { components } from "react-select"; | |||
| import {fetchTeamCombo,fetchTeamCashFlowChartData} from "@/app/api/teamCashflow"; | |||
| const CompanyTeamCashFlow: React.FC = () => { | |||
| const todayDate = new Date(); | |||
| const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||
| const [teamOptions, setTeamOptions]: any[] = React.useState([]); | |||
| const [teamId, setTeamId]:any = React.useState(null); | |||
| const [monthlyIncomeList, setMonthlyIncomeList]: any[] = React.useState([]); | |||
| const [monthlyCumulativeIncomeList, setMonthlyCumulativeIncomeList]: any[] = React.useState([]); | |||
| const [monthlyExpenditureList, setMonthlyExpenditureList]: any[] = React.useState([]); | |||
| const [monthlyCumulativeExpenditureList, setMonthlyCumulativeExpenditureList]: any[] = React.useState([]); | |||
| const [monthlyChartLeftMax, setMonthlyChartLeftMax]: any[] = React.useState(0); | |||
| const [monthlyChartRightMax, setMonthlyChartRightMax]: any[] = React.useState(0); | |||
| const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | |||
| todayDate.getFullYear(), | |||
| ); | |||
| const teamOptions = [ | |||
| { value: 1, label: "XXX Team" }, | |||
| { value: 2, label: "YYY Team" }, | |||
| { value: 3, label: "ZZZ Team" }, | |||
| ]; | |||
| const fetchChartData = async () => { | |||
| const cashFlowMonthlyChartData:any = await fetchTeamCashFlowChartData(cashFlowYear,teamId); | |||
| console.log(cashFlowMonthlyChartData[0]) | |||
| const monthlyIncome = [] | |||
| const cumulativeIncome = [] | |||
| const monthlyExpenditure = [] | |||
| const cumulativeExpenditure = [] | |||
| var leftMax = 0 | |||
| var rightMax = 0 | |||
| // if (cashFlowMonthlyChartData.length !== 0) { | |||
| for (var i = 0; i < cashFlowMonthlyChartData[0].teamCashFlowIncome.length; i++) { | |||
| if (leftMax < cashFlowMonthlyChartData[0].teamCashFlowIncome[i].income || leftMax < cashFlowMonthlyChartData[0].teamCashFlowExpenditure[i].expenditure){ | |||
| leftMax = Math.max(cashFlowMonthlyChartData[0].teamCashFlowIncome[i].income,cashFlowMonthlyChartData[0].teamCashFlowExpenditure[i].expenditure) | |||
| } | |||
| monthlyIncome.push(cashFlowMonthlyChartData[0].teamCashFlowIncome[i].income) | |||
| cumulativeIncome.push(cashFlowMonthlyChartData[0].teamCashFlowIncome[i].cumulativeIncome) | |||
| } | |||
| for (var i = 0; i < cashFlowMonthlyChartData[0].teamCashFlowExpenditure.length; i++) { | |||
| if (rightMax < cashFlowMonthlyChartData[0].teamCashFlowIncome[i].income || rightMax < cashFlowMonthlyChartData[0].teamCashFlowExpenditure[i].expenditure){ | |||
| rightMax = Math.max(cashFlowMonthlyChartData[0].teamCashFlowIncome[i].income,cashFlowMonthlyChartData[0].teamCashFlowExpenditure[i].expenditure) | |||
| } | |||
| monthlyExpenditure.push(cashFlowMonthlyChartData[0].teamCashFlowExpenditure[i].expenditure) | |||
| cumulativeExpenditure.push(cashFlowMonthlyChartData[0].teamCashFlowExpenditure[i].cumulativeExpenditure) | |||
| } | |||
| setMonthlyIncomeList(monthlyIncome) | |||
| setMonthlyCumulativeIncomeList(cumulativeIncome) | |||
| setMonthlyExpenditureList(monthlyExpenditure) | |||
| setMonthlyCumulativeExpenditureList(cumulativeExpenditure) | |||
| setMonthlyChartLeftMax(leftMax) | |||
| setMonthlyChartRightMax(rightMax) | |||
| // } else { | |||
| // setMonthlyIncomeList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| // setMonthlyCumulativeIncomeList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| // setMonthlyExpenditureList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| // setMonthlyCumulativeExpenditureList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| // } | |||
| } | |||
| const fetchComboData = async () => { | |||
| const teamComboList = [] | |||
| const teamCombo = await fetchTeamCombo(); | |||
| for (var i = 0; i < teamCombo.records.length; i++) { | |||
| teamComboList.push({value: teamCombo.records[i].id, label: teamCombo.records[i].label}) | |||
| } | |||
| setTeamOptions(teamComboList) | |||
| } | |||
| useEffect(() => { | |||
| fetchComboData() | |||
| }, []); | |||
| useEffect(() => { | |||
| fetchChartData() | |||
| }, [cashFlowYear,teamId]); | |||
| const columns = [ | |||
| { | |||
| @@ -158,7 +216,7 @@ const CompanyTeamCashFlow: React.FC = () => { | |||
| text: "Monthly Income and Expenditure(HKD)", | |||
| }, | |||
| min: 0, | |||
| max: 3700000, | |||
| max: monthlyChartLeftMax, | |||
| tickAmount: 5, | |||
| labels: { | |||
| formatter: function (val) { | |||
| @@ -173,7 +231,7 @@ const CompanyTeamCashFlow: React.FC = () => { | |||
| text: "Monthly Expenditure (HKD)", | |||
| }, | |||
| min: 0, | |||
| max: 3700000, | |||
| max: monthlyChartLeftMax, | |||
| tickAmount: 5, | |||
| }, | |||
| { | |||
| @@ -183,7 +241,7 @@ const CompanyTeamCashFlow: React.FC = () => { | |||
| text: "Cumulative Income and Expenditure(HKD)", | |||
| }, | |||
| min: 0, | |||
| max: 21000000, | |||
| max: monthlyChartRightMax, | |||
| tickAmount: 5, | |||
| labels: { | |||
| formatter: function (val) { | |||
| @@ -199,7 +257,7 @@ const CompanyTeamCashFlow: React.FC = () => { | |||
| text: "Cumulative Expenditure (HKD)", | |||
| }, | |||
| min: 0, | |||
| max: 21000000, | |||
| max: monthlyChartRightMax, | |||
| tickAmount: 5, | |||
| }, | |||
| ], | |||
| @@ -212,37 +270,25 @@ const CompanyTeamCashFlow: React.FC = () => { | |||
| name: "Monthly_Income", | |||
| type: "column", | |||
| color: "#ffde91", | |||
| data: [ | |||
| 1280000, 170000, 3600000, 2400000, 1000000, 1800000, 1800000, 1200000, | |||
| 1250000, 1200000, 600000, 2400000, | |||
| ], | |||
| data: monthlyIncomeList, | |||
| }, | |||
| { | |||
| name: "Monthly_Expenditure", | |||
| type: "column", | |||
| color: "#82b59a", | |||
| data: [ | |||
| 1200000, 1400000, 2000000, 1400000, 1450000, 1800000, 1200000, | |||
| 1400000, 1200000, 1600000, 2000000, 1600000, | |||
| ], | |||
| data: monthlyExpenditureList, | |||
| }, | |||
| { | |||
| name: "Cumulative_Income", | |||
| type: "line", | |||
| color: "#EE6D7A", | |||
| data: [ | |||
| 500000, 3000000, 7000000, 9000000, 10000000, 13000000, 14000000, | |||
| 16000000, 17000000, 17500000, 18000000, 20000000, | |||
| ], | |||
| data: monthlyCumulativeIncomeList, | |||
| }, | |||
| { | |||
| name: "Cumulative_Expenditure", | |||
| type: "line", | |||
| color: "#7cd3f2", | |||
| data: [ | |||
| 400000, 2800000, 4000000, 5200000, 7100000, 8000000, 10000000, | |||
| 11000000, 12100000, 14000000, 15400000, 17200000, | |||
| ], | |||
| data: monthlyCumulativeExpenditureList, | |||
| }, | |||
| ], | |||
| }; | |||
| @@ -296,6 +342,13 @@ const CompanyTeamCashFlow: React.FC = () => { | |||
| placeholder="All Team" | |||
| options={teamOptions} | |||
| isClearable={true} | |||
| onChange={(selectedOption:any) => { | |||
| if (selectedOption === null) { | |||
| setTeamId(null); | |||
| } else { | |||
| setTeamId(selectedOption.value); | |||
| } | |||
| }} | |||
| /> | |||
| </div> | |||
| <ReactApexChart | |||
| @@ -19,7 +19,7 @@ import SearchBox, { Criterion } from "../SearchBox"; | |||
| import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | |||
| import { Suspense } from "react"; | |||
| import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | |||
| import { fetchProjectsCashFlow,fetchProjectsCashFlowMonthlyChart,fetchProjectsCashFlowReceivableAndExpenditure,fetchProjectsCashFlowAnticipate} from "@/app/api/cashflow"; | |||
| import { fetchProjectsCashFlow,fetchProjectsCashFlowMonthlyChart,fetchProjectsCashFlowReceivableAndExpenditure,fetchProjectsCashFlowAnticipate,fetchProjectsCashFlowLedger} from "@/app/api/cashflow"; | |||
| import { Input, Label } from "reactstrap"; | |||
| import { CashFlow } from "@/app/api/cashflow"; | |||
| import dayjs from 'dayjs'; | |||
| @@ -43,6 +43,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| const [monthlyCumulativeExpenditureList, setMonthlyCumulativeExpenditureList]: any[] = React.useState([]); | |||
| const [monthlyChartLeftMax, setMonthlyChartLeftMax]: any[] = React.useState(0); | |||
| const [monthlyChartRightMax, setMonthlyChartRightMax]: any[] = React.useState(0); | |||
| const [monthlyAnticipateLeftMax, setMonthlyAnticipateLeftMax]: any[] = React.useState(0); | |||
| const [receivedPercentage,setReceivedPercentage]: any[] = React.useState(0); | |||
| const [totalBudget,setTotalBudget]: any[] = React.useState(0); | |||
| const [totalInvoiced,setTotalInvoiced]: any[] = React.useState(0); | |||
| @@ -51,6 +52,9 @@ const ProjectCashFlow: React.FC = () => { | |||
| const [totalExpenditure,setTotalExpenditure]: any[] = React.useState(0); | |||
| const [expenditureReceivable,setExpenditureReceivable]: any[] = React.useState(0); | |||
| const [expenditurePercentage,setExpenditurePercentage]: any[] = React.useState(0); | |||
| const [monthlyAnticipateIncomeList, setMonthlyAnticipateIncomeList]: any[] = React.useState([0,0,0,0,0,0,0,0,0,0,0,0]); | |||
| const [monthlyAnticipateExpenditureList, setMonthlyAnticipateExpenditureList]: any[] = React.useState([0,0,0,0,0,0,0,0,0,0,0,0]); | |||
| const [ledgerData, setLedgerData]: any[] = React.useState([]); | |||
| const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | |||
| todayDate.getFullYear(), | |||
| ); | |||
| @@ -105,6 +109,11 @@ const ProjectCashFlow: React.FC = () => { | |||
| setMonthlyCumulativeExpenditureList(cumulativeExpenditure) | |||
| setMonthlyChartLeftMax(leftMax) | |||
| setMonthlyChartRightMax(rightMax) | |||
| } else { | |||
| setMonthlyIncomeList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| setMonthlyCumulativeIncomeList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| setMonthlyExpenditureList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| setMonthlyCumulativeExpenditureList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| } | |||
| } | |||
| @@ -122,7 +131,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| } | |||
| } | |||
| const fetchAnticipateData = async () => { | |||
| const cashFlowAnticipateData = await fetchProjectsCashFlowAnticipate(selectedProjectIdList,cashFlowYear); | |||
| const cashFlowAnticipateData = await fetchProjectsCashFlowAnticipate(selectedProjectIdList,anticipateCashFlowYear); | |||
| const monthlyAnticipateIncome = [] | |||
| var anticipateLeftMax = 0 | |||
| if(cashFlowAnticipateData.length !== 0){ | |||
| @@ -132,8 +141,51 @@ const ProjectCashFlow: React.FC = () => { | |||
| } | |||
| monthlyAnticipateIncome.push(cashFlowAnticipateData[0].anticipateIncomeList[i].anticipateIncome) | |||
| } | |||
| } else { | |||
| setMonthlyAnticipateIncomeList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| setMonthlyAnticipateExpenditureList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| } | |||
| console.log(monthlyAnticipateIncome) | |||
| setMonthlyAnticipateIncomeList(monthlyAnticipateIncome) | |||
| if(cashFlowAnticipateData.length !== 0){ | |||
| if (cashFlowAnticipateData[0].anticipateExpenditureList.length !== 0) { | |||
| const anticipateExpenditureList = [] | |||
| for (var i = 0; i < cashFlowAnticipateData[0].anticipateExpenditureList.length; i++) { | |||
| const subAnticipateExpenditure = [] | |||
| var duration = cashFlowAnticipateData[0].anticipateExpenditureList[i].Duration | |||
| var month = cashFlowAnticipateData[0].anticipateExpenditureList[i].startMonth | |||
| const anticipateExpenditure = cashFlowAnticipateData[0].anticipateExpenditureList[i].aniticipateExpenditure | |||
| for (var j = 1; j < 13; j++){ | |||
| if (month === j && duration > 0) { | |||
| subAnticipateExpenditure.push(anticipateExpenditure) | |||
| duration = duration - 1 | |||
| } else { | |||
| subAnticipateExpenditure.push(0) | |||
| } | |||
| } | |||
| anticipateExpenditureList.push(subAnticipateExpenditure) | |||
| } | |||
| const result = new Array(anticipateExpenditureList[0].length).fill(0); | |||
| for (const arr of anticipateExpenditureList) { | |||
| for (let i = 0; i < arr.length; i++) { | |||
| result[i] += arr[i]; | |||
| } | |||
| } | |||
| setMonthlyAnticipateExpenditureList(result) | |||
| for (var i = 0; i < monthlyAnticipateIncome.length; i++) { | |||
| if (anticipateLeftMax < monthlyAnticipateIncome[i] || result[i]){ | |||
| anticipateLeftMax = Math.max(monthlyAnticipateIncome[i],result[i]) | |||
| } | |||
| setMonthlyAnticipateLeftMax(anticipateLeftMax) | |||
| } | |||
| } else { | |||
| setMonthlyAnticipateExpenditureList([0,0,0,0,0,0,0,0,0,0,0,0]) | |||
| } | |||
| } | |||
| } | |||
| const fetchProjectCashFlowLedger = async () => { | |||
| const cashFlowLedgerData = await fetchProjectsCashFlowLedger(selectedProjectIdList); | |||
| setLedgerData(cashFlowLedgerData) | |||
| } | |||
| useEffect(() => { | |||
| fetchData() | |||
| @@ -143,7 +195,11 @@ const ProjectCashFlow: React.FC = () => { | |||
| fetchChartData() | |||
| fetchReceivableAndExpenditureData() | |||
| fetchAnticipateData() | |||
| fetchProjectCashFlowLedger() | |||
| }, [cashFlowYear,selectedProjectIdList]); | |||
| useEffect(() => { | |||
| fetchAnticipateData() | |||
| }, [anticipateCashFlowYear,selectedProjectIdList]); | |||
| const columns = [ | |||
| { | |||
| id: "projectCode", | |||
| @@ -207,18 +263,39 @@ const ProjectCashFlow: React.FC = () => { | |||
| field: "expenditure", | |||
| headerName: "Expenditure (HKD)", | |||
| flex: 0.6, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.expenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| } | |||
| }, | |||
| { | |||
| id: "income", | |||
| field: "income", | |||
| headerName: "Income (HKD)", | |||
| flex: 0.6, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.income.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| } | |||
| }, | |||
| { | |||
| id: "cashFlowBalance", | |||
| field: "cashFlowBalance", | |||
| id: "balance", | |||
| field: "balance", | |||
| headerName: "Cash Flow Balance (HKD)", | |||
| flex: 0.6, | |||
| renderCell: (params:any) => { | |||
| if (params.row.balance < 0) { | |||
| return ( | |||
| <span>(${Math.abs(params.row.balance).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })})</span> | |||
| ) | |||
| } else { | |||
| return ( | |||
| <span>${params.row.balance.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| } | |||
| }, | |||
| }, | |||
| { | |||
| id: "remarks", | |||
| @@ -383,50 +460,50 @@ const ProjectCashFlow: React.FC = () => { | |||
| text: "Anticipate Monthly Income and Expenditure(HKD)", | |||
| }, | |||
| min: 0, | |||
| max: monthlyChartLeftMax, | |||
| tickAmount: 5, | |||
| labels: { | |||
| formatter: function (val) { | |||
| return val.toLocaleString() | |||
| } | |||
| } | |||
| }, | |||
| { | |||
| show: false, | |||
| seriesName: "Monthly_Expenditure", | |||
| title: { | |||
| text: "Monthly Expenditure (HKD)", | |||
| }, | |||
| min: 0, | |||
| max: monthlyChartLeftMax, | |||
| tickAmount: 5, | |||
| }, | |||
| { | |||
| seriesName: "Cumulative_Income", | |||
| opposite: true, | |||
| title: { | |||
| text: "Cumulative Income and Expenditure(HKD)", | |||
| }, | |||
| min: 0, | |||
| max: monthlyChartRightMax, | |||
| tickAmount: 5, | |||
| labels: { | |||
| formatter: function (val) { | |||
| return val.toLocaleString() | |||
| } | |||
| } | |||
| }, | |||
| { | |||
| show: false, | |||
| seriesName: "Cumulative_Expenditure", | |||
| opposite: true, | |||
| title: { | |||
| text: "Cumulative Expenditure (HKD)", | |||
| }, | |||
| min: 0, | |||
| max: monthlyChartRightMax, | |||
| max: monthlyAnticipateLeftMax, | |||
| tickAmount: 5, | |||
| // labels: { | |||
| // formatter: function (val) { | |||
| // return val.toLocaleString() | |||
| // } | |||
| // } | |||
| }, | |||
| // { | |||
| // show: false, | |||
| // seriesName: "Monthly_Expenditure", | |||
| // title: { | |||
| // text: "Monthly Expenditure (HKD)", | |||
| // }, | |||
| // min: 0, | |||
| // max: monthlyAnticipateLeftMax, | |||
| // tickAmount: 5, | |||
| // }, | |||
| // { | |||
| // seriesName: "Cumulative_Income", | |||
| // opposite: true, | |||
| // title: { | |||
| // text: "Cumulative Income and Expenditure(HKD)", | |||
| // }, | |||
| // min: 0, | |||
| // max: MonthlyAnticipateLeftMax, | |||
| // tickAmount: 5, | |||
| // labels: { | |||
| // formatter: function (val) { | |||
| // return val.toLocaleString() | |||
| // } | |||
| // } | |||
| // }, | |||
| // { | |||
| // show: false, | |||
| // seriesName: "Cumulative_Expenditure", | |||
| // opposite: true, | |||
| // title: { | |||
| // text: "Cumulative Expenditure (HKD)", | |||
| // }, | |||
| // min: 0, | |||
| // max: monthlyChartRightMax, | |||
| // tickAmount: 5, | |||
| // }, | |||
| ], | |||
| grid: { | |||
| borderColor: "#f1f1f1", | |||
| @@ -437,16 +514,13 @@ const ProjectCashFlow: React.FC = () => { | |||
| name: "Monthly_Income", | |||
| type: "column", | |||
| color: "#f1c48a", | |||
| data: [0, 110000, 0, 0, 185000, 0, 0, 189000, 0, 0, 300000, 0], | |||
| data: monthlyAnticipateIncomeList, | |||
| }, | |||
| { | |||
| name: "Monthly_Expenditure", | |||
| type: "column", | |||
| color: "#89d7f3", | |||
| data: [ | |||
| 60000, 60000, 60000, 60000, 60000, 60000, 60000, 60000, 60000, 60000, | |||
| 60000, 60000, | |||
| ], | |||
| data: monthlyAnticipateExpenditureList, | |||
| } | |||
| ], | |||
| }; | |||
| @@ -635,7 +709,6 @@ const ProjectCashFlow: React.FC = () => { | |||
| remarks: "Monthly Manpower Expenditure", | |||
| }, | |||
| ]; | |||
| const [ledgerData, setLedgerData]: any[] = React.useState(ledgerRows); | |||
| const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | |||
| () => [ | |||
| @@ -771,7 +844,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#6b87cf" }} | |||
| > | |||
| {totalInvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| ${totalInvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div | |||
| @@ -784,7 +857,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#6b87cf" }} | |||
| > | |||
| {totalReceived.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| ${totalReceived.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div | |||
| @@ -797,7 +870,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| className="text-lg font-medium ml-5 mb-2" | |||
| style={{ color: "#6b87cf" }} | |||
| > | |||
| {receivable.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| ${receivable.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| </Card> | |||
| </Card> | |||
| @@ -833,7 +906,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#6b87cf" }} | |||
| > | |||
| {totalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| ${totalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div | |||
| @@ -846,7 +919,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#6b87cf" }} | |||
| > | |||
| {totalExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| ${totalExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div | |||
| @@ -859,7 +932,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| className="text-lg font-medium ml-5 mb-2" | |||
| style={{ color: "#6b87cf" }} | |||
| > | |||
| {expenditureReceivable.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| ${expenditureReceivable.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| </Card> | |||
| </Card> | |||
| @@ -894,7 +967,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| </div> | |||
| <div className="inline-block ml-1"> | |||
| <button | |||
| onClick={() => setAnticipateCashFlowYear(cashFlowYear - 1)} | |||
| onClick={() => setAnticipateCashFlowYear(anticipateCashFlowYear - 1)} | |||
| className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base" | |||
| > | |||
| < | |||
| @@ -902,7 +975,7 @@ const ProjectCashFlow: React.FC = () => { | |||
| </div> | |||
| <div className="inline-block ml-1"> | |||
| <button | |||
| onClick={() => setAnticipateCashFlowYear(cashFlowYear + 1)} | |||
| onClick={() => setAnticipateCashFlowYear(anticipateCashFlowYear + 1)} | |||
| className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base" | |||
| > | |||
| > | |||
| @@ -140,7 +140,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||
| minWidth:50, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalFee}</span> | |||
| <span>${params.row.totalFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -151,7 +151,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||
| minWidth:50, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalBudget}</span> | |||
| <span>${params.row.totalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -162,7 +162,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||
| minWidth:280, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.cumulativeExpenditure}</span> | |||
| <span>${params.row.cumulativeExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -173,7 +173,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalInvoiced}</span> | |||
| <span>${params.row.totalInvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -184,7 +184,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalUninvoiced}</span> | |||
| <span>${params.row.totalUninvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -195,7 +195,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalReceived}</span> | |||
| <span>${params.row.totalReceived.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -307,7 +307,7 @@ const columns2 = [ | |||
| minWidth:50, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalFee}</span> | |||
| <span>${params.row.totalFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -318,7 +318,7 @@ const columns2 = [ | |||
| minWidth:50, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalBudget}</span> | |||
| <span>${params.row.totalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -329,7 +329,7 @@ const columns2 = [ | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.cumulativeExpenditure}</span> | |||
| <span>${params.row.cumulativeExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -340,7 +340,7 @@ const columns2 = [ | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalInvoiced}</span> | |||
| <span>${params.row.totalInvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -351,7 +351,7 @@ const columns2 = [ | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalUninvoiced}</span> | |||
| <span>${params.row.totalUninvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||
| @@ -362,7 +362,7 @@ const columns2 = [ | |||
| minWidth:250, | |||
| renderCell: (params:any) => { | |||
| return ( | |||
| <span>${params.row.totalReceived}</span> | |||
| <span>${params.row.totalReceived.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</span> | |||
| ) | |||
| }, | |||
| }, | |||