浏览代码

Update financial summary V2

pull/3/head
cyril.tsui 7 个月前
父节点
当前提交
4dcf9c851c
共有 3 个文件被更改,包括 436 次插入2 次删除
  1. +391
    -2
      src/main/java/com/ffii/tsms/modules/data/service/DashboardService.kt
  2. +18
    -0
      src/main/java/com/ffii/tsms/modules/data/web/DashboardController.kt
  3. +27
    -0
      src/main/java/com/ffii/tsms/modules/data/web/models/ExportDashboardExcelRequest.kt

+ 391
- 2
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.*
@@ -3405,7 +3407,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 +3511,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 +3715,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 +4050,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 +4152,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
}
}



+ 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,
)

正在加载...
取消
保存