Parcourir la source

update workspace, export finanical status by client excel

tags/Baseline_30082024_FRONTEND_UAT
cyril.tsui il y a 1 an
Parent
révision
383944b844
8 fichiers modifiés avec 67 ajouts et 16 suppressions
  1. +29
    -1
      src/app/api/financialsummary/actions.ts
  2. +2
    -0
      src/app/api/projects/index.ts
  3. +7
    -2
      src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx
  4. +4
    -2
      src/components/UserWorkspacePage/AssignedProjects.tsx
  5. +9
    -7
      src/components/UserWorkspacePage/ProjectGrid.tsx
  6. +6
    -2
      src/components/UserWorkspacePage/UserWorkspacePage.tsx
  7. +5
    -1
      src/components/UserWorkspacePage/UserWorkspaceWrapper.tsx
  8. +5
    -1
      src/middleware.ts

+ 29
- 1
src/app/api/financialsummary/actions.ts Voir le fichier

@@ -1,9 +1,10 @@
"use server";

import { serverFetchJson } from "@/app/utils/fetchUtil";
import { serverFetchBlob, serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { Dayjs } from "dayjs";
import { cache } from "react";
import { FileResponse } from "../reports/actions";


export interface FinancialSummaryByClientResult {
@@ -65,3 +66,30 @@ export const searchFinancialSummaryByProject = cache(async (teamId?: number, cus
}
});

export interface FinancialSummaryByClientExcel {
customerCode: string;
customerName: string;
projectNo: number;
totalFee: number;
cumulativeExpenditure: number;
totalInvoiced: number;
totalReceived: number;
}

export interface ExportFinancialSummaryByClientExcel {
financialSummaryByClients: FinancialSummaryByClientExcel[]
}

export const exportFinancialSummaryByClientExcel = cache(async (data: ExportFinancialSummaryByClientExcel) => {
const reportBlob = await serverFetchBlob<FileResponse>(
`${BASE_API_URL}/dashboard/exportFinancialSummaryByClientExcel`,
{
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
},
);

return reportBlob
})

+ 2
- 0
src/app/api/projects/index.ts Voir le fichier

@@ -92,6 +92,8 @@ export interface AssignedProject extends ProjectWithTasks {
// Manhour info
hoursSpent: number;
hoursSpentOther: number;
currentStaffHoursSpent: number;
currentStaffHoursSpentOther: number;
hoursAllocated: number;
}



+ 7
- 2
src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx Voir le fichier

@@ -19,9 +19,10 @@ import SearchBox, { Criterion } from "../SearchBox";
import ProgressByClientSearch from "@/components/ProgressByClientSearch";
import { Suspense } from "react";
import { fetchFinancialSummaryCard } from "@/app/api/financialsummary";
import { searchFinancialSummaryByClient,searchFinancialSummaryByProject } from "@/app/api/financialsummary/actions";
import { exportFinancialSummaryByClientExcel, searchFinancialSummaryByClient,searchFinancialSummaryByProject } from "@/app/api/financialsummary/actions";
import ProjectFinancialCard from "./ProjectFinancialCard";
import VisibilityIcon from '@mui/icons-material/Visibility';
import { downloadFile } from "@/app/utils/commonUtil";

const ProjectFinancialSummary: React.FC = () => {
const [SearchCriteria, setSearchCriteria] = React.useState({});
@@ -458,7 +459,11 @@ const columns2 = [
fetchProjectTableData(params.row.teamId,params.row.cid)
};

const handleExportByClient = () => {
const handleExportByClient = async () => {
const response = await exportFinancialSummaryByClientExcel({financialSummaryByClients: clientFinancialRows})
if (response) {
downloadFile(new Uint8Array(response.blobValue), response.filename!!)
}
console.log(clientFinancialRows)
};



+ 4
- 2
src/components/UserWorkspacePage/AssignedProjects.tsx Voir le fichier

@@ -16,9 +16,11 @@ import { Props as UserWorkspaceProps } from "./UserWorkspacePage";

interface Props {
assignedProjects: UserWorkspaceProps["assignedProjects"];
maintainNormalStaffWorkspaceAbility?: boolean;
maintainManagementStaffWorkspaceAbility?: boolean;
}

const AssignedProjects: React.FC<Props> = ({ assignedProjects }) => {
const AssignedProjects: React.FC<Props> = ({ assignedProjects, maintainNormalStaffWorkspaceAbility, maintainManagementStaffWorkspaceAbility }) => {
const { t } = useTranslation("home");

// Projects
@@ -78,7 +80,7 @@ const AssignedProjects: React.FC<Props> = ({ assignedProjects }) => {
</Stack>
</CardContent>
</Card>
<ProjectGrid projects={filteredProjects} />
<ProjectGrid projects={filteredProjects} maintainNormalStaffWorkspaceAbility={maintainNormalStaffWorkspaceAbility} maintainManagementStaffWorkspaceAbility={maintainManagementStaffWorkspaceAbility}/>
</>
);
};


+ 9
- 7
src/components/UserWorkspacePage/ProjectGrid.tsx Voir le fichier

@@ -6,9 +6,11 @@ import { AssignedProject } from "@/app/api/projects";

interface Props {
projects: AssignedProject[];
maintainNormalStaffWorkspaceAbility?: boolean;
maintainManagementStaffWorkspaceAbility?: boolean;
}

const ProjectGrid: React.FC<Props> = ({ projects }) => {
const ProjectGrid: React.FC<Props> = ({ projects, maintainNormalStaffWorkspaceAbility, maintainManagementStaffWorkspaceAbility }) => {
const { t } = useTranslation("home");
return (
<Box>
@@ -30,7 +32,7 @@ const ProjectGrid: React.FC<Props> = ({ projects }) => {
{project.name}
</Typography>
{/* Hours Spent */}
<Typography variant="subtitle2">{t("Hours Spent:")}</Typography>
{(Boolean(maintainNormalStaffWorkspaceAbility) || Boolean(maintainManagementStaffWorkspaceAbility)) && <><Typography variant="subtitle2">{t("Hours Spent:")}</Typography>
<Box
sx={{
display: "flex",
@@ -40,7 +42,7 @@ const ProjectGrid: React.FC<Props> = ({ projects }) => {
>
<Typography variant="caption">{t("Normal")}</Typography>
<Typography>
{manhourFormatter.format(project.hoursSpent)}
{manhourFormatter.format(Boolean(maintainManagementStaffWorkspaceAbility) ? project.hoursSpent : project.currentStaffHoursSpent)}
</Typography>
</Box>
<Box
@@ -52,11 +54,11 @@ const ProjectGrid: React.FC<Props> = ({ projects }) => {
>
<Typography variant="caption">{t("(Others)")}</Typography>
<Typography>{`(${manhourFormatter.format(
project.hoursSpentOther,
Boolean(maintainManagementStaffWorkspaceAbility) ? project.hoursSpentOther : project.currentStaffHoursSpentOther,
)})`}</Typography>
</Box>
</Box></>}
{/* Hours Allocated */}
<Box
{Boolean(maintainManagementStaffWorkspaceAbility) && <Box
sx={{
display: "flex",
justifyContent: "space-between",
@@ -69,7 +71,7 @@ const ProjectGrid: React.FC<Props> = ({ projects }) => {
<Typography>
{manhourFormatter.format(project.hoursAllocated)}
</Typography>
</Box>
</Box>}
</CardContent>
</Card>
</Grid>


+ 6
- 2
src/components/UserWorkspacePage/UserWorkspacePage.tsx Voir le fichier

@@ -35,7 +35,9 @@ export interface Props {
holidays: HolidaysResult[];
teamTimesheets: TeamTimeSheets;
teamLeaves: TeamLeaves;
fastEntryEnabled?: boolean;
fastEntryEnabled: boolean;
maintainNormalStaffWorkspaceAbility: boolean;
maintainManagementStaffWorkspaceAbility: boolean;
}

const menuItemSx: SxProps = {
@@ -53,6 +55,8 @@ const UserWorkspacePage: React.FC<Props> = ({
teamTimesheets,
teamLeaves,
fastEntryEnabled,
maintainNormalStaffWorkspaceAbility,
maintainManagementStaffWorkspaceAbility,
}) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);

@@ -190,7 +194,7 @@ const UserWorkspacePage: React.FC<Props> = ({
timesheetRecords={defaultTimesheets}
/>
{assignedProjects.length > 0 ? (
<AssignedProjects assignedProjects={assignedProjects} />
<AssignedProjects assignedProjects={assignedProjects} maintainNormalStaffWorkspaceAbility={maintainNormalStaffWorkspaceAbility} maintainManagementStaffWorkspaceAbility={maintainManagementStaffWorkspaceAbility}/>
) : (
<Typography variant="subtitle1">
{t("You have no assigned projects!")}


+ 5
- 1
src/components/UserWorkspacePage/UserWorkspaceWrapper.tsx Voir le fichier

@@ -12,7 +12,7 @@ import {
} from "@/app/api/timesheets";
import { fetchHolidays } from "@/app/api/holidays";
import { getUserAbilities } from "@/app/utils/commonUtil";
import { MAINTAIN_TIMESHEET_FAST_TIME_ENTRY } from "@/middleware";
import { MAINTAIN_TIMESHEET_FAST_TIME_ENTRY, MAINTAIN_NORMAL_STAFF_WORKSPACE, MAINTAIN_MANAGEMENT_STAFF_WORKSPACE } from "@/middleware";

const UserWorkspaceWrapper: React.FC = async () => {
const [
@@ -38,6 +38,8 @@ const UserWorkspaceWrapper: React.FC = async () => {
]);

const fastEntryEnabled = abilities.includes(MAINTAIN_TIMESHEET_FAST_TIME_ENTRY)
const maintainNormalStaffWorkspaceAbility = abilities.includes(MAINTAIN_NORMAL_STAFF_WORKSPACE)
const maintainManagementStaffWorkspaceAbility = abilities.includes(MAINTAIN_MANAGEMENT_STAFF_WORKSPACE)

return (
<UserWorkspacePage
@@ -51,6 +53,8 @@ const UserWorkspaceWrapper: React.FC = async () => {
holidays={holidays}
// Change to access check
fastEntryEnabled={fastEntryEnabled}
maintainNormalStaffWorkspaceAbility={maintainNormalStaffWorkspaceAbility}
maintainManagementStaffWorkspaceAbility={maintainManagementStaffWorkspaceAbility}
/>
);
};


+ 5
- 1
src/middleware.ts Voir le fichier

@@ -58,6 +58,8 @@ export const [
DELETE_PROJECT,
MAINTAIN_TIMESHEET_FAST_TIME_ENTRY,
VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING,
MAINTAIN_NORMAL_STAFF_WORKSPACE,
MAINTAIN_MANAGEMENT_STAFF_WORKSPACE,
] = [
'MAINTAIN_USER',
'MAINTAIN_TIMESHEET',
@@ -96,7 +98,9 @@ export const [
'MAINTAIN_PROJECT',
'DELETE_PROJECT',
'MAINTAIN_TIMESHEET_FAST_TIME_ENTRY',
'VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING'
'VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING',
'MAINTAIN_NORMAL_STAFF_WORKSPACE',
'MAINTAIN_MANAGEMENT_STAFF_WORKSPACE'
]

const PRIVATE_ROUTES = [


Chargement…
Annuler
Enregistrer