MSI\2Fi 1 год назад
Родитель
Сommit
7f79cd1fee
15 измененных файлов: 306 добавлений и 110 удалений
  1. +0
    -97
      src/main/java/com/ffii/tsms/modules/common/service/ExcelReportService.kt
  2. +43
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/Invoice.kt
  3. +9
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt
  4. +2
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/Milestone.kt
  5. +2
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/MilestonePayment.kt
  6. +1
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/MilestonePaymentRepository.kt
  7. +1
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/Project.kt
  8. +11
    -3
      src/main/java/com/ffii/tsms/modules/project/service/InvoiceService.kt
  9. +160
    -0
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  10. +19
    -9
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  11. +1
    -1
      src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt
  12. +39
    -0
      src/main/resources/db/changelog/changes/20240503_01_cyril/01_create_invoice.sql
  13. +9
    -0
      src/main/resources/db/changelog/changes/20240503_01_cyril/02_update_invoice.sql
  14. +9
    -0
      src/main/resources/db/changelog/changes/20240503_01_cyril/03_update_invoice.sql
  15. Двоичные данные
      src/main/resources/templates/report/EX02_Project Cash Flow Report.xlsx

+ 0
- 97
src/main/java/com/ffii/tsms/modules/common/service/ExcelReportService.kt Просмотреть файл

@@ -1,97 +0,0 @@
package com.ffii.tsms.modules.common.service

import com.ffii.tsms.modules.project.entity.Project
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellStyle
import org.apache.poi.ss.usermodel.HorizontalAlignment
import org.apache.poi.ss.usermodel.Row
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.util.CellRangeAddress
import org.apache.poi.ss.util.CellUtil
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

@Service
open class ExcelReportService {
private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd")
private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER)

private val EX02_PROJECT_CASH_FLOW_REPORT = "templates/report/EX02_Project Cash Flow Report.xlsx"

// ==============================|| GENERATE REPORT ||============================== //
@Throws(IOException::class)
fun generateEX02ProjectCashFlowReport(project: Project): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook = createEX02ProjectCashFlowReport(project, EX02_PROJECT_CASH_FLOW_REPORT)

// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
workbook.close()

return outputStream.toByteArray()
}

// ==============================|| CREATE REPORT ||============================== //
@Throws(IOException::class)
private fun createEX02ProjectCashFlowReport(
project: Project,
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)

// val alignLeftStyle: CellStyle = workbook.createCellStyle().apply {
// alignment = HorizontalAlignment.LEFT // Set the alignment to left
// }
//
// val alignRightStyle: CellStyle = workbook.createCellStyle().apply {
// alignment = HorizontalAlignment.RIGHT // Set the alignment to right
// }

var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field
var columnIndex = 2
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(FORMATTED_TODAY)
}

rowIndex = 2
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(project.code)
}

rowIndex = 3
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(project.name)
}

rowIndex = 4
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(if (project.customer?.name == null) "N/A" else project.customer?.name)
}

rowIndex = 5
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(if (project.teamLead?.team?.name == null) "N/A" else project.teamLead?.team?.name)
}

rowIndex = 9
sheet.getRow(rowIndex).apply {
getCell(1).setCellValue(project.expectedTotalFee!! * 0.8)
getCell(2).setCellValue(project.expectedTotalFee!!)
}

return workbook
}
}

+ 43
- 0
src/main/java/com/ffii/tsms/modules/project/entity/Invoice.kt Просмотреть файл

@@ -0,0 +1,43 @@
package com.ffii.tsms.modules.project.entity

import com.ffii.core.entity.BaseEntity
import com.ffii.tsms.modules.data.entity.Customer
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.Table
import jakarta.validation.constraints.NotNull
import java.time.LocalDate

