|
|
@@ -20,6 +20,7 @@ import org.apache.poi.ss.util.CellAddress |
|
|
|
import org.apache.poi.ss.util.CellRangeAddress |
|
|
|
import org.apache.poi.ss.util.CellUtil |
|
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook |
|
|
|
import org.hibernate.jdbc.Work |
|
|
|
import org.springframework.core.io.ClassPathResource |
|
|
|
import org.springframework.stereotype.Service |
|
|
|
import java.io.ByteArrayOutputStream |
|
|
@@ -50,6 +51,8 @@ open class ReportService( |
|
|
|
private val SALART_LIST_TEMPLATE = "templates/report/Salary Template.xlsx" |
|
|
|
private val LATE_START_REPORT = "templates/report/AR01_Late Start Report v01.xlsx" |
|
|
|
private val RESOURCE_OVERCONSUMPTION_REPORT = "templates/report/AR03_Resource Overconsumption.xlsx" |
|
|
|
private val COMPLETE_PROJECT_OUTSTANDING_RECEIVABLE = "templates/report/AR06_Project Completion Report with Outstanding Accounts Receivable v02.xlsx" |
|
|
|
private val COMPLETION_PROJECT = "templates/report/AR05_Project Completion Report.xlsx" |
|
|
|
|
|
|
|
// ==============================|| GENERATE REPORT ||============================== // |
|
|
|
|
|
|
@@ -174,6 +177,28 @@ open class ReportService( |
|
|
|
|
|
|
|
return outputStream.toByteArray() |
|
|
|
} |
|
|
|
@Throws(IOException::class) |
|
|
|
fun generateProjectCompletionReport( |
|
|
|
args: MutableMap<String, Any>, |
|
|
|
result: List<Map<String, Any>> |
|
|
|
): ByteArray { |
|
|
|
var REPORT_PATH: String = COMPLETE_PROJECT_OUTSTANDING_RECEIVABLE |
|
|
|
if (args.get("outstanding") as Boolean == false) { |
|
|
|
REPORT_PATH = COMPLETION_PROJECT |
|
|
|
} |
|
|
|
// Generate the Excel report with query results |
|
|
|
val workbook: Workbook = createProjectCompletionReport( |
|
|
|
args, |
|
|
|
result, |
|
|
|
REPORT_PATH |
|
|
|
) |
|
|
|
// Write the workbook to a ByteArrayOutputStream |
|
|
|
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() |
|
|
|
workbook.write(outputStream) |
|
|
|
workbook.close() |
|
|
|
|
|
|
|
return outputStream.toByteArray() |
|
|
|
} |
|
|
|
|
|
|
|
@Throws(IOException::class) |
|
|
|
fun exportSalaryList(salarys: List<Salary>): ByteArray { |
|
|
@@ -1061,6 +1086,49 @@ open class ReportService( |
|
|
|
|
|
|
|
return workbook |
|
|
|
} |
|
|
|
private fun createProjectCompletionReport( |
|
|
|
args: MutableMap<String, Any>, |
|
|
|
result: List<Map<String, Any>>, |
|
|
|
templatePath: String |
|
|
|
): Workbook { |
|
|
|
val resource = ClassPathResource(templatePath) |
|
|
|
val templateInputStream = resource.inputStream |
|
|
|
val workbook: Workbook = XSSFWorkbook(templateInputStream) |
|
|
|
|
|
|
|
val accountingStyle = workbook.createDataFormat().getFormat("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)") |
|
|
|
val monthStyle = workbook.createDataFormat().getFormat("MMM YYYY") |
|
|
|
val dateStyle = workbook.createDataFormat().getFormat("dd/mm/yyyy") |
|
|
|
|
|
|
|
val sheet: Sheet = workbook.getSheetAt(0) |
|
|
|
|
|
|
|
var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field |
|
|
|
var columnIndex = 2 |
|
|
|
var tempRow = sheet.getRow(rowIndex) |
|
|
|
var tempCell = tempRow.getCell(columnIndex) |
|
|
|
tempCell.setCellValue(FORMATTED_TODAY) |
|
|
|
|
|
|
|
rowIndex = 2 |
|
|
|
tempCell = sheet.getRow(rowIndex).getCell(columnIndex) |
|
|
|
tempCell.setCellValue("${args.get("startDate").toString()} to ${args.get("endDate").toString()}") |
|
|
|
|
|
|
|
rowIndex = 5 |
|
|
|
columnIndex = 0 |
|
|
|
result.forEachIndexed { index, obj -> |
|
|
|
tempCell = sheet.getRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue((index + 1).toDouble()) |
|
|
|
val keys = obj.keys.toList() |
|
|
|
keys.forEachIndexed { keyIndex, key -> |
|
|
|
tempCell = sheet.getRow(rowIndex).getCell(columnIndex + keyIndex + 1) ?: sheet.getRow(rowIndex).createCell(columnIndex + keyIndex + 1) |
|
|
|
when (obj[key]) { |
|
|
|
is Double -> tempCell.setCellValue(obj[key] as Double) |
|
|
|
else -> tempCell.setCellValue(obj[key] as String ) |
|
|
|
} |
|
|
|
} |
|
|
|
rowIndex++ |
|
|
|
} |
|
|
|
return workbook |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun createProjectResourceOverconsumptionReport( |
|
|
|
team: String, |
|
|
@@ -1273,6 +1341,54 @@ open class ReportService( |
|
|
|
) |
|
|
|
return jdbcDao.queryForList(sql.toString(), args) |
|
|
|
} |
|
|
|
open fun getProjectCompletionReport(args: Map<String, Any>): List<Map<String, Any>> { |
|
|
|
val sql = StringBuilder("select" |
|
|
|
+ " result.code, " |
|
|
|
+ " result.name, " |
|
|
|
+ " result.teamCode, " |
|
|
|
+ " result.custCode, " ) |
|
|
|
if (args.get("outstanding") as Boolean) { |
|
|
|
sql.append(" result.totalBudget - COALESCE(i.issueAmount , 0) + COALESCE(i.issueAmount, 0) - COALESCE(i.paidAmount, 0) as `Receivable Remained`, ") |
|
|
|
} |
|
|
|
sql.append( |
|
|
|
" DATE_FORMAT(result.actualEnd, '%d/%m/%Y') as actualEnd " |
|
|
|
+ " from ( " |
|
|
|
+ " SELECT " |
|
|
|
+ " pt.project_id, " |
|
|
|
+ " min(p.code) as code, " |
|
|
|
+ " min(p.name) as name, " |
|
|
|
+ " min(t.code) as teamCode, " |
|
|
|
+ " min(c.code) as custCode, " |
|
|
|
+ " min(p.actualEnd) as actualEnd, " |
|
|
|
+ " sum(COALESCE(tns.totalConsumed*sal.hourlyRate, 0)) as totalBudget " |
|
|
|
+ " FROM ( " |
|
|
|
+ " SELECT " |
|
|
|
+ " t.staffId, " |
|
|
|
+ " sum(t.normalConsumed + COALESCE(t.otConsumed, 0)) as totalConsumed, " |
|
|
|
+ " t.projectTaskId AS taskId " |
|
|
|
+ " FROM timesheet t " |
|
|
|
+ " LEFT JOIN staff s ON t.staffId = s.id " |
|
|
|
+ " LEFT JOIN team te on s.teamId = te.id " |
|
|
|
+ " GROUP BY t.staffId, t.projectTaskId " |
|
|
|
+ " order by t.staffId " |
|
|
|
+ " ) AS tns " |
|
|
|
+ " inner join project_task pt ON tns.taskId = pt.id " |
|
|
|
+ " left JOIN staff s ON tns.staffId = s.id " |
|
|
|
+ " left join salary sal on s.salaryId = sal.salaryPoint " |
|
|
|
+ " left JOIN team t ON s.teamId = t.id " |
|
|
|
+ " left join project p on p.id = pt.project_id " |
|
|
|
+ " left join customer c on c.id = p.customerId " |
|
|
|
+ " where p.deleted = false " |
|
|
|
+ " and p.status = 'Completed' " |
|
|
|
+ " and p.actualEnd BETWEEN :startDate and :endDate " |
|
|
|
+ " group by pt.project_id " |
|
|
|
+ " ) as result " |
|
|
|
+ " left join invoice i on result.code = i.projectCode " |
|
|
|
+ " order by result.actualEnd " |
|
|
|
) |
|
|
|
|
|
|
|
return jdbcDao.queryForList(sql.toString(), args) |
|
|
|
} |
|
|
|
|
|
|
|
open fun getProjectResourceOverconsumptionReport(args: Map<String, Any>): List<Map<String, Any>> { |
|
|
|
val sql = StringBuilder("WITH teamNormalConsumed AS (" |
|
|
|