|
|
@@ -21,10 +21,10 @@ import java.io.IOException |
|
|
|
import java.time.LocalDate |
|
|
|
import java.time.format.DateTimeFormatter |
|
|
|
import java.util.* |
|
|
|
import org.apache.poi.ss.util.CellUtil |
|
|
|
import kotlin.time.times |
|
|
|
|
|
|
|
data class DayInfo(val date: String?, val weekday: String?) |
|
|
|
|
|
|
|
@Service |
|
|
|
open class ReportService( |
|
|
|
private val jdbcDao: JdbcDao, |
|
|
@@ -108,8 +108,8 @@ open class ReportService( |
|
|
|
} |
|
|
|
|
|
|
|
@Throws(IOException::class) |
|
|
|
fun generateLateStartReport(project: Project): ByteArray { |
|
|
|
val workbook: Workbook = createLateStartReport(project, LATE_START_REPORT) |
|
|
|
fun generateLateStartReport(project: Project?): ByteArray { |
|
|
|
val workbook: Workbook = createLateStartReport(project,LATE_START_REPORT) |
|
|
|
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() |
|
|
|
workbook.write(outputStream) |
|
|
|
workbook.close() |
|
|
@@ -370,6 +370,9 @@ open class ReportService( |
|
|
|
templatePath: String, |
|
|
|
): Workbook { |
|
|
|
// val yearMonth = YearMonth.of(2022, 5) // May 2022 |
|
|
|
println("t $timesheets") |
|
|
|
println("l $leaves") |
|
|
|
println("p $projectList") |
|
|
|
val resource = ClassPathResource(templatePath) |
|
|
|
val templateInputStream = resource.inputStream |
|
|
|
val workbook: Workbook = XSSFWorkbook(templateInputStream) |
|
|
@@ -398,210 +401,195 @@ open class ReportService( |
|
|
|
var columnSize = 0 |
|
|
|
|
|
|
|
var dayInt = 0 |
|
|
|
// tempCell = tempRow.createCell(columnIndex) |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(FORMATTED_TODAY) |
|
|
|
} |
|
|
|
println(sheet.getRow(1).getCell(2)) |
|
|
|
var tempCell: Cell |
|
|
|
|
|
|
|
tempCell = sheet.getRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(FORMATTED_TODAY) |
|
|
|
|
|
|
|
rowIndex = 2 |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(month) |
|
|
|
cellStyle.dataFormat = monthStyle |
|
|
|
} |
|
|
|
tempCell = sheet.getRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(month) |
|
|
|
tempCell.cellStyle.dataFormat = monthStyle |
|
|
|
|
|
|
|
rowIndex = 3 |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(staff.name) |
|
|
|
} |
|
|
|
tempCell. sheet.getRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(staff.name) |
|
|
|
|
|
|
|
rowIndex = 4 |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(staff.team.name) |
|
|
|
} |
|
|
|
tempCell.sheet.getRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(staff.team.name) |
|
|
|
|
|
|
|
|
|
|
|
rowIndex = 5 |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(staff.grade.code) |
|
|
|
} |
|
|
|
tempCell = sheet.getRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(staff.grade.code) |
|
|
|
|
|
|
|
val DoubleBorderBottom: MutableMap<String?, Any?> = mutableMapOf() |
|
|
|
DoubleBorderBottom["borderTop"] = BorderStyle.THIN |
|
|
|
DoubleBorderBottom["borderBottom"] = BorderStyle.DOUBLE |
|
|
|
|
|
|
|
val ThinBorderBottom: MutableMap<String?, Any?> = mutableMapOf() |
|
|
|
ThinBorderBottom["borderBottom"] = BorderStyle.THIN |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
rowIndex = 7 |
|
|
|
daysOfMonth.forEach { dayInfo -> |
|
|
|
rowIndex++ |
|
|
|
rowSize++ |
|
|
|
sheet.getRow(rowIndex).getCell(0).apply { |
|
|
|
setCellValue(dayInfo.date) |
|
|
|
cellStyle.dataFormat = dateStyle |
|
|
|
cellStyle.setFont(boldFont) |
|
|
|
} |
|
|
|
sheet.getRow(rowIndex).getCell(1).apply { |
|
|
|
setCellValue(dayInfo.weekday) |
|
|
|
cellStyle.setFont(boldFont) |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(0) |
|
|
|
tempCell.setCellValue(dayInfo.date) |
|
|
|
tempCell.cellStyle.dataFormat = dateStyle |
|
|
|
tempCell.cellStyle.setFont(boldFont) |
|
|
|
// cellStyle.alignment = HorizontalAlignment.LEFT |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(1) |
|
|
|
tempCell.setCellValue(dayInfo.weekday) |
|
|
|
tempCell.cellStyle.setFont(boldFont) |
|
|
|
// cellStyle.alignment = HorizontalAlignment.LEFT |
|
|
|
} |
|
|
|
|
|
|
|
rowIndex += 1 |
|
|
|
sheet.getRow(rowIndex).getCell(0).apply { |
|
|
|
setCellValue("Sub-total") |
|
|
|
cellStyle.setFont(boldFont) |
|
|
|
// cellStyle.borderTop = BorderStyle.THIN |
|
|
|
// cellStyle.borderBottom = BorderStyle.DOUBLE |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
} |
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex, rowIndex, 0, 1)) |
|
|
|
// |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(0) |
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1)) |
|
|
|
tempCell.setCellValue("Sub-total") |
|
|
|
tempCell.cellStyle.setFont(boldFont) |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(1) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) |
|
|
|
|
|
|
|
rowIndex += 1 |
|
|
|
sheet.getRow(rowIndex).getCell(0).apply { |
|
|
|
setCellValue("Total Normal Hours [A]") |
|
|
|
// cellStyle.setFont(boldFont) |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(0) |
|
|
|
tempCell.setCellValue("Total Normal Hours [A]") |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
|
|
|
|
var normalConsumed = 0.0 |
|
|
|
var otConsumed = 0.0 |
|
|
|
var leaveHours = 0.0 |
|
|
|
if (timesheets.isNotEmpty()) { |
|
|
|
timesheets.forEach { t -> |
|
|
|
normalConsumed += t.normalConsumed!! |
|
|
|
otConsumed += t.otConsumed!! |
|
|
|
otConsumed += t.otConsumed ?: 0.0 |
|
|
|
} |
|
|
|
} |
|
|
|
sheet.getRow(rowIndex).getCell(2).apply { |
|
|
|
setCellValue(normalConsumed) |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex, rowIndex, 0, 1)) |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(2) |
|
|
|
tempCell.setCellValue(normalConsumed) |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
|
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1)) |
|
|
|
// |
|
|
|
rowIndex += 1 |
|
|
|
sheet.getRow(rowIndex).getCell(0).apply { |
|
|
|
setCellValue("Total Other Hours [B]") |
|
|
|
cellStyle.setFont(boldFont) |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
} |
|
|
|
sheet.getRow(rowIndex).getCell(2).apply { |
|
|
|
setCellValue(otConsumed) |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(0) |
|
|
|
tempCell.setCellValue("Total Other Hours [B]") |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
tempCell.cellStyle.setFont(boldFont) |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(2) |
|
|
|
tempCell.setCellValue(otConsumed) |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
|
|
|
|
|
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex, rowIndex, 0, 1)) |
|
|
|
|
|
|
|
// Total Leave Hours |
|
|
|
rowIndex += 1 |
|
|
|
sheet.getRow(rowIndex).getCell(0).apply { |
|
|
|
setCellValue("Total Leave Hours") |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(0) |
|
|
|
tempCell.setCellValue("Total Leave Hours") |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1)) |
|
|
|
if (leaves.isNotEmpty()) { |
|
|
|
leaves.forEach { l -> |
|
|
|
leaveHours += l.leaveHours!! |
|
|
|
} |
|
|
|
} |
|
|
|
sheet.getRow(rowIndex).getCell(2).apply { |
|
|
|
setCellValue(leaveHours) |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(2) |
|
|
|
tempCell.setCellValue(leaveHours) |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
|
|
|
|
// Total Spent Manhours |
|
|
|
rowIndex += 1 |
|
|
|
sheet.getRow(rowIndex).getCell(0).apply { |
|
|
|
setCellValue("Total Spent Manhours [A+B]") |
|
|
|
cellStyle.setFont(boldFont) |
|
|
|
cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
// cellStyle.borderTop = BorderStyle.THIN |
|
|
|
// cellStyle.borderBottom = BorderStyle.DOUBLE |
|
|
|
} |
|
|
|
sheet.getRow(rowIndex).getCell(2).apply { |
|
|
|
cellFormula = "C${rowIndex - 2}+C${rowIndex - 1}" |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
// cellStyle.borderTop = BorderStyle.THIN |
|
|
|
// cellStyle.borderBottom = BorderStyle.DOUBLE |
|
|
|
} |
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex, rowIndex, 0, 1)) |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(0) |
|
|
|
tempCell.setCellValue("Total Spent Manhours [A+B]") |
|
|
|
tempCell.cellStyle.setFont(boldFont) |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(1) |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) |
|
|
|
|
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(2) |
|
|
|
tempCell.cellFormula = "C${rowIndex-2}+C${rowIndex-1}" |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) |
|
|
|
|
|
|
|
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1)) |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
rowIndex = 7 |
|
|
|
columnIndex = 2 |
|
|
|
projectList.forEachIndexed { index, title -> |
|
|
|
sheet.getRow(7).getCell(columnIndex + index).apply { |
|
|
|
setCellValue(title) |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(7).createCell(columnIndex + index) |
|
|
|
tempCell.setCellValue(title) |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.RIGHT) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) |
|
|
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
if (timesheets.isNotEmpty()) { |
|
|
|
projectList.forEach { _ -> |
|
|
|
for (i in 0 until rowSize) { |
|
|
|
tempCell = sheet.createRow(8 + i).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(0.0) |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
timesheets.forEach { timesheet -> |
|
|
|
dayInt = timesheet.recordDate!!.dayOfMonth |
|
|
|
sheet.getRow(dayInt.plus(7)).getCell(columnIndex).apply { |
|
|
|
setCellValue(timesheet.normalConsumed!!) |
|
|
|
} |
|
|
|
tempCell = sheet.createRow(dayInt.plus(7)).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(timesheet.normalConsumed!!) |
|
|
|
|
|
|
|
} |
|
|
|
columnIndex++ |
|
|
|
} |
|
|
|
} |
|
|
|
// dates |
|
|
|
if (leaves.isNotEmpty()) { |
|
|
|
leaves.forEach { leave -> |
|
|
|
dayInt = leave.recordDate!!.dayOfMonth |
|
|
|
sheet.getRow(dayInt.plus(7)).getCell(columnIndex).apply { |
|
|
|
setCellValue(leave.leaveHours!!) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
sheet.getRow(rowIndex).apply { |
|
|
|
getCell(columnIndex).setCellValue("Leave Hours") |
|
|
|
getCell(columnIndex).cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
for (i in 0 until rowSize) { |
|
|
|
tempCell = sheet.createRow(8 + i).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(0.0) |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
|
|
|
|
columnIndex += 1 |
|
|
|
getCell(columnIndex).setCellValue("Daily Manhour Spent\n" + "(Excluding Leave Hours)") |
|
|
|
getCell(columnIndex).cellStyle.alignment = HorizontalAlignment.CENTER |
|
|
|
columnSize = columnIndex |
|
|
|
} |
|
|
|
sheet.addMergedRegion(CellRangeAddress(6, 6, 2, columnIndex)) |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
for (i in 2 until columnIndex) { |
|
|
|
for (k in 0 until rowSize) { |
|
|
|
sheet.getRow(8 + k).getCell(i).apply { |
|
|
|
setCellValue(0.0) |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
dayInt = leave.recordDate!!.dayOfMonth |
|
|
|
tempCell = sheet.createRow(dayInt.plus(7)).createCell(columnIndex) |
|
|
|
tempCell.setCellValue(leave.leaveHours!!) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
///////////////////////////////////////////////////////// Leave Hours //////////////////////////////////////////////////////////////////// |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue("Leave Hours") |
|
|
|
CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) |
|
|
|
|
|
|
|
columnIndex += 1 |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.setCellValue("Daily Manhour Spent\n(Excluding Leave Hours)") |
|
|
|
CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) |
|
|
|
|
|
|
|
sheet.addMergedRegion(CellRangeAddress(6,6 , 2, columnIndex)) |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
rowIndex = 8 |
|
|
|
if (sheet.getRow(rowIndex - 1).getCell(2).stringCellValue != "Leave Hours") { |
|
|
|
// cal daily spent manhour |
|
|
|
for (i in 0 until rowSize) { |
|
|
|
val cell = |
|
|
|
sheet.getRow(rowIndex)?.getCell(columnIndex) ?: sheet.getRow(rowIndex + i)?.createCell(columnIndex) |
|
|
|
cell?.cellFormula = |
|
|
|
"SUM(${getColumnAlphabet(2)}${rowIndex + 1}:${getColumnAlphabet(columnIndex)}${rowIndex + 1})" // should columnIndex - 2 |
|
|
|
rowIndex++ |
|
|
|
} |
|
|
|
// cal subtotal |
|
|
|
for (i in 0 until columnSize) { // minus last col |
|
|
|
val cell = sheet.getRow(rowIndex)?.getCell(2) ?: sheet.getRow(rowIndex)?.createCell(2) |
|
|
|
cell?.cellFormula = |
|
|
|
"SUM(${getColumnAlphabet(2)}${rowIndex}:${getColumnAlphabet(columnIndex + i)}${rowIndex})" |
|
|
|
cell?.cellStyle?.dataFormat = accountingStyle |
|
|
|
cell?.cellStyle?.setFont(boldFont) |
|
|
|
// cell?.cellStyle?.borderTop = BorderStyle.THIN |
|
|
|
// cell?.cellStyle?.borderBottom = BorderStyle.DOUBLE |
|
|
|
} |
|
|
|
} else { // just for preview when no data |
|
|
|
// if (sheet.createRow(rowIndex - 1).getCell(2).stringCellValue != "Leave Hours") { |
|
|
|
// cal daily spent manhour |
|
|
|
for (i in 0 until rowSize) { |
|
|
|
val cell = |
|
|
|
sheet.getRow(rowIndex)?.getCell(columnIndex) ?: sheet.getRow(rowIndex + i)?.createCell(columnIndex) |
|
|
|
cell?.setCellValue("daily spent manhour") |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(columnIndex) |
|
|
|
tempCell.cellFormula = "SUM(${getColumnAlphabet(2)}${rowIndex+1}:${getColumnAlphabet(columnIndex - 2)}${rowIndex+1})" // should columnIndex - 2 |
|
|
|
rowIndex++ |
|
|
|
} |
|
|
|
// cal subtotal |
|
|
|
for (i in 0 until columnSize) { // minus last col |
|
|
|
val cell = sheet.getRow(rowIndex)?.getCell(2) ?: sheet.getRow(rowIndex)?.createCell(2) |
|
|
|
cell?.setCellValue("testing subtotal") |
|
|
|
cell?.cellStyle?.dataFormat = accountingStyle |
|
|
|
cell?.cellStyle?.setFont(boldFont) |
|
|
|
// cell?.cellStyle?.borderTop = BorderStyle.THIN |
|
|
|
// cell?.cellStyle?.borderBottom = BorderStyle.DOUBLE |
|
|
|
} |
|
|
|
println(rowIndex) |
|
|
|
for (i in 0 until columnSize - 2) { // minus last col |
|
|
|
tempCell = sheet.createRow(rowIndex).createCell(2 + i) |
|
|
|
tempCell.cellFormula = "SUM(${getColumnAlphabet(2 + i)}9:${getColumnAlphabet(2 + i)}${rowIndex})" |
|
|
|
tempCell.cellStyle.dataFormat = accountingStyle |
|
|
|
tempCell.cellStyle.setFont(boldFont) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, DoubleBorderBottom) |
|
|
|
// } |
|
|
|
} |
|
|
|
return workbook |
|
|
|
} |
|
|
@@ -647,16 +635,15 @@ open class ReportService( |
|
|
|
} |
|
|
|
|
|
|
|
private fun createLateStartReport( |
|
|
|
project: Project, |
|
|
|
project: Project?, |
|
|
|
templatePath: String |
|
|
|
):Workbook{ |
|
|
|
|
|
|
|
project |
|
|
|
val resource = ClassPathResource(templatePath) |
|
|
|
val templateInputStream = resource.inputStream |
|
|
|
val workbook: Workbook = XSSFWorkbook(templateInputStream) |
|
|
|
val sheet = workbook.getSheetAt(0) |
|
|
|
|
|
|
|
|
|
|
|
// Formatting the current date to "YYYY/MM/DD" and setting it to cell C2 |
|
|
|
val formattedToday = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) |
|
|
|
val dateCell = sheet.getRow(1)?.getCell(2) ?: sheet.getRow(1).createCell(2) |
|
|
@@ -674,7 +661,7 @@ open class ReportService( |
|
|
|
// projectDataRow.createCell(5).setCellValue( |
|
|
|
// project.planStart?.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) ?: "N/A" // Column F |
|
|
|
// ) |
|
|
|
|
|
|
|
|
|
|
|
// Styling for cell A1: Font size 16 and bold |
|
|
|
val headerFont = workbook.createFont().apply { |
|
|
|
bold = true |
|
|
|