浏览代码

Receievd Inovice

tags/Baseline_30082024_BACKEND_UAT
MSI\2Fi 1年前
父节点
当前提交
57eae66d03
共有 7 个文件被更改,包括 181 次插入31 次删除
  1. +1
    -1
      src/main/java/com/ffii/tsms/modules/project/entity/Invoice.kt
  2. +2
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt
  3. +5
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/projections/InvoiceInfo.kt
  4. +164
    -28
      src/main/java/com/ffii/tsms/modules/project/service/InvoiceService.kt
  5. +5
    -0
      src/main/java/com/ffii/tsms/modules/project/web/InvoiceController.kt
  6. +2
    -0
      src/main/java/com/ffii/tsms/modules/project/web/models/InvoiceResponse.kt
  7. +2
    -2
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt

+ 1
- 1
src/main/java/com/ffii/tsms/modules/project/entity/Invoice.kt 查看文件

@@ -38,7 +38,7 @@ open class Invoice : BaseEntity<Long>(){
open var unpaidAmount: Double? = null open var unpaidAmount: Double? = null


@Column(name = "paidAmount") @Column(name = "paidAmount")
open var paidAmount: Double? = null
open var paidAmount: BigDecimal? = null


@Column(name = "projectCode") @Column(name = "projectCode")
open var projectCode: String? = null open var projectCode: String? = null


+ 2
- 0
src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt 查看文件

@@ -9,5 +9,7 @@ interface InvoiceRepository : AbstractRepository<Invoice, Long> {


fun findInvoiceInfoBy(): List<InvoiceInfo> fun findInvoiceInfoBy(): List<InvoiceInfo>


fun findInvoiceInfoByPaidAmountIsNotNull(): List<InvoiceInfo>

fun findByInvoiceNo(invoiceNo: String): Invoice fun findByInvoiceNo(invoiceNo: String): Invoice
} }

+ 5
- 0
src/main/java/com/ffii/tsms/modules/project/entity/projections/InvoiceInfo.kt 查看文件

@@ -36,6 +36,11 @@ interface InvoiceInfo {


val dueDate: LocalDate? val dueDate: LocalDate?


val receiptDate: LocalDate?

@get:Value("#{target.paidAmount}")
val receivedAmount: BigDecimal?

@get:Value("#{target.issueAmount}") @get:Value("#{target.issueAmount}")
val issuedAmount: BigDecimal? val issuedAmount: BigDecimal?



+ 164
- 28
src/main/java/com/ffii/tsms/modules/project/service/InvoiceService.kt 查看文件

@@ -17,6 +17,7 @@ import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.Sheet import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook import org.apache.poi.ss.usermodel.Workbook
import org.springframework.core.io.ClassPathResource import org.springframework.core.io.ClassPathResource
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
import java.io.InputStream import java.io.InputStream
@@ -93,6 +94,20 @@ open class InvoiceService(
return jdbcDao.queryForList(sql.toString(), args) return jdbcDao.queryForList(sql.toString(), args)
} }


open fun getMilestonePaymentWithProjectCode(code: List<String>): List<Map<String, Any>> {
val sql = StringBuilder("select "
+ " p.code, mp.* "
+ " from milestone_payment mp "
+ " left join milestone m on mp.milestoneId = m.id "
+ " left join project p on p.id = m.projectId "
+ " where p.deleted = false "
+ " and p.code in (:code) "
)
val args = mapOf("code" to code)

return jdbcDao.queryForList(sql.toString(), args)
}

open fun getInvoiceByInvoiceNo(invoiceNo: String): Invoice { open fun getInvoiceByInvoiceNo(invoiceNo: String): Invoice {
return invoiceRepository.findByInvoiceNo(invoiceNo) return invoiceRepository.findByInvoiceNo(invoiceNo)
} }
@@ -159,26 +174,100 @@ open class InvoiceService(
} }


