diff --git a/build.gradle.kts b/build.gradle.kts index 2894a75..5abd28d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,6 +38,8 @@ dependencies { implementation("org.apache.httpcomponents:httpclient:4.5.14") implementation("org.apache.poi:poi: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-yaml:0.81") kapt("net.cactusthorn.config:config-compiler:0.81") diff --git a/src/main/kotlin/com/restapi/controllers/Excel.kt b/src/main/kotlin/com/restapi/controllers/Excel.kt index 4d45758..3f9b910 100644 --- a/src/main/kotlin/com/restapi/controllers/Excel.kt +++ b/src/main/kotlin/com/restapi/controllers/Excel.kt @@ -1,13 +1,28 @@ 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.HSSFWorkbook 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 -enum class DataType { - QUOTE, PO, VENDOR -} +import java.text.SimpleDateFormat +import java.time.LocalDate +import java.time.ZoneId +import java.util.* + fun createHeaderRow(cols :List, sh :HSSFSheet) { sh.createRow(0).apply { cols.forEachIndexed{index, value -> @@ -15,14 +30,340 @@ fun createHeaderRow(cols :List, sh :HSSFSheet) { } } } -fun ExportToExcel(cols :List, data :List>) { +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) { val wb = HSSFWorkbook() val sh = wb.createSheet() - createHeaderRow(cols, sh) - for((rowCount, row) in data.withIndex()) { - sh.createRow(rowCount).apply{ - for((colCount, cell) in row.withIndex()) { - createCell(colCount).setCellValue(cell) + + val headers : List = 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") + createHeaderRow(headers, sh) + val totalCols = headers.size + 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){ + val wb = HSSFWorkbook() + val sh = wb.createSheet() + + val headers : List = 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){ + val wb = HSSFWorkbook() + val sh = wb.createSheet() + + val headers : List = 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){ + val wb = HSSFWorkbook() + val sh = wb.createSheet() + + val headers : List = 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 = mutableMapOf() + val quotesList : List = 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(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 = 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 } } } diff --git a/src/main/kotlin/com/restapi/domain/models.kt b/src/main/kotlin/com/restapi/domain/models.kt index 6b75540..d1f742f 100644 --- a/src/main/kotlin/com/restapi/domain/models.kt +++ b/src/main/kotlin/com/restapi/domain/models.kt @@ -12,7 +12,9 @@ import java.time.LocalDateTime import javax.persistence.* 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 { PENDING, APPROVED, REJECTED } @@ -259,7 +261,7 @@ open class PurchaseOrder :BaseTenantModel() { @ManyToOne var vendor :Vendor? = null var referenceQuotation :String = "" - var totalAmount :Int = 0 + var totalAmount :Double = 0.0 var poNum: String = "" var poDate: LocalDate? = null var validTill: LocalDate? = null @@ -274,7 +276,7 @@ enum class UOM { } @Entity open class Product :BaseTenantModel() { - var id: Int? = null + var id: Long? = null var name :String = "" var description :String = "" var hsnCode :String = "" @@ -288,7 +290,7 @@ open class Quotation :BaseTenantModel() { var products :MutableList = mutableListOf() @ManyToOne var vendor :Vendor? = null - var totalAmount :Long = 0 + var totalAmount :Double = 0.0 var reqForQuoteNum: String = "" var quoteNum: String = "" @@ -309,7 +311,8 @@ open class Document :BaseTenantModel() { var name :String = "" @Enumerated(EnumType.STRING) var typeOfDoc :DocType? = null - var refId: Long? = null + //could be quoteNum, PoNum, InvoiceNum + var refId: String? = null var description :String = "" var url :String = "" var docDate :LocalDate? = null