소스 검색

Merge branch 'develop'

develop
MSI\2Fi 7 달 전
부모
커밋
2fdd8f7e79
7개의 변경된 파일463개의 추가작업 그리고 16개의 파일을 삭제
  1. +411
    -10
      src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt
  2. +1
    -2
      src/main/java/com/ffii/tsms/modules/data/service/StaffsService.kt
  3. +18
    -0
      src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt
  4. +27
    -0
      src/main/java/com/ffii/tsms/modules/data/web/models/ExportDashboardExcelRequest.kt
  5. +2
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/ProjectRepository.kt
  6. +3
    -3
      src/main/java/com/ffii/tsms/modules/project/service/ProjectsService.kt
  7. +1
    -1
      src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt

+ 411
- 10
src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt 파일 보기

@@ -5,6 +5,8 @@ import com.ffii.core.utils.CheckingUtils
import com.ffii.tsms.modules.data.entity.CustomerRepository
import com.ffii.tsms.modules.data.entity.CustomerTypeRepository
import com.ffii.tsms.modules.data.entity.TeamRepository
import com.ffii.tsms.modules.data.web.models.ExportFinancialSummaryV2ByClientRequest
import com.ffii.tsms.modules.data.web.models.ExportFinancialSummaryV2ByProjectRequest
import com.ffii.tsms.modules.data.web.models.FinancialSummaryByClient
import com.ffii.tsms.modules.data.web.models.FinancialSummaryByProject
import com.ffii.tsms.modules.project.entity.*
@@ -2743,14 +2745,20 @@ open class DashboardService(
if (thisTeam == null || thisTeam.team.id != teamId) {
continue
}
System.out.println("-----------------------------------")
System.out.println("Staff Name: ${curr.name}")
var dateListSize = dateList.size
var publicHolidayListSize = publicHolidayList.size
var companyHolidaySize = companyHoliday.size
if (curr.departDate != null) {
dateList.filter { it.isBefore(curr.departDate) }
publicHolidayList.filter { it.isBefore(curr.departDate) }
companyHoliday.filter { it.date.isBefore(curr.departDate) }
System.out.println("Depart Date: ${curr.departDate}")
dateListSize = dateList.filter { it.isBefore(curr.departDate) || it.isEqual(curr.departDate) }.toMutableList().size
publicHolidayListSize = publicHolidayList.filter { it.isBefore(curr.departDate) || it.isEqual(curr.departDate) }.size
companyHolidaySize = companyHoliday.filter { it.date.isBefore(curr.departDate) || it.date.isEqual(curr.departDate) }.size
}
thisArgs["staffId"] = curr.id!!
val submittedWeek = weeklySubmittedTimesheet(thisArgs)
val unsubmittedCount = dateList.size - publicHolidayList.size - companyHoliday.size - submittedWeek.size
val unsubmittedCount = dateListSize - publicHolidayListSize - companyHolidaySize - submittedWeek.size
if (unsubmittedCount <= 0) continue
result.add(
mapOf(
@@ -2794,14 +2802,20 @@ open class DashboardService(
if (thisTeam == null || thisTeam.team.id != teamId) {
continue
}
System.out.println("-----------------------------------")
System.out.println("Staff Name: ${curr.name}")
var dateListSize = dateList.size
var publicHolidayListSize = publicHolidayList.size
var companyHolidaySize = companyHoliday.size
if (curr.departDate != null) {
dateList.filter { it.isBefore(curr.departDate) }
publicHolidayList.filter { it.isBefore(curr.departDate) }
companyHoliday.filter { it.date.isBefore(curr.departDate) }
System.out.println("Depart Date: ${curr.departDate}")
dateListSize = dateList.filter { it.isBefore(curr.departDate) || it.isEqual(curr.departDate) }.toMutableList().size
publicHolidayListSize = publicHolidayList.filter { it.isBefore(curr.departDate) || it.isEqual(curr.departDate) }.size
companyHolidaySize = companyHoliday.filter { it.date.isBefore(curr.departDate) || it.date.isEqual(curr.departDate) }.size
}
thisArgs["staffId"] = curr.id!!
val submittedMonth = monthlySubmittedTimesheet(thisArgs)
val unsubmittedCount = dateList.size - publicHolidayList.size - companyHoliday.size - submittedMonth.size
val unsubmittedCount = dateListSize - publicHolidayListSize - companyHolidaySize - submittedMonth.size
if (unsubmittedCount <= 0) continue
result.add(
mapOf(
@@ -3405,7 +3419,7 @@ open class DashboardService(
}

createCell(4).apply {
cellFormula = "IFERROR(IF(K${rowIndex}=0, 0, K${rowIndex}/J${rowIndex}),0)"
cellFormula = "IFERROR(IF(M${rowIndex}=0, 0, M${rowIndex}/J${rowIndex}),0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
@@ -3509,6 +3523,195 @@ open class DashboardService(
return workbook
}

@Throws(IOException::class)
fun exportFinancialSummaryV2ByClientExcel(
financialSummaryByClients: List<ExportFinancialSummaryV2ByClientRequest>,
): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook =
createFinancialSummaryV2ByClientExcel(financialSummaryByClients, FINANCIAL_SUMMARY_FOR_CLIENT)

// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
workbook.close()

return outputStream.toByteArray()
}

@Throws(IOException::class)
private fun createFinancialSummaryV2ByClientExcel(
financialSummaryByClients: List<ExportFinancialSummaryV2ByClientRequest>,
templatePath: String,
): Workbook {
// please create a new function for each report template
val resource = ClassPathResource(templatePath)
val templateInputStream = resource.inputStream
val workbook: Workbook = XSSFWorkbook(templateInputStream)

val sheet: Sheet = workbook.getSheetAt(0)

// accounting style + comma style
val accountingStyle = workbook.createDataFormat().getFormat("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)")

// normal font
val normalFont = workbook.createFont().apply {
fontName = "Times New Roman"
}

// val normalFontStyle = workbook.createCellStyle().apply {
// setFont(normalFont)
// }

var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field
var columnIndex = 1
sheet.getRow(rowIndex).createCell(columnIndex).apply {
setCellValue(FORMATTED_TODAY)
}

rowIndex = 4
financialSummaryByClients.forEach { financialSummaryByClient: ExportFinancialSummaryV2ByClientRequest ->
sheet.createRow(rowIndex++).apply {
createCell(0).apply {
setCellValue(financialSummaryByClient.customerCode)
cellStyle.apply {
setFont(normalFont)
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(1).apply {
setCellValue(financialSummaryByClient.customerName)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(2).apply {
setCellValue(financialSummaryByClient.sumOfProjects)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(3).apply {
cellFormula = "IF(E${rowIndex}>=1,\"Positive\",\"Negative\")"
cellStyle.apply {
setFont(normalFont)
}
CellUtil.setAlignment(this, HorizontalAlignment.CENTER)
}

createCell(4).apply {
cellFormula = "IFERROR(IF(M${rowIndex}=0, 0, M${rowIndex}/J${rowIndex}),0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(5).apply {
cellFormula = "IF(G${rowIndex}>=1,\"Positive\",\"Negative\")"
cellStyle.apply {
setFont(normalFont)
}
CellUtil.setAlignment(this, HorizontalAlignment.CENTER)
}

createCell(6).apply {
cellFormula = "IFERROR(H${rowIndex}/J${rowIndex},0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(7).apply {
setCellValue(financialSummaryByClient.totalFee)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(8).apply {
// cellFormula = "H${rowIndex}*80%"
setCellValue(financialSummaryByClient.totalBudget)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(9).apply {
// setCellValue(financialSummaryByClient.cumulativeExpenditure)
cellFormula = "IFERROR(K${rowIndex}+L${rowIndex},0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}


createCell(10).apply {
setCellValue(financialSummaryByClient.manhourExpense)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(11).apply {
setCellValue(financialSummaryByClient.projectExpense)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(12).apply {
setCellValue(financialSummaryByClient.invoicedAmount)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(13).apply {
cellFormula = "IF(H${rowIndex}-M${rowIndex}<0,0,H${rowIndex}-M${rowIndex})"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(14).apply {
setCellValue(financialSummaryByClient.paidAmount)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}
}
}

return workbook
}

@Throws(IOException::class)
fun exportFinancialSummaryByProjectExcel(
financialSummaryByProjects: List<FinancialSummaryByProject>,
@@ -3524,6 +3727,23 @@ open class DashboardService(

return outputStream.toByteArray()
}

@Throws(IOException::class)
fun exportFinancialSummaryV2ByProjectExcel(
financialSummaryByProjects: List<ExportFinancialSummaryV2ByProjectRequest>,
): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook =
createFinancialSummaryV2ByProjectExcel(financialSummaryByProjects, FINANCIAL_SUMMARY_FOR_PROJECT)

// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
workbook.close()

return outputStream.toByteArray()
}

open fun testing3(
projectId: Long,
startDate: LocalDate?,
@@ -3842,7 +4062,7 @@ open class DashboardService(
}

createCell(5).apply {
cellFormula = "IFERROR(IF(L${rowIndex}=0, 0,L${rowIndex}/K${rowIndex}),0)"
cellFormula = "IFERROR(IF(N${rowIndex}=0, 0,N${rowIndex}/K${rowIndex}),0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
@@ -3944,6 +4164,187 @@ open class DashboardService(

return workbook
}

@Throws(IOException::class)
private fun createFinancialSummaryV2ByProjectExcel(
financialSummaryByProjects: List<ExportFinancialSummaryV2ByProjectRequest>,
templatePath: String,
): Workbook {
// please create a new function for each report template
val resource = ClassPathResource(templatePath)
val templateInputStream = resource.inputStream
val workbook: Workbook = XSSFWorkbook(templateInputStream)

val sheet: Sheet = workbook.getSheetAt(0)

// accounting style + comma style
val accountingStyle = workbook.createDataFormat().getFormat("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)")

// normal font
val normalFont = workbook.createFont().apply {
fontName = "Times New Roman"
}

// val normalFontStyle = workbook.createCellStyle().apply {
// setFont(normalFont)
// }

var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field
var columnIndex = 1
sheet.getRow(rowIndex).createCell(columnIndex).apply {
setCellValue(FORMATTED_TODAY)
}

rowIndex = 4
financialSummaryByProjects.forEach { financialSummaryByProject: ExportFinancialSummaryV2ByProjectRequest ->
sheet.createRow(rowIndex++).apply {
createCell(0).apply {
setCellValue(financialSummaryByProject.projectCode)
cellStyle.apply {
setFont(normalFont)
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(1).apply {
setCellValue(financialSummaryByProject.projectName)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(2).apply {
setCellValue(financialSummaryByProject.customerName)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(3).apply {
setCellValue(financialSummaryByProject.subsidiaryName ?: "N/A")
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.LEFT)
}

createCell(4).apply {
cellFormula = "IF(F${rowIndex}>=1,\"Positive\",\"Negative\")"
cellStyle.apply {
setFont(normalFont)
}
CellUtil.setAlignment(this, HorizontalAlignment.CENTER)
}

createCell(5).apply {
cellFormula = "IFERROR(IF(N${rowIndex}=0, 0,N${rowIndex}/K${rowIndex}),0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(6).apply {
cellFormula = "IF(H${rowIndex}>=1,\"Positive\",\"Negative\")"
cellStyle.apply {
setFont(normalFont)
}
CellUtil.setAlignment(this, HorizontalAlignment.CENTER)
}

createCell(7).apply {
cellFormula = "IFERROR(I${rowIndex}/K${rowIndex},0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(8).apply {
setCellValue(financialSummaryByProject.totalFee)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(9).apply {
// cellFormula = "I${rowIndex}*80%"
setCellValue(financialSummaryByProject.totalBudget)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(10).apply {
// setCellValue(financialSummaryByProject.cumulativeExpenditure)
cellFormula = "IFERROR(L${rowIndex}+M${rowIndex},0)"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(11).apply {
setCellValue(financialSummaryByProject.manhourExpense)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(12).apply {
setCellValue(financialSummaryByProject.projectExpense)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(13).apply {
setCellValue(financialSummaryByProject.invoicedAmount)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(14).apply {
cellFormula = "IF(I${rowIndex}-N${rowIndex}<0,0,I${rowIndex}-N${rowIndex})"
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}

createCell(15).apply {
setCellValue(financialSummaryByProject.paidAmount)
cellStyle.apply {
setFont(normalFont)
dataFormat = accountingStyle
}
CellUtil.setAlignment(this, HorizontalAlignment.RIGHT)
}
}
}

return workbook
}
}



+ 1
- 2
src/main/java/com/ffii/tsms/modules/data/service/StaffsService.kt 파일 보기

@@ -377,9 +377,8 @@ open class StaffsService(
val user = userRepository.findByUsernameAndDeletedFalse(staff.staffId).orElseThrow()

user.apply {
locked = LocalDate.now().isAfter(staff.departDate)
locked = if (staff.departDate != null) { LocalDate.now().isAfter(staff.departDate) } else false
}

users += user
}



+ 18
- 0
src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt 파일 보기

@@ -19,6 +19,8 @@ import com.ffii.tsms.modules.data.entity.TeamRepository
import com.ffii.tsms.modules.data.service.*
import com.ffii.tsms.modules.data.web.models.ExportFinancialSummaryByClientExcelRequest
import com.ffii.tsms.modules.data.web.models.ExportFinancialSummaryByProjectExcelRequest
import com.ffii.tsms.modules.data.web.models.ExportFinancialSummaryV2ByClientRequest
import com.ffii.tsms.modules.data.web.models.ExportFinancialSummaryV2ByProjectRequest
import com.ffii.tsms.modules.project.entity.ProjectRepository
import org.springframework.core.io.ByteArrayResource
import org.springframework.core.io.Resource
@@ -511,6 +513,14 @@ class DashboardController(
.body(ByteArrayResource(reportResult))
}

@PostMapping("/exportFinancialSummaryV2ByClientExcel")
fun exportFinancialSummaryV2ByClientExcel(@Valid @RequestBody request: List<ExportFinancialSummaryV2ByClientRequest>): ResponseEntity<Resource> {
val reportResult: ByteArray = dashboardService.exportFinancialSummaryV2ByClientExcel(request)
return ResponseEntity.ok()
.header("filename", "Financial Summary for Client - " + LocalDate.now() + ".xlsx")
.body(ByteArrayResource(reportResult))
}

@PostMapping("/exportFinancialSummaryByProjectExcel")
fun exportFinancialSummaryByProjectExcel(@Valid @RequestBody request: ExportFinancialSummaryByProjectExcelRequest): ResponseEntity<Resource> {
val reportResult: ByteArray = dashboardService.exportFinancialSummaryByProjectExcel(request.financialSummaryByProjects)
@@ -518,4 +528,12 @@ class DashboardController(
.header("filename", "Financial Summary for Project - " + LocalDate.now() + ".xlsx")
.body(ByteArrayResource(reportResult))
}

@PostMapping("/exportFinancialSummaryV2ByProjectExcel")
fun exportFinancialSummaryV2ByProjectExcel(@Valid @RequestBody request: List<ExportFinancialSummaryV2ByProjectRequest>): ResponseEntity<Resource> {
val reportResult: ByteArray = dashboardService.exportFinancialSummaryV2ByProjectExcel(request)
return ResponseEntity.ok()
.header("filename", "Financial Summary for Project - " + LocalDate.now() + ".xlsx")
.body(ByteArrayResource(reportResult))
}
}

+ 27
- 0
src/main/java/com/ffii/tsms/modules/data/web/models/ExportDashboardExcelRequest.kt 파일 보기

@@ -41,4 +41,31 @@ data class FinancialSummaryByProject (

data class ExportFinancialSummaryByProjectExcelRequest (
val financialSummaryByProjects: List<FinancialSummaryByProject>
)

data class ExportFinancialSummaryV2ByClientRequest (
val customerCode: String,
val customerName: String,
val sumOfProjects: Double,
val totalFee: Double,
val totalBudget: Double,
// val cumulativeExpenditure: Double,
val manhourExpense: Double,
val projectExpense: Double,
val invoicedAmount: Double,
val paidAmount: Double,
)

data class ExportFinancialSummaryV2ByProjectRequest (
val projectCode: String,
val projectName: String,
val customerName: String,
val subsidiaryName: String?,
val totalFee: Double,
val totalBudget: Double,
// val cumulativeExpenditure: Double,
val manhourExpense: Double,
val projectExpense: Double,
val invoicedAmount: Double,
val paidAmount: Double,
)

+ 2
- 0
src/main/java/com/ffii/tsms/modules/project/entity/ProjectRepository.kt 파일 보기

@@ -38,6 +38,8 @@ interface ProjectRepository : AbstractRepository<Project, Long> {

fun findByCode(code: String): Project?

fun findByCodeAndDeletedIsFalse(code: String): Project?

@Query("SELECT p.id FROM Project p WHERE substring_index(substring_index(p.code, '-', 2), '-', -1) like concat('%', substring_index(substring_index(?1, '-', 2), '-', -1), '%')")
fun checkMainProjectByCodeLike(code: String): List<Long?>?



+ 3
- 3
src/main/java/com/ffii/tsms/modules/project/service/ProjectsService.kt 파일 보기

@@ -210,7 +210,7 @@ open class ProjectsService(
// if (request.projectCode != null && request.mainProjectId == null) projectRepository.checkMainProjectByCodeLike(request.projectCode) else null

val duplicateProject =
if (request.projectCode != null) projectRepository.findByCode(request.projectCode) else null
if (request.projectCode != null) projectRepository.findByCodeAndDeletedIsFalse(request.projectCode) else null

//check duplicate project
// if (!duplicateProject.isNullOrEmpty() && !duplicateProject.contains(request.projectId)) {
@@ -597,7 +597,7 @@ open class ProjectsService(
mainProjectCode + '-' + String.format("%03d", splitProjectCode[1].split(')')[0].toInt())

val mainProject =
projectRepository.findByCode(mainProjectCode) ?: projectRepository.saveAndFlush(
projectRepository.findByCodeAndDeletedIsFalse(mainProjectCode) ?: projectRepository.saveAndFlush(
Project().apply {
name = row.getCell(1).stringCellValue
description = row.getCell(1).stringCellValue
@@ -617,7 +617,7 @@ open class ProjectsService(
projectCode = splitProjectCode[0] + '-' + String.format("%04d", splitProjectCode[1].toInt())
}

val project = projectRepository.findByCode(projectCode)
val project = projectRepository.findByCodeAndDeletedIsFalse(projectCode)
val projectId = project?.id
logger.info("projectCode :$projectCode")



+ 1
- 1
src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt 파일 보기

@@ -240,7 +240,7 @@ open class TimesheetsService(
}
logger.info("Project Code: $projectCode")

val project = projectRepository.findByCode(projectCode)
val project = projectRepository.findByCodeAndDeletedIsFalse(projectCode)

// process project task
logger.info("---------project task-------")


불러오는 중...
취소
저장