@Entity
@Table(name = "invoice")
open class Invoice : BaseEntity<Long>(){

@NotNull
@Column(name = "invoiceNo", length = 45)
open var invoiceNo: String? = null

@NotNull
@ManyToOne
@JoinColumn(name = "milestonePaymentId")
open var milestonePayment: MilestonePayment? = null

@NotNull
@Column(name = "invoiceDate")
open var invoiceDate: LocalDate? = null

@NotNull
@Column(name = "dueDate")
open var dueDate: LocalDate? = null

@Column(name = "receiptDate")
open var receiptDate: LocalDate? = null

@NotNull
@Column(name = "unpaidAmount")
open var unpaidAmount: Double? = null

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

+ 9
- 0
src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt Просмотреть файл

@@ -0,0 +1,9 @@
package com.ffii.tsms.modules.project.entity

import com.ffii.core.support.AbstractRepository

interface InvoiceRepository : AbstractRepository<Invoice, Long> {

fun findAllByPaidAmountIsNotNullAndMilestonePaymentIn(milestonePayment: List<MilestonePayment>): List<Invoice>

}

+ 2
- 0
src/main/java/com/ffii/tsms/modules/project/entity/Milestone.kt Просмотреть файл

@@ -1,5 +1,6 @@
package com.ffii.tsms.modules.project.entity package com.ffii.tsms.modules.project.entity


import com.fasterxml.jackson.annotation.JsonManagedReference
import com.ffii.core.entity.IdEntity import com.ffii.core.entity.IdEntity
import jakarta.persistence.* import jakarta.persistence.*
import jakarta.validation.constraints.NotNull import jakarta.validation.constraints.NotNull
@@ -15,6 +16,7 @@ open class Milestone : IdEntity<Long>() {
@Column(name = "description") @Column(name = "description")
open var description: String? = null open var description: String? = null


@JsonManagedReference
@OneToMany(mappedBy = "milestone", cascade = [CascadeType.ALL], orphanRemoval = true) @OneToMany(mappedBy = "milestone", cascade = [CascadeType.ALL], orphanRemoval = true)
open var milestonePayments: MutableList<MilestonePayment> = mutableListOf() open var milestonePayments: MutableList<MilestonePayment> = mutableListOf()




+ 2
- 0
src/main/java/com/ffii/tsms/modules/project/entity/MilestonePayment.kt Просмотреть файл

@@ -1,5 +1,6 @@
package com.ffii.tsms.modules.project.entity package com.ffii.tsms.modules.project.entity


import com.fasterxml.jackson.annotation.JsonBackReference
import com.ffii.core.entity.IdEntity import com.ffii.core.entity.IdEntity
import jakarta.persistence.* import jakarta.persistence.*
import jakarta.validation.constraints.NotNull import jakarta.validation.constraints.NotNull
@@ -21,6 +22,7 @@ open class MilestonePayment : IdEntity<Long>() {
open var description: String? = null open var description: String? = null


@ManyToOne @ManyToOne
@JsonBackReference
@JoinColumn(name = "milestoneId") @JoinColumn(name = "milestoneId")
open var milestone: Milestone? = null open var milestone: Milestone? = null
} }

+ 1
- 0
src/main/java/com/ffii/tsms/modules/project/entity/MilestonePaymentRepository.kt Просмотреть файл

@@ -3,4 +3,5 @@ package com.ffii.tsms.modules.project.entity;
import com.ffii.core.support.AbstractRepository import com.ffii.core.support.AbstractRepository


interface MilestonePaymentRepository : AbstractRepository<MilestonePayment, Long> { interface MilestonePaymentRepository : AbstractRepository<MilestonePayment, Long> {
fun findAllByMilestoneIn(milestones: List<Milestone>): List<MilestonePayment>
} }

+ 1
- 0
src/main/java/com/ffii/tsms/modules/project/entity/Project.kt Просмотреть файл

@@ -1,5 +1,6 @@
package com.ffii.tsms.modules.project.entity package com.ffii.tsms.modules.project.entity


import com.fasterxml.jackson.annotation.JsonManagedReference
import com.ffii.core.entity.BaseEntity import com.ffii.core.entity.BaseEntity
import com.ffii.tsms.modules.data.entity.* import com.ffii.tsms.modules.data.entity.*
import jakarta.persistence.* import jakarta.persistence.*


+ 11
- 3
src/main/java/com/ffii/tsms/modules/project/service/InvoiceService.kt Просмотреть файл

@@ -4,9 +4,8 @@ import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.core.support.AbstractIdEntityService import com.ffii.core.support.AbstractIdEntityService
import com.ffii.core.support.JdbcDao import com.ffii.core.support.JdbcDao
import com.ffii.core.utils.PdfUtils import com.ffii.core.utils.PdfUtils
import com.ffii.tsms.modules.project.entity.*


import com.ffii.tsms.modules.project.entity.MilestonePayment
import com.ffii.tsms.modules.project.entity.MilestonePaymentRepository
import com.ffii.tsms.modules.project.entity.projections.InvoicePDFReq import com.ffii.tsms.modules.project.entity.projections.InvoicePDFReq
import com.ffii.tsms.modules.project.entity.projections.InvoiceSearchInfo import com.ffii.tsms.modules.project.entity.projections.InvoiceSearchInfo
import net.sf.jasperreports.engine.JasperCompileManager import net.sf.jasperreports.engine.JasperCompileManager
@@ -21,9 +20,18 @@ import java.time.format.DateTimeFormatter


@Service @Service
open class InvoiceService( open class InvoiceService(
private val invoiceRepository: InvoiceRepository,
private val milestoneRepository: MilestoneRepository,
private val milestonePaymentRepository: MilestonePaymentRepository, private val milestonePaymentRepository: MilestonePaymentRepository,
private val jdbcDao: JdbcDao, private val jdbcDao: JdbcDao,
) : AbstractIdEntityService<MilestonePayment, Long, MilestonePaymentRepository>(jdbcDao, milestonePaymentRepository){
) : AbstractIdEntityService<Invoice, Long, InvoiceRepository>(jdbcDao, invoiceRepository){

open fun findAllByProjectAndPaidAmountIsNotNull(project: Project): List<Invoice> {
val milestones = milestoneRepository.findAllByProject(project)
val milestonePayments = milestonePaymentRepository.findAllByMilestoneIn(milestones)
return invoiceRepository.findAllByPaidAmountIsNotNullAndMilestonePaymentIn(milestonePayments)
}

open fun allMilestonePayments(): List<Map<String, Any>> { open fun allMilestonePayments(): List<Map<String, Any>> {
val sql = StringBuilder(" select " val sql = StringBuilder(" select "
+ " mp.id, " + " mp.id, "


+ 160
- 0
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt Просмотреть файл

@@ -0,0 +1,160 @@
package com.ffii.tsms.modules.report.service

import com.ffii.tsms.modules.project.entity.Invoice
import com.ffii.tsms.modules.project.entity.Project
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFDataFormat
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@Service
open class ReportService {
private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd")
private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER)

private val PROJECT_CASH_FLOW_REPORT = "templates/report/EX02_Project Cash Flow Report.xlsx"

// ==============================|| GENERATE REPORT ||============================== //
@Throws(IOException::class)
fun generateProjectCashFlowReport(project: Project, invoices: List<Invoice>): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook = createProjectCashFlowReport(project, invoices, PROJECT_CASH_FLOW_REPORT)

// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
workbook.close()

return outputStream.toByteArray()
}

// ==============================|| CREATE REPORT ||============================== //
@Throws(IOException::class)
private fun createProjectCashFlowReport(
project: Project,
invoices: List<Invoice>,
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);_(* \"-\"??_);_(@_)")

var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field
var columnIndex = 2
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(FORMATTED_TODAY)
}

rowIndex = 2
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(project.code)
}

rowIndex = 3
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(project.name)
}

rowIndex = 4
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(if (project.customer?.name == null) "N/A" else project.customer?.name)
}

rowIndex = 5
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(if (project.teamLead?.team?.name == null) "N/A" else project.teamLead?.team?.name)
}

rowIndex = 9
sheet.getRow(rowIndex).apply {
getCell(1).apply {
setCellValue(project.expectedTotalFee!!)
cellStyle.dataFormat = accountingStyle
}

getCell(2).apply {
setCellValue(project.expectedTotalFee!! / 0.8)
cellStyle.dataFormat = accountingStyle
}
}

rowIndex = 10
val actualIncome = invoices.sumOf { invoice -> invoice.paidAmount!! }
sheet.getRow(rowIndex).apply {
getCell(1).apply {
// TODO: Replace by actual expenditure
setCellValue(actualIncome * 0.8)
cellStyle.dataFormat = accountingStyle
}

getCell(2).apply {
setCellValue(actualIncome)
cellStyle.dataFormat = accountingStyle
}
}

rowIndex = 11
sheet.getRow(rowIndex).apply {
getCell(1).apply {
// TODO: Replace by actual expenditure
cellFormula = "B10-B11"
cellStyle.dataFormat = accountingStyle
}

getCell(2).apply {
cellFormula = "C10-C11"
cellStyle.dataFormat = accountingStyle
}
}

// TODO: Add expenditure
// formula =IF(B17>0,D16-B17,D16+C17)
rowIndex = 15
val dateFormatter = DateTimeFormatter.ofPattern("MMM YYYY")
invoices.forEach { invoice: Invoice ->
sheet.getRow(rowIndex++).apply {
getCell(0).apply {
setCellValue(invoice.receiptDate!!.format(dateFormatter))
}

getCell(1).apply {
setCellValue(0.0)
cellStyle.dataFormat = accountingStyle
}

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

getCell(3).apply {
val lastRow = rowIndex - 1
if (lastRow == 15) {
cellFormula = "C{currentRow}".replace("{currentRow}", rowIndex.toString())
} else {
cellFormula = "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace("{currentRow}", rowIndex.toString()).replace("{lastRow}", lastRow.toString())
}
cellStyle.dataFormat = accountingStyle
}

getCell(4).apply {
setCellValue(invoice.milestonePayment!!.description!!)
}
}
}

return workbook
}
}

