浏览代码

financial update

tags/Baseline_180220205_Frontend
MSI\derek 9 个月前
父节点
当前提交
44adddeaba
共有 3 个文件被更改,包括 61 次插入68 次删除
  1. +25
    -23
      src/components/ProjectFinancialSummaryV2/FinancialSummary.tsx
  2. +1
    -17
      src/components/ProjectFinancialSummaryV2/FinancialSummaryWrapper.tsx
  3. +35
    -28
      src/components/ProjectFinancialSummaryV2/FinnancialStatusByProject.tsx

+ 25
- 23
src/components/ProjectFinancialSummaryV2/FinancialSummary.tsx 查看文件

@@ -1,8 +1,6 @@
"use client";
import { fetchFinancialSummary, fetchFinancialSummaryByProject, FinancialSummaryByProject, FinancialSummaryType, FinancialSummaryByClient, FinancialByProject, fetchFinancialSummaryByProjectV2 } from '@/app/api/financialsummary';
import { Box, Card, CardContent, CardHeader, FormControl, InputLabel, Link, MenuItem, Select, Stack } from '@mui/material';
import { usePathname, useSearchParams } from 'next/navigation';
import { useRouter } from 'next/navigation';
import { FinancialByProject, fetchFinancialSummaryByProjectV2 } from '@/app/api/financialsummary';
import { Box, Card, CardContent, CardHeader, FormControl, InputLabel, MenuItem, Select, Stack } from '@mui/material';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from "react-i18next";
import ProjectFinancialCard from '../ProjectFinancialSummary/ProjectFinancialCard';
@@ -12,7 +10,6 @@ import { SumOfByClient, SumOfByTeam, sumUpByClient, sumUpByTeam } from './gptFn'
import FinancialStatusByProject from './FinnancialStatusByProject';

interface Props {
// _financialSumm: FinancialSummaryType[],
_teamId: number,
financialSummByProject: FinancialByProject[]
}
@@ -23,6 +20,7 @@ interface Props {
}

