add excel import and export

This commit is contained in:
arsalan 2024-01-22 18:32:24 +05:30
parent 0b75681236
commit 2fecc4b3fd
3 changed files with 360 additions and 14 deletions

View File

@ -38,6 +38,8 @@ dependencies {
implementation("org.apache.httpcomponents:httpclient:4.5.14") implementation("org.apache.httpcomponents:httpclient:4.5.14")
implementation("org.apache.poi:poi:5.0.0") implementation("org.apache.poi:poi:5.0.0")
implementation("org.apache.poi:poi-ooxml:5.0.0") implementation("org.apache.poi:poi-ooxml:5.0.0")
implementation("com.google.code.gson:gson:2.8.8")
api ("net.cactusthorn.config:config-core:0.81") api ("net.cactusthorn.config:config-core:0.81")
api ("net.cactusthorn.config:config-yaml:0.81") api ("net.cactusthorn.config:config-yaml:0.81")
kapt("net.cactusthorn.config:config-compiler:0.81") kapt("net.cactusthorn.config:config-compiler:0.81")

View File

@ -1,13 +1,28 @@
package com.restapi.controllers package com.restapi.controllers
import com.google.gson.Gson
import com.restapi.domain.*
import com.restapi.domain.Document
import com.restapi.domain.PurchaseOrder
import com.restapi.domain.Quotation
import org.apache.poi.hssf.usermodel.HSSFSheet import org.apache.poi.hssf.usermodel.HSSFSheet
import org.apache.poi.hssf.usermodel.HSSFWorkbook import org.apache.poi.hssf.usermodel.HSSFWorkbook
import com.restapi.domain.Session.database import com.restapi.domain.Session.database
import com.restapi.domain.Vendor
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.DateUtil
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.usermodel.WorkbookFactory
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream import java.io.FileOutputStream
enum class DataType { import java.text.SimpleDateFormat
QUOTE, PO, VENDOR import java.time.LocalDate
} import java.time.ZoneId
import java.util.*
fun createHeaderRow(cols :List<String>, sh :HSSFSheet) { fun createHeaderRow(cols :List<String>, sh :HSSFSheet) {
sh.createRow(0).apply { sh.createRow(0).apply {
cols.forEachIndexed{index, value -> cols.forEachIndexed{index, value ->
@ -15,14 +30,340 @@ fun createHeaderRow(cols :List<String>, sh :HSSFSheet) {
} }
} }
} }
fun ExportToExcel(cols :List<String>, data :List<List<String>>) { fun String.parseDate(format: String): Date? {
val locale = Locale.getDefault()
return try {
SimpleDateFormat(format, locale).parse(this)
} catch (e: Exception) {
null
}
}
fun dateFromCellHelper(cell: Cell): LocalDate?{
val date = when(cell.cellType){
CellType.STRING -> cell.stringCellValue.parseDate("yyyy-MM-dd")
CellType.NUMERIC -> {
if (DateUtil.isCellDateFormatted(cell)) {
cell.getDateCellValue()
} else{
null
}
}
else -> null
}
return date?.toInstant()?.atZone(ZoneId.systemDefault())?.toLocalDate()
}
fun stringFromCellHelper(cell: Cell): String {
val string = when(cell.cellType){
CellType.NUMERIC -> cell.numericCellValue.toString()
CellType.STRING -> cell.stringCellValue
else -> ""
}
return string
}
fun doubleFromCellHelper(cell: Cell): Double {
val double = when(cell.cellType){
CellType.NUMERIC -> cell.numericCellValue
CellType.STRING -> cell.stringCellValue.toDoubleOrNull()
else -> 0.0
}
return double?:0.0
}
fun enumFromCellHelper(cell: Cell, enumFor: EnumFor) :String{
var string = ""
val cellValue = cell.stringCellValue
when(enumFor){
EnumFor.UOM -> {
string = "uom"
}
EnumFor.DocType -> {
string = "doc"
}
}
return string
}
fun longIntFromCellHelper(cell : Cell) :Long {
val long = when(cell.cellType){
CellType.NUMERIC -> cell.numericCellValue.toLong()
CellType.STRING -> cell.stringCellValue.toLong()
else -> 0
}
return long
}
enum class FileType {
QUOTES, POS, VENDORS, PRODS, DOCS
}
enum class EnumFor {
UOM, DocType
}
fun ExportQuotations(quotes :List<Quotation>) {
val wb = HSSFWorkbook() val wb = HSSFWorkbook()
val sh = wb.createSheet() val sh = wb.createSheet()
createHeaderRow(cols, sh)
for((rowCount, row) in data.withIndex()) { val headers : List<String> = listOf("Quotation Number", "Date", "Open Till", "Product Id", "Product Name", "Product Unit Price", "Quantity", "Vendor Name", "Vendor Address", "RFQ Number", "Total AMount", "Terms and Conditions")
sh.createRow(rowCount).apply{ createHeaderRow(headers, sh)
for((colCount, cell) in row.withIndex()) { val totalCols = headers.size
createCell(colCount).setCellValue(cell) var rowCnt = 1
for(quote in quotes){
val prodCnt = quote.products.size
for (j in 0..prodCnt - 1){
val row = sh.createRow(rowCnt++)
var i = 0;
row.createCell(i++).setCellValue(quote.quoteNum)
row.createCell(i++).setCellValue(quote.quoteDate)
row.createCell(i++).setCellValue(quote.validTill)
//6 would be repeated
row.createCell(i++).setCellValue(quote.products[j].productId)
row.createCell(i++).setCellValue(quote.products[j].productName)
row.createCell(i++).setCellValue(quote.products[j].unitPrice)
row.createCell(i++).setCellValue(quote.products[j].quantity)
row.createCell(i++).setCellValue(quote.vendor?.name)
row.createCell(i++).setCellValue(quote.vendor?.address)
row.createCell(i++).setCellValue(quote.reqForQuoteNum)
row.createCell(i++).setCellValue(quote.totalAmount)
row.createCell(i++).setCellValue(quote.tnc.joinToString(";"))
}
}
}
fun ExportVendors(vendors :List<Vendor>){
val wb = HSSFWorkbook()
val sh = wb.createSheet()
val headers : List<String> = listOf("Name", "MSME", "GST Number", "Address", "Rating", "Contact Name", "Contact Email", "Contact Mobile")
createHeaderRow(headers, sh)
val totalCols = headers.size
var rowCnt = 1
for (vendor in vendors){
val contactCnt = vendor.contacts.size
for (j in 0..contactCnt - 1){
val row = sh.createRow(rowCnt++)
var i = 0
row.createCell(i++).setCellValue(vendor.msme)
row.createCell(i++).setCellValue(vendor.gstNumber)
row.createCell(i++).setCellValue(vendor.address)
row.createCell(i++).setCellValue(vendor.rating)
row.createCell(i++).setCellValue(vendor.contacts[j].name)
row.createCell(i++).setCellValue(vendor.contacts[j].email)
row.createCell(i++).setCellValue(vendor.contacts[j].mobile)
}
}
}
fun ExportProds(prods :List<Product>){
val wb = HSSFWorkbook()
val sh = wb.createSheet()
val headers : List<String> = listOf("Id", "Name", "Description", "HSN Code", "UOM")
createHeaderRow(headers, sh)
val totalCols = headers.size
var rowCnt = 1
for (prod in prods){
val row = sh.createRow(rowCnt++)
var i = 0
row.createCell(i++).setCellValue(prod.id.toString())
row.createCell(i++).setCellValue(prod.name)
row.createCell(i++).setCellValue(prod.description)
row.createCell(i++).setCellValue(prod.hsnCode)
row.createCell(i++).setCellValue(prod.uom?.name)
}
}
fun ExportPos(pos :List<PurchaseOrder>){
val wb = HSSFWorkbook()
val sh = wb.createSheet()
val headers : List<String> = listOf("Number", "Date", "Open Till", "Reference Quotation Number", "Vendor Name", "Vendor Address", "Product Id", "Product Name", "Unit Price", "Quantity", "Total Amount", "Terms and Conditions")
createHeaderRow(headers, sh)
val totalCols = headers.size
var rowCnt = 1
for(po in pos){
val prodCnt = po.products.size
for (j in 0..prodCnt - 1){
val row = sh.createRow(rowCnt++)
var i = 0
row.createCell(i++).setCellValue(po.poNum)
row.createCell(i++).setCellValue(po.poDate)
row.createCell(i++).setCellValue(po.validTill)
row.createCell(i++).setCellValue(po.referenceQuotation)
row.createCell(i++).setCellValue(po.vendor?.name)
row.createCell(i++).setCellValue(po.vendor?.address)
//6 would be repeated
row.createCell(i++).setCellValue(po.products[j].productId)
row.createCell(i++).setCellValue(po.products[j].productName)
row.createCell(i++).setCellValue(po.products[j].unitPrice)
row.createCell(i++).setCellValue(po.products[j].quantity)
row.createCell(i++).setCellValue(po.totalAmount)
row.createCell(i++).setCellValue(po.tnc.joinToString(";"))
}
}
}
fun main() {
ImportFromExcel(FileType.QUOTES, "C:\\Users\\arsalan\\Downloads\\Book.xlsx")
}
fun ImportFromExcel(fileType: FileType, filePath : String) {
val wb = WorkbookFactory.create(File(filePath))
val sh = wb.getSheetAt(0)
when(fileType){
FileType.QUOTES -> {
//Quote Number, ProductName, Product Quantity, Product Uom, Total Amount, RFQ Number, Quote Date, Valid Till, TNC[], Documents[]
val quotesMap : MutableMap<String, Quotation> = mutableMapOf()
val quotesList : List<Quotation> = mutableListOf()
sh.rowIterator().forEach { row ->
if(row == null){
//reached eof
return@forEach
}
val quoteNum = stringFromCellHelper(row.getCell(0))
val quoteDate = dateFromCellHelper(row.getCell(1))
val rfqNum = stringFromCellHelper(row.getCell(2))
val quoteValidTill = dateFromCellHelper(row.getCell(3))
val vendorName = stringFromCellHelper(row.getCell(4))
val vendorGstNum = stringFromCellHelper(row.getCell(5))
val vendorAddress = stringFromCellHelper(row.getCell(6))
val prodName = stringFromCellHelper(row.getCell(7))
val prodQuantity = doubleFromCellHelper(row.getCell(8))
val prodUnitPrice = doubleFromCellHelper(row.getCell(9))
val prodUom = enumFromCellHelper(row.getCell(10), EnumFor.UOM)
val totalQuoteAmount = doubleFromCellHelper(row.getCell(11))
val prod = POProducts("", prodName, prodUnitPrice, prodQuantity)
if (quotesMap.containsKey(quoteNum)) {
//duplicated row
quotesMap.get(quoteNum)?.products?.add(prod)
}else {
val vendor = Vendor()
vendor.name = vendorName
vendor.address = vendorAddress
vendor.gstNumber = vendorGstNum
val quote = Quotation()
quote.quoteNum = quoteNum
quote.quoteDate = quoteDate
quote.reqForQuoteNum = rfqNum
quote.validTill = quoteValidTill
quote.products = mutableListOf<POProducts>(prod)
quote.vendor = vendor
quote.totalAmount = totalQuoteAmount
quotesMap.put(quoteNum, quote)
}
}
//docs, tncs
// println("$quotesMap")
quotesMap.forEach { (k, v) ->
println("$v")
}
}
FileType.POS -> {
//poNum, poDate, validTill, refQuoteNum, prodName, prodQuantity, totalAmount, products, vendorName, vendorGst, vendorAddress, tnc[]. docs[]
val PoMap : MutableMap<String, PurchaseOrder> = mutableMapOf()
sh.rowIterator().forEach { row ->
if(row == null) return@forEach
val poNum = stringFromCellHelper(row.getCell(0))
val poDate = dateFromCellHelper(row.getCell(1))
val refQuoteNum = stringFromCellHelper(row.getCell(2))
val poValidTill = dateFromCellHelper(row.getCell(3))
val prodName = stringFromCellHelper(row.getCell(4))
val prodQuantity = doubleFromCellHelper(row.getCell(5))
val vendorName = stringFromCellHelper(row.getCell(6))
val vendorGstNum = stringFromCellHelper(row.getCell(7))
val vendorAddress = stringFromCellHelper(row.getCell(8))
val totalPoAmount = doubleFromCellHelper(row.getCell(9))
//tncs, docs
val prod = POProducts("", prodName, 0.0, prodQuantity,"")
if(PoMap.containsKey(poNum)){
//repeated row
PoMap.get(poNum)?.products?.add(prod)
}else{
val vendor = Vendor()
vendor.name = vendorName
vendor.address = vendorAddress
vendor.gstNumber = vendorGstNum
val po = PurchaseOrder()
po.poNum = poNum
po.poDate = poDate
po.referenceQuotation = refQuoteNum
po.validTill = poValidTill
PoMap.put(poNum, po)
}
}
}
FileType.VENDORS -> {
sh.rowIterator().forEach { row ->
//name, msme, gstNum, addresss, rating, contacts
if(row == null) return@forEach
val name = stringFromCellHelper(row.getCell(0))
val msme = stringFromCellHelper(row.getCell(1))
val gstNum = stringFromCellHelper(row.getCell(2))
val address = stringFromCellHelper(row.getCell(3))
val rating = doubleFromCellHelper(row.getCell(4))
//vendor object
val vendor = Vendor()
vendor.name = name
vendor.address = address
vendor.msme = msme
vendor.gstNumber = gstNum
vendor.rating = rating
}
}
FileType.PRODS -> {
sh.rowIterator().forEach { row ->
if(row == null) return@forEach
//id, name, description, hsnCode, uom
val prodId = longIntFromCellHelper(row.getCell(0))
val prodName = stringFromCellHelper(row.getCell(1))
val prodDesc = stringFromCellHelper(row.getCell(2))
val prodHsnCode = stringFromCellHelper(row.getCell(3))
val prodUom = stringFromCellHelper(row.getCell(4))
//new prod object
val prod = Product()
prod.id = prodId
prod.name = prodName
prod.description = prodDesc
prod.hsnCode = prodHsnCode
prod.uom = when(prodUom) {
"nos" -> UOM.NOS
"ltr" -> UOM.LTR
"mtr" -> UOM.MTR
else -> UOM.ALL
}
}
}
FileType.DOCS -> {
sh.rowIterator().forEach { row ->
//Document Name, Document Type, RefID, url
if (row == null) return@forEach
val docName = stringFromCellHelper(row.getCell(0))
val docType = stringFromCellHelper(row.getCell(1))
val refId = stringFromCellHelper(row.getCell(2))
val url = stringFromCellHelper(row.getCell(3))
//new doc object
val doc = Document()
doc.name = docName
doc.typeOfDoc = when(docType) {
"quote" -> DocType.QUOTE
"po" -> DocType.PO
"invoice" -> DocType.INVOICE
else -> DocType.ALL
}
doc.refId = refId
doc.url = url
} }
} }
} }

View File

@ -12,7 +12,9 @@ import java.time.LocalDateTime
import javax.persistence.* import javax.persistence.*
data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now()) data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now())
data class POProducts(val productId: String = "", val unitPrice :Double = 0.0, val quantity: Double = 0.0, val description :String = "") data class POProducts(val productId: String = "", val productName: String = "", val unitPrice :Double = 0.0, val quantity: Double = 0.0, val description :String = "")
enum class ApprovalStatus { enum class ApprovalStatus {
PENDING, APPROVED, REJECTED PENDING, APPROVED, REJECTED
} }
@ -259,7 +261,7 @@ open class PurchaseOrder :BaseTenantModel() {
@ManyToOne @ManyToOne
var vendor :Vendor? = null var vendor :Vendor? = null
var referenceQuotation :String = "" var referenceQuotation :String = ""
var totalAmount :Int = 0 var totalAmount :Double = 0.0
var poNum: String = "" var poNum: String = ""
var poDate: LocalDate? = null var poDate: LocalDate? = null
var validTill: LocalDate? = null var validTill: LocalDate? = null
@ -274,7 +276,7 @@ enum class UOM {
} }
@Entity @Entity
open class Product :BaseTenantModel() { open class Product :BaseTenantModel() {
var id: Int? = null var id: Long? = null
var name :String = "" var name :String = ""
var description :String = "" var description :String = ""
var hsnCode :String = "" var hsnCode :String = ""
@ -288,7 +290,7 @@ open class Quotation :BaseTenantModel() {
var products :MutableList<POProducts> = mutableListOf() var products :MutableList<POProducts> = mutableListOf()
@ManyToOne @ManyToOne
var vendor :Vendor? = null var vendor :Vendor? = null
var totalAmount :Long = 0 var totalAmount :Double = 0.0
var reqForQuoteNum: String = "" var reqForQuoteNum: String = ""
var quoteNum: String = "" var quoteNum: String = ""
@ -309,7 +311,8 @@ open class Document :BaseTenantModel() {
var name :String = "" var name :String = ""
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
var typeOfDoc :DocType? = null var typeOfDoc :DocType? = null
var refId: Long? = null //could be quoteNum, PoNum, InvoiceNum
var refId: String? = null
var description :String = "" var description :String = ""
var url :String = "" var url :String = ""
var docDate :LocalDate? = null var docDate :LocalDate? = null