Compare commits

...

9 Commits

Author SHA1 Message Date
7e8f70a7c2 UI 2024-02-05 09:42:06 +05:30
4688b92314 ExcelToDb complete 2024-01-24 18:33:01 +05:30
471c043218 merge complete 2024-01-24 17:49:30 +05:30
d8ab337fde Merge remote-tracking branch 'origin/master'
# Conflicts:
#	build.gradle.kts
#	src/main/kotlin/com/restapi/Main.kt
#	src/main/kotlin/com/restapi/controllers/Excel.kt
#	src/main/kotlin/com/restapi/controllers/Filters.kt
2024-01-24 17:46:49 +05:30
d23ac5261d Excel to Db 2024-01-24 11:25:18 +05:30
976aebec5b Product Excel Validation 2024-01-23 18:18:55 +05:30
a3f7614979 Product Excel Validation 2024-01-23 16:59:25 +05:30
8745db2127 Excel R/W 2024-01-22 15:12:58 +05:30
438daacdc6 ProductFilters 2024-01-19 17:47:18 +05:30
7 changed files with 282 additions and 68 deletions

View File

@@ -93,46 +93,6 @@ Authorization: {{auth-token}}
DELETE http://localhost:9001/api/vehicle/KA01HD6667
Authorization: {{auth-token}}
### get po for id
GET http://localhost:9001/api/vendor/product
Authorization: {{auth-token}}
### get product for id
GET http://localhost:9001/api/vendor/product/7
Authorization: {{auth-token}}
### get row
GET http://localhost:9001/api/vendor/product/7
Authorization: Bearer {{auth-token}}
### create product
POST http://localhost:9001/api/vendor/product
Content-Type: application/json
Authorization: {{auth-token}}
{
"name": "Shirt",
"description": "Black Shirt",
"hsnCode": "BSM1XL"
}
### update field
PATCH http://localhost:9001/api/vendor/product/11
Content-Type: application/json
Authorization: {{auth-token}}
### upate a row
PUT http://localhost:9001/api/vendor/product/11
Content-Type: application/json
Authorization: {{auth-token}}
### delete a row
DELETE http://localhost:9001/api/vendor/product/2
Authorization: {{auth-token}}
### create vendor
POST http://localhost:9001/api/vendor/
Content-Type: application/json
@@ -359,3 +319,38 @@ Authorization: {{auth-token}}
"quoteFilters": {}
}
### CREATE PRODUCT
POST http://localhost:9001/api/vendor/product/create
Content-Type: application/json
Authorization: {{auth-token}}
{
"name" : "aa",
"description": "aa",
"hsnCode" : "aa",
"uom": "NOS"
}
### GET ALL PRODUCTS
GET http://localhost:9001/api/vendor/product/getAll
Authorization: {{auth-token}}
### GET PRODUCT BY KEY
GET http://localhost:9001/api/vendor/product/of/6
Authorization: {{auth-token}}
### GET PRODUCT BY HSNCODE
DELETE http://localhost:9001/api/vendor/product/3
Authorization: {{auth-token}}
### PRODUCT EXCEl
GET http://localhost:9001/api/vendor/product/to/excel
Authorization: {{auth-token}}
### EXCEL VALIDATE
GET http://localhost:9001/api/vendor/product/valid/excel
Authorization: {{auth-token}}
### EXCEL TO DB (IMPORT)
POST http://localhost:9001/api/vendor/product/excelToDb
Authorization: {{auth-token}}

View File

