Преглед изворни кода

Merge branch 'master' of https://git.2fi-solutions.com/davidhui/TSMS-backend

tags/Baseline_30082024_BACKEND_UAT
cyril.tsui пре 1 година
родитељ
комит
d0ba55599c
4 измењених фајлова са 139 додато и 2 уклоњено
  1. +1
    -1
      src/main/java/com/ffii/tsms/modules/project/service/InvoiceService.kt
  2. +106
    -1
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  3. +29
    -0
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  4. +3
    -0
      src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt

+ 1
- 1
src/main/java/com/ffii/tsms/modules/project/service/InvoiceService.kt Прегледај датотеку

@@ -395,7 +395,7 @@ open class InvoiceService(

for (i in 2..sheet.lastRowNum){
val paymentMilestoneId = getMilestonePaymentId(ExcelUtils.getCell(sheet, i, 1).stringCellValue, ExcelUtils.getCell(sheet, i, 5).stringCellValue)
println("paymentMilestoneId--------------: $paymentMilestoneId")
// println("paymentMilestoneId--------------: $paymentMilestoneId")
val milestonePayment = milestonePaymentRepository.findById(paymentMilestoneId).orElseThrow()
val invoice = Invoice().apply {
invoiceNo = ExcelUtils.getCell(sheet, i, 0).stringCellValue


+ 106
- 1
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt Прегледај датотеку

@@ -16,6 +16,7 @@ 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
@@ -23,11 +24,23 @@ open class ReportService {
private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd")
private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER)

private val FINANCIAL_STATUS_REPORT = "templates/report/EX01_Financial Status Report.xlsx"
private val PROJECT_CASH_FLOW_REPORT = "templates/report/EX02_Project Cash Flow Report.xlsx"
private val MONTHLY_WORK_HOURS_ANALYSIS_REPORT = "templates/report/AR08_Monthly Work Hours Analysis Report.xlsx"
private val SALART_LIST_TEMPLATE = "templates/report/Salary Template.xlsx"
private val LATE_START_REPORT = "templates/report/AR01_Late Start Report v01.xlsx"

// ==============================|| GENERATE REPORT ||============================== //

fun genFinancialStatusReport(): ByteArray {
val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT)

val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
workbook.close()

return outputStream.toByteArray()
}
@Throws(IOException::class)
fun generateProjectCashFlowReport(project: Project, invoices: List<Invoice>, timesheets: List<Timesheet>): ByteArray {
// Generate the Excel report with query results
@@ -67,7 +80,28 @@ open class ReportService {
return outputStream.toByteArray()
}

@Throws(IOException::class)
fun generateLateStartReport(project: Project): ByteArray {
val workbook: Workbook = createLateStartReport(project,LATE_START_REPORT)
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
workbook.close()
return outputStream.toByteArray()
}

// ==============================|| CREATE REPORT ||============================== //

// EX01 Financial Report
private fun createFinancialStatusReport(
templatePath: String,
) : Workbook {
val resource = ClassPathResource(templatePath)
val templateInputStream = resource.inputStream
val workbook: Workbook = XSSFWorkbook(templateInputStream)

return workbook
}

@Throws(IOException::class)
private fun createProjectCashFlowReport(
project: Project,
@@ -83,7 +117,7 @@ open class ReportService {
val sheet: Sheet = workbook.getSheetAt(0)

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

var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field
var columnIndex = 2
@@ -529,4 +563,75 @@ open class ReportService {
return workbook
}

private fun createLateStartReport(
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)
dateCell.setCellValue(formattedToday)
// Styling for cell A1: Font size 16 and bold
val headerFont = workbook.createFont().apply {
bold = true
fontHeightInPoints = 16
}
val headerCellStyle = workbook.createCellStyle().apply {
setFont(headerFont)
}
val headerCell = sheet.getRow(0)?.getCell(0) ?: sheet.getRow(0).createCell(0)
headerCell.cellStyle = headerCellStyle
headerCell.setCellValue("Report Title")
// Apply styles from A2 to A4 (bold)
val boldFont = workbook.createFont().apply { bold = true }
val boldCellStyle = workbook.createCellStyle().apply { setFont(boldFont) }
listOf(1, 2, 3).forEach { rowIndex ->
val row = sheet.getRow(rowIndex)
val cell = row?.getCell(0) ?: row.createCell(0)
cell.cellStyle = boldCellStyle
}
// Apply styles from A6 to J6 (bold, bottom border, center alignment)
val styleA6ToJ6 = workbook.createCellStyle().apply {
setFont(boldFont)
alignment = HorizontalAlignment.CENTER
borderBottom = BorderStyle.THIN
}
for (colIndex in 0..9) {
val cellAddress = CellAddress(5, colIndex) // Row 6 (0-based index), Columns A to J
val row = sheet.getRow(cellAddress.row)
val cell = row?.getCell(cellAddress.column) ?: row.createCell(cellAddress.column)
cell.cellStyle = styleA6ToJ6
}
// Setting column widths dynamically based on content length (example logic)
val maxContentWidths = IntArray(10) { 8 } // Initial widths for A to J
for (rowIndex in 0..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex)
for (colIndex in 0..9) {
val cell = row.getCell(colIndex)
if (cell != null) {
val length = cell.toString().length
if (length > maxContentWidths[colIndex]) {
maxContentWidths[colIndex] = length
}
}
}
}
for (colIndex in 0..9) {
sheet.setColumnWidth(colIndex, (maxContentWidths[colIndex] + 2) * 256) // Set the width for each column
}
return workbook
}

}

+ 29
- 0
src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt Прегледај датотеку

@@ -5,6 +5,7 @@ import com.ffii.tsms.modules.data.entity.projections.StaffSearchInfo
import com.ffii.tsms.modules.project.entity.*
import com.ffii.tsms.modules.report.service.ReportService
import com.ffii.tsms.modules.project.service.InvoiceService
import com.ffii.tsms.modules.report.web.model.FinancialStatusReportRequest
import com.ffii.tsms.modules.report.web.model.ProjectCashFlowReportRequest
import com.ffii.tsms.modules.report.web.model.StaffMonthlyWorkHourAnalysisReportRequest
import com.ffii.tsms.modules.timesheet.entity.LeaveRepository
@@ -21,6 +22,8 @@ import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import java.io.IOException
import java.time.LocalDate

@@ -37,6 +40,18 @@ class ReportController(
private val leaveRepository: LeaveRepository,
private val invoiceService: InvoiceService) {

@PostMapping("/fetchProjectsFinancialStatusReport")
@Throws(ServletRequestBindingException::class, IOException::class)
fun getFinancialStatusReport(@RequestBody @Valid request: FinancialStatusReportRequest): ResponseEntity<Resource> {

val reportResult: ByteArray = excelReportService.genFinancialStatusReport()

return ResponseEntity.ok()
.header("filename", "Financial Status Report - " + LocalDate.now() + ".xlsx")
.body(ByteArrayResource(reportResult))
}


@PostMapping("/ProjectCashFlowReport")
@Throws(ServletRequestBindingException::class, IOException::class)
fun getProjectCashFlowReport(@RequestBody @Valid request: ProjectCashFlowReportRequest): ResponseEntity<Resource> {
@@ -80,4 +95,18 @@ class ReportController(
val project = projectRepository.findById(id).orElseThrow()
return invoiceService.findAllByProjectAndPaidAmountIsNotNull(project)
}

@PostMapping("/downloadLateStartReport")
fun downloadLateStartReport(): ResponseEntity<ByteArrayResource> {
val reportBytes = excelReportService.generateLateStartReport(Project())
val headers = HttpHeaders()
headers.add("Content-Disposition", "attachment; filename=Late_Start_Report_${LocalDate.now()}.xlsx")

return ResponseEntity.ok()
.headers(headers)
.contentLength(reportBytes.size.toLong())
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
.body(ByteArrayResource(reportBytes))
}

}

+ 3
- 0
src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt Прегледај датотеку

@@ -2,6 +2,9 @@ package com.ffii.tsms.modules.report.web.model

import java.time.YearMonth

data class FinancialStatusReportRequest (
val projectId: Long
)
data class ProjectCashFlowReportRequest (
val projectId: Long
)


Loading…
Откажи
Сачувај