|
|
@@ -35,11 +35,16 @@ import java.math.RoundingMode |
|
|
|
import java.time.Year |
|
|
|
import javax.swing.plaf.synth.Region |
|
|
|
import kotlin.collections.ArrayList |
|
|
|
import kotlin.collections.HashMap |
|
|
|
|
|
|
|
|
|
|
|
data class DayInfo(val date: String?, val weekday: String?) |
|
|
|
data class TsData(var manhour: Double, var cost: Double) |
|
|
|
data class InOut(var In: TsData, var Out: TsData) |
|
|
|
data class CrossTeamP4InOut( |
|
|
|
// String = "${staffCode} ${staffName} (${teamCode})" |
|
|
|
var In: MutableMap<String, MutableMap<String, TsData>>, |
|
|
|
) |
|
|
|
|
|
|
|
@Service |
|
|
|
open class ReportService( |
|
|
@@ -71,7 +76,14 @@ open class ReportService( |
|
|
|
|
|
|
|
private fun cellBorderArgs(top: Int, bottom: Int, left: Int, right: Int): MutableMap<String, Any> { |
|
|
|
var cellBorderArgs = mutableMapOf<String, Any>() |
|
|
|
when (top) { |
|
|
|
// val thicknessMap = mapOf( |
|
|
|
// 1 to BorderStyle.THIN, |
|
|
|
// 2 to BorderStyle.THICK, |
|
|
|
// ) |
|
|
|
// if (top > 0) { |
|
|
|
// cellBorderArgs.put(CellUtil.BORDER_TOP, thicknessMap[top]) |
|
|
|
// } |
|
|
|
when (top ) { |
|
|
|
1 -> cellBorderArgs.put(CellUtil.BORDER_TOP, BorderStyle.THIN) |
|
|
|
2 -> cellBorderArgs.put(CellUtil.BORDER_TOP, BorderStyle.THICK) |
|
|
|
} |
|
|
@@ -90,22 +102,30 @@ open class ReportService( |
|
|
|
return cellBorderArgs |
|
|
|
} |
|
|
|
private fun setRegionBorders(top: Int, bottom: Int, left: Int, right: Int, region: CellRangeAddress, sheet: Sheet) { |
|
|
|
when (top) { |
|
|
|
1 -> RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet) |
|
|
|
2 -> RegionUtil.setBorderTop(BorderStyle.THICK, region, sheet) |
|
|
|
} |
|
|
|
when (bottom) { |
|
|
|
1 -> RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet) |
|
|
|
2 -> RegionUtil.setBorderBottom(BorderStyle.THICK, region, sheet) |
|
|
|
} |
|
|
|
when (left) { |
|
|
|
1 -> RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet) |
|
|
|
2 -> RegionUtil.setBorderLeft(BorderStyle.THICK, region, sheet) |
|
|
|
} |
|
|
|
when (right) { |
|
|
|
1 -> RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet) |
|
|
|
2 -> RegionUtil.setBorderRight(BorderStyle.THICK, region, sheet) |
|
|
|
} |
|
|
|
val thicknessMap = mapOf( |
|
|
|
1 to BorderStyle.THIN, |
|
|
|
2 to BorderStyle.THICK, |
|
|
|
) |
|
|
|
RegionUtil.setBorderTop(thicknessMap[top], region, sheet) |
|
|
|
RegionUtil.setBorderBottom(thicknessMap[bottom], region, sheet) |
|
|
|
RegionUtil.setBorderLeft(thicknessMap[left], region, sheet) |
|
|
|
RegionUtil.setBorderRight(thicknessMap[right], region, sheet) |
|
|
|
// when (top) { |
|
|
|
// 1 -> RegionUtil.setBorderTop(thicknessMap[1], region, sheet) |
|
|
|
// 2 -> RegionUtil.setBorderTop(BorderStyle.THICK, region, sheet) |
|
|
|
// } |
|
|
|
// when (bottom) { |
|
|
|
// 1 -> RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet) |
|
|
|
// 2 -> RegionUtil.setBorderBottom(BorderStyle.THICK, region, sheet) |
|
|
|
// } |
|
|
|
// when (left) { |
|
|
|
// 1 -> RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet) |
|
|
|
// 2 -> RegionUtil.setBorderLeft(BorderStyle.THICK, region, sheet) |
|
|
|
// } |
|
|
|
// when (right) { |
|
|
|
// 1 -> RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet) |
|
|
|
// 2 -> RegionUtil.setBorderRight(BorderStyle.THICK, region, sheet) |
|
|
|
// } |
|
|
|
} |
|
|
|
|
|
|
|
private val chargeFee = 1.15 |
|
|
@@ -3600,9 +3620,9 @@ open class ReportService( |
|
|
|
return jdbcDao.queryForList(sql.toString(), args) |
|
|
|
} |
|
|
|
|
|
|
|
private fun generateTeamBlock( |
|
|
|
private fun generateTeamsInOutMap( |
|
|
|
teams: List<Team>, |
|
|
|
sortedTeams: MutableList<Team>, |
|
|
|
desiredTeam: MutableList<Team>, |
|
|
|
grades: List<Grade>, |
|
|
|
timesheets: List<Timesheet>, |
|
|
|
gradeLog: List<GradeLog>, |
|
|
@@ -3632,63 +3652,60 @@ open class ReportService( |
|
|
|
}.toMutableMap() |
|
|
|
} |
|
|
|
} |
|
|
|
println("teamsMap") |
|
|
|
println(gradeMap) |
|
|
|
// teamsMap["TW"]!!["1"]!!.In.manhour += 1000 |
|
|
|
println(teamsMap) |
|
|
|
sortedTeams.forEach { team -> |
|
|
|
val currentTeam = team.code |
|
|
|
val _timesheets = timesheets.filter { ts -> |
|
|
|
// for after team log is implemented |
|
|
|
// val thisStaffTeam = teamlog.filter { |
|
|
|
// it.from.isBefore(ts.recordDate) |
|
|
|
// && it.to != null |
|
|
|
// && it.staff.id == ts.staff!!.id |
|
|
|
// }.maxByOrNull { it.from } |
|
|
|
// val thisProjectTeam = teamlog.filter { |
|
|
|
// it.from.isBefore(ts.recordDate) |
|
|
|
// && it.to != null |
|
|
|
// && it.staff.id == ts.project!!.teamLead!!.team.id |
|
|
|
// }.maxByOrNull { it.from } |
|
|
|
var _timesheets: List<Timesheet> |
|
|
|
// if have target team, desiredTeams should only be that team |
|
|
|
if (desiredTeam.size == 1) { |
|
|
|
val team = desiredTeam[0] |
|
|
|
val targetTeam = team.code |
|
|
|
_timesheets = timesheets.filter { ts -> |
|
|
|
val staffTeam = ts.staff!!.team.code |
|
|
|
val projectTeam = ts.project!!.teamLead!!.team.code |
|
|
|
(staffTeam == currentTeam && projectTeam != staffTeam) |
|
|
|
|| (projectTeam == currentTeam && projectTeam != staffTeam) // check isCrossTeam |
|
|
|
// ts.project!!.teamLead!!.team.id != thisStaffTeam!!.team.id // for team log |
|
|
|
projectTeam != staffTeam && |
|
|
|
(staffTeam == targetTeam || projectTeam == targetTeam ) |
|
|
|
} |
|
|
|
_timesheets.forEach {ts -> |
|
|
|
// this team charging others |
|
|
|
// get the grade and salary data of the record |
|
|
|
val _grade = gradeLog.find { it.staff.id == ts.staff!!.id } |
|
|
|
val gradeCode = _grade!!.grade.code |
|
|
|
val otMultiplier = 1.15 |
|
|
|
val thisSE = salaryEffective.filter { |
|
|
|
it.staff.id == ts.staff!!.id |
|
|
|
&& |
|
|
|
it.date.isBefore(ts.recordDate) |
|
|
|
}.maxByOrNull { it.date } |
|
|
|
val normalHour = ts.normalConsumed ?: 0.0 |
|
|
|
val otHour = ts.otConsumed ?: 0.0 |
|
|
|
val normalCost = normalHour.times(thisSE!!.salary.hourlyRate.toDouble()) |
|
|
|
val otCost = otHour.times(thisSE.salary.hourlyRate.toDouble()).times(otMultiplier) |
|
|
|
//assigning data |
|
|
|
val projectTeam = ts.project!!.teamLead!!.team.code |
|
|
|
} else { |
|
|
|
_timesheets = timesheets.filter { ts -> |
|
|
|
val staffTeam = ts.staff!!.team.code |
|
|
|
// write in |
|
|
|
println("putting in") |
|
|
|
var tsInData = teamsMap[projectTeam]!![gradeCode]!!.In |
|
|
|
println(tsInData) |
|
|
|
tsInData.manhour += normalHour + otHour |
|
|
|
tsInData.cost += normalCost + otCost |
|
|
|
// write out |
|
|
|
println("putting out") |
|
|
|
val tsOutData = teamsMap[staffTeam]!!.get(gradeCode)!!.Out |
|
|
|
tsOutData.manhour += normalHour + otHour |
|
|
|
tsOutData.cost += normalCost + otCost |
|
|
|
val projectTeam = ts.project!!.teamLead!!.team.code |
|
|
|
projectTeam != staffTeam |
|
|
|
} |
|
|
|
} |
|
|
|
println("all team - gradeMap") |
|
|
|
println(teamsMap) |
|
|
|
_timesheets.forEach {ts -> |
|
|
|
// this team charging others |
|
|
|
// get the grade and salary data of the record |
|
|
|
val _grade = gradeLog.find { |
|
|
|
it.staff.id == ts.staff!!.id |
|
|
|
&& |
|
|
|
it.from.isBefore(ts.recordDate) && (it.to == null || it.to.isAfter(ts.recordDate)) |
|
|
|
&& |
|
|
|
it.deleted == false |
|
|
|
} |
|
|
|
val gradeCode = _grade!!.grade.code |
|
|
|
val otMultiplier = 1.15 |
|
|
|
val thisSE = salaryEffective.find { |
|
|
|
it.staff.id == ts.staff!!.id |
|
|
|
&& |
|
|
|
it.startDate.isBefore(ts.recordDate) && (it.endDate.isAfter(ts.recordDate) || it.endDate == null) |
|
|
|
} |
|
|
|
val normalHour = ts.normalConsumed ?: 0.0 |
|
|
|
val otHour = ts.otConsumed ?: 0.0 |
|
|
|
val normalCost = normalHour.times(thisSE!!.salary.hourlyRate.toDouble()) |
|
|
|
val otCost = otHour.times(thisSE.salary.hourlyRate.toDouble()).times(otMultiplier) |
|
|
|
//assigning data |
|
|
|
val projectTeam = ts.project!!.teamLead!!.team.code |
|
|
|
val staffTeam = ts.staff!!.team.code |
|
|
|
// write in |
|
|
|
//println("putting in") |
|
|
|
var tsInData = teamsMap[projectTeam]!![gradeCode]!!.In |
|
|
|
tsInData.manhour += normalHour + otHour |
|
|
|
tsInData.cost += normalCost + otCost |
|
|
|
// write out |
|
|
|
//println("putting out") |
|
|
|
val tsOutData = teamsMap[staffTeam]!!.get(gradeCode)!!.Out |
|
|
|
tsOutData.manhour += normalHour + otHour |
|
|
|
tsOutData.cost += normalCost + otCost |
|
|
|
} |
|
|
|
|
|
|
|
return teamsMap |
|
|
|
} |
|
|
|
|
|
|
@@ -3697,6 +3714,23 @@ open class ReportService( |
|
|
|
CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.TOP) |
|
|
|
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) |
|
|
|
} |
|
|
|
|
|
|
|
private fun setAlignment(cell: Cell, verticalAlignment: String, horizontalAlignment: String) { |
|
|
|
val verticalAlignmentMap = mapOf( |
|
|
|
"top" to VerticalAlignment.TOP, |
|
|
|
"center" to VerticalAlignment.CENTER, |
|
|
|
"bottom" to VerticalAlignment.BOTTOM, |
|
|
|
) |
|
|
|
val horizontalAlignmentMap = mapOf( |
|
|
|
"left" to HorizontalAlignment.LEFT, |
|
|
|
"center" to HorizontalAlignment.CENTER, |
|
|
|
"right" to HorizontalAlignment.RIGHT, |
|
|
|
"fill" to HorizontalAlignment.FILL, |
|
|
|
"justify" to HorizontalAlignment.JUSTIFY, |
|
|
|
) |
|
|
|
CellUtil.setVerticalAlignment(cell, verticalAlignmentMap[verticalAlignment]) |
|
|
|
CellUtil.setAlignment(cell, horizontalAlignmentMap[horizontalAlignment]) |
|
|
|
} |
|
|
|
private fun createCrossTeamForm( |
|
|
|
workbook: Workbook, |
|
|
|
sheet: Sheet, |
|
|
@@ -3914,15 +3948,15 @@ open class ReportService( |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(convertReportMonth) |
|
|
|
} |
|
|
|
var sortedTeams = teams.toMutableList() |
|
|
|
var desiredTeam = teams.toMutableList() |
|
|
|
if (teamId.lowercase() != "all") { |
|
|
|
// sortedTeams = teams.sortedWith(compareBy { if (it.id == teamId.toLong()) 0 else 1 }).toMutableList() |
|
|
|
sortedTeams = mutableListOf(teams.find { teamId.toLong() == it.id }!!) |
|
|
|
// desiredTeam = teams.sortedWith(compareBy { if (it.id == teamId.toLong()) 0 else 1 }).toMutableList() |
|
|
|
desiredTeam = mutableListOf(teams.find { teamId.toLong() == it.id }!!) |
|
|
|
} |
|
|
|
//// generate info map ///// |
|
|
|
val teamsInOutMap: MutableMap<String, MutableMap<String, InOut>> = generateTeamBlock( |
|
|
|
val teamsInOutMap: MutableMap<String, MutableMap<String, InOut>> = generateTeamsInOutMap( |
|
|
|
teams, |
|
|
|
sortedTeams, |
|
|
|
desiredTeam, |
|
|
|
grades, |
|
|
|
timesheets, |
|
|
|
gradeLog, |
|
|
@@ -3942,6 +3976,306 @@ open class ReportService( |
|
|
|
sheet.setColumnWidth(i, 20 * 256) |
|
|
|
} |
|
|
|
} |
|
|
|
private fun createCrossTeamForm4TH( |
|
|
|
workbook: Workbook, |
|
|
|
sheet: Sheet, |
|
|
|
teamsMap: MutableMap<String, CrossTeamP4InOut> |
|
|
|
) { |
|
|
|
var rowIndex = 2 |
|
|
|
var columnIndex = 0 |
|
|
|
var tempRow: Row |
|
|
|
var tempCell: Cell |
|
|
|
val accountingStyle = workbook.createDataFormat().getFormat("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)") |
|
|
|
fun dataFormatArgs(accountingStyle: Short): MutableMap<String, Any> { |
|
|
|
val dataFormatArgs = mutableMapOf<String, Any>( |
|
|
|
CellUtil.DATA_FORMAT to accountingStyle |
|
|
|
) |
|
|
|
return dataFormatArgs |
|
|
|
} |
|
|
|
fun fontArgs(fontName: String, isBold: Boolean, isWrap: Boolean): MutableMap<String, Any>{ |
|
|
|
val font = sheet.workbook.createFont() |
|
|
|
font.bold = isBold |
|
|
|
font.fontName = fontName |
|
|
|
val fontArgs = mutableMapOf<String, Any>( |
|
|
|
CellUtil.FONT to font.index, |
|
|
|
CellUtil.WRAP_TEXT to isWrap, |
|
|
|
) |
|
|
|
return fontArgs |
|
|
|
} |
|
|
|
for ((teamCode, crossTeamP4InOut) in teamsMap) { |
|
|
|
columnIndex = 0 |
|
|
|
rowIndex++ |
|
|
|
tempRow = getOrCreateRow(sheet, rowIndex) |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue("Team") |
|
|
|
alignTopCenter(tempCell) |
|
|
|
CellUtil.setCellStyleProperties( |
|
|
|
tempCell, |
|
|
|
fontArgs("Times New Roman", true, true) |
|
|
|
+ cellBorderArgs(2,2,1,1) |
|
|
|
) |
|
|
|
columnIndex = 1 |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue("Cross Team Staffs") |
|
|
|
alignTopCenter(tempCell) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
fontArgs("Times New Roman", true, true) |
|
|
|
+ cellBorderArgs(2,2,1,1) |
|
|
|
) |
|
|
|
////// getting unique header list with columnIndex /////// |
|
|
|
var projectList = mutableListOf<String>() |
|
|
|
for ((_, projectTsDataMap) in crossTeamP4InOut.In) { |
|
|
|
for(key in projectTsDataMap.keys) { |
|
|
|
if (key !in projectList) { |
|
|
|
projectList.add(key) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
tempRow = getOrCreateRow(sheet, rowIndex) |
|
|
|
columnIndex = 2 |
|
|
|
projectList.forEach{ str -> |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue(str) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, fontArgs("Times New Roman", true, true)) |
|
|
|
alignTopCenter(tempCell) |
|
|
|
val titleRegion = CellRangeAddress(rowIndex, rowIndex,columnIndex,columnIndex+1) |
|
|
|
sheet.addMergedRegion(titleRegion) |
|
|
|
setRegionBorders(2,2,1,1,titleRegion, sheet) |
|
|
|
columnIndex += 2 |
|
|
|
} |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue("Total By Staff") |
|
|
|
CellUtil.setCellStyleProperties(tempCell, fontArgs("Times New Roman", true, true)) |
|
|
|
alignTopCenter(tempCell) |
|
|
|
val titleRegion = CellRangeAddress(rowIndex, rowIndex,columnIndex,columnIndex+1) |
|
|
|
sheet.addMergedRegion(titleRegion) |
|
|
|
setRegionBorders(2,2,2,2,titleRegion, sheet) |
|
|
|
alignTopCenter(tempCell) |
|
|
|
/////////////////////////////////////////////////////////////////////////////////// |
|
|
|
// total column = columnIndex + list.size |
|
|
|
rowIndex++ |
|
|
|
columnIndex = 0 |
|
|
|
tempRow = getOrCreateRow(sheet, rowIndex) |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue(teamCode) // team column |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
fontArgs("Times New Roman", false, false) |
|
|
|
) |
|
|
|
setAlignment(tempCell, "top", "center") |
|
|
|
|
|
|
|
var startingRow = rowIndex |
|
|
|
for ((staff, projectTsDataMap) in crossTeamP4InOut.In) { |
|
|
|
columnIndex = 1 |
|
|
|
tempRow = getOrCreateRow(sheet, rowIndex) |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue(staff) // team column |
|
|
|
setAlignment(tempCell, "top", "center") |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,1,1,1) |
|
|
|
+ fontArgs("Times New Roman", false, false) |
|
|
|
) |
|
|
|
var pidx = 0 |
|
|
|
var manhourFormula = mutableListOf<String>() |
|
|
|
var costFormula = mutableListOf<String>() |
|
|
|
while (pidx < projectList.size) { |
|
|
|
var manhour = 0.0 |
|
|
|
var cost = 0.0 |
|
|
|
if (projectTsDataMap.containsKey(projectList[pidx])) { |
|
|
|
manhour = projectTsDataMap[projectList[pidx]]?.manhour ?: 0.0 |
|
|
|
cost = projectTsDataMap[projectList[pidx]]?.cost ?: 0.0 |
|
|
|
} |
|
|
|
columnIndex++ |
|
|
|
val manhourLetter = CellReference.convertNumToColString(columnIndex) |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue(manhour) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,1,1,1) |
|
|
|
+ fontArgs("Times New Roman", false, false) |
|
|
|
+ dataFormatArgs(accountingStyle) |
|
|
|
) |
|
|
|
manhourFormula.add("${manhourLetter}${rowIndex+1}") |
|
|
|
columnIndex++ |
|
|
|
val costLetter = CellReference.convertNumToColString(columnIndex) |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue(cost) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,1,1,1) |
|
|
|
+ fontArgs("Times New Roman", false, false) |
|
|
|
+ dataFormatArgs(accountingStyle) |
|
|
|
) |
|
|
|
costFormula.add("${costLetter}${rowIndex+1}") |
|
|
|
pidx++ |
|
|
|
} |
|
|
|
// total by staff |
|
|
|
columnIndex++ |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,1,2,1) |
|
|
|
+ fontArgs("Times New Roman", false, false) |
|
|
|
+ dataFormatArgs(accountingStyle) |
|
|
|
) |
|
|
|
tempCell.cellFormula = manhourFormula.joinToString(separator = "+") |
|
|
|
columnIndex++ |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,1,1,1) |
|
|
|
+ fontArgs("Times New Roman", false, false) |
|
|
|
+ dataFormatArgs(accountingStyle) |
|
|
|
) |
|
|
|
tempCell.cellFormula = costFormula.joinToString(separator = "+") |
|
|
|
rowIndex++ |
|
|
|
} |
|
|
|
columnIndex = 0 |
|
|
|
val teamCodeRegion = CellRangeAddress(startingRow, rowIndex, columnIndex, columnIndex) |
|
|
|
sheet.addMergedRegion(teamCodeRegion) |
|
|
|
setRegionBorders(2,2,1,1, teamCodeRegion, sheet) |
|
|
|
columnIndex = 1 |
|
|
|
tempRow = getOrCreateRow(sheet, rowIndex) |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
tempCell.setCellValue("Total by Project:") |
|
|
|
setAlignment(tempCell, "top", "center") |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,2,1,1) |
|
|
|
+ fontArgs("Times New Roman", true, false) |
|
|
|
) |
|
|
|
|
|
|
|
// (project title + total by staff) * 2 |
|
|
|
columnIndex = 2 |
|
|
|
val numberOfColumns = (projectList.size + 1) * 2 |
|
|
|
var i = 0 |
|
|
|
while (i < numberOfColumns) { |
|
|
|
var leftBorder = 1 |
|
|
|
if (i == numberOfColumns - 2) { |
|
|
|
leftBorder = 2 |
|
|
|
} |
|
|
|
tempCell = getOrCreateCell(tempRow, columnIndex) |
|
|
|
val columnLetter = CellReference.convertNumToColString(columnIndex) |
|
|
|
tempCell.cellFormula = "SUM(${columnLetter}${startingRow+1}:${columnLetter}${rowIndex})" |
|
|
|
CellUtil.setCellStyleProperties(tempCell, |
|
|
|
cellBorderArgs(1,2,leftBorder,1) |
|
|
|
+ fontArgs("Times New Roman", false, false) |
|
|
|
+ dataFormatArgs(accountingStyle) |
|
|
|
) |
|
|
|
columnIndex++ |
|
|
|
i++ |
|
|
|
} |
|
|
|
rowIndex++ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
private fun generatePageFourTeamsInOutMap( |
|
|
|
teams: List<Team>, |
|
|
|
desiredTeams: MutableList<Team>, |
|
|
|
grades: List<Grade>, |
|
|
|
timesheets: List<Timesheet>, |
|
|
|
gradeLog: List<GradeLog>, |
|
|
|
salaryEffective: List<SalaryEffective>, |
|
|
|
): MutableMap<String, CrossTeamP4InOut> { |
|
|
|
var teamsMap: MutableMap<String, CrossTeamP4InOut> = mutableMapOf() |
|
|
|
// teams.forEach { team -> |
|
|
|
// val key = team.code |
|
|
|
// if (key !in teamsMap) { |
|
|
|
// teamsMap[key] = CrossTeamP4InOut( |
|
|
|
// In = mutableMapOf(), |
|
|
|
// ) |
|
|
|
// } |
|
|
|
// } |
|
|
|
var _timesheets: List<Timesheet> |
|
|
|
// if have target team, desiredTeams should only be that team |
|
|
|
if (desiredTeams.size == 1) { |
|
|
|
val team = desiredTeams[0] |
|
|
|
val targetTeam = team.code |
|
|
|
_timesheets = timesheets.filter { ts -> |
|
|
|
val staffTeam = ts.staff!!.team.code |
|
|
|
val projectTeam = ts.project!!.teamLead!!.team.code |
|
|
|
projectTeam != staffTeam && |
|
|
|
(staffTeam == targetTeam || projectTeam == targetTeam ) |
|
|
|
} |
|
|
|
} else { |
|
|
|
_timesheets = timesheets.filter { ts -> |
|
|
|
val staffTeam = ts.staff!!.team.code |
|
|
|
val projectTeam = ts.project!!.teamLead!!.team.code |
|
|
|
projectTeam != staffTeam |
|
|
|
} |
|
|
|
} |
|
|
|
_timesheets.forEach { ts -> |
|
|
|
val otMultiplier = 1.15 |
|
|
|
val thisSE = salaryEffective.filter { |
|
|
|
it.staff.id == ts.staff!!.id |
|
|
|
&& |
|
|
|
it.date.isBefore(ts.recordDate) |
|
|
|
}.maxByOrNull { it.date } |
|
|
|
val normalHour = ts.normalConsumed ?: 0.0 |
|
|
|
val otHour = ts.otConsumed ?: 0.0 |
|
|
|
val normalCost = normalHour.times(thisSE!!.salary.hourlyRate.toDouble()) |
|
|
|
val otCost = otHour.times(thisSE.salary.hourlyRate.toDouble()).times(otMultiplier) |
|
|
|
val staff = ts.staff!! |
|
|
|
val project = ts.project!! |
|
|
|
val projectNameCode = "${project.code}\n${project.name}" |
|
|
|
val projectTeam = project.teamLead!!.team.code |
|
|
|
val inOut_Key = "${staff.staffId} ${staff.name} (${staff.team.code})" |
|
|
|
if (!teamsMap.containsKey(projectTeam)) { |
|
|
|
teamsMap.put(projectTeam, CrossTeamP4InOut( |
|
|
|
In = mutableMapOf(), |
|
|
|
)) |
|
|
|
} |
|
|
|
val tsInData = teamsMap[projectTeam]!!.In |
|
|
|
|
|
|
|
|
|
|
|
if (!tsInData.containsKey(inOut_Key)) { |
|
|
|
tsInData.put(inOut_Key, mutableMapOf(projectNameCode to TsData(0.0, 0.0))) |
|
|
|
} |
|
|
|
if (!tsInData[inOut_Key]!!.containsKey(projectNameCode)) { |
|
|
|
tsInData[inOut_Key]!!.put(projectNameCode, TsData(0.0, 0.0)) |
|
|
|
} |
|
|
|
tsInData[inOut_Key]!![projectNameCode]!!.manhour += normalHour + otHour |
|
|
|
tsInData[inOut_Key]!![projectNameCode]!!.cost += normalCost + otCost |
|
|
|
} |
|
|
|
|
|
|
|
return teamsMap |
|
|
|
} |
|
|
|
private fun createFourthSheetTeamChargeReport( |
|
|
|
month: String, |
|
|
|
workbook: Workbook, |
|
|
|
timesheets: List<Timesheet>, |
|
|
|
teams: List<Team>, |
|
|
|
grades: List<Grade>, |
|
|
|
teamId: String, |
|
|
|
gradeLog: List<GradeLog>, |
|
|
|
salaryEffective: List<SalaryEffective>, |
|
|
|
) { |
|
|
|
var sheet: Sheet = workbook.getSheetAt(3) |
|
|
|
val rowIndex = 1 // Assuming the location is in (1,2), which is the report date field |
|
|
|
val columnIndex = 2 |
|
|
|
val monthFormat = DateTimeFormatter.ofPattern("MMMM yyyy", Locale.ENGLISH) |
|
|
|
val reportMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyy-MM")) |
|
|
|
val convertReportMonth = YearMonth.of(reportMonth.year, reportMonth.month).format(monthFormat) |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex).apply { |
|
|
|
setCellValue(convertReportMonth) |
|
|
|
} |
|
|
|
val _teams = teams |
|
|
|
var desiredTeams = teams.toMutableList() |
|
|
|
if (teamId.lowercase() != "all") { |
|
|
|
desiredTeams = mutableListOf(teams.find { teamId.toLong() == it.id }!!) |
|
|
|
_teams.sortedWith(compareBy { if (it.id == teamId.toLong()) 0 else 1 }) |
|
|
|
} |
|
|
|
val teamsInOutMap: MutableMap<String, CrossTeamP4InOut> = generatePageFourTeamsInOutMap( |
|
|
|
_teams, |
|
|
|
desiredTeams, |
|
|
|
grades, |
|
|
|
timesheets, |
|
|
|
gradeLog, |
|
|
|
salaryEffective, |
|
|
|
) |
|
|
|
println("4th ------- teamsInOutMap") |
|
|
|
println(teamsInOutMap) |
|
|
|
createCrossTeamForm4TH( |
|
|
|
workbook, |
|
|
|
sheet, |
|
|
|
teamsInOutMap |
|
|
|
) |
|
|
|
} |
|
|
|
@Throws(IOException::class) |
|
|
|
private fun createCrossTeamChargeReport( |
|
|
|
month: String, |
|
|
@@ -4530,6 +4864,17 @@ open class ReportService( |
|
|
|
gradeLog, |
|
|
|
salaryEffective |
|
|
|
) |
|
|
|
// page 4 |
|
|
|
createFourthSheetTeamChargeReport( |
|
|
|
month, |
|
|
|
workbook, |
|
|
|
timesheets, |
|
|
|
_teams, |
|
|
|
grades, |
|
|
|
teamId, |
|
|
|
gradeLog, |
|
|
|
salaryEffective |
|
|
|
) |
|
|
|
return workbook |
|
|
|
} |
|
|
|
// Use to Calculate cummunlative expenditure |
|
|
|