+ 19
- 9
src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt Просмотреть файл

@@ -1,36 +1,46 @@
package com.ffii.tsms.modules.report.web package com.ffii.tsms.modules.report.web


import com.ffii.tsms.modules.common.service.ExcelReportService
import com.ffii.tsms.modules.project.entity.ProjectRepository
import com.ffii.tsms.modules.report.web.model.EX02ProjectCashFlowReportRequest
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.ProjectCashFlowReportRequest
import jakarta.validation.Valid import jakarta.validation.Valid
import org.springframework.core.io.ByteArrayResource import org.springframework.core.io.ByteArrayResource
import org.springframework.core.io.Resource import org.springframework.core.io.Resource
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.web.bind.ServletRequestBindingException import org.springframework.web.bind.ServletRequestBindingException
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
import java.io.IOException import java.io.IOException
import java.time.LocalDate import java.time.LocalDate


@RestController @RestController
@RequestMapping("/reports") @RequestMapping("/reports")
class ReportController(private val excelReportService: ExcelReportService, private val projectRepository: ProjectRepository) {
class ReportController(private val invoiceRepository: InvoiceRepository, private val milestonePaymentRepository: MilestonePaymentRepository, private val excelReportService: ReportService, private val projectRepository: ProjectRepository, private val invoiceService: InvoiceService) {


@PostMapping("/EX02-ProjectCashFlowReport")
@PostMapping("/ProjectCashFlowReport")
@Throws(ServletRequestBindingException::class, IOException::class) @Throws(ServletRequestBindingException::class, IOException::class)
fun getEx02ProjectCashFlowReport(@RequestBody @Valid request: EX02ProjectCashFlowReportRequest): ResponseEntity<Resource> {
fun getProjectCashFlowReport(@RequestBody @Valid request: ProjectCashFlowReportRequest): ResponseEntity<Resource> {


val project = projectRepository.findById(request.projectId).orElseThrow() val project = projectRepository.findById(request.projectId).orElseThrow()
val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project)


val reportResult: ByteArray = excelReportService.generateEX02ProjectCashFlowReport(project)
val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices)
// val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") // val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
return ResponseEntity.ok() return ResponseEntity.ok()
// .contentType(mediaType) // .contentType(mediaType)
.header("filename", "EX02 - Project Cash Flow Report - " + LocalDate.now() + ".xlsx")
.header("filename", "Project Cash Flow Report - " + LocalDate.now() + ".xlsx")
.body(ByteArrayResource(reportResult)) .body(ByteArrayResource(reportResult))
} }