/** /**
* To Check the invoice no with DB Records
* return the List of existing invoice no * return the List of existing invoice no
* @param checkDuplicate true, return duplicate Invoice No
*/ */
open fun checkInvocieNo(
open fun checkInvoiceNo(
invoiceNo: String, invoiceNo: String,
invoices: List<InvoiceInfo>, invoices: List<InvoiceInfo>,
invoicesResult: MutableList<String>, invoicesResult: MutableList<String>,
checkDuplicate: Boolean checkDuplicate: Boolean
): List<String?>{ ): List<String?>{
val existingInvoiceNos: List<String?> val existingInvoiceNos: List<String?>
existingInvoiceNos = if(checkDuplicate){
invoices.filter { it.invoiceNo == invoiceNo }.map { it.invoiceNo }
existingInvoiceNos = invoices.filter { it.invoiceNo == invoiceNo }.map { it.invoiceNo }

if (checkDuplicate){
if (existingInvoiceNos.isNotEmpty()) {
invoicesResult.add(invoiceNo)
}
}else{ }else{
invoices.filter { it.invoiceNo != invoiceNo }.map { it.invoiceNo }
if (existingInvoiceNos.isEmpty()) {
invoicesResult.add(invoiceNo)
}
} }


if (existingInvoiceNos.isNotEmpty()) {
invoicesResult.add(invoiceNo)
return invoicesResult
}

open fun checkDuplicateItemInImportedInvoice(
sheet: Sheet,
startingRow: Int,
columnIndex: Int
): List<String> {
val uniqueValues = HashSet<String>()
val duplicateValues = HashSet<String>()

for (i in startingRow..sheet.lastRowNum) {
val row = sheet.getRow(i)
val cell = row?.getCell(columnIndex)
if (cell != null && cell.cellType == CellType.STRING) {
val cellValue = cell.stringCellValue
if (uniqueValues.contains(cellValue)) {
duplicateValues.add(cellValue)
} else {
uniqueValues.add(cellValue)
}
}
} }


return invoicesResult
return duplicateValues.toList()
}

/**
* @return true when cellValue Object exist in DB
*/
fun checkStringExists(list: List<Map<String, Any>>, cellValue: Map<String, Any>): Boolean {
println("LIST-------------: $list")
println("CELL VALUE-------------: $cellValue")
return list.contains(cellValue)
}
open fun checkMilestonePayment(
sheet: Sheet,
startingRow: Int,
columnIndex: Int,
invoiceColumnIndex: Int,
projectCodeColumnIndex: Int,
paymentMilestoneWithCode: List<Map<String, Any>>
): List<Map<String, Any>> {
val nonExistMilestone: MutableList<Map<String, Any>> = mutableListOf()

for (i in startingRow..sheet.lastRowNum) {
val row = sheet.getRow(i)
val milestonePaymentCell = row?.getCell(columnIndex)
val invoiceNoCell = row?.getCell(invoiceColumnIndex)
val projectCodeCell = row?.getCell(projectCodeColumnIndex)
if (milestonePaymentCell != null && milestonePaymentCell.cellType == CellType.STRING &&
invoiceNoCell != null && invoiceNoCell.cellType == CellType.STRING &&
projectCodeCell != null && projectCodeCell.cellType == CellType.STRING)
{
val milestonePaymentCellValue = milestonePaymentCell.stringCellValue
val invoiceNoCellValue = invoiceNoCell.stringCellValue
val projectCodeCellValue = projectCodeCell.stringCellValue

val cellValue = mapOf("code" to projectCodeCellValue, "description" to milestonePaymentCellValue)

if(!checkStringExists(paymentMilestoneWithCode, cellValue)) {
if(!nonExistMilestone.contains(mapOf("paymentMilestone" to milestonePaymentCellValue, "invoiceNo" to invoiceNoCellValue))){
nonExistMilestone.add(mapOf("paymentMilestone" to milestonePaymentCellValue, "invoiceNo" to invoiceNoCellValue))
}
}
println("nonExistMilestone $nonExistMilestone")
}

}

return nonExistMilestone.toList()
} }


open fun checkMandatoryField( open fun checkMandatoryField(
@@ -192,13 +281,13 @@ open class InvoiceService(
// (CellType.NUMERIC, CellType.STRING, CellType.BOOLEAN, CellType.ERROR) // (CellType.NUMERIC, CellType.STRING, CellType.BOOLEAN, CellType.ERROR)
when(ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).cellType){ when(ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).cellType){
CellType.NUMERIC -> { CellType.NUMERIC -> {
println("NUMERIC" + ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).numericCellValue)
// println("NUMERIC" + ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).numericCellValue)
if (ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).numericCellValue.isNaN()){ if (ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).numericCellValue.isNaN()){
emptyRowList.add(row) emptyRowList.add(row)
} }
} }
CellType.STRING -> { CellType.STRING -> {
println("STRING" + ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).stringCellValue)
// println("STRING" + ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).stringCellValue)
if(ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).stringCellValue.isBlank()){ if(ExcelUtils.getCell(sheet, row, mandatoryColumns[i]).stringCellValue.isBlank()){
emptyRowList.add(row) emptyRowList.add(row)
} }
@@ -218,6 +307,10 @@ open class InvoiceService(
return invoiceRepository.findInvoiceInfoBy() return invoiceRepository.findInvoiceInfoBy()
} }


