|
|
@@ -1,12 +1,16 @@ |
|
|
|
package com.ffii.tsms.modules.report.service |
|
|
|
|
|
|
|
import com.ffii.core.support.JdbcDao |
|
|
|
import com.ffii.tsms.modules.data.entity.Salary |
|
|
|
import com.ffii.tsms.modules.data.entity.Staff |
|
|
|
import com.ffii.tsms.modules.project.entity.Invoice |
|
|
|
import com.ffii.tsms.modules.project.entity.Project |
|
|
|
import com.ffii.tsms.modules.timesheet.entity.Leave |
|
|
|
import com.ffii.tsms.modules.timesheet.entity.Timesheet |
|
|
|
import org.apache.commons.logging.Log |
|
|
|
import org.apache.commons.logging.LogFactory |
|
|
|
import org.apache.poi.ss.usermodel.* |
|
|
|
import org.apache.poi.ss.util.CellAddress |
|
|
|
import org.apache.poi.ss.util.CellRangeAddress |
|
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook |
|
|
|
import org.springframework.core.io.ClassPathResource |
|
|
@@ -16,11 +20,14 @@ import java.io.IOException |
|
|
|
import java.time.LocalDate |
|
|
|
import java.time.format.DateTimeFormatter |
|
|
|
import java.util.* |
|
|
|
import org.apache.poi.ss.util.CellAddress |
|
|
|
|
|
|
|
data class DayInfo(val date: String?, val weekday: String?) |
|
|
|
@Service |
|
|
|
open class ReportService { |
|
|
|
open class ReportService ( |
|
|
|
private val jdbcDao: JdbcDao, |
|
|
|
) |
|
|
|
{ |
|
|
|
private val logger: Log = LogFactory.getLog(javaClass) |
|
|
|
private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd") |
|
|
|
private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER) |
|
|
|
|
|
|
@@ -32,8 +39,8 @@ open class ReportService { |
|
|
|
|
|
|
|
// ==============================|| GENERATE REPORT ||============================== // |
|
|
|
|
|
|
|
fun genFinancialStatusReport(): ByteArray { |
|
|
|
val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT) |
|
|
|
fun genFinancialStatusReport(projectId: Long): ByteArray { |
|
|
|
val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT, projectId) |
|
|
|
|
|
|
|
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() |
|
|
|
workbook.write(outputStream) |
|
|
@@ -94,6 +101,7 @@ open class ReportService { |
|
|
|
// EX01 Financial Report |
|
|
|
private fun createFinancialStatusReport( |
|
|
|
templatePath: String, |
|
|
|
projectId: Long, |
|
|
|
) : Workbook { |
|
|
|
val resource = ClassPathResource(templatePath) |
|
|
|
val templateInputStream = resource.inputStream |
|
|
@@ -191,30 +199,40 @@ open class ReportService { |
|
|
|
// TODO: Add expenditure |
|
|
|
rowIndex = 15 |
|
|
|
val combinedResults = (invoices.map { it.receiptDate } + timesheets.map { it.recordDate }).filterNotNull().sortedBy { it } |
|
|
|
|
|
|
|
logger.info("combinedResults-------------- $combinedResults") |
|
|
|
invoices.forEach{ |
|
|
|
logger.info("Invoice--------- $it. \n") |
|
|
|
} |
|
|
|
val dateFormatter = DateTimeFormatter.ofPattern("MMM YYYY") |
|
|
|
combinedResults.forEach { result: LocalDate -> |
|
|
|
val invoice = invoices.find { invoice: Invoice -> invoice.receiptDate == result } |
|
|
|
val timesheet = timesheets.find { timesheet: Timesheet -> timesheet.recordDate == result} |
|
|
|
|
|
|
|
logger.info("result--------------: $result") |
|
|
|
if (invoice != null) { |
|
|
|
sheet.getRow(rowIndex++).apply { |
|
|
|
|
|
|
|
getCell(0).apply { |
|
|
|
setCellValue(result.format(dateFormatter)) |
|
|
|
sheet.getRow(rowIndex++)?.apply { |
|
|
|
|
|
|
|
logger.info("INVOICE NOT NULL--------------:") |
|
|
|
logger.info("getCell(0)--------------: ${getCell(0)}") |
|
|
|
logger.info("dateFormatter--------------: $dateFormatter") |
|
|
|
logger.info("result.format--------------: ${result.format(dateFormatter)}") |
|
|
|
getCell(0)?.apply { |
|
|
|
setCellValue(result.format(dateFormatter).toString()) |
|
|
|
} |
|
|
|
|
|
|
|
getCell(1).apply { |
|
|
|
getCell(1)?.apply { |
|
|
|
setCellValue(0.0) |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
|
|
|
|
getCell(2).apply { |
|
|
|
logger.info("invoice.paidAmount------------: ${invoice.paidAmount}") |
|
|
|
logger.info("invoice.paidAmount------------: ${invoice.paidAmount!!.toDouble()}") |
|
|
|
getCell(2)?.apply { |
|
|
|
setCellValue(invoice.paidAmount!!.toDouble()) |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
|
|
|
|
getCell(3).apply { |
|
|
|
getCell(3)?.apply { |
|
|
|
val lastRow = rowIndex - 1 |
|
|
|
if (lastRow == 15) { |
|
|
|
cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) |
|
|
@@ -224,30 +242,34 @@ open class ReportService { |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
|
|
|
|
getCell(4).apply { |
|
|
|
getCell(4)?.apply { |
|
|
|
setCellValue(invoice.milestonePayment!!.description!!) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (timesheet != null) { |
|
|
|
sheet.getRow(rowIndex++).apply { |
|
|
|
sheet.getRow(rowIndex++)?.apply { |
|
|
|
|
|
|
|
getCell(0).apply { |
|
|
|
logger.info("TIMESHEET NOT NULL--------------:") |
|
|
|
logger.info("getCell(0)--------------: ${getCell(0)}") |
|
|
|
logger.info("dateFormatter--------------: $dateFormatter") |
|
|
|
logger.info("result.format--------------: ${result.format(dateFormatter)}") |
|
|
|
getCell(0)?.apply { |
|
|
|
setCellValue(result.format(dateFormatter)) |
|
|
|
} |
|
|
|
|
|
|
|
getCell(1).apply { |
|
|
|
getCell(1)?.apply { |
|
|
|
setCellValue(timesheet.staff!!.salary.hourlyRate.toDouble() * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0))) |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
|
|
|
|
getCell(2).apply { |
|
|
|
getCell(2)?.apply { |
|
|
|
setCellValue(0.0) |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
|
|
|
|
getCell(3).apply { |
|
|
|
getCell(3)?.apply { |
|
|
|
val lastRow = rowIndex - 1 |
|
|
|
if (lastRow == 15) { |
|
|
|
cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) |
|
|
@@ -257,7 +279,7 @@ open class ReportService { |
|
|
|
cellStyle.dataFormat = accountingStyle |
|
|
|
} |
|
|
|
|
|
|
|
getCell(4).apply { |
|
|
|
getCell(4)?.apply { |
|
|
|
setCellValue("Monthly Manpower Expenditure") |
|
|
|
} |
|
|
|
} |
|
|
@@ -634,4 +656,33 @@ open class ReportService { |
|
|
|
return workbook |
|
|
|
} |
|
|
|
|
|
|
|
open fun getFinancialStatus(projectId: Long?): List<Map<String, Any>> { |
|
|
|
val sql = StringBuilder( |
|
|
|
"with cte_invoice as (select p.code, sum(i.issueAmount) as sumIssuedAmount , sum(i.paidAmount) as sumPaidAmount" |
|
|
|
+ "from invoice i" |
|
|
|
+ "left join project p on p.code = i.projectCode" |
|
|
|
+ "group by p.code" |
|
|
|
+ ")" |
|
|
|
+ " Select p.code, p.description, c.name, t2.name, p.planStart , p.planEnd , p.expectedTotalFee ," |
|
|
|
+ " s.name , IFNULL(t.normalConsumed, 0) as normalConsumed, IFNULL(t.otConsumed , 0) as otConsumed, s2.hourlyRate," |
|
|
|
+ " cte_i.sumIssuedAmount, cte_i.sumPaidAmount" |
|
|
|
+ " from timesheet t" |
|
|
|
+ " left join project_task pt on pt.id = t.projectTaskId" |
|
|
|
+ " left join project p ON p.id = pt.project_id" |
|
|
|
+ " left join staff s on s.id = t.staffId" |
|
|
|
+ " left join salary s2 on s.salaryId = s2.salaryPoint" |
|
|
|
+ " left join customer c on c.id = p.customerId" |
|
|
|
+ " left join team t2 on t2.id = s.teamId" |
|
|
|
+ " left join cte_invoice cte_i on cte_i.code = p.code" |
|
|
|
) |
|
|
|
|
|
|
|
if (projectId!! > 0){ |
|
|
|
sql.append(" where p.id = :projectId ") |
|
|
|
} |
|
|
|
sql.append(" order by p.code") |
|
|
|
val args = mapOf("projectId" to projectId) |
|
|
|
|
|
|
|
return jdbcDao.queryForList(sql.toString(), args) |
|
|
|
} |
|
|
|
|
|
|
|
} |