@@ -11,8 +11,8 @@ import java.util.Map; | |||||
import java.util.Optional; | import java.util.Optional; | ||||
public interface StaffRepository extends AbstractRepository<Staff, Long> { | public interface StaffRepository extends AbstractRepository<Staff, Long> { | ||||
List<StaffSearchInfo> findStaffSearchInfoByAndDeletedFalse(); | |||||
List<StaffSearchInfo> findStaffSearchInfoByAndDeletedFalseAndTeamIdIsNull(); | |||||
List<StaffSearchInfo> findStaffSearchInfoByAndDeletedFalseOrderByStaffIdAsc(); | |||||
List<StaffSearchInfo> findStaffSearchInfoByAndDeletedFalseAndTeamIdIsNullOrderByStaffIdAsc(); | |||||
List<StaffSearchInfo> findAllStaffSearchInfoByIdIn(List<Serializable> ids); | List<StaffSearchInfo> findAllStaffSearchInfoByIdIn(List<Serializable> ids); | ||||
Optional<Staff> findByStaffId(@Param("staffId") String staffId); | Optional<Staff> findByStaffId(@Param("staffId") String staffId); | ||||
@@ -41,10 +41,10 @@ open class StaffsService( | |||||
} | } | ||||
open fun allStaff(): List<StaffSearchInfo> { | open fun allStaff(): List<StaffSearchInfo> { | ||||
return staffRepository.findStaffSearchInfoByAndDeletedFalse(); | |||||
return staffRepository.findStaffSearchInfoByAndDeletedFalseOrderByStaffIdAsc(); | |||||
} | } | ||||
open fun StaffWithoutTeam(): List<StaffSearchInfo> { | open fun StaffWithoutTeam(): List<StaffSearchInfo> { | ||||
return staffRepository.findStaffSearchInfoByAndDeletedFalseAndTeamIdIsNull(); | |||||
return staffRepository.findStaffSearchInfoByAndDeletedFalseAndTeamIdIsNullOrderByStaffIdAsc(); | |||||
} | } | ||||
open fun getStaff(id: Long): Staff { | open fun getStaff(id: Long): Staff { | ||||
@@ -115,7 +115,7 @@ open class StaffsService( | |||||
@Transactional(rollbackFor = [Exception::class]) | @Transactional(rollbackFor = [Exception::class]) | ||||
open fun saveStaff(req: NewStaffRequest): Staff { | open fun saveStaff(req: NewStaffRequest): Staff { | ||||
val checkStaffIdList: List<StaffSearchInfo> = staffRepository.findStaffSearchInfoByAndDeletedFalse() | |||||
val checkStaffIdList: List<StaffSearchInfo> = staffRepository.findStaffSearchInfoByAndDeletedFalseOrderByStaffIdAsc() | |||||
checkStaffIdList.forEach{ s -> | checkStaffIdList.forEach{ s -> | ||||
if (s.staffId == req.staffId) { | if (s.staffId == req.staffId) { | ||||
throw UnprocessableEntityException("Duplicated StaffId Found") | throw UnprocessableEntityException("Duplicated StaffId Found") | ||||
@@ -20,6 +20,7 @@ open class Project : BaseEntity<Long>() { | |||||
@NotNull | @NotNull | ||||
@Column(name = "code", length = 30) | @Column(name = "code", length = 30) | ||||
@OrderBy("code asc") | |||||
open var code: String? = null | open var code: String? = null | ||||
@ManyToOne | @ManyToOne | ||||
@@ -12,7 +12,7 @@ import java.io.Serializable | |||||
import java.time.LocalDate | import java.time.LocalDate | ||||
interface ProjectRepository : AbstractRepository<Project, Long> { | interface ProjectRepository : AbstractRepository<Project, Long> { | ||||
fun findProjectSearchInfoByOrderByCreatedDesc(): List<ProjectSearchInfo> | |||||
fun findProjectSearchInfoByDeletedIsFalseOrderByCodeDesc(): List<ProjectSearchInfo> | |||||
fun findInvoiceSearchInfoBy(): List<InvoiceSearchInfo> | fun findInvoiceSearchInfoBy(): List<InvoiceSearchInfo> | ||||
@@ -24,9 +24,9 @@ interface ProjectRepository : AbstractRepository<Project, Long> { | |||||
fun findAllByPlanStartLessThanEqualAndPlanEndGreaterThanEqual(remainedDateFrom: LocalDate?, remainedDateTo: LocalDate?):List<Project> | fun findAllByPlanStartLessThanEqualAndPlanEndGreaterThanEqual(remainedDateFrom: LocalDate?, remainedDateTo: LocalDate?):List<Project> | ||||
@Query("SELECT max(cast(substring_index(substring_index(p.code, '-', 2), '-', -1) as long)) FROM Project p WHERE p.isClpProject = ?1 and p.id != ?2" + | |||||
@Query("SELECT max(cast(substring_index(substring_index(p.code, '-', 2), '-', -1) as long)) FROM Project p WHERE p.id != ?1" + | |||||
"") | "") | ||||
fun getLatestCodeNumberByMainProject(isClpProject: Boolean, id: Serializable?): Long? | |||||
fun getLatestCodeNumberByMainProject(id: Serializable?): Long? | |||||
@Query("SELECT max(case when length(p.code) - length(replace(p.code, '-', '')) > 1 then cast(substring_index(p.code, '-', -1) as long) end) FROM Project p WHERE p.code like %?1% and p.id != ?2") | @Query("SELECT max(case when length(p.code) - length(replace(p.code, '-', '')) > 1 then cast(substring_index(p.code, '-', -1) as long) end) FROM Project p WHERE p.code like %?1% and p.id != ?2") | ||||
fun getLatestCodeNumberBySubProject(code: String, id: Serializable?): Long? | fun getLatestCodeNumberBySubProject(code: String, id: Serializable?): Long? | ||||
@@ -4,6 +4,7 @@ import com.ffii.core.utils.ExcelUtils | |||||
import com.ffii.tsms.modules.common.SecurityUtils | import com.ffii.tsms.modules.common.SecurityUtils | ||||
import com.ffii.tsms.modules.data.entity.* | import com.ffii.tsms.modules.data.entity.* | ||||
import com.ffii.tsms.modules.data.service.* | import com.ffii.tsms.modules.data.service.* | ||||
import com.ffii.tsms.modules.data.web.models.SaveCustomerResponse | |||||
import com.ffii.tsms.modules.project.entity.* | import com.ffii.tsms.modules.project.entity.* | ||||
import com.ffii.tsms.modules.project.entity.Milestone | import com.ffii.tsms.modules.project.entity.Milestone | ||||
import com.ffii.tsms.modules.project.entity.projections.InvoiceInfoSearchInfo | import com.ffii.tsms.modules.project.entity.projections.InvoiceInfoSearchInfo | ||||
@@ -12,12 +13,18 @@ import com.ffii.tsms.modules.project.entity.projections.ProjectSearchInfo | |||||
import com.ffii.tsms.modules.project.web.models.* | import com.ffii.tsms.modules.project.web.models.* | ||||
import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository | import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository | ||||
import org.apache.commons.logging.LogFactory | import org.apache.commons.logging.LogFactory | ||||
import org.apache.poi.ss.usermodel.CellType | |||||
import org.apache.poi.ss.usermodel.DataFormatter | |||||
import org.apache.poi.ss.usermodel.DateUtil | |||||
import org.apache.poi.ss.usermodel.Sheet | import org.apache.poi.ss.usermodel.Sheet | ||||
import org.apache.poi.ss.usermodel.Workbook | import org.apache.poi.ss.usermodel.Workbook | ||||
import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||
import java.time.LocalDate | import java.time.LocalDate | ||||
import java.time.ZoneId | |||||
import java.time.format.DateTimeFormatter | import java.time.format.DateTimeFormatter | ||||
import java.time.format.FormatStyle | |||||
import java.util.Locale | |||||
import kotlin.jvm.optionals.getOrNull | import kotlin.jvm.optionals.getOrNull | ||||
@@ -53,8 +60,7 @@ open class ProjectsService( | |||||
private val customerSubsidiaryService: CustomerSubsidiaryService, | private val customerSubsidiaryService: CustomerSubsidiaryService, | ||||
) { | ) { | ||||
open fun allProjects(): List<ProjectSearchInfo> { | open fun allProjects(): List<ProjectSearchInfo> { | ||||
return projectRepository.findProjectSearchInfoByOrderByCreatedDesc() | |||||
.sortedByDescending { it.status?.lowercase() != "deleted" } | |||||
return projectRepository.findProjectSearchInfoByDeletedIsFalseOrderByCodeDesc() | |||||
} | } | ||||
open fun allInvoices(): List<InvoiceSearchInfo> { | open fun allInvoices(): List<InvoiceSearchInfo> { | ||||
@@ -132,7 +138,7 @@ open class ProjectsService( | |||||
val checkIsClpProject = isClpProject != null && isClpProject | val checkIsClpProject = isClpProject != null && isClpProject | ||||
val prefix = if (checkIsClpProject) "C" else "M" | val prefix = if (checkIsClpProject) "C" else "M" | ||||
val latestProjectCode = projectRepository.getLatestCodeNumberByMainProject(checkIsClpProject, project.id ?: -1) | |||||
val latestProjectCode = projectRepository.getLatestCodeNumberByMainProject(project.id ?: -1) | |||||
if (latestProjectCode != null) { | if (latestProjectCode != null) { | ||||
val lastFix = latestProjectCode | val lastFix = latestProjectCode | ||||
@@ -186,17 +192,31 @@ open class ProjectsService( | |||||
val project = | val project = | ||||
if (request.projectId != null && request.projectId > 0) projectRepository.findById(request.projectId) | if (request.projectId != null && request.projectId > 0) projectRepository.findById(request.projectId) | ||||
.orElseThrow() else Project() | .orElseThrow() else Project() | ||||
val duplicateProject = | |||||
if (request.projectCode != null) projectRepository.findByCode(request.projectCode) else null | |||||
//check duplicate project | |||||
if (duplicateProject != null && !duplicateProject.deleted && duplicateProject.id?.equals(request.projectId) == false) { | |||||
return NewProjectResponse( | |||||
id = request.projectId, | |||||
code = request.projectCode, | |||||
name = request.projectName, | |||||
client = null, | |||||
category = null, | |||||
team = null, | |||||
message = "The project code has already existed", | |||||
errorPosition = "projectCode" | |||||
); | |||||
} | |||||
project.apply { | project.apply { | ||||
name = request.projectName | name = request.projectName | ||||
description = request.projectDescription | description = request.projectDescription | ||||
code = request.projectCode | |||||
?: if (this.code.isNullOrEmpty() && request.mainProjectId == null) createProjectCode( | |||||
request.isClpProject, | |||||
project | |||||
) else if (this.code.isNullOrEmpty() && request.mainProjectId != null && mainProject != null) createSubProjectCode( | |||||
mainProject, | |||||
project | |||||
) else this.code | |||||
code = if (request.mainProjectId != null && mainProject != null) createSubProjectCode( | |||||
mainProject, | |||||
project | |||||
) else request.projectCode | |||||
expectedTotalFee = request.expectedProjectFee | expectedTotalFee = request.expectedProjectFee | ||||
subContractFee = request.subContractFee | subContractFee = request.subContractFee | ||||
totalManhour = request.totalManhour | totalManhour = request.totalManhour | ||||
@@ -305,7 +325,8 @@ open class ProjectsService( | |||||
val milestonesToDelete = milestoneRepository.findAllByProject(project).subtract(milestones.toSet()) | val milestonesToDelete = milestoneRepository.findAllByProject(project).subtract(milestones.toSet()) | ||||
val mapTasksToSave = tasksToSave.map { it.task!!.id } | val mapTasksToSave = tasksToSave.map { it.task!!.id } | ||||
val tasksToDelete = projectTaskRepository.findAllByProject(project).filter { !mapTasksToSave.contains(it.task!!.id) } | |||||
val tasksToDelete = | |||||
projectTaskRepository.findAllByProject(project).filter { !mapTasksToSave.contains(it.task!!.id) } | |||||
val gradeAllocationsToDelete = | val gradeAllocationsToDelete = | ||||
gradeAllocationRepository.findByProject(project).subtract(gradeAllocations.toSet()) | gradeAllocationRepository.findByProject(project).subtract(gradeAllocations.toSet()) | ||||
milestoneRepository.deleteAll(milestonesToDelete) | milestoneRepository.deleteAll(milestonesToDelete) | ||||
@@ -336,7 +357,9 @@ open class ProjectsService( | |||||
name = it.name, | name = it.name, | ||||
client = it.customer?.name, | client = it.customer?.name, | ||||
category = it.projectCategory?.name, | category = it.projectCategory?.name, | ||||
team = it.teamLead?.team?.code | |||||
team = it.teamLead?.team?.code, | |||||
message = "Success", | |||||
errorPosition = null, | |||||
) | ) | ||||
} | } | ||||
} | } | ||||
@@ -523,14 +546,15 @@ open class ProjectsService( | |||||
val splitMainProjectCode = splitProjectCode[0].split('-') | val splitMainProjectCode = splitProjectCode[0].split('-') | ||||
logger.info("splitProjectCode: " + splitProjectCode[1].split(')')[0]) | logger.info("splitProjectCode: " + splitProjectCode[1].split(')')[0]) | ||||
val mainProjectCode = splitMainProjectCode[0] + '-' + String.format( | |||||
"%04d", | |||||
splitMainProjectCode[1].toInt() | |||||
) | |||||
projectCode = | projectCode = | ||||
splitMainProjectCode[0] + '-' + String.format( | |||||
"%04d", | |||||
splitMainProjectCode[1].toInt() | |||||
) + '-' + String.format("%03d", splitProjectCode[1].split(')')[0].toInt()) | |||||
mainProjectCode + '-' + String.format("%03d", splitProjectCode[1].split(')')[0].toInt()) | |||||
val mainProject = | val mainProject = | ||||
projectRepository.findByCode(splitProjectCode[0]) ?: projectRepository.saveAndFlush( | |||||
projectRepository.findByCode(mainProjectCode) ?: projectRepository.saveAndFlush( | |||||
Project().apply { | Project().apply { | ||||
name = row.getCell(1).stringCellValue | name = row.getCell(1).stringCellValue | ||||
description = row.getCell(1).stringCellValue | description = row.getCell(1).stringCellValue | ||||
@@ -642,7 +666,8 @@ open class ProjectsService( | |||||
keySelector = { it.taskGroup!!.id!! }, | keySelector = { it.taskGroup!!.id!! }, | ||||
valueTransform = { it.percentage!! } | valueTransform = { it.percentage!! } | ||||
) | ) | ||||
val projectTasks = if (project != null) projectTaskRepository.findAllByProject(project) else mutableListOf() | |||||
val projectTasks = | |||||
if (project != null) projectTaskRepository.findAllByProject(project) else mutableListOf() | |||||
var groupedProjectTasks = mapOf<Long, List<Long>>() | var groupedProjectTasks = mapOf<Long, List<Long>>() | ||||
if (projectTasks.isNotEmpty()) { | if (projectTasks.isNotEmpty()) { | ||||
groupedProjectTasks = projectTasks.groupBy { | groupedProjectTasks = projectTasks.groupBy { | ||||
@@ -652,7 +677,7 @@ open class ProjectsService( | |||||
} | } | ||||
} | } | ||||
val taskGroups = mutableMapOf<Long, TaskGroupAllocation>() | val taskGroups = mutableMapOf<Long, TaskGroupAllocation>() | ||||
groups.entries.forEach{ (key, value) -> | |||||
groups.entries.forEach { (key, value) -> | |||||
var taskIds = tasks[key]!!.map { it.id!! } | var taskIds = tasks[key]!!.map { it.id!! } | ||||
if (groupedProjectTasks.isNotEmpty() && !groupedProjectTasks[key].isNullOrEmpty()) { | if (groupedProjectTasks.isNotEmpty() && !groupedProjectTasks[key].isNullOrEmpty()) { | ||||
taskIds = (taskIds + groupedProjectTasks[key]!!).distinct() | taskIds = (taskIds + groupedProjectTasks[key]!!).distinct() | ||||
@@ -7,4 +7,6 @@ data class NewProjectResponse( | |||||
val category: String?, | val category: String?, | ||||
val team: String?, | val team: String?, | ||||
val client: String?, | val client: String?, | ||||
val message: String?, | |||||
val errorPosition: String?, | |||||
) | ) |
@@ -1,6 +1,7 @@ | |||||
package com.ffii.tsms.modules.report.service | package com.ffii.tsms.modules.report.service | ||||
import com.ffii.core.support.JdbcDao | import com.ffii.core.support.JdbcDao | ||||
import com.ffii.core.utils.ExcelUtils | |||||
import com.ffii.tsms.modules.data.entity.Customer | import com.ffii.tsms.modules.data.entity.Customer | ||||
import com.ffii.tsms.modules.data.entity.Grade | import com.ffii.tsms.modules.data.entity.Grade | ||||
import com.ffii.tsms.modules.data.entity.Salary | import com.ffii.tsms.modules.data.entity.Salary | ||||
@@ -59,6 +60,20 @@ open class ReportService( | |||||
private val COMPLETION_PROJECT = "templates/report/AR05_Project Completion Report.xlsx" | private val COMPLETION_PROJECT = "templates/report/AR05_Project Completion Report.xlsx" | ||||
private val CROSS_TEAM_CHARGE_REPORT = "templates/report/Cross Team Charge Report.xlsx" | private val CROSS_TEAM_CHARGE_REPORT = "templates/report/Cross Team Charge Report.xlsx" | ||||
private fun conditionalFormattingNegative(sheet: Sheet) { | |||||
// Create a conditional formatting rule | |||||
val sheetCF = sheet.sheetConditionalFormatting | |||||
val ruleNegative = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "0").apply { | |||||
createFontFormatting().apply { | |||||
fontColorIndex = IndexedColors.RED.index | |||||
} | |||||
} | |||||
val lastCell = sheet.maxOf { it.lastCellNum - 1 } | |||||
val regions = arrayOf(CellRangeAddress(0, sheet.lastRowNum, 0, lastCell)) | |||||
sheetCF.addConditionalFormatting(regions, ruleNegative) | |||||
} | |||||
// ==============================|| GENERATE REPORT ||============================== // | // ==============================|| GENERATE REPORT ||============================== // | ||||
fun generalCreateReportIndexed( // just loop through query records one by one, return rowIndex | fun generalCreateReportIndexed( // just loop through query records one by one, return rowIndex | ||||
sheet: Sheet, | sheet: Sheet, | ||||
@@ -655,6 +670,8 @@ open class ReportService( | |||||
cellStyle.dataFormat = accountingStyle | cellStyle.dataFormat = accountingStyle | ||||
} | } | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -760,6 +777,7 @@ open class ReportService( | |||||
cellStyle.dataFormat = accountingStyle | cellStyle.dataFormat = accountingStyle | ||||
} | } | ||||
} | } | ||||
var regions = arrayOf(CellRangeAddress(12, 12, 1, 2)) | |||||
rowIndex = 16 | rowIndex = 16 | ||||
@@ -814,7 +832,7 @@ open class ReportService( | |||||
combinedResults.forEach { result: String -> | combinedResults.forEach { result: String -> | ||||
if (groupedInvoices.containsKey(result)) { | if (groupedInvoices.containsKey(result)) { | ||||
groupedInvoices[result]!!.forEachIndexed { _, invoice -> | |||||
// groupedInvoices[result]!!.forEachIndexed { _, invoice -> | |||||
sheet.createRow(rowIndex++).apply { | sheet.createRow(rowIndex++).apply { | ||||
createCell(0).apply { | createCell(0).apply { | ||||
setCellValue(result) | setCellValue(result) | ||||
@@ -826,7 +844,7 @@ open class ReportService( | |||||
} | } | ||||
createCell(2).apply { | createCell(2).apply { | ||||
setCellValue(invoice["paidAmount"] as Double) | |||||
setCellValue(groupedInvoices[result]?.sumOf { it["paidAmount"] as Double } ?: 0.0) | |||||
cellStyle.dataFormat = accountingStyle | cellStyle.dataFormat = accountingStyle | ||||
} | } | ||||
@@ -847,9 +865,9 @@ open class ReportService( | |||||
createCell(4)?.apply { | createCell(4)?.apply { | ||||
// setCellValue(invoice["description"].toString()) | // setCellValue(invoice["description"].toString()) | ||||
setCellValue("Invoice Receipt: " + (invoice["invoiceNo"] ?: "N/A").toString()) | |||||
setCellValue("Invoice Receipt: " + (groupedInvoices[result]?.map { it["invoiceNo"] }?.joinToString() ?: "N/A").toString()) | |||||
} | } | ||||
} | |||||
// } | |||||
} | } | ||||
} | } | ||||
@@ -892,6 +910,8 @@ open class ReportService( | |||||
} | } | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -1053,6 +1073,8 @@ open class ReportService( | |||||
} | } | ||||
} | } | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -1348,6 +1370,9 @@ open class ReportService( | |||||
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) | CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) | ||||
} | } | ||||
} | } | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -1368,25 +1393,43 @@ open class ReportService( | |||||
salarys.forEachIndexed { index, salary -> | salarys.forEachIndexed { index, salary -> | ||||
sheet.getRow(rowIndex++).apply { | |||||
val row = sheet.getRow(rowIndex) ?: sheet.createRow(rowIndex) | |||||
row?.apply { | |||||
getCell(0).setCellValue(salary.salaryPoint.toDouble()) | |||||
val cell = getCell(0) ?: createCell(0) | |||||
cell.setCellValue(salary.salaryPoint.toDouble()) | |||||
when (index) { | when (index) { | ||||
0 -> getCell(1).setCellValue(salary.lowerLimit.toDouble()) | |||||
0 -> { | |||||
val cell1 = getCell(1) ?: createCell(1) | |||||
cell1.setCellValue(salary.lowerLimit.toDouble()) | |||||
} | |||||
else -> getCell(1).cellFormula = | |||||
"(C{previousRow}+1)".replace("{previousRow}", (rowIndex - 1).toString()) | |||||
else -> { | |||||
val cell1 = getCell(1) ?: createCell(1) | |||||
cell1.cellFormula = | |||||
"(C{previousRow}+1)".replace("{previousRow}", (rowIndex).toString()) | |||||
} | |||||
} | } | ||||
getCell(2).cellFormula = "(B{currentRow}+D{currentRow})-1".replace("{currentRow}", rowIndex.toString()) | |||||
val cell2 = getCell(2) ?: createCell(2) | |||||
cell2.cellFormula = "(B{currentRow}+D{currentRow})-1".replace("{currentRow}", (rowIndex+1).toString()) | |||||
// getCell(2).cellStyle.dataFormat = accountingStyle | // getCell(2).cellStyle.dataFormat = accountingStyle | ||||
getCell(3).setCellValue(salary.increment.toDouble()) | |||||
getCell(4).cellFormula = | |||||
"(((C{currentRow}+B{currentRow})/2)/20)/8".replace("{currentRow}", rowIndex.toString()) | |||||
val cell3 = getCell(3)?:createCell(3) | |||||
cell3.setCellValue(salary.increment.toDouble()) | |||||
val cell4 = getCell(4)?:createCell(4) | |||||
cell4.cellFormula = | |||||
"(((C{currentRow}+B{currentRow})/2)/20)/8".replace("{currentRow}", (rowIndex+1).toString()) | |||||
// getCell(4).cellStyle.dataFormat = accountingStyle | // getCell(4).cellStyle.dataFormat = accountingStyle | ||||
cell4.cellStyle.dataFormat = accountingStyle | |||||
} | } | ||||
rowIndex++; | |||||
} | } | ||||
// println(salarys.size) | // println(salarys.size) | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -1419,6 +1462,9 @@ open class ReportService( | |||||
columnIndex = 0 | columnIndex = 0 | ||||
generalCreateReportIndexed(sheet, result.distinct(), rowIndex, columnIndex) | generalCreateReportIndexed(sheet, result.distinct(), rowIndex, columnIndex) | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -1476,6 +1522,8 @@ open class ReportService( | |||||
val regions = arrayOf(CellRangeAddress.valueOf("\$K7:\$L${rowIndex + 1}")) | val regions = arrayOf(CellRangeAddress.valueOf("\$K7:\$L${rowIndex + 1}")) | ||||
sheetCF.addConditionalFormatting(regions, cfRules); | sheetCF.addConditionalFormatting(regions, cfRules); | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -1510,6 +1558,8 @@ open class ReportService( | |||||
// Automatically adjust column widths to fit content | // Automatically adjust column widths to fit content | ||||
autoSizeColumns(sheet) | autoSizeColumns(sheet) | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -2396,6 +2446,8 @@ open class ReportService( | |||||
CellUtil.setCellStyleProperty(panlCellTitle, "borderBottom", BorderStyle.DOUBLE) | CellUtil.setCellStyleProperty(panlCellTitle, "borderBottom", BorderStyle.DOUBLE) | ||||
CellUtil.setCellStyleProperty(panlCell, "borderBottom", BorderStyle.DOUBLE) | CellUtil.setCellStyleProperty(panlCell, "borderBottom", BorderStyle.DOUBLE) | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -2630,6 +2682,8 @@ open class ReportService( | |||||
sheet.setRowBreak(rowNum++); | sheet.setRowBreak(rowNum++); | ||||
} | } | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
@@ -2941,6 +2995,8 @@ open class ReportService( | |||||
} | } | ||||
// } | // } | ||||
conditionalFormattingNegative(sheet) | |||||
return workbook | return workbook | ||||
} | } | ||||
} | } |
@@ -90,7 +90,7 @@ class ReportController( | |||||
// val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") | // val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") | ||||
return ResponseEntity.ok() | return ResponseEntity.ok() | ||||
// .contentType(mediaType) | // .contentType(mediaType) | ||||
.header("filename", "Project Cash Flow Report - " + LocalDate.now() + ".xlsx") | |||||
.header("filename", "Project Cash Flow Report (${if(request.dateType == "Date") "by Date" else "by Month"}) - " + LocalDate.now() + ".xlsx") | |||||
.body(ByteArrayResource(reportResult)) | .body(ByteArrayResource(reportResult)) | ||||
} | } | ||||
@@ -182,7 +182,7 @@ public class GroupService extends AbstractBaseEntityService<Group, Long, GroupRe | |||||
+ " where g.deleted = false " | + " where g.deleted = false " | ||||
+ " and u.id = :userId" | + " and u.id = :userId" | ||||
); | ); | ||||
return jdbcDao.queryForString(sql.toString(), args); | |||||
return jdbcDao.queryForList(sql.toString(), args).stream().map(String::valueOf).collect(Collectors.joining(",")); | |||||
} | } | ||||
@@ -0,0 +1,7 @@ | |||||
-- liquibase formatted sql | |||||
-- changeset cyril:authority, user_authority | |||||
INSERT INTO authority (authority,name) | |||||
VALUES ('VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING','View Project Resource Consumption Ranking in Dashboard'); | |||||
INSERT INTO `user_authority` VALUES (1,41); |