open fun allInvoicePaid(): List<InvoiceInfo>{
return invoiceRepository.findInvoiceInfoByPaidAmountIsNotNull()
}

@Transactional(rollbackFor = [Exception::class]) @Transactional(rollbackFor = [Exception::class])
open fun importIssueInvoice(workbook: Workbook?): InvoiceResponse { open fun importIssueInvoice(workbook: Workbook?): InvoiceResponse {


@@ -226,39 +319,57 @@ open class InvoiceService(


// For checking existence of projecrt code // For checking existence of projecrt code
val newProjectCodes: MutableList<String> = mutableListOf() val newProjectCodes: MutableList<String> = mutableListOf()
val projectsCodes: MutableList<String> = mutableListOf()


// For checking mandatory field in each row // For checking mandatory field in each row
val emptyRowList: MutableList<Int> = mutableListOf() val emptyRowList: MutableList<Int> = mutableListOf()
val mandatoryColumns = listOf(0,1,4,5,10,11,12) // Mandatory Field in column 0,1,4,5,10,11,12 val mandatoryColumns = listOf(0,1,4,5,10,11,12) // Mandatory Field in column 0,1,4,5,10,11,12


if (workbook == null) { if (workbook == null) {
return InvoiceResponse(false, "No Excel import", newProjectCodes, emptyRowList, invoicesResult) // if workbook is null
return InvoiceResponse(false, "No Excel import", newProjectCodes, emptyRowList, invoicesResult, ArrayList(), ArrayList()) // if workbook is null
} }


val sheet: Sheet = workbook.getSheetAt(0) val sheet: Sheet = workbook.getSheetAt(0)
val sheetValues: MutableList<Map<String, Any>> = ArrayList()
// val sheetValues: MutableList<Map<String, Any>> = ArrayList()


// Get All invoices and Porjects from DB // Get All invoices and Porjects from DB
val invoices = allInvoice() val invoices = allInvoice()
val projects = projectService.allProjects() val projects = projectService.allProjects()


val duplicateItemsInInvoice = checkDuplicateItemInImportedInvoice(sheet,2,0)

// Check the import invoice with the data in DB
for (i in 2..sheet.lastRowNum){ for (i in 2..sheet.lastRowNum){
val sheetInvoice = ExcelUtils.getCell(sheet, i, 0).stringCellValue val sheetInvoice = ExcelUtils.getCell(sheet, i, 0).stringCellValue
val sheetProjectCode = ExcelUtils.getCell(sheet, i, 1).stringCellValue val sheetProjectCode = ExcelUtils.getCell(sheet, i, 1).stringCellValue
checkInvocieNo(sheetInvoice, invoices, invoicesResult, true)
checkInvoiceNo(sheetInvoice, invoices, invoicesResult, true)
checkProjectCode(sheetProjectCode, projects, newProjectCodes) checkProjectCode(sheetProjectCode, projects, newProjectCodes)
checkMandatoryField(mandatoryColumns, sheet, i, emptyRowList, 1) checkMandatoryField(mandatoryColumns, sheet, i, emptyRowList, 1)
println("For: $invoicesResult")
println("For: $newProjectCodes")
// println("For: $invoicesResult")
// println("For: $newProjectCodes")
if(!projectsCodes.contains(ExcelUtils.getCell(sheet, i, 1).stringCellValue)){
projectsCodes.add(ExcelUtils.getCell(sheet, i, 1).stringCellValue)
}
}

if (newProjectCodes.size == 0){
val milestonepaymentWithCode = getMilestonePaymentWithProjectCode(projectsCodes)
// println("newProjectCodes == 0")
// println(checkMilestonePayment(sheet, 2, 5, 0, 1, milestonepaymentWithCode))
val paymenMilestones = checkMilestonePayment(sheet, 2, 5, 0, 1, milestonepaymentWithCode)
if (paymenMilestones.isNotEmpty()){
return InvoiceResponse(false, "Imported Invoice's format is incorrect", newProjectCodes, emptyRowList, invoicesResult, duplicateItemsInInvoice, paymenMilestones)
}
} }


if (invoicesResult.size >= 1 || if (invoicesResult.size >= 1 ||
newProjectCodes.size >= 1 || newProjectCodes.size >= 1 ||
emptyRowList.size >= 1
emptyRowList.size >= 1 ||
duplicateItemsInInvoice.isNotEmpty()
){ ){
println("invoicesResult") println("invoicesResult")
println(invoicesResult) println(invoicesResult)
return InvoiceResponse(false, "Imported Invoice's format is incorrect", newProjectCodes, emptyRowList, invoicesResult)
return InvoiceResponse(false, "Imported Invoice's format is incorrect", newProjectCodes, emptyRowList, invoicesResult, duplicateItemsInInvoice, ArrayList())
} }


for (i in 2..sheet.lastRowNum){ for (i in 2..sheet.lastRowNum){
@@ -280,7 +391,7 @@ open class InvoiceService(
saveAndFlush(invoice) saveAndFlush(invoice)
} }


return InvoiceResponse(true, "OK", newProjectCodes, emptyRowList, invoicesResult)
return InvoiceResponse(true, "OK", newProjectCodes, emptyRowList, invoicesResult, duplicateItemsInInvoice, ArrayList())
} }


@Transactional(rollbackFor = [Exception::class]) @Transactional(rollbackFor = [Exception::class])
@@ -294,10 +405,10 @@ open class InvoiceService(


// For checking mandatory field in each row // For checking mandatory field in each row
val emptyRowList: MutableList<Int> = mutableListOf() val emptyRowList: MutableList<Int> = mutableListOf()
val mandatoryColumns = listOf(0,1,4,5) // Mandatory Field in column 0,1,4,5,10,11,12
val mandatoryColumns = listOf(0,1,4,5) // Mandatory Field in column 0,1,4,5


if (workbook == null) { if (workbook == null) {
return InvoiceResponse(false, "No Excel import", newProjectCodes, emptyRowList, invoicesResult) // if workbook is null
return InvoiceResponse(false, "No Excel import", newProjectCodes, emptyRowList, invoicesResult, ArrayList(), ArrayList()) // if workbook is null
} }


val sheet: Sheet = workbook.getSheetAt(0) val sheet: Sheet = workbook.getSheetAt(0)
@@ -307,32 +418,57 @@ open class InvoiceService(
val invoices = allInvoice() val invoices = allInvoice()
val projects = projectService.allProjects() val projects = projectService.allProjects()


val duplicateItemsInInvoice = checkDuplicateItemInImportedInvoice(sheet,2,0)

for (i in 2..sheet.lastRowNum){ for (i in 2..sheet.lastRowNum){
val sheetInvoice = ExcelUtils.getCell(sheet, i, 0).stringCellValue val sheetInvoice = ExcelUtils.getCell(sheet, i, 0).stringCellValue
val sheetProjectCode = ExcelUtils.getCell(sheet, i, 1).stringCellValue val sheetProjectCode = ExcelUtils.getCell(sheet, i, 1).stringCellValue
checkInvocieNo(sheetInvoice, invoices, invoicesResult, false)
checkInvoiceNo(sheetInvoice, invoices, invoicesResult, false)
checkProjectCode(sheetProjectCode, projects, newProjectCodes) checkProjectCode(sheetProjectCode, projects, newProjectCodes)
checkMandatoryField(mandatoryColumns, sheet, i, emptyRowList, 1) checkMandatoryField(mandatoryColumns, sheet, i, emptyRowList, 1)
println("For: $invoicesResult")
println("For: $newProjectCodes")
sheetValues.add((mapOf("invoicesNo" to sheetInvoice, "projectCode" to sheetProjectCode)))
} }


if (invoicesResult.size >= 1 ||
newProjectCodes.size >= 1 ||
emptyRowList.size >= 1

if (invoicesResult.size == 0){
val invoiceCode: MutableList<Map<String,Any>> = mutableListOf()
for (sheetValue in sheetValues){
val matched = invoices.filter{
value ->
// println("value: -------- ${value["invoicesNo"]} ${value["projectCode"]} ")
// println("${invoice.invoiceNo} -------- ${invoice.projectCode}")
// println("invoicesNo ${value["invoicesNo"]} ${value["invoicesNo"] == invoice.invoiceNo} ${invoice.invoiceNo}")
// println("projectCode ${value["projectCode"]} ${value["projectCode"] == invoice.projectCode} ${invoice.projectCode}")
sheetValue["invoicesNo"] == value.invoiceNo && sheetValue["projectCode"] == value.projectCode
}
// println("matched: ${matched}")
if (matched.isEmpty()){
// println("IF Matched.isNotEmpty: ${sheetValue["projectCode"]} ${sheetValue["invoicesNo"]}")
invoiceCode.add(mapOf("projectCode" to sheetValue["projectCode"]!!, "invoicesNo" to sheetValue["invoicesNo"]!!))
}
}
if(invoiceCode.isNotEmpty()){
return InvoiceResponse(false, "Imported Invoice's format is incorrect", newProjectCodes, emptyRowList, invoicesResult, duplicateItemsInInvoice, invoiceCode)
}
}

if (newProjectCodes.size >= 1 ||
invoicesResult.size >= 1 ||
emptyRowList.size >= 1 ||
duplicateItemsInInvoice.isNotEmpty()
){ ){
println("duplicateInvoices") println("duplicateInvoices")
println(invoicesResult) println(invoicesResult)
return InvoiceResponse(false, "Imported Invoice's format is incorrect", newProjectCodes, emptyRowList, invoicesResult)
return InvoiceResponse(false, "Imported Invoice's format is incorrect", newProjectCodes, emptyRowList, invoicesResult, duplicateItemsInInvoice, ArrayList())
} }


for (i in 2..sheet.lastRowNum){ for (i in 2..sheet.lastRowNum){
val invoice = getInvoiceByInvoiceNo(ExcelUtils.getCell(sheet, i, 0).stringCellValue) val invoice = getInvoiceByInvoiceNo(ExcelUtils.getCell(sheet, i, 0).stringCellValue)
invoice.paidAmount = ExcelUtils.getCell(sheet, i, 5).numericCellValue
invoice.paidAmount = ExcelUtils.getCell(sheet, i, 5).numericCellValue.toBigDecimal()
invoice.receiptDate = ExcelUtils.getCell(sheet, i, 4).dateCellValue.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() invoice.receiptDate = ExcelUtils.getCell(sheet, i, 4).dateCellValue.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
saveAndFlush(invoice) saveAndFlush(invoice)
} }


return InvoiceResponse(true, "OK", newProjectCodes, emptyRowList, invoicesResult)
return InvoiceResponse(true, "OK", newProjectCodes, emptyRowList, invoicesResult, duplicateItemsInInvoice, ArrayList())
} }
} }