type DateParams = {
0: InputDate;
2: InputDate;
3: InputDate;
4: InputDate;
@@ -32,16 +30,18 @@ const FinancialSummaryPage: React.FC<Props> = ({
_teamId,
financialSummByProject
}) => {
console.log(financialSummByProject)
const { t } = useTranslation();
const curr = useMemo(() => dayjs().format(INPUT_DATE_FORMAT), [])
const currYear = useMemo(() => dayjs().get("year"), [])
const startDate = useMemo(() => "10-01", [])
const endDate = useMemo(() => "09-30", [])
const startDate = "10-01"
const endDate = "09-30"
const currFinancialYear = useMemo(() => curr > `${currYear}-${startDate}` ? currYear + 1 : currYear, [currYear])
const [mainData, setMainData] = useState<FinancialByProject[]>(financialSummByProject)
const [byTeam, setByTeam] = useState<SumOfByTeam[]>(() => sumUpByTeam(mainData)) // do fetch to set
const [byProject, setByProject] = useState<FinancialByProject[]>(financialSummByProject)
const [byClient, setByClient] = useState<SumOfByClient[]>(() => sumUpByClient(mainData))
const [isLoading, setIsLoading] = useState(false)
const allTeam = useMemo(()=> {
var _allTeam: SumOfByTeam = {
id: 0,
@@ -66,12 +66,14 @@ const FinancialSummaryPage: React.FC<Props> = ({
}
return _allTeam
}, [mainData])
console.log(allTeam)

const [teamId, setTeamId] = useState(_teamId)
const [isCardClickedIndex, setIsCardClickedIndex] = useState(_teamId || 0);
const [period, setPeriod] = useState(0);

const dateMap: DateParams = useMemo(() => ({
0: {startDate: "", endDate: ""},
2: {startDate: `${currFinancialYear-2}-${startDate}`, endDate: `${currFinancialYear-1}-${endDate}`},
3: {startDate: `${currFinancialYear-3}-${startDate}`, endDate: `${currFinancialYear-2}-${endDate}`},
4: {startDate: `${currFinancialYear-4}-${startDate}`, endDate: `${currFinancialYear-3}-${endDate}`},
@@ -79,11 +81,13 @@ const FinancialSummaryPage: React.FC<Props> = ({
}), [currYear, startDate, endDate])

const fetchFinancialSummaryByProject = useCallback(async (endDate: string, startDate: string) => {
setIsLoading(true)
const data = await fetchFinancialSummaryByProjectV2(_teamId, endDate, startDate)
setMainData(data)
setByTeam(sumUpByTeam(data))
setByProject(data)
setByClient(sumUpByClient(data))
setIsLoading(false)
}, [setMainData, setByTeam, setByProject, setByClient])

const handleCardClick = useCallback((teamId: number) => {
@@ -96,10 +100,7 @@ const FinancialSummaryPage: React.FC<Props> = ({
console.log(value)
var _startDate: string = ""
var _endDate = ""
if (value == 0) {
_startDate = ""
_endDate == ""
} else if (value == 1) {
if (value == 1) {
if (curr <= `${currYear}-${endDate}`) {
_startDate = `${currYear - 1}-${startDate}`
_endDate = `${currYear}-${endDate}`
@@ -164,7 +165,7 @@ const FinancialSummaryPage: React.FC<Props> = ({
<CardHeader className="text-slate-500" title= {t("Active Project Financial Status")}/>
<CardContent component={Stack} spacing={4}>
<div className="ml-10 mr-10" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'start'}}>
{allTeam &&
{_teamId == 0 && allTeam &&
<div className="hover:cursor-pointer ml-4 inline-block" key={0} onClick={() => handleCardClick(0)}>
<ProjectFinancialCard
Title={t("All Team")}
@@ -172,15 +173,15 @@ const FinancialSummaryPage: React.FC<Props> = ({
TotalActiveProjectNumber={allTeam.activeProject}
TotalFees={allTeam.totalFee}
TotalBudget={allTeam.totalBudget}
TotalCumulative={allTeam.projectExpense + allTeam.invoicedAmount}
TotalCumulative={allTeam.manhourExpense + allTeam.projectExpense}
TotalProjectExpense={allTeam.projectExpense}
TotalInvoicedAmount={allTeam.invoicedAmount}
TotalUnInvoicedAmount={allTeam.totalFee - allTeam.invoicedAmount}
TotalReceivedAmount={allTeam.paidAmount}
CashFlowStatus={allTeam.invoicedAmount >= (allTeam.projectExpense + allTeam.invoicedAmount) ? "Positive" : "Negative"}
CostPerformanceIndex={allTeam.invoicedAmount/(allTeam.projectExpense + allTeam.invoicedAmount) || 0}
ProjectedCashFlowStatus={allTeam.totalFee >= (allTeam.projectExpense + allTeam.invoicedAmount) ? "Positive" : "Negative"}
ProjectedCPI={allTeam.totalFee/(allTeam.projectExpense + allTeam.invoicedAmount)}
CashFlowStatus={allTeam.invoicedAmount >= (allTeam.projectExpense + allTeam.manhourExpense) ? "Positive" : "Negative"}
CostPerformanceIndex={allTeam.invoicedAmount/(allTeam.projectExpense + allTeam.manhourExpense) || 0}
ProjectedCashFlowStatus={allTeam.totalFee >= (allTeam.projectExpense + allTeam.manhourExpense) ? "Positive" : "Negative"}
ProjectedCPI={allTeam.totalFee/(allTeam.projectExpense + allTeam.manhourExpense)}
ClickedIndex={isCardClickedIndex}
Index={0}/>
</div>}
@@ -192,15 +193,15 @@ const FinancialSummaryPage: React.FC<Props> = ({
TotalActiveProjectNumber={record.activeProject}
TotalFees={record.totalFee}
TotalBudget={record.totalBudget}
TotalCumulative={record.projectExpense + record.invoicedAmount}
TotalCumulative={record.projectExpense + record.manhourExpense}
TotalProjectExpense={record.projectExpense}
TotalInvoicedAmount={record.invoicedAmount}
TotalUnInvoicedAmount={record.totalFee - record.invoicedAmount}
TotalUnInvoicedAmount={Math.abs(record.totalFee - record.invoicedAmount)}
TotalReceivedAmount={record.paidAmount}
CashFlowStatus={record.invoicedAmount >= (record.projectExpense + record.invoicedAmount) ? "Positive" : "Negative"}
CostPerformanceIndex={record.invoicedAmount/(record.projectExpense + record.invoicedAmount) || 0}
ProjectedCashFlowStatus={record.totalFee >= (record.projectExpense + record.invoicedAmount) ? "Positive" : "Negative"}
ProjectedCPI={record.totalFee/(record.projectExpense + record.invoicedAmount)}
CashFlowStatus={record.invoicedAmount >= (record.projectExpense + record.manhourExpense) ? "Positive" : "Negative"}
CostPerformanceIndex={record.invoicedAmount/(record.projectExpense + record.manhourExpense) || 0}
ProjectedCashFlowStatus={record.totalFee >= (record.projectExpense + record.manhourExpense) ? "Positive" : "Negative"}
ProjectedCPI={record.totalFee/(record.projectExpense + record.manhourExpense)}
ClickedIndex={isCardClickedIndex}
Index={record.id}/>
</div>
@@ -211,6 +212,7 @@ const FinancialSummaryPage: React.FC<Props> = ({
<FinancialStatusByProject
financialSummByProject={byProject}
financialSummByClient={byClient}
isLoading={isLoading}
/>
</>
)


+ 1
- 17
src/components/ProjectFinancialSummaryV2/FinancialSummaryWrapper.tsx 查看文件

@@ -2,7 +2,7 @@ import React from "react";
import FinancialSummaryLoading from "./FinancialSummaryLoading";
import FinancialSummary from "./FinancialSummary";
import { fetchUserStaff, searchParamsProps } from "@/app/utils/fetchUtil";
import { fetchFinancialSummary, fetchFinancialSummaryByProject, fetchFinancialSummaryByProjectV2, FinancialSummaryByProject, FinancialSummaryType } from "@/app/api/financialsummary";
import { fetchFinancialSummaryByProjectV2 } from "@/app/api/financialsummary";
import { Grid } from "@mui/material";
import FinancialStatusByProject from "./FinnancialStatusByProject";

@@ -16,29 +16,13 @@ interface SubComponents {
const FinancialSummaryWrapper: React.FC<searchParamsProps> & SubComponents = async ({
searchParams,
}) => {
// const curr = new Date()
// const currYear = curr.getFullYear()
// const start = "10-01"
// const end = "09-30"
// var defaultEnd: string
// var defaultStart: string
// if (curr.toISOString().split('T')[0] <= `${currYear}-${end}`) {
// defaultStart = `${currYear-1}-${start}`
// defaultEnd = `${currYear}-${end}`
// } else {
// defaultStart = `${currYear}-${start}`
// defaultEnd = `${currYear+1}-${end}`
// }
const userStaff = await fetchUserStaff();
const teamId = userStaff?.isTeamLead ? userStaff.teamId : 0;
const [
// financialSumm,
financialSummByProject
] = await Promise.all([
// fetchFinancialSummary(defaultEnd, teamId, defaultStart),
fetchFinancialSummaryByProjectV2(teamId, "", "")
]);
// console.log(financialSummByProject)

return (
<Grid>


+ 35
- 28
src/components/ProjectFinancialSummaryV2/FinnancialStatusByProject.tsx 查看文件

@@ -1,8 +1,6 @@
"use client";

import {
FinancialSummaryByProject,
FinancialSummaryByClient,
FinancialByProject,
} from "@/app/api/financialsummary";
import SearchBox, { Criterion } from "../SearchBox";
@@ -10,15 +8,16 @@ import { useEffect, useMemo, useState } from "react";
import CustomDatagrid from "../CustomDatagrid";
import { useTranslation } from "react-i18next";
import { useRouter } from "next/navigation";
import { Box, Grid } from "@mui/material";
import { Box } from "@mui/material";
import { SumOfByClient } from "./gptFn";
// import { summarizeFinancialData } from "./gptFn";

interface Props {
financialSummByProject: FinancialByProject[];
financialSummByClient: SumOfByClient[];
isLoading: Boolean
}
type SearchQuery = Partial<Omit<FinancialSummaryByProject, "id">>;
type SearchQuery = Partial<Omit<FinancialByProject, "id">>;
type SearchParamNames = keyof SearchQuery;

type SearchQuery2 = Partial<Omit<SumOfByClient, "id">>;
@@ -26,18 +25,14 @@ type SearchParamNames2 = keyof SearchQuery2;

const FinancialStatusByProject: React.FC<Props> = ({
financialSummByProject,
financialSummByClient
financialSummByClient,
isLoading
}) => {
console.log(financialSummByProject);
// console.log(financialSummByClient);
const { t } = useTranslation("dashboard");
const router = useRouter();
const [filteredByProjectRows, setFilteredByProjectRows] = useState(financialSummByProject);
const [filteredByClientRows, setFilteredByClientRows] = useState(financialSummByClient);
console.log(filteredByProjectRows);
console.log(filteredByClientRows);

// const testing = useMemo(() => summarizeFinancialData(filteredByProjectRows), [])
const greenColor = "text-lime-500";
const redColor = "text-red-500";
const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
@@ -117,7 +112,7 @@ console.log(filteredByProjectRows);
headerName: "CPI",
minWidth: 50,
renderCell: (params: any) => {
var cpi = params.invoicedAmount/(params.projectExpense + params.invoicedAmount) || 0
var cpi = params.row.invoicedAmount/(params.row.projectExpense + params.row.invoicedAmount) || 0
return (
<span className={cpi >= 1 ? greenColor : redColor}>
{cpi.toLocaleString(undefined, {
@@ -148,15 +143,15 @@ console.log(filteredByProjectRows);
headerName: t("Projected CPI"),
minWidth: 50,
renderCell: (params: any) => {
var projectedCpi = params.row.totalFee/(params.row.projectExpense + params.row.invoicedAmount)
var projectedCpi = params.row.totalFee/(params.row.projectExpense + params.row.invoicedAmount) == Infinity ? 'N/A' : params.row.totalFee/(params.row.projectExpense + params.row.invoicedAmount)
return (
<span
className={projectedCpi >= 1 ? greenColor : redColor}
className={(typeof projectedCpi == "number" && projectedCpi >= 1 ? greenColor : redColor)}
>
{projectedCpi.toLocaleString(undefined, {
{typeof projectedCpi == "number" ? projectedCpi.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
}) : projectedCpi}
</span>
);
},
@@ -281,7 +276,7 @@ console.log(filteredByProjectRows);
return (
<span>
$
{nonInvoiced.toLocaleString(undefined, {
{Math.abs(nonInvoiced).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
@@ -555,13 +550,18 @@ console.log(filteredByProjectRows);
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
setFilteredByProjectRows(
filteredByProjectRows.filter(
(cp:any) =>
cp.projectCode.toLowerCase().includes(query.projectCode.toLowerCase()) &&
cp.projectName.toLowerCase().includes(query.projectName.toLowerCase())
),
);
console.log(query)
if (query.projectCode.length > 0 || query.projectName.length > 0) {
setFilteredByProjectRows(
financialSummByProject.filter(
(cp) =>
cp.projectCode.toLowerCase().includes(query.projectCode.trim().toLowerCase()) &&
cp.projectName.toLowerCase().includes(query.projectName.trim().toLowerCase())
),
);
} else {
setFilteredByProjectRows(financialSummByProject)
}
}}
/>
<div style={{ display: "inline-block", width: "99%", marginLeft: 10 }}>
@@ -570,6 +570,7 @@ console.log(filteredByProjectRows);
columns={columns1}
columnWidth={200}
dataGridHeight={300}
loading={isLoading}
/>
</div>
{/* <SearchResults<StaffResult> items={filteredStaff} columns={columns} /> */}
@@ -578,13 +579,18 @@ console.log(filteredByProjectRows);
<SearchBox
criteria={searchCriteria2}
onSearch={(query) => {
console.log(query)
if (query.customerCode.length > 0 || query.customerName.length > 0) {
setFilteredByClientRows(
filteredByClientRows.filter(
(cp:any) =>
cp.customerCode.toLowerCase().includes(query.customerCode.toLowerCase()) &&
cp.customerName.toLowerCase().includes(query.customerName.toLowerCase())
financialSummByClient.filter(
(cp) =>
cp.customerCode.toLowerCase().includes(query.customerCode.trim().toLowerCase()) &&
cp.customerName.toLowerCase().includes(query.customerName.trim().toLowerCase())
),
);
);
} else {
setFilteredByClientRows(financialSummByClient)
}
}}
/>
<div style={{ display: "inline-block", width: "99%", marginLeft: 10 }}>
@@ -593,6 +599,7 @@ console.log(filteredByProjectRows);
columns={columns2}
columnWidth={200}
dataGridHeight={300}
loading={isLoading}
/>
</div>
</Box>


正在加载...
取消
保存