From 953adbaaf0c6a511a591ca08d26464b50e92b5e1 Mon Sep 17 00:00:00 2001 From: "Mac\\David" Date: Sun, 26 May 2024 19:03:07 +0800 Subject: [PATCH] add dashboard api --- .../modules/data/service/DashboardService.kt | 365 +++++++++++++++++- .../modules/data/web/DashboardController.kt | 20 + 2 files changed, 383 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt b/src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt index d3b2c09..279a397 100644 --- a/src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt +++ b/src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt @@ -509,8 +509,8 @@ open class DashboardService( + " p.name as projectName," + " t.code as team," + " s.name as teamLead," - + " p.actualStart as startDate," - + " p.planEnd as targetEndDate," + + " date_format(p.actualStart, '%Y-%m-%d') as startDate," + + " date_format(p.planEnd, '%Y-%m-%d') as targetEndDate," + " c.name as client," + " coalesce(s2.name,'N/A') as subsidiary" + " from project p" @@ -524,6 +524,367 @@ open class DashboardService( return jdbcDao.queryForList(sql.toString(), args) } + fun CashFlowMonthlyIncomeByMonth(args: Map): List> { + val sql = StringBuilder("select" + + " months.month as monthInvoice," + + " coalesce (invoice.invoiceMonth,'-') as invoiceMonth," + + " coalesce (invoice.income,0) as income," + + " SUM(COALESCE(invoice.income, 0)) OVER (ORDER BY months.month) AS cumulativeIncome" + + " FROM (" + + " SELECT 01 AS month" + + " UNION" + + " SELECT 02" + + " UNION" + + " SELECT 03" + + " UNION" + + " SELECT 04" + + " UNION" + + " SELECT 05" + + " UNION" + + " SELECT 06" + + " UNION" + + " SELECT 07" + + " UNION" + + " SELECT 08" + + " UNION" + + " SELECT 09" + + " UNION" + + " SELECT 10" + + " UNION" + + " SELECT 11" + + " union" + + " select 12" + + " ) AS months" + + " left join(" + + " select" + + " month(i.receiptDate) as invoiceMonth," + + " coalesce(sum(i.paidAmount),0) as income" + + " from project p" + + " left join invoice i on p.code = i.projectCode" + + " where p.status = 'On-going'" + + " and p.id in (:projectIds)" + + " and year(i.receiptDate) = :year" + + " and i.id is not null" + + " group by month(i.receiptDate)" + + " ) as invoice on months.month = invoice.invoiceMonth" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + + fun CashFlowMonthlyExpenditureByMonth(args: Map): List> { + val sql = StringBuilder("select" + + " months.month as monthExpenditure," + + " coalesce (expenditure.recordMonth,'-') as recordMonth," + + " coalesce (expenditure.expenditure,0) as expenditure," + + " SUM(COALESCE(expenditure.expenditure, 0)) OVER (ORDER BY months.month) AS cumulativeExpenditure" + + " FROM (" + + " SELECT 01 AS month" + + " UNION" + + " SELECT 02" + + " UNION" + + " SELECT 03" + + " UNION" + + " SELECT 04" + + " UNION" + + " SELECT 05" + + " UNION" + + " SELECT 06" + + " UNION" + + " SELECT 07" + + " UNION" + + " SELECT 08" + + " UNION" + + " SELECT 09" + + " UNION" + + " SELECT 10" + + " UNION" + + " SELECT 11" + + " union" + + " select 12" + + " ) AS months" + + " left join(" + + " SELECT" + + " r.recordMonth as recordMonth," + + " sum(r.cumulativeExpenditure) as expenditure" + + " from(" + + " select" + + " month(t.recordDate) as recordMonth," + + " (coalesce(sum(t.normalConsumed),0) * s2.hourlyRate) + (coalesce(sum(t.otConsumed),0) * s2.hourlyRate * 1.0) as cumulativeExpenditure" + + " from project p" + + " left join project_task pt on p.id = pt.project_id" + + " left join timesheet t on pt.id = t.projectTaskId" + + " left join staff s on t.staffId = s.id" + + " left join salary s2 on s.salaryId = s2.salaryPoint" + + " where t.id is not null" + + " and p.id in (:projectIds)" + + " and year(t.recordDate) = :year" + + " group by month(t.recordDate),s2.hourlyRate" + + " ) as r" + + " group by r.recordMonth" + + " ) as expenditure on months.month = expenditure.recordMonth" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + fun CashFlowReceivableAndExpenditure(args: Map): List> { + val sql = StringBuilder("select" + + "coalesce (round(sum(i.paidAmount)/sum(i.issueAmount)*100,0)) as receivedPercentage," + + "coalesce (round(expenditure.expenditure/(sum(p.expectedTotalFee)*0.8)*100,0)) as expenditurePercentage," + + " coalesce (sum(i.issueAmount),0) as totalInvoiced," + + " coalesce (sum(i.paidAmount),0) as totalReceived," + + " coalesce (sum(i.issueAmount) - sum(i.paidAmount),0) as receivable," + + " coalesce (round(sum(p.expectedTotalFee)*0.8,2),0) as totalBudget," + + " coalesce (expenditure.expenditure) as totalExpenditure" + + " from project p" + + " left join invoice i on p.code = i.projectCode" + + " left join(" + + " select" + + " sum(r.expenditure) as expenditure" + + " from(" + + " select" + + " (coalesce(sum(t.normalConsumed),0) * s2.hourlyRate) + (coalesce(sum(t.otConsumed),0) * s2.hourlyRate * 1.0) as expenditure" + + " from project p" + + " left join project_task pt on p.id = pt.project_id" + + " left join timesheet t on pt.id = t.projectTaskId" + + " left join staff s on t.staffId = s.id" + + " left join salary s2 on s.salaryId = s2.salaryPoint" + + " where t.id is not null" + + " and p.id in (:projectIds)" + + " group by s2.hourlyRate" + + " ) as r" + + " ) as expenditure on 1=1" + + " where p.id in (:projectIds)" + + " group by expenditure.expenditure" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + fun CashFlowAnticipateIncome(args: Map): List> { + val sql = StringBuilder("select" + + " months.month as monthanticipateIncome," + + " coalesce (anticipateIncome.anticipateIncomeDate,'-') as anticipateIncomeDate," + + " coalesce (anticipateIncome.anticipateIncome,0) as anticipateIncome" + + " FROM (" + + " SELECT 01 AS month" + + " UNION" + + " SELECT 02" + + " UNION" + + " SELECT 03" + + " UNION" + + " SELECT 04" + + " UNION" + + " SELECT 05" + + " UNION" + + " SELECT 06" + + " UNION" + + " SELECT 07" + + " UNION" + + " SELECT 08" + + " UNION" + + " SELECT 09" + + " UNION" + + " SELECT 10" + + " UNION" + + " SELECT 11" + + " union" + + " select 12" + + " ) AS months" + + " left join(" + + " select" + + " month(mp.date) as anticipateIncomeDate," + + " sum(mp.amount) as anticipateIncome" + + " from project p" + + " left join milestone m on p.id = m.projectId" + + " left join milestone_payment mp on m.id = mp.milestoneId" + + " where p.id in (:projecIds)" + + " group by month(mp.date)" + + " ) as anticipateIncome on months.month = anticipateIncome.anticipateIncomeDate" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + fun CashFlowAnticipateExpenditure(args: Map): List> { + val sql = StringBuilder("select" + + " p.id, p.name," + + " date_format(p.planStart, '%Y-%m') as planStart," + + " date_format(p.planEnd, '%Y-%m') as planEnd," + + " month(p.planStart) as startMonth," + + " PERIOD_DIFF(DATE_FORMAT(p.planEnd, '%Y%m'), DATE_FORMAT(p.planStart, '%Y%m'))+1 AS 'Duration'," + + " ROUND(p.totalManhour / (PERIOD_DIFF(DATE_FORMAT(p.planEnd, '%Y%m'), DATE_FORMAT(p.planStart, '%Y%m'))+1), 2) AS 'Average Manhours'," + + " p.teamLead, p.totalManhour" + + " FROM project p" + + " WHERE p.status = 'On-going'" + + " and p.id in (:productIds)" + + " order by teamLead, planStart" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + fun CashFlowLedger(args: Map): List> { + val sql = StringBuilder("select" + + " date," + + " COALESCE(ROUND(income, 2), 0) AS income," + + " COALESCE(ROUND(expenditure, 2), 0) AS expenditure," + + " ROUND(SUM(COALESCE(income, 0) - COALESCE(expenditure, 0)) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 2) AS balance," + + " CASE" + + " WHEN income > 0 THEN paymentMilestone" + + " ELSE 'Monthly Manpower Expenditure'" + + " END AS remarks" + + " FROM" + + " (" + + " SELECT" + + " date_format(i.receiptDate, '%b %y') AS date," + + " sum(i.paidAmount) AS income," + + " NULL AS expenditure," + + " i.paymentMilestone AS paymentMilestone" + + " FROM" + + " project p" + + " LEFT JOIN invoice i ON p.code = i.projectCode" + + " WHERE" + + " p.id IN (:projectIds)" + + " AND i.paidAmount IS NOT NULL" + + " GROUP BY" + + " date_format(i.receiptDate, '%b %y')," + + " i.paymentMilestone" + + " UNION" + + " SELECT" + + " date_format(r.date, '%b %y') AS date," + + " NULL AS income," + + " sum(r.expenditure) AS expenditure," + + " NULL AS paymentMilestone" + + " FROM" + + " (" + + " SELECT" + + " t.recordDate AS date," + + " (COALESCE(SUM(t.normalConsumed), 0) * s2.hourlyRate) + (COALESCE(SUM(t.otConsumed), 0) * s2.hourlyRate * 1.0) AS expenditure" + + " FROM" + + " project p" + + " LEFT JOIN project_task pt ON p.id = pt.project_id" + + " LEFT JOIN timesheet t ON pt.id = t.projectTaskId" + + " LEFT JOIN staff s ON t.staffId = s.id" + + " LEFT JOIN salary s2 ON s.salaryId = s2.salaryPoint" + + " WHERE" + + " t.id IS NOT NULL" + + " AND p.id IN (:projectIds)" + + " GROUP BY" + + " s2.hourlyRate," + + " t.recordDate" + + " ) AS r" + + " GROUP BY" + + " date_format(r.date, '%b %y')" + + " ) AS combined_data" + + " ORDER BY" + + " date" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + fun TeamCashFlowIncome(args: Map): List> { + val sql = StringBuilder("select" + + " months.month as monthInvoice," + + " coalesce (invoice.invoiceMonth,'-') as invoiceMonth," + + " coalesce (invoice.income,0) as income," + + " SUM(COALESCE(invoice.income, 0)) OVER (ORDER BY months.month) AS cumulativeIncome" + + " FROM (" + + " SELECT 01 AS month" + + " UNION" + + " SELECT 02" + + " UNION" + + " SELECT 03" + + " UNION" + + " SELECT 04" + + " UNION" + + " SELECT 05" + + " UNION" + + " SELECT 06" + + " UNION" + + " SELECT 07" + + " UNION" + + " SELECT 08" + + " UNION" + + " SELECT 09" + + " UNION" + + " SELECT 10" + + " UNION" + + " SELECT 11" + + " union" + + " select 12" + + " ) AS months" + + " left join(" + + " select" + + " month(i.receiptDate) as invoiceMonth," + + " coalesce(sum(i.paidAmount),0) as income" + + " from project p" + + " left join team t on p.teamLead = t.teamLead" + + " left join invoice i on p.code = i.projectCode" + + " where p.status = 'On-going'" + + " and t.id = :teamId" + + " and year(i.receiptDate) = :year" + + " and i.id is not null" + + " group by month(i.receiptDate)" + + " ) as invoice on months.month = invoice.invoiceMonth" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + fun TeamCashFlowExpenditure(args: Map): List> { + val sql = StringBuilder("select" + + " months.month as monthExpenditure," + + " coalesce (expenditure.recordMonth,'-') as recordMonth," + + " coalesce (expenditure.expenditure,0) as expenditure," + + " SUM(COALESCE(expenditure.expenditure, 0)) OVER (ORDER BY months.month) AS cumulativeExpenditure" + + " FROM (" + + " SELECT 01 AS month" + + " UNION" + + " SELECT 02" + + " UNION" + + " SELECT 03" + + " UNION" + + " SELECT 04" + + " UNION" + + " SELECT 05" + + " UNION" + + " SELECT 06" + + " UNION" + + " SELECT 07" + + " UNION" + + " SELECT 08" + + " UNION" + + " SELECT 09" + + " UNION" + + " SELECT 10" + + " UNION" + + " SELECT 11" + + " union" + + " select 12" + + " ) AS months" + + " left join(" + + " SELECT" + + " r.recordMonth as recordMonth," + + " sum(r.cumulativeExpenditure) as expenditure" + + " from(" + + " select" + + " month(t.recordDate) as recordMonth," + + " (coalesce(sum(t.normalConsumed),0) * s2.hourlyRate) + (coalesce(sum(t.otConsumed),0) * s2.hourlyRate * 1.0) as cumulativeExpenditure" + + " from project p" + + " left join team t2 on p.teamLead = t2.teamLead" + + " left join project_task pt on p.id = pt.project_id" + + " left join timesheet t on pt.id = t.projectTaskId" + + " left join staff s on t.staffId = s.id" + + " left join salary s2 on s.salaryId = s2.salaryPoint" + + " where t.id is not null" + + " and t2.id = :teamId" + + " and year(t.recordDate) = :year" + + " group by month(t.recordDate),s2.hourlyRate" + + " ) as r" + + " group by r.recordMonth" + + " ) as expenditure on months.month = expenditure.recordMonth" + ) + + return jdbcDao.queryForList(sql.toString(), args) + } + } diff --git a/src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt b/src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt index 7926dcc..dcd5b35 100644 --- a/src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt +++ b/src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt @@ -131,4 +131,24 @@ class DashboardController( val args = mutableMapOf() return dashboardService.CashFlowProject(args) } + @GetMapping("/searchCashFlowByMonth") + fun searchCashFlowByMonth(request: HttpServletRequest?): List> { + val args = mutableMapOf() + val projectIdList = request?.getParameter("projectIdList") + val year = request?.getParameter("year") + val projectIds = projectIdList?.split(",")?.map { it.toInt() }?.toList() + if (projectIds != null) { + args["projectIds"] = projectIds + } + if (year != null) { + args["year"] = year + } + val result = mutableMapOf() + val cashFlowMonthlyIncome = dashboardService.CashFlowMonthlyIncomeByMonth(args) + val cashFlowMonthlyExpenditure = dashboardService.CashFlowMonthlyExpenditureByMonth(args) + result["incomeList"] = cashFlowMonthlyIncome + result["expenditureList"] = cashFlowMonthlyExpenditure + return listOf(result) + } + } \ No newline at end of file