+ 5
- 0
src/main/java/com/ffii/tsms/modules/project/web/InvoiceController.kt 查看文件

@@ -75,6 +75,11 @@ class InvoiceController(
return invoiceService.allInvoice() return invoiceService.allInvoice()
} }


@GetMapping("/v2/allInvoices/paid")
fun allInvoice_paid_v2(): List<InvoiceInfo> {
return invoiceService.allInvoicePaid()
}

@PostMapping("/import/issued") @PostMapping("/import/issued")
fun importIssuedInvoice(request: HttpServletRequest): ResponseEntity<*> { fun importIssuedInvoice(request: HttpServletRequest): ResponseEntity<*> {
var workbook: Workbook? = null var workbook: Workbook? = null


+ 2
- 0
src/main/java/com/ffii/tsms/modules/project/web/models/InvoiceResponse.kt 查看文件

@@ -6,4 +6,6 @@ data class InvoiceResponse (
val projectList: List<String>, val projectList: List<String>,
val emptyRowList: List<Int>, val emptyRowList: List<Int>,
val invoiceList: List<String>, val invoiceList: List<String>,
val duplicateItem: List<String>,
val paymentMilestones: List<Map<String, Any>>
) )

+ 2
- 2
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt 查看文件

@@ -117,7 +117,7 @@ open class ReportService {
} }


getCell(2).apply { getCell(2).apply {
setCellValue(actualIncome)
setCellValue(actualIncome.toDouble())
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }
} }
@@ -158,7 +158,7 @@ open class ReportService {
} }


getCell(2).apply { getCell(2).apply {
setCellValue(invoice.paidAmount!!)
setCellValue(invoice.paidAmount!!.toDouble())
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }




正在加载...
取消
保存