@GetMapping("/test/{id}")
fun test(@PathVariable id: Long): List<Invoice> {
val project = projectRepository.findById(id).orElseThrow()
return invoiceService.findAllByProjectAndPaidAmountIsNotNull(project)
}
} }

+ 1
- 1
src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt Просмотреть файл

@@ -1,5 +1,5 @@
package com.ffii.tsms.modules.report.web.model package com.ffii.tsms.modules.report.web.model


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

+ 39
- 0
src/main/resources/db/changelog/changes/20240503_01_cyril/01_create_invoice.sql Просмотреть файл

@@ -0,0 +1,39 @@
-- liquibase formatted sql
-- changeset cyril:create invoice

CREATE TABLE `invoice` (
`id` INT NOT NULL AUTO_INCREMENT,
`version` INT NOT NULL DEFAULT '0',
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdBy` VARCHAR(30) NULL DEFAULT NULL,
`modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` VARCHAR(30) NULL DEFAULT NULL,
`deleted` TINYINT(1) NOT NULL DEFAULT '0',
`invoiceNo` VARCHAR(45) NOT NULL,
`projectId` INT NOT NULL,
`milestonePaymentId` INT NOT NULL,
`clientId` INT NOT NULL,
`invoiceDate` DATE NOT NULL,
`dueDate` DATE NOT NULL,
`receiptDate` DATE NULL,
`unpaidAmount` DECIMAL(16,2) NOT NULL,
`paidAmount` DECIMAL(16,2) NULL,
PRIMARY KEY (`id`),
INDEX `FK_INVOICE_ON_PROJECTID` (`projectId` ASC) VISIBLE,
INDEX `FK_INVOICE_ON_MILESTONEPAYMENTID` (`milestonePaymentId` ASC) VISIBLE,
INDEX `FK_INVOICE_ON_CLIENTID` (`clientId` ASC) VISIBLE,
CONSTRAINT `FK_INVOICE_ON_PROJECTID`
FOREIGN KEY (`projectId`)
REFERENCES `project` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `FK_INVOICE_ON_MILESTONEPAYMENTID`
FOREIGN KEY (`milestonePaymentId`)
REFERENCES `milestone_payment` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `FK_INVOICE_ON_CLIENTID`
FOREIGN KEY (`clientId`)
REFERENCES `customer` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);

+ 9
- 0
src/main/resources/db/changelog/changes/20240503_01_cyril/02_update_invoice.sql Просмотреть файл

@@ -0,0 +1,9 @@
-- liquibase formatted sql
-- changeset cyril:update invoice

ALTER TABLE `invoice`
DROP FOREIGN KEY `FK_INVOICE_ON_CLIENTID`;
ALTER TABLE `invoice`
DROP COLUMN `clientId`,
DROP INDEX `FK_INVOICE_ON_CLIENTID` ;
;

+ 9
- 0
src/main/resources/db/changelog/changes/20240503_01_cyril/03_update_invoice.sql Просмотреть файл

@@ -0,0 +1,9 @@
-- liquibase formatted sql
-- changeset cyril:update invoice

ALTER TABLE `invoice`
DROP FOREIGN KEY `FK_INVOICE_ON_PROJECTID`;
ALTER TABLE `invoice`
DROP COLUMN `projectId`,
DROP INDEX `FK_INVOICE_ON_PROJECTID` ;
;

Двоичные данные
src/main/resources/templates/report/EX02_Project Cash Flow Report.xlsx Просмотреть файл


Загрузка…
Отмена
Сохранить