diff --git a/src/app/api/reports/index.ts b/src/app/api/reports/index.ts index bf4bea8..223a680 100644 --- a/src/app/api/reports/index.ts +++ b/src/app/api/reports/index.ts @@ -1,3 +1,4 @@ +import { WildCard } from "@/app/utils/commonUtil"; import { records } from "../staff/actions"; export interface FinancialStatusReportFilter { @@ -68,9 +69,10 @@ export interface ProjectResourceOverconsumptionReportFilter { lowerLimit: number; } -export interface ProjectResourceOverconsumptionReportRequest { +export interface ProjectResourceOverconsumptionReportRequest extends WildCard { teamId?: number custId?: number + subsidiaryId?: number status: "All" | "Within Budget" | "Potential Overconsumption" | "Overconsumption" lowerLimit: number } diff --git a/src/app/utils/commonUtil.ts b/src/app/utils/commonUtil.ts index 72d4a56..d942bec 100644 --- a/src/app/utils/commonUtil.ts +++ b/src/app/utils/commonUtil.ts @@ -1,3 +1,8 @@ +export interface WildCard { + [key: string]: any; +} + + export const dateInRange = (currentDate: string, startDate: string, endDate: string) => { if (currentDate === undefined) { @@ -28,4 +33,19 @@ export const downloadFile = (blobData: Uint8Array, filename: string) => { link.href = url; link.setAttribute("download", filename); link.click(); -} \ No newline at end of file +} + +export function readIntFromString(input: string): [string, number | null] | string { + // Split the input string by the "-" character + if (!input.includes("-")) { + return [input, null] + } + const parts = input.split("-"); + + // Extract the string part and the integer part (if available) + const stringPart = parts.slice(0, parts.length - 1).join("-"); + const intPartStr = parts[parts.length - 1]; + const intPart = intPartStr ? parseInt(intPartStr, 10) : null; + + return [stringPart, intPart]; + } \ No newline at end of file diff --git a/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx b/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx index 5b08202..c6ee254 100644 --- a/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx +++ b/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx @@ -4,26 +4,38 @@ import SearchBox, { Criterion } from "../SearchBox"; import { useTranslation } from "react-i18next"; import { ProjectResult } from "@/app/api/projects"; import { fetchMonthlyWorkHoursReport, fetchProjectCashFlowReport, fetchProjectResourceOverconsumptionReport } from "@/app/api/reports/actions"; -import { downloadFile } from "@/app/utils/commonUtil"; +import { downloadFile, readIntFromString } from "@/app/utils/commonUtil"; import { BASE_API_URL } from "@/config/api"; import { ProjectResourceOverconsumptionReportFilter, ProjectResourceOverconsumptionReportRequest } from "@/app/api/reports"; import { StaffResult } from "@/app/api/staff"; import { TeamResult } from "@/app/api/team"; import { Customer } from "@/app/api/customer"; +import { Subsidiary } from "@/app/api/subsidiary"; interface Props { team: TeamResult[] customer: Customer[] + subsidiaries: Subsidiary[] } type SearchQuery = Partial>; type SearchParamNames = keyof SearchQuery; -const ResourceOverconsumptionReport: React.FC = ({ team, customer }) => { +const ResourceOverconsumptionReport: React.FC = ({ team, customer, subsidiaries }) => { const { t } = useTranslation("report"); - const teamCombo = team.map(t => `${t.name} - ${t.code}`) - const custCombo = customer.map(c => ({label: `${c.name} - ${c.code}`, value: c.id})) + console.log(customer) const statusCombo = ["Overconsumption", "Potential Overconsumption"] + const teamCombo = team.map(t => `${t.name} - ${t.code}`) + const custCombo = customer.map(c => ({ + value: `custId-${c.id}`, + label: `${c.code} - ${c.name}`, + group: t("Client") + })) + const subsidiariesCombo = subsidiaries.map(sub => ({ + value: `subsidiaryId-${sub.id}`, + label: `${sub.code} - ${sub.name}`, + group: t("Subsidiary") + })) // const staffCombo = staffs.map(staff => `${staff.name} - ${staff.staffId}`) // console.log(staffs) @@ -40,8 +52,8 @@ const ResourceOverconsumptionReport: React.FC = ({ team, customer }) => { label: t("Client"), paramName: "customer", type: "autocomplete", - options: custCombo, - needAll: true + options: [...subsidiariesCombo, ...custCombo], + // needAll: true }, { label: t("Status"), @@ -51,7 +63,7 @@ const ResourceOverconsumptionReport: React.FC = ({ team, customer }) => { needAll: true }, { - label: t("lowerLimit"), + label: t("Potential Overconsumption Threshold"), paramName: "lowerLimit", type: "number", }, @@ -65,6 +77,7 @@ return ( formType={"download"} criteria={searchCriteria} onSearch={async (query: any) => { + const [custType, id] = readIntFromString(query.customer) as [string, number] let index = 0 let postData: ProjectResourceOverconsumptionReportRequest = { status: "All", @@ -73,13 +86,13 @@ return ( if (query.team.length > 0 && query.team.toLocaleLowerCase() !== "all") { index = teamCombo.findIndex(team => team === query.team) postData.teamId = team[index].id - } - if (typeof query.customer === "string" && query.customer.toLocaleLowerCase() !== "all") { - postData.custId = query.customer } if (Boolean(query.lowerLimit)) { postData.lowerLimit = query.lowerLimit/100 } + if (id) { + postData[custType] = id + } postData.status = query.status console.log(postData) const response = await fetchProjectResourceOverconsumptionReport(postData) diff --git a/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReportWrapper.tsx b/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReportWrapper.tsx index 1ab9d24..0f6e234 100644 --- a/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReportWrapper.tsx +++ b/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReportWrapper.tsx @@ -1,18 +1,27 @@ import React from "react"; import ResourceOvercomsumptionReportLoading from "./ResourceOverconsumptionReportLoading"; import ResourceOverconsumptionReport from "./ResourceOverconsumptionReport"; -import { fetchAllCustomers } from "@/app/api/customer"; import { fetchTeam } from "@/app/api/team"; +import { fetchAllCustomers } from "@/app/api/customer"; +import { fetchAllSubsidiaries } from "@/app/api/subsidiary"; interface SubComponents { Loading: typeof ResourceOvercomsumptionReportLoading; } const ResourceOvercomsumptionReportWrapper: React.FC & SubComponents = async () => { - const customers = await fetchAllCustomers() - const teams = await fetchTeam () + const [ + teams, + customers, + subsidiaries] + = await Promise.all( + [ + fetchTeam(), + fetchAllCustomers(), + fetchAllSubsidiaries() + ]) - return ; + return ; }; ResourceOvercomsumptionReportWrapper.Loading = ResourceOvercomsumptionReportLoading;