@@ -36,10 +36,9 @@ dependencies {
implementation("org.yaml:snakeyaml:2.2")
implementation("io.minio:minio:8.5.7")
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("org.apache.poi:poi:5.2.3")
implementation("org.apache.poi:poi-ooxml:5.2.3")
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")

View File

@@ -6,6 +6,8 @@ import com.restapi.config.AppConfig.Companion.appConfig
import com.restapi.config.Auth.validateAuthToken
import com.restapi.controllers.*
import com.restapi.domain.DataNotFoundException
import com.restapi.domain.Product
import com.restapi.domain.Session.a
import com.restapi.domain.Session.currentTenant
import com.restapi.domain.Session.currentUser
import com.restapi.domain.Session.objectMapper
@@ -17,19 +19,20 @@ import io.javalin.Javalin
import io.javalin.apibuilder.ApiBuilder.*
import io.javalin.http.ContentType
import io.javalin.http.Context
import io.javalin.http.HandlerType
import io.javalin.http.UnauthorizedResponse
import io.javalin.http.util.NaiveRateLimit
import io.javalin.http.util.RateLimitUtil
import io.javalin.json.JavalinJackson
import org.jose4j.jwt.consumer.InvalidJwtException
import org.slf4j.LoggerFactory
import java.io.InputStream
import java.security.MessageDigest
import java.time.LocalDateTime
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.jvm.optionals.getOrDefault
fun main(args: Array<String>) {
val logger = LoggerFactory.getLogger("api")
val adminRole = Role.Standard(Action.ADMIN)
@@ -77,6 +80,8 @@ fun main(args: Array<String>) {
TimeUnit.MINUTES
)
if(ctx.method() == HandlerType.OPTIONS) return@before
val authToken = ctx.getAuthHeader() ?: throw UnauthorizedResponse()
@@ -138,13 +143,16 @@ fun main(args: Array<String>) {
get("/rfq/{rfqNum}", QuotationCtrl::reqForQuote, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW"))))
delete("/{id}", QuotationCtrl::delete, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN"))))
}
path("/product"){
post("", ProductCtrl::create, Roles(Role.Explicit(listOf("ROLE_PRODUCT_CREATE", "ROLE_ADMIN", "ROLE_VENDOR_CREATE"))))
//get("/{hsnCode}", ProductCtrl::get, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
path("/product") {
post("/create", ProductCtrl::create, Roles(Role.Explicit(listOf("ROLE_PRODUCT_CREATE", "ROLE_ADMIN"))))
get("/getAll", ProductCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
get("/of/{key}", ProductCtrl::get, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
put("/{id}", ProductCtrl::update, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "ROLE_ADMIN"))))
//patch("/{id}", ProductCtrl::patch, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "ROLE_ADMIN"))))
patch("/{id}", ProductCtrl::patch, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "ROLE_ADMIN"))))
delete("/{id}", ProductCtrl::delete, Roles(Role.Explicit(listOf("ROLE_PRODUCT_DELETE", "ROLE_ADMIN"))))
get("", ProductCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
get("/to/excel", ProductCtrl::prodExcel)
get("/valid/excel") { ctx -> ctx.json(ExcelRead()) }
post("/excelToDb") {ctx -> ctx.json(excelToDb())}
}
path("/doc"){
post("", Document::create, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_ADMIN"))))

View File

@@ -17,7 +17,11 @@ import com.restapi.integ.Scripting
import io.ebean.CallableSql
import io.ebean.RawSqlBuilder
import io.javalin.http.*
import org.apache.poi.ss.usermodel.WorkbookFactory
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.sql.Types
import java.time.LocalDate
import java.time.LocalDateTime
@@ -436,20 +440,19 @@ object PurchaseOrderCtrl {
data class ProductSearch(
var isSort: String? = null
)
object ProductCtrl {
fun get(ctx :Context){
val hsnCode = ctx.pathParam("hsnCode")
val product = database.find(Product::class.java, hsnCode) ?: throw NotFoundResponse("Product not found for $hsnCode")
val key = ctx.pathParam("key")
val product = database.find(Product::class.java, key) ?: throw NotFoundResponse("Product not found for $key")
ctx.json(product)
}
fun getAll(ctx: Context){
val productList = Session.database.find(Product::class.java)
val productList = database.find(Product::class.java)
.findList()
.sortedBy { it.hsnCode }
//.removeAt(4)
ctx.json(productList)
}
@@ -461,7 +464,7 @@ object ProductCtrl {
fun delete(ctx: Context) {
val id = ctx.pathParam("id")
val product = database.delete(Product::class.java, id)
val product = database.deletePermanent(Product::class.java,id)
}
fun patch(ctx: Context) {
@@ -469,9 +472,41 @@ object ProductCtrl {
}
fun update(ctx: Context) {
val id = ctx.pathParam("id")
//have to implement
}
fun prodExcel(it: Context) {
val product = database.find(Product::class.java).findList()
it.result(CreateExcel(product)).contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
.header("Content-Disposition", "attachment; filename=\"product.xlsx\"")
}
data class ProductList(
val name: String,
val description: String,
val hsnCode: String,
val uom: String?,
)
fun excelToDb(it: Context){
val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\Untitled 1.xlsx")
val workbook = WorkbookFactory.create(inputStream)
val workSheet = workbook.getSheetAt(0)
val dataList = mutableListOf<ProductList>()
for (row in workSheet) {
val cell1Value = row.getCell(0).stringCellValue
val cell2Value = row.getCell(1).stringCellValue
val cell3Value = row.getCell(2).stringCellValue
val cell4Value = row.getCell(3).stringCellValue
val data = ProductList(cell1Value, cell2Value, cell3Value, cell4Value)
dataList.add(data)
}
database.saveAll(dataList)
}
}
object QuotationCtrl {

View File

@@ -1,4 +1,7 @@
package com.restapi.controllers
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.google.gson.Gson
import com.restapi.domain.*
import com.restapi.domain.Document
@@ -11,15 +14,10 @@ import com.restapi.domain.Session.database
import com.restapi.domain.Vendor
import org.apache.poi.hssf.usermodel.DVConstraint
import org.apache.poi.hssf.usermodel.HSSFDataValidation
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 org.apache.poi.ss.usermodel.*
import org.apache.poi.ss.util.CellRangeAddressList
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.io.*
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.ZoneId
@@ -389,7 +387,7 @@ fun ImportFromExcel(fileType: FileType, filePath : String) {
"nos" -> UOM.NOS
"ltr" -> UOM.LTR
"mtr" -> UOM.MTR
else -> UOM.ALL
else -> UOM.LTR
}
}
}
@@ -417,3 +415,167 @@ fun ImportFromExcel(fileType: FileType, filePath : String) {
}
}
}
data class validateExcel(
val name: String,
val description: String,
val hsnCode: String,
val ok: Boolean,
val err: String,
)
val app_common_om = jacksonObjectMapper().apply {
registerModule(JavaTimeModule())
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
}
fun ExcelRead(): String{
val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\Untitled 1.xlsx")
val workbook = WorkbookFactory.create(inputStream)
val workSheet = workbook.getSheetAt(0)
var h = true
//Header check
if(workSheet.getRow(0).getCell(0).stringCellValue.equals("Name")) {
if (workSheet.getRow(0).getCell(1).stringCellValue.equals("Description")) {
if (workSheet.getRow(0).getCell(2).stringCellValue.equals("HSN")) {
if (workSheet.getRow(0).getCell(3).stringCellValue.equals("UOM")) {
h = false
}else return "Header UOM mismatch"
}else return "Header-HSN mismatch"
}else return "Header-Desc mismatch"
}else return "Header-Name mismatch"
val resp = arrayListOf<validateExcel>()
if(h==false) {
workSheet.rowIterator().forEach { row ->
if (row == null) return@forEach
if (h) {
val pName = row.getCell(0).run {
when {
this == null -> ""
this.cellType == CellType.STRING -> this.stringCellValue
else -> ""
}
}
val pDesc = row.getCell(1).run {
when {
this == null -> ""
this.cellType == CellType.STRING -> this.stringCellValue
else -> ""
}
}
val pHsn = row.getCell(2).run {
when {
this == null -> ""
this.cellType == CellType.STRING -> this.stringCellValue
else -> ""
}
}
if (pName.isEmpty() && pDesc.isEmpty() && pHsn.isEmpty()) {
return@forEach
}
if (pName.isEmpty()) {
resp.add(
validateExcel(
name = pName,
description = pDesc,
hsnCode = pHsn,
ok = false,
err = "Product name is required"
)
)
return@forEach
}
if (pDesc.isEmpty()) {
resp.add(
validateExcel(
name = pName,
description = pDesc,
hsnCode = pHsn,
ok = false,
err = "Product description is required"
)
)
return@forEach
}
if (pHsn.isEmpty()) {
resp.add(
validateExcel(
name = pName,
description = pDesc,
hsnCode = pHsn,
ok = false,
err = "Product HSN is required"
)
)
return@forEach
}
}
h = true
}
}
return app_common_om.writeValueAsString(resp)
}
fun CreateExcel(productList: List<Product>): InputStream {
val wb = XSSFWorkbook()
val sh = wb.createSheet()
val rows: Row = sh.createRow(0)
rows.createCell(0).setCellValue("Name")
rows.createCell(1).setCellValue("Description")
rows.createCell(2).setCellValue("HSN")
rows.createCell(3).setCellValue("UOM")
var rowNum = 1
for (product in productList) {
val row: Row = sh.createRow(rowNum++)
row.createCell(0).setCellValue(product.name)
row.createCell(1).setCellValue(product.description)
row.createCell(2).setCellValue(product.hsnCode)
val uomCell: Cell = row.createCell(3)
uomCell.setCellValue(product.uom?.name ?: "")
}
val baos = ByteArrayOutputStream()
wb.write(baos)
wb.close()
return ByteArrayInputStream(baos.toByteArray())
}
fun excelToDb(): List<Product> {
val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\Untitled 1.xlsx")
val workbook = WorkbookFactory.create(inputStream)
val workSheet = workbook.getSheetAt(0)
for (row in workSheet) {
val cell1Value = row.getCell(0).stringCellValue
val cell2Value = row.getCell(1).stringCellValue
val cell3Value = row.getCell(2).stringCellValue
val cell4Value = row?.getCell(3)?.stringCellValue
val prod = Product()
prod.name = cell1Value
prod.description = cell2Value
prod.hsnCode = cell3Value
prod.uom = when(cell4Value) {
"nos" -> UOM.NOS
"ltr" -> UOM.LTR
"mtr" -> UOM.MTR
else -> UOM.ALL
}
database.saveAll(prod)
}
val productList = Session.database.find(Product::class.java).findList()
return productList
}

View File

@@ -29,10 +29,14 @@ data class POFilters (
val validBefore: LocalDate = maxDate,
val refQuotation :String = IGNORE,
) : CustomFilters
enum class UOMFilter {
ALL //fixme: later
}
data class ProductFilters (
val nameLike :String = IGNORE,
val hsnLike :String = IGNORE,
val uom :UOM = UOM.ALL,
val uom :UOMFilter = UOMFilter.ALL,
) : CustomFilters
data class DocumentFilters (
val nameLike :String = IGNORE,
@@ -142,3 +146,12 @@ fun searchRFQ(commonFilters: CommonFilters, rfqFilters: RFQFilters) : List<ReqFo
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList()
}
fun searchProduct(commonFilters: CommonFilters, productFilters: ProductFilters): List<Product> {
val p = database.find(Product::class.java)
.where()
.ilike("hsnCode", productFilters.hsnLike)
.ilike("Pname", productFilters.nameLike)
applySortHelper(p, commonFilters.sortBy, commonFilters.sortAsc)
return p.findList()
}

View File

@@ -9,6 +9,7 @@ import io.ebean.annotation.*
import io.ebean.annotation.Index
import java.time.LocalDate
import java.time.LocalDateTime
import java.util.*
import javax.persistence.*
data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now())
@@ -274,6 +275,7 @@ open class PurchaseOrder :BaseTenantModel() {
enum class UOM {
NOS, LTR, MTR, ALL
}
@Entity
open class Product :BaseTenantModel() {
var id: Long? = null