@@ -131,6 +131,9 @@ export function convertLocaleStringToNumber(numberString: string): number { | |||
} | |||
export function timestampToDateString(timestamp: string): string { | |||
if (timestamp === null){ | |||
return "-" | |||
} | |||
const date = new Date(timestamp); | |||
const year = date.getFullYear(); | |||
const month = String(date.getMonth() + 1).padStart(2, "0"); | |||
@@ -344,7 +344,7 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||
/> | |||
</Grid> | |||
<Grid item xs={6}> | |||
{/* <Grid item xs={6}> | |||
<Checkbox | |||
{...register("isClpProject")} | |||
checked={Boolean(watch("isClpProject"))} | |||
@@ -353,7 +353,7 @@ const ProjectClientDetails: React.FC<Props> = ({ | |||
<Typography variant="overline" display="inline"> | |||
{t("CLP Project")} | |||
</Typography> | |||
</Grid> | |||
</Grid> */} | |||
</Grid> | |||
</Box> | |||
@@ -86,7 +86,7 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice, invoic | |||
const formData = new FormData(); | |||
formData.append('multipartFileList', file); | |||
const response = await importInvoices(formData); | |||
const response = await importIssuedInovice(formData); | |||
// response: status, message, projectList, emptyRowList, invoiceList | |||
console.log(response) | |||
@@ -236,7 +236,7 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice, invoic | |||
{ name: "projectName", label: t("Project Name") }, | |||
{ name: "team", label: t("Team") }, | |||
{ name: "issuedDate", label: t("Issue Date") }, | |||
{ name: "receivedAmount", label: t("Amount (HKD)") }, | |||
{ name: "issuedAmount", label: t("Amount (HKD)") }, | |||
{ name: "receiptDate", label: t("Settle Date") }, | |||
{ name: "receivedAmount", label: t("Actual Received Amount (HKD)") }, | |||
], | |||
@@ -271,8 +271,8 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice, invoic | |||
flexWrap="wrap" | |||
spacing={2} | |||
> | |||
{/* <ButtonGroup variant="contained"> */} | |||
{/* <Button startIcon={<FileUploadIcon />} variant="contained" component="label"> | |||
<ButtonGroup variant="contained"> | |||
<Button startIcon={<FileUploadIcon />} variant="contained" component="label"> | |||
<input | |||
id='importExcel' | |||
type='file' | |||
@@ -291,9 +291,9 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice, invoic | |||
onChange={(event) => {handleRecImportClick(event)}} | |||
/> | |||
{t("Import Invoice Amount Receive Summary")} | |||
</Button> */} | |||
{/* </ButtonGroup> */} | |||
<Button startIcon={<FileUploadIcon />} variant="contained" component="label"> | |||
</Button> | |||
</ButtonGroup> | |||
{/* <Button startIcon={<FileUploadIcon />} variant="contained" component="label"> | |||
<input | |||
id='importExcel' | |||
type='file' | |||
@@ -302,7 +302,7 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice, invoic | |||
onChange={(event) => {handleImportClick(event)}} | |||
/> | |||
{t("Import Invoice Summary")} | |||
</Button> | |||
</Button> */} | |||
</Stack> | |||
{ | |||
// tabIndex == 0 && | |||
@@ -56,9 +56,9 @@ const InvoiceSearchWrapper: React.FC & SubComponents = async () => { | |||
projectName: invoice.projectName, | |||
team: invoice.team, | |||
issuedDate: timestampToDateString(invoice.invoiceDate)!!, | |||
receiptDate: timestampToDateString(invoice.receiptDate??0)!!, | |||
receiptDate: timestampToDateString(invoice.receiptDate??null)!!, | |||
issuedAmount: moneyFormatter.format(invoice.issueAmount), | |||
receivedAmount: moneyFormatter.format(invoice.paidAmount) | |||
receivedAmount: invoice.paidAmount === null ? "-" : moneyFormatter.format(invoice.paidAmount) | |||
} | |||
}) | |||
@@ -67,16 +67,16 @@ import { | |||
MAINTAIN_GROUP, | |||
MAINTAIN_HOLIDAY, | |||
VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING, | |||
GENERATE_LATE_START_REPORTS, | |||
GENERATE_LATE_START_REPORT, | |||
GENERATE_PROJECT_POTENTIAL_DELAY_REPORT, | |||
GENERATE_RESOURCE_OVERCONSUMPTION_REPORT, | |||
GENERATE_COST_ANT_EXPENSE_REPORT, | |||
GENERATE_COST_AND_EXPENSE_REPORT, | |||
GENERATE_PROJECT_COMPLETION_REPORT, | |||
GENERATE_PROJECT_PANDL_REPORT, | |||
GENERATE_FINANCIAL_STATUS_REPORT, | |||
GENERATE_PROJECT_CASH_FLOW_REPORT, | |||
GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT | |||
} from "@/middleware"; | |||
import { SessionWithAbilities } from "../AppBar/NavigationToggle"; | |||
import { authOptions } from "@/config/authConfig"; | |||
@@ -190,16 +190,16 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
label: "Analysis Report", | |||
path: "", | |||
isHidden: ![ | |||
GENERATE_LATE_START_REPORTS, | |||
GENERATE_LATE_START_REPORT, | |||
GENERATE_PROJECT_POTENTIAL_DELAY_REPORT, | |||
GENERATE_RESOURCE_OVERCONSUMPTION_REPORT, | |||
GENERATE_COST_ANT_EXPENSE_REPORT, | |||
GENERATE_COST_AND_EXPENSE_REPORT, | |||
GENERATE_PROJECT_COMPLETION_REPORT, | |||
GENERATE_PROJECT_PANDL_REPORT, | |||
GENERATE_FINANCIAL_STATUS_REPORT, | |||
GENERATE_PROJECT_CASH_FLOW_REPORT, | |||
GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT | |||
].some((ability) => | |||
abilities!.includes(ability), | |||
), | |||
@@ -208,7 +208,7 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
icon: <Analytics />, | |||
label: "Late Start Report", | |||
path: "/analytics/LateStartReport", | |||
isHidden: ![GENERATE_LATE_START_REPORTS].some((ability) => | |||
isHidden: ![GENERATE_LATE_START_REPORT].some((ability) => | |||
abilities!.includes(ability), | |||
), | |||
}, | |||
@@ -232,7 +232,7 @@ const NavigationContent: React.FC<Props> = ({ abilities, username }) => { | |||
icon: <Analytics />, | |||
label: "Cost and Expense Report", | |||
path: "/analytics/CostandExpenseReport", | |||
isHidden: ![GENERATE_COST_ANT_EXPENSE_REPORT].some((ability) => | |||
isHidden: ![GENERATE_COST_AND_EXPENSE_REPORT].some((ability) => | |||
abilities!.includes(ability), | |||
), | |||
}, | |||
@@ -954,7 +954,7 @@ const ProjectCashFlow: React.FC = () => { | |||
className="text-sm font-medium ml-5" | |||
style={{ color: "#898d8d" }} | |||
> | |||
Accounts Receivable | |||
Remaining Budget | |||
</div> | |||
<div | |||
className="text-lg font-medium ml-5 mb-2" | |||
@@ -362,7 +362,7 @@ const StaffUtilization: React.FC<Props> = ({ abilities, staff }) => { | |||
const startCount = weeklyPlanned[i].startCount | |||
const endCount = weeklyPlanned[i].endCount | |||
for (var j = 0; j < weeklyPlanned[i].searchDuration; j++) { | |||
if (j >= startCount && j < endCount) { | |||
if (j >= startCount && j <= endCount) { | |||
weeklyPlannedSubList.push(weeklyPlanned[i].AverageManhours) | |||
} else { | |||
weeklyPlannedSubList.push(0) | |||
@@ -503,7 +503,8 @@ const StaffUtilization: React.FC<Props> = ({ abilities, staff }) => { | |||
const fetchMonthlyUnsubmittedData = async () => { | |||
const fetchResult = await fetchMonthlyUnsubmit(teamUnsubmitTeamId, unsubmitMonthlyFromValue.format('YYYY-MM-DD'), unsubmitMonthlyToValue.endOf('month').format('YYYY-MM-DD'), holidayDates); | |||
const fetchResult = await fetchMonthlyUnsubmit(teamUnsubmitTeamId, unsubmitMonthlyFromValue.startOf('month').format('YYYY-MM-DD'), unsubmitMonthlyToValue.endOf('month').format('YYYY-MM-DD'), holidayDates); | |||
const result = [] | |||
const staffList = [] | |||
var maxValue = 5 | |||
@@ -59,16 +59,16 @@ export const [ | |||
VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING, | |||
MAINTAIN_NORMAL_STAFF_WORKSPACE, | |||
MAINTAIN_MANAGEMENT_STAFF_WORKSPACE, | |||
GENERATE_LATE_START_REPORTS, | |||
GENERATE_LATE_START_REPORT, | |||
GENERATE_PROJECT_POTENTIAL_DELAY_REPORT, | |||
GENERATE_RESOURCE_OVERCONSUMPTION_REPORT, | |||
GENERATE_COST_ANT_EXPENSE_REPORT, | |||
GENERATE_COST_AND_EXPENSE_REPORT, | |||
GENERATE_PROJECT_COMPLETION_REPORT, | |||
GENERATE_PROJECT_PANDL_REPORT, | |||
GENERATE_FINANCIAL_STATUS_REPORT, | |||
GENERATE_PROJECT_CASH_FLOW_REPORT, | |||
GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT | |||
] = [ | |||
'MAINTAIN_USER', | |||
'MAINTAIN_TIMESHEET', | |||
@@ -109,16 +109,16 @@ export const [ | |||
'VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING', | |||
'MAINTAIN_NORMAL_STAFF_WORKSPACE', | |||
'MAINTAIN_MANAGEMENT_STAFF_WORKSPACE', | |||
'GENERATE_LATE_START_REPORTS', | |||
'GENERATE_PROJECT_POTENTIAL_DELAY_REPORT', | |||
'GENERATE_RESOURCE_OVERCONSUMPTION_REPORT', | |||
'GENERATE_COST_ANT_EXPENSE_REPORT', | |||
'GENERATE_PROJECT_COMPLETION_REPORT', | |||
'GENERATE_PROJECT_P&L_REPORT', | |||
'GENERATE_FINANCIAL_STATUS_REPORT', | |||
'GENERATE_PROJECT_CASH_FLOW_REPORT', | |||
'GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT', | |||
'GENERATE_CROSS_TEAM_CHARGE_REPORT', | |||
'G_LATE_START_REPORT', | |||
'G_PROJECT_POTENTIAL_DELAY_REPORT', | |||
'G_RESOURCE_OVERCONSUMPTION_REPORT', | |||
'G_COST_AND_EXPENSE_REPORT', | |||
'G_PROJECT_COMPLETION_REPORT', | |||
'G_PROJECT_P&L_REPORT', | |||
'G_FINANCIAL_STATUS_REPORT', | |||
'G_PROJECT_CASH_FLOW_REPORT', | |||
'G_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT', | |||
'G_CROSS_TEAM_CHARGE_REPORT' | |||
] | |||
const PRIVATE_ROUTES = [ | |||
@@ -243,20 +243,21 @@ export default async function middleware( | |||
if (req.nextUrl.pathname.startsWith('/analytics')) { | |||
isAuth = [ | |||
GENERATE_LATE_START_REPORTS, | |||
GENERATE_LATE_START_REPORT, | |||
GENERATE_PROJECT_POTENTIAL_DELAY_REPORT, | |||
GENERATE_RESOURCE_OVERCONSUMPTION_REPORT, | |||
GENERATE_COST_ANT_EXPENSE_REPORT, | |||
GENERATE_COST_AND_EXPENSE_REPORT, | |||
GENERATE_PROJECT_COMPLETION_REPORT, | |||
GENERATE_PROJECT_PANDL_REPORT, | |||
GENERATE_FINANCIAL_STATUS_REPORT, | |||
GENERATE_PROJECT_CASH_FLOW_REPORT, | |||
GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT, | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT,].some((ability) => abilities.includes(ability)); | |||
GENERATE_CROSS_TEAM_CHARGE_REPORT | |||
].some((ability) => abilities.includes(ability)); | |||
} | |||
if (req.nextUrl.pathname.startsWith('/analytics/LateStartReport')) { | |||
isAuth = [GENERATE_LATE_START_REPORTS].some((ability) => abilities.includes(ability)); | |||
isAuth = [GENERATE_LATE_START_REPORT].some((ability) => abilities.includes(ability)); | |||
} | |||
if (req.nextUrl.pathname.startsWith('/analytics/ProjectPotentialDelayReport')) { | |||
@@ -268,7 +269,7 @@ export default async function middleware( | |||
} | |||
if (req.nextUrl.pathname.startsWith('/analytics/CostandExpenseReport')) { | |||
isAuth = [GENERATE_COST_ANT_EXPENSE_REPORT].some((ability) => abilities.includes(ability)); | |||
isAuth = [GENERATE_COST_AND_EXPENSE_REPORT].some((ability) => abilities.includes(ability)); | |||
} | |||
if (req.nextUrl.pathname.startsWith('/analytics/ProjectCompletionReport')) { | |||