Compare commits

6 Commits

Author SHA1 Message Date
cfa3a7e289 Excel to Db 2024-01-24 17:27:37 +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
10 changed files with 404 additions and 948 deletions

Binary file not shown.

244
api.http
View File

@@ -93,16 +93,20 @@ Authorization: {{auth-token}}
DELETE http://localhost:9001/api/vehicle/KA01HD6667 DELETE http://localhost:9001/api/vehicle/KA01HD6667
Authorization: {{auth-token}} Authorization: {{auth-token}}
### get po for id ### get products
GET http://localhost:9001/api/vendor/product GET http://localhost:9001/api/vendor/product
Authorization: {{auth-token}} Authorization: {{auth-token}}
### get product for id ### get products by hsn code
GET http://localhost:9001/api/vendor/product/7 GET http://localhost:9001/api/vendor/product/#123
Authorization: {{auth-token}} Authorization: {{auth-token}}
### get row ### create excel for products
GET http://localhost:9001/api/vendor/product/7 POST http://localhost:9001/api/vendor/product/product-excel
Authorization: {{auth-token}}
### excel read
GET http://localhost:9001/api/vendor/product/validation
Authorization: Bearer {{auth-token}} Authorization: Bearer {{auth-token}}
### create product ### create product
@@ -130,233 +134,9 @@ Authorization: {{auth-token}}
### delete a row ### delete a row
DELETE http://localhost:9001/api/vendor/product/2 DELETE http://localhost:9001/api/vendor/product/#1
Authorization: {{auth-token}} Authorization: {{auth-token}}
### create vendor ###
POST http://localhost:9001/api/vendor/ POST http://localhost:9001/api/vendor/product/import
Content-Type: application/json
Authorization: {{auth-token}} Authorization: {{auth-token}}
{
"name": "arsalan",
"msme": "1234",
"hsnCode": "1234",
"gstNumber": "GST123",
"address": "Bangalore",
"rating": 2,
"contacts": [
{
"name": "contact1",
"email": "abc@cyz.com",
"mobile": "01234567890"
}
]
}
### create batch vendor
POST http://localhost:9001/api/vendor/batch
Content-Type: application/json
Authorization: {{auth-token}}
[
{
"name": "john",
"description": "5678",
"hsnCode": "5678",
"gstNumber": "GST567",
"address": "Mumbai",
"rating": 4,
"contacts": [
{
"name": "contact1",
"email": "xyz@abc.com",
"phone": "9876543210"
}
]
},
{
"name": "emma",
"description": "7890",
"hsnCode": "7890",
"gstNumber": "GST789",
"address": "Delhi",
"rating": 3,
"contacts": [
{
"name": "contact2",
"email": "def@uvw.com",
"phone": "8765432109"
}
]
},
{
"name": "alex",
"description": "2345",
"hsnCode": "2345",
"gstNumber": "GST234",
"address": "Chennai",
"rating": 5,
"contacts": [
{
"name": "contact3",
"email": "ghi@rst.com",
"phone": "7654321098"
}
]
}
]
### GET ALL VENDORS
POST http://localhost:9001/api/vendor/getAll
Content-Type: application/json
Authorization: {{auth-token}}
{
"common": {
"sortAsc": true
},
"vendorFilters": {
"nameLike": "a"
}
}
### create batch pos
POST http://localhost:9001/api/vendor/po/batch
Content-Type: application/json
Authorization: {{auth-token}}
[
{
"products": [
{
"productId": "1232",
"productName": "chair",
"unitPrice": 34.2,
"quantity": 10,
"description": "wooden chair"
}
],
"referenceQuotation": "12323",
"totalAmount": 342,
"poNum": "1",
"poDate": "2024-01-10",
"validTill": "2024-02-10",
"tnc": ["tnc1", "tnc2"]
},
{
"products": [
{
"productId": "5678",
"productName": "table",
"unitPrice": 45.5,
"quantity": 5,
"description": "glass table"
}
],
"referenceQuotation": "56789",
"totalAmount": 227.5,
"poNum": "2",
"poDate": "2024-10-25",
"validTill": "2024-10-25",
"tnc": ["tnc3", "tnc4"]
},
{
"products": [
{
"productId": "91011",
"productName": "lamp",
"unitPrice": 15.75,
"quantity": 20,
"description": "floor lamp"
}
],
"referenceQuotation": "9101112",
"totalAmount": 315,
"poNum": "3",
"poDate": "2024-10-25",
"validTill": "2024-12-25",
"tnc": ["tnc5", "tnc6"]
}
]
### GET ALL POS
POST http://localhost:9001/api/vendor/po/getAll
Content-Type: application/json
Authorization: {{auth-token}}
{
"common" : {},
"poFilters": {}
}
### CREATE QUOTES
POST http://localhost:9001/api/vendor/quote/batch
Content-Type: application/json
Authorization: {{auth-token}}
[
{
"products": [
{
"productId": "1232",
"productName": "chair",
"unitPrice": 34.2,
"quantity": 10,
"description": "wooden chair"
}
],
"reqForQuoteNum": "12323",
"totalAmount": 342,
"quoteNum": "1",
"quoteDate": "2024-10-24",
"validTill": "2024-11-24",
"tnc": ["tnc1", "tnc2"]
},
{
"products": [
{
"productId": "5678",
"productName": "table",
"unitPrice": 45.5,
"quantity": 5,
"description": "glass table"
}
],
"reqForQuoteNum": "56789",
"totalAmount": 227.5,
"quoteNum": "2",
"quoteDate": "2024-10-25",
"validTill": "2024-11-25",
"tnc": ["tnc3", "tnc4"]
},
{
"products": [
{
"productId": "91011",
"productName": "lamp",
"unitPrice": 15.75,
"quantity": 20,
"description": "floor lamp"
}
],
"reqForQuoteNum": "9101112",
"totalAmount": 315,
"quoteNum": "3",
"quoteDate": "2024-10-25",
"validTill": "2024-12-25",
"tnc": ["tnc5", "tnc6"]
}
]
### GET ALL QUOTES
POST http://localhost:9001/api/vendor/quote/getAll
Content-Type: application/json
Authorization: {{auth-token}}
{
"common" : {},
"quoteFilters": {}
}

View File

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

@@ -6,6 +6,8 @@ import com.restapi.config.AppConfig.Companion.appConfig
import com.restapi.config.Auth.validateAuthToken import com.restapi.config.Auth.validateAuthToken
import com.restapi.controllers.* import com.restapi.controllers.*
import com.restapi.domain.DataNotFoundException 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.currentTenant
import com.restapi.domain.Session.currentUser import com.restapi.domain.Session.currentUser
import com.restapi.domain.Session.objectMapper import com.restapi.domain.Session.objectMapper
@@ -23,6 +25,7 @@ import io.javalin.http.util.RateLimitUtil
import io.javalin.json.JavalinJackson import io.javalin.json.JavalinJackson
import org.jose4j.jwt.consumer.InvalidJwtException import org.jose4j.jwt.consumer.InvalidJwtException
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.InputStream
import java.security.MessageDigest import java.security.MessageDigest
import java.time.LocalDateTime import java.time.LocalDateTime
import java.util.* import java.util.*
@@ -110,84 +113,158 @@ fun main(args: Array<String>) {
it.json(mapOf("status" to true)) it.json(mapOf("status" to true))
} }
path("/vendor"){ path("/vendor") {
path("/"){ path("/") {
post("", VendorCtrl::create, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE", "ROLE_ADMIN")))) post("", Vendor::create, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE", "ROLE_ADMIN"))))
post("/batch", VendorCtrl::createBatch, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE", "ROLE_ADMIN")))) get(
get("/{id}", VendorCtrl::get, Roles(Role.Explicit(listOf("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE", "ROLE_ADMIN")))) "",
post("/getAll", VendorCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE")))) Vendor::get,
get("quotes/{id}", VendorCtrl::getQuotes, Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_QUOTE_VIEW", "ROLE_QUOTE_CREATE", "ROLE_VENDOR_VIEW")))) Roles(Role.Explicit(listOf("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE", "ROLE_ADMIN")))
get("pos/{id}", VendorCtrl::getPos, Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_PO_VIEW", "ROLE_PO_CREATE`")))) )
put("/rate/{id}/{rating}", VendorCtrl::rate, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE")))) get(
"quotes/{id}",
Vendor::getQuotes,
Roles(
Role.Explicit(
listOf(
"ROLE_ADMIN",
"ROLE_QUOTE_VIEW",
"ROLE_QUOTE_CREATE",
"ROLE_VENDOR_VIEW"
)
)
)
)
get(
"pos/{id}",
Vendor::getPos,
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_PO_VIEW", "ROLE_PO_CREATE`")))
)
put("/rate/{id}/{rating}", Vendor::rate, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE"))))
} }
path("/po"){ path("/po") {
post("", PurchaseOrderCtrl::create, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_ADMIN")))) post("", PurchaseOrder::create, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_ADMIN"))))
post("/batch", PurchaseOrderCtrl::createBatch, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_VENDOR_CREATE", "ROLE_ADMIN")))) get(
post("/getAll", PurchaseOrderCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_CREATE", "ROLE_VENDOR_CREATE", "ROLE_ADMIN")))) "/{id}",
get("/{id}", PurchaseOrderCtrl::get, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_QUOTE_CREATE")))) PurchaseOrder::get,
put("/approve/{id}", PurchaseOrderCtrl::approve, Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_APPROVE")))) Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_QUOTE_CREATE")))
put("/reject/{id}", PurchaseOrderCtrl::reject, Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_APPROVE")))) )
get("/refQuote/{id}", PurchaseOrderCtrl::quoteReference, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_VIEW")))) put(
"/approve/{id}",
PurchaseOrder::approve,
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_APPROVE")))
)
put(
"/reject/{id}",
PurchaseOrder::reject,
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_APPROVE")))
)
get(
"/refQuote/{id}",
PurchaseOrder::quoteReference,
Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_VIEW")))
)
} }
path("/quote"){ path("/quote") {
post("", QuotationCtrl::create, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN")))) post("", Quotation::create, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN"))))
post("/batch", QuotationCtrl::createBatch, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN", "ROLE_VENDOR_CREATE")))) get(
post("/getAll", QuotationCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN", "ROLE_VENDOR_CREATE")))) "/{id}",
get("/{id}", QuotationCtrl::get, Roles(Role.Explicit(listOf("ROLE_QUOTE_VIEW", "ROLE_ADMIN", "ROLE_PO_CREATE", "ROLE_QUOTE_CREATE")))) Quotation::get,
get("/po/{id}", QuotationCtrl::generatePO, Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_PO_CRETE")))) Roles(
get("/rfq/{rfqNum}", QuotationCtrl::reqForQuote, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW")))) Role.Explicit(
delete("/{id}", QuotationCtrl::delete, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN")))) listOf(
"ROLE_QUOTE_VIEW",
"ROLE_ADMIN",
"ROLE_PO_CREATE",
"ROLE_QUOTE_CREATE"
)
)
)
)
get(
"/po/{id}",
Quotation::generatePO,
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_PO_CRETE")))
)
get(
"/rfq/{rfqNum}",
Quotation::reqForQuote,
Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW")))
)
delete(
"/{id}",
Quotation::delete,
Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN")))
)
} }
path("/product"){ path("/product") {
post("", ProductCtrl::create, Roles(Role.Explicit(listOf("ROLE_PRODUCT_CREATE", "ROLE_ADMIN")))) post("", ProductCtrl::create, Roles(Role.Explicit(listOf("ROLE_PRODUCT_CREATE", "ROLE_ADMIN"))))
//get("/{hsnCode}", ProductCtrl::get, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN")))) get("/{hsnCode}", ProductCtrl::get, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
patch("/{id}", ProductCtrl::patch, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "ROLE_ADMIN"))))
put("/{id}", ProductCtrl::update, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "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"))))
delete("/{id}", ProductCtrl::delete, Roles(Role.Explicit(listOf("ROLE_PRODUCT_DELETE", "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("", ProductCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
post("/product-excel", ProductCtrl::prodExcel)
post("/import") {ctx -> ctx.json(excelToDb())}
} }
path("/doc"){ path("/doc") {
post("", Document::create, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_ADMIN")))) post("", Document::create, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_ADMIN"))))
//why type and refid are clubbed ?? //why type and refid are clubbed ??
get("/{type}/{refId}", Document::getWithRefId, Roles(Role.Explicit(listOf("ROLE_DOC_VIEW", "ROLE_ADMIN", "ROLE_PRODUCT_CREATE")))) get(
get("/{id}", Document::get, Roles(Role.Explicit(listOf("ROLE_DOC_VIEW", "ROLE_ADMIN", "ROLE_PRODUCT_CREATE")))) "/{type}/{refId}",
get("/print/{id}", Document::print, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_DOC_VIEW")))) Document::getWithRefId,
delete("/{id}", Document::delete, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE")))) Roles(Role.Explicit(listOf("ROLE_DOC_VIEW", "ROLE_ADMIN", "ROLE_PRODUCT_CREATE")))
} )
path("/reqForQuote"){ get(
post("", RequestForQuote::create, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE")))) "/{id}",
get("/{id}", RequestForQuote::get, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE", "ROLE_RFQ_VIEW")))) Document::get,
put("/{id}", RequestForQuote::update, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE")))) Roles(Role.Explicit(listOf("ROLE_DOC_VIEW", "ROLE_ADMIN", "ROLE_PRODUCT_CREATE")))
)
get(
"/print/{id}",
Document::print,
Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_DOC_VIEW")))
)
delete("/{id}", Document::delete, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE"))))
}
path("/reqForQuote") {
post("", RequestForQuote::create, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE"))))
get(
"/{id}",
RequestForQuote::get,
Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE", "ROLE_RFQ_VIEW")))
)
put("/{id}", RequestForQuote::update, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE"))))
}
} }
post("/script/database/{name}", Entities::executeStoredProcedure, Roles(adminRole, Role.DbOps))
post("/script/{file}/{name}", Entities::executeScript, Roles(adminRole, Role.DbOps))
get("/{entity}/{id}", Entities::view, Roles(adminRole, viewRole))
post("/{entity}/query/{id}", Entities::sqlQueryById, Roles(adminRole, viewRole))
post("/{entity}/query", Entities::sqlQueryRaw, Roles(adminRole, viewRole))
post("/{entity}", Entities::create, Roles(adminRole, createRole))
put("/{entity}/approve/{id}", Entities::approve, Roles(adminRole, approveOrRejectRole))
put("/{entity}/reject/{id}", Entities::reject, Roles(adminRole, approveOrRejectRole))
put("/{entity}/{action}/{id}", Entities::action, Roles(adminRole, Role.Entity))
put("/{entity}/{id}", Entities::update, Roles(adminRole, updateRole))
patch("/{entity}/{id}", Entities::patch, Roles(adminRole, updateRole))
delete("/{entity}/{id}", Entities::delete, Roles(adminRole, Role.Standard(Action.DELETE)))
} }
post("/script/database/{name}", Entities::executeStoredProcedure, Roles(adminRole, Role.DbOps))
post("/script/{file}/{name}", Entities::executeScript, Roles(adminRole, Role.DbOps))
get("/{entity}/{id}", Entities::view, Roles(adminRole, viewRole))
post("/{entity}/query/{id}", Entities::sqlQueryById, Roles(adminRole, viewRole))
post("/{entity}/query", Entities::sqlQueryRaw, Roles(adminRole, viewRole))
post("/{entity}", Entities::create, Roles(adminRole, createRole))
put("/{entity}/approve/{id}", Entities::approve, Roles(adminRole, approveOrRejectRole))
put("/{entity}/reject/{id}", Entities::reject, Roles(adminRole, approveOrRejectRole))
put("/{entity}/{action}/{id}", Entities::action, Roles(adminRole, Role.Entity))
put("/{entity}/{id}", Entities::update, Roles(adminRole, updateRole))
patch("/{entity}/{id}", Entities::patch, Roles(adminRole, updateRole))
delete("/{entity}/{id}", Entities::delete, Roles(adminRole, Role.Standard(Action.DELETE)))
} }
.exception(DuplicateKeyException::class.java, Exceptions.dupKeyExceptionHandler)
.exception(DataIntegrityException::class.java, Exceptions.dataIntegrityException)
.exception(DataNotFoundException::class.java, Exceptions.dataNotFoundException)
.exception(IllegalArgumentException::class.java, Exceptions.illegalArgumentException)
.exception(JsonMappingException::class.java, Exceptions.jsonMappingException)
.exception(InvalidJwtException::class.java, Exceptions.invalidJwtException)
.start(appConfig.portNumber())
} }
.exception(DuplicateKeyException::class.java, Exceptions.dupKeyExceptionHandler)
.exception(DataIntegrityException::class.java, Exceptions.dataIntegrityException)
.exception(DataNotFoundException::class.java, Exceptions.dataNotFoundException)
.exception(IllegalArgumentException::class.java, Exceptions.illegalArgumentException)
.exception(JsonMappingException::class.java, Exceptions.jsonMappingException)
.exception(InvalidJwtException::class.java, Exceptions.invalidJwtException)
.start(appConfig.portNumber())
}
private fun Context.getAuthHeader() = header("Authorization") private fun Context.getAuthHeader() = header("Authorization")
?.replace("Bearer ", "") ?.replace("Bearer ", "")
?.replace("Bearer: ", "") ?.replace("Bearer: ", "")
?.trim() ?.trim()

View File

@@ -17,7 +17,13 @@ import com.restapi.integ.Scripting
import io.ebean.CallableSql import io.ebean.CallableSql
import io.ebean.RawSqlBuilder import io.ebean.RawSqlBuilder
import io.javalin.http.* import io.javalin.http.*
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.WorkbookFactory
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.sql.Types import java.sql.Types
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
@@ -373,47 +379,25 @@ object Entities {
false false
} }
} }
data class Filters(val common :CommonFilters, val custom :CustomFilters)
data class BatchPos(val pos :List<PurchaseOrder>) object PurchaseOrder {
object PurchaseOrderCtrl {
fun get(ctx :Context){ fun get(ctx :Context){
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id") val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
ctx.json(po).status(HttpStatus.OK)
} ctx.json(po)
data class PF(val common: CommonFilters, val poFilters: POFilters)
fun getAll(ctx :Context){
val filters = ctx.bodyAsClass<PF>()
val pos = searchPos(filters.common, filters.poFilters)
ctx.json(pos).status(HttpStatus.OK)
} }
fun create(ctx :Context){ fun create(ctx :Context){
val po = ctx.bodyAsClass<PurchaseOrder>() val po = ctx.bodyAsClass<PurchaseOrder>()
database.save(po) database.save(po)
ctx.json(po).status(HttpStatus.CREATED) ctx.result("po created")
}
fun createBatch(ctx :Context){
val pos = ctx.bodyAsClass<List<PurchaseOrder>>()
val txn = database.beginTransaction()
try {
txn.isBatchMode = true
for(po in pos) database.save(po)
txn.commit()
ctx.status(HttpStatus.CREATED).result("POS Created")
} catch(e :Exception){
txn.rollback()
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR).result("Pos Creation failed" + e.message)
} finally {
txn.end()
}
ctx.result("pos batch created").status(HttpStatus.CREATED)
} }
fun approve(ctx :Context){ fun approve(ctx :Context){
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id") val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
po.approvalStatus = ApprovalStatus.APPROVED po.approvalStatus = ApprovalStatus.APPROVED
po.save() po.save()
ctx.json(po).status(HttpStatus.CREATED) ctx.result("po with id $id approved")
//reject all other pos pertaining to the same tx ?? //reject all other pos pertaining to the same tx ??
} }
fun reject(ctx :Context){ fun reject(ctx :Context){
@@ -421,7 +405,7 @@ object PurchaseOrderCtrl {
val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id") val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
po.approvalStatus = ApprovalStatus.REJECTED po.approvalStatus = ApprovalStatus.REJECTED
po.save() po.save()
ctx.json(po).status(HttpStatus.CREATED) ctx.result("po with id $id rejected")
} }
fun quoteReference(ctx :Context){ fun quoteReference(ctx :Context){
//gets the quote reference on which this po is based on //gets the quote reference on which this po is based on
@@ -436,7 +420,6 @@ object PurchaseOrderCtrl {
data class ProductSearch( data class ProductSearch(
var isSort: String? = null var isSort: String? = null
) )
object ProductCtrl { object ProductCtrl {
@@ -449,7 +432,7 @@ object ProductCtrl {
fun getAll(ctx: Context){ fun getAll(ctx: Context){
val productList = Session.database.find(Product::class.java) val productList = Session.database.find(Product::class.java)
.findList() .findList()
.sortedBy { it.hsnCode } //.sortedBy { it.hsnCode }
ctx.json(productList) ctx.json(productList)
} }
@@ -468,25 +451,22 @@ object ProductCtrl {
} }
fun update(ctx: Context) { fun update(ctx: Context) {
val id = ctx.pathParam("id")
} }
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\"")
}
} }
object QuotationCtrl { object Quotation {
fun get(ctx :Context){ fun get(ctx :Context){
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val quote = database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for $id") val quote = database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for $id")
ctx.status(HttpStatus.OK)
ctx.json(quote) ctx.json(quote)
} }
data class QF(val common: CommonFilters, val quoteFilters: QuoteFilters)
fun getAll(ctx :Context){
val filters = ctx.bodyAsClass<QF>()
val quotes = searchQuotes(filters.common, filters.quoteFilters)
ctx.json(quotes).status(HttpStatus.OK)
}
fun create(ctx :Context){ fun create(ctx :Context){
val quote = ctx.bodyAsClass<Quotation>() val quote = ctx.bodyAsClass<Quotation>()
//we have to check if the quotation created date is below the expiry of rfq //we have to check if the quotation created date is below the expiry of rfq
@@ -499,44 +479,25 @@ object QuotationCtrl {
if(quote.quoteDate!! <= rfq.openTill) { if(quote.quoteDate!! <= rfq.openTill) {
//valid //valid
database.save(quote) database.save(quote)
ctx.status(HttpStatus.CREATED) ctx.result("quote created")
ctx.json(quote)
}else { }else {
ctx.status(HttpStatus.BAD_REQUEST)
ctx.result("request for quote closed") ctx.result("request for quote closed")
} }
}else { }else {
throw NotFoundResponse("request for quote not found for this quotation") throw NotFoundResponse("request for quote not found for this quotation")
} }
}
fun createBatch(ctx :Context){
val quotes = ctx.bodyAsClass<List<Quotation>>()
val txn = database.beginTransaction()
try {
txn.isBatchMode = true
for(quote in quotes) database.save(quote)
txn.commit()
ctx.status(HttpStatus.CREATED).result("Quotes Created")
} catch(e :Exception){
txn.rollback()
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR).result("Quotes Creation failed" + e.message)
} finally {
txn.end()
}
ctx.result("Quotes batch created").status(HttpStatus.CREATED)
} }
fun delete(ctx :Context){ fun delete(ctx :Context){
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val quote = database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for id $id") val quote = database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for id $id")
quote.delete() quote.delete()
ctx.status(HttpStatus.OK)
ctx.result("quote with $id deleted") ctx.result("quote with $id deleted")
} }
fun generatePO(ctx :Context){ fun generatePO(ctx :Context){
//user should be redirected to a po form submission with prefilled values //user should be redirected to a po form submission with prefilled values
//create a PO object with values from the quote and then send it as body to vendor/po/create ?? //create a PO object with values from the quote and then send it as body to vendor/po/create ??
} }
fun reqForQuote(ctx :Context){ fun reqForQuote(ctx :Context){
val reqForQuoteNum = ctx.pathParam(("rfqNum")) val reqForQuoteNum = ctx.pathParam(("rfqNum"))
@@ -544,7 +505,6 @@ object QuotationCtrl {
.where() .where()
.eq("reqForQuoteNum", reqForQuoteNum) .eq("reqForQuoteNum", reqForQuoteNum)
?: throw NotFoundResponse("request for quote not found for this quotation") ?: throw NotFoundResponse("request for quote not found for this quotation")
ctx.status(HttpStatus.OK)
ctx.json(rfq) ctx.json(rfq)
} }
} }
@@ -552,14 +512,12 @@ object Document {
fun get(ctx :Context){ fun get(ctx :Context){
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val doc = database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id") val doc = database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id")
ctx.status(HttpStatus.OK)
ctx.json(doc) ctx.json(doc)
} }
fun create(ctx :Context){ fun create(ctx :Context){
val doc = ctx.bodyAsClass<Document>() val doc = ctx.bodyAsClass<Document>()
database.save(doc) database.save(doc)
ctx.status(HttpStatus.CREATED) ctx.result("doc created")
ctx.json(doc)
} }
fun print(ctx :Context){ fun print(ctx :Context){
//would be handled in the frontend ?? //would be handled in the frontend ??
@@ -568,8 +526,7 @@ object Document {
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val doc = database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id") val doc = database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id")
//doc.delete() //doc.delete()
ctx.status(HttpStatus.OK) ctx.result("document deleted")
ctx.result("document deleted with id $id")
} }
fun getWithRefId(ctx :Context){ fun getWithRefId(ctx :Context){
//fetches a particular doc (po, quote) with ref id //fetches a particular doc (po, quote) with ref id
@@ -578,47 +535,20 @@ object Document {
.where() .where()
.eq("refId", refId) .eq("refId", refId)
?: throw NotFoundResponse("no doc found for refId $refId") ?: throw NotFoundResponse("no doc found for refId $refId")
ctx.status(HttpStatus.OK)
ctx.json(doc) ctx.json(doc)
} }
} }
object VendorCtrl { object Vendor {
fun get(ctx :Context){ fun get(ctx :Context){
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val vendor = database.find(Vendor::class.java, id) ?: throw NotFoundResponse("no vendor found with id $id") val vendor = database.find(Vendor::class.java, id) ?: throw NotFoundResponse("no vendor found with id $id")
ctx.status(HttpStatus.OK)
ctx.json(vendor) ctx.json(vendor)
} }
data class VF(val common : CommonFilters, val vendorFilters: VendorFilters) fun create(ctx :Context){
fun getAll(ctx :Context){
val filters = ctx.bodyAsClass<VF>()
println(filters.common)
println(filters.vendorFilters)
val pos = searchVendors(filters.common, filters.vendorFilters)
ctx.status(HttpStatus.OK)
ctx.json(pos)
}
fun createBatch(ctx: Context){
val vendors = ctx.bodyAsClass<List<Vendor>>()
val txn = database.beginTransaction()
try {
txn.isBatchMode = true
for(v in vendors) database.save(v)
txn.commit()
ctx.status(HttpStatus.CREATED).result("Vendors Created")
} catch(e :Exception){
txn.rollback()
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR).result("Vendor Creation failed" + e.message)
} finally {
txn.end()
}
}
fun create(ctx :Context){
val vendor = ctx.bodyAsClass<Vendor>() val vendor = ctx.bodyAsClass<Vendor>()
database.save(vendor) database.save(vendor)
ctx.status(HttpStatus.CREATED) ctx.result("vendor created")
ctx.json(vendor)
} }
fun update(ctx :Context){ fun update(ctx :Context){
@@ -632,7 +562,6 @@ object VendorCtrl {
.where() .where()
.eq("vendor", id) .eq("vendor", id)
.findList() .findList()
ctx.status(HttpStatus.OK)
ctx.json(quotes) ctx.json(quotes)
} }
fun getPos(ctx :Context){ fun getPos(ctx :Context){
@@ -641,7 +570,6 @@ object VendorCtrl {
.where() .where()
.eq("vendor", id) .eq("vendor", id)
.findList() .findList()
ctx.status(HttpStatus.OK)
ctx.json(pos) ctx.json(pos)
} }
fun rate(ctx :Context){ fun rate(ctx :Context){
@@ -651,29 +579,24 @@ object VendorCtrl {
//could place some rating validation checks //could place some rating validation checks
vendor.rating = rating vendor.rating = rating
vendor.save() vendor.save()
ctx.status(HttpStatus.OK)
ctx.result("rating changed") ctx.result("rating changed")
} }
} }
object RequestForQuote { object RequestForQuote {
fun create(ctx: Context) { fun create(ctx :Context) {
val rfq = ctx.bodyAsClass<ReqForQuote>() val rfq = ctx.bodyAsClass<ReqForQuote>()
database.save(rfq) database.save(rfq)
//ctx.result("request for quote created") //ctx.result("request for quote created")
//ctx.json(rfq) //ctx.json(rfq)
ctx.status(HttpStatus.CREATED) //ctx.status(HttpStatus.CREATED)
ctx.json("asss") //ctx.json("asss")
} }
fun get(ctx :Context){
fun get(ctx: Context) {
val id = ctx.pathParam("id") val id = ctx.pathParam("id")
val rfq = database.find(ReqForQuote::class.java, id) val rfq = database.find(ReqForQuote::class.java, id) ?: throw NotFoundResponse("request for quote not found for id $id")
?: throw NotFoundResponse("request for quote not found for id $id")
ctx.status(HttpStatus.OK)
ctx.json(rfq) ctx.json(rfq)
} }
fun update(ctx :Context){
fun update(ctx: Context) {
//shuld we compare the new body fields with preexisting ones and prepare a sql query to update those fields?? //shuld we compare the new body fields with preexisting ones and prepare a sql query to update those fields??
} }

View File

@@ -1,419 +1,184 @@
package com.restapi.controllers package com.restapi.controllers
import com.google.gson.Gson
import com.restapi.domain.* import com.fasterxml.jackson.databind.DeserializationFeature
import com.restapi.domain.Document import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.restapi.domain.PurchaseOrder import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.restapi.domain.Quotation import com.restapi.domain.Product
import com.restapi.domain.Session.currentUser import com.restapi.domain.Session
import org.apache.poi.hssf.usermodel.HSSFSheet
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 com.restapi.domain.UOM
import org.apache.poi.hssf.usermodel.DVConstraint import io.ebean.text.json.JsonContext
import org.apache.poi.hssf.usermodel.HSSFDataValidation import io.javalin.http.Context
import org.apache.poi.ss.usermodel.Cell import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellType import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.DateUtil import org.apache.poi.ss.usermodel.Row
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.usermodel.WorkbookFactory import org.apache.poi.ss.usermodel.WorkbookFactory
import org.apache.poi.ss.util.CellRangeAddressList import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.io.File import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.FileInputStream import java.io.FileInputStream
import java.io.FileOutputStream import java.io.InputStream
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.ZoneId
import java.util.*
fun createHeaderRow(cols :List<String>, sh :HSSFSheet, wb: Workbook) { fun CreateExcel(productList: List<Product>): InputStream {
val boldFont = wb.createFont() val wb = XSSFWorkbook()
boldFont.bold = true
val style = wb.createCellStyle()
style.setFont(boldFont)
style.locked = true
sh.createRow(0).apply {
cols.forEachIndexed{index, value ->
val cell = createCell(index)
cell.setCellValue(value)
cell.setCellStyle(style)
}
}
}
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 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 saveExcelFileLocally(fileName :String, wb: Workbook){
val out = FileOutputStream(fileName)
wb.use {
it.write(out)
}
out.close()
}
fun TemplateExcelFile(fileType: FileType){
when(fileType){
FileType.QUOTES -> {
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")
val wb = HSSFWorkbook()
val sh = wb.createSheet()
createHeaderRow(headers, sh, wb)
saveExcelFileLocally("Quotes_Template.xls", wb)
}
FileType.POS -> {
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")
val wb = HSSFWorkbook()
val sh = wb.createSheet()
createHeaderRow(headers, sh, wb)
saveExcelFileLocally("Purchase_Order_Template.xls", wb)
}
FileType.VENDORS -> {
val headers : List<String> = listOf("Name", "MSME", "GST Number", "Address", "Rating", "Contact Name", "Contact Email", "Contact Mobile")
val wb = HSSFWorkbook()
val sh = wb.createSheet()
createHeaderRow(headers, sh, wb)
saveExcelFileLocally("Vendors_Template.xls", wb)
}
FileType.PRODS -> {
val headers : List<String> = listOf("Id", "Name", "Description", "HSN Code", "UOM")
val wb = HSSFWorkbook()
val sh = wb.createSheet()
createHeaderRow(headers, sh, wb)
val r0 = CellRangeAddressList(0, 1000, 4, 4)
val dv0 = HSSFDataValidation(r0, DVConstraint.createExplicitListConstraint(arrayOf("LTR", "MTR", "NOS", "ALL"))).apply {
suppressDropDownArrow = true
}
sh.addValidationData(dv0)
saveExcelFileLocally("Products_Template.xls", wb)
}
FileType.DOCS -> {
}
}
}
fun ExportQuotations(quotes :List<Quotation>) {
val wb = HSSFWorkbook()
val sh = wb.createSheet() 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")
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") var rowNum = 1
createHeaderRow(headers, sh, wb) for (product in productList) {
val totalCols = headers.size val row: Row = sh.createRow(rowNum++)
var rowCnt = 1
for(quote in quotes){
val prodCnt = quote.products.size
for (j in 0..prodCnt - 1){ row.createCell(0).setCellValue(product.name)
val row = sh.createRow(rowCnt++) row.createCell(1).setCellValue(product.description)
var i = 0; row.createCell(2).setCellValue(product.hsnCode)
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) val uomCell: Cell = row.createCell(3)
row.createCell(i++).setCellValue(quote.vendor?.address) uomCell.setCellValue(product.uom?.name ?: "")
row.createCell(i++).setCellValue(quote.reqForQuoteNum)
row.createCell(i++).setCellValue(quote.totalAmount)
row.createCell(i++).setCellValue(quote.tnc.joinToString(";"))
}
} }
val baos = ByteArrayOutputStream()
wb.write(baos)
wb.close()
return ByteArrayInputStream(baos.toByteArray())
} }
fun ExportVendors(vendors :List<Vendor>){ data class validateExcel(
val wb = HSSFWorkbook() val name: String,
val sh = wb.createSheet() val description: String,
val hsnCode: String,
val ok: Boolean,
val err: String,
)
val headers : List<String> = listOf("Name", "MSME", "GST Number", "Address", "Rating", "Contact Name", "Contact Email", "Contact Mobile") val app_common_om = jacksonObjectMapper().apply {
createHeaderRow(headers, sh, wb) registerModule(JavaTimeModule())
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
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>){ fun ExcelRead(): String{
val wb = HSSFWorkbook() val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\product-4.xlsx")
val sh = wb.createSheet() 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 headers : List<String> = listOf("Id", "Name", "Description", "HSN Code", "UOM") val resp = arrayListOf<validateExcel>()
createHeaderRow(headers, sh, wb)
val totalCols = headers.size if(h==false) {
var rowCnt = 1 workSheet.rowIterator().forEach { row ->
for (prod in prods){ if (row == null) return@forEach
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") if (h) {
createHeaderRow(headers, sh, wb)
val totalCols = headers.size val pName = row.getCell(0).run {
var rowCnt = 1 when {
for(po in pos){ this == null -> ""
val prodCnt = po.products.size this.cellType == CellType.STRING -> this.stringCellValue
else -> ""
}
}
for (j in 0..prodCnt - 1){ val pDesc = row.getCell(1).run {
val row = sh.createRow(rowCnt++) when {
var i = 0 this == null -> ""
row.createCell(i++).setCellValue(po.poNum) this.cellType == CellType.STRING -> this.stringCellValue
row.createCell(i++).setCellValue(po.poDate) else -> ""
row.createCell(i++).setCellValue(po.validTill) }
row.createCell(i++).setCellValue(po.referenceQuotation) }
row.createCell(i++).setCellValue(po.vendor?.name) val pHsn = row.getCell(2).run {
row.createCell(i++).setCellValue(po.vendor?.address) when {
this == null -> ""
this.cellType == CellType.STRING -> this.stringCellValue
else -> ""
}
}
//6 would be repeated if (pName.isEmpty() && pDesc.isEmpty() && pHsn.isEmpty()) {
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")
TemplateExcelFile(FileType.PRODS)
}
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, 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 return@forEach
} }
val quoteNumber = stringFromCellHelper(row.getCell(0)) if (pName.isEmpty()) {
val quoteDt = dateFromCellHelper(row.getCell(1)) resp.add(
val rfqNum = stringFromCellHelper(row.getCell(2)) validateExcel(
val quoteValidTill = dateFromCellHelper(row.getCell(3)) name = pName,
val vendorName = stringFromCellHelper(row.getCell(4)) description = pDesc,
val vendorGstNum = stringFromCellHelper(row.getCell(5)) hsnCode = pHsn,
val vendorAddress = stringFromCellHelper(row.getCell(6)) ok = false,
val prodName = stringFromCellHelper(row.getCell(7)) err = "Product name is required"
val prodQuantity = doubleFromCellHelper(row.getCell(8)) )
val prodUnitPrice = doubleFromCellHelper(row.getCell(9)) )
val totalQuoteAmount = doubleFromCellHelper(row.getCell(10)) return@forEach
val prod = POProducts("", prodName, prodUnitPrice, prodQuantity) }
if (pDesc.isEmpty()) {
if (quotesMap.containsKey(quoteNumber)) { resp.add(
//duplicated row validateExcel(
quotesMap.get(quoteNumber)?.products?.add(prod) name = pName,
}else { description = pDesc,
val v = Vendor() hsnCode = pHsn,
v.apply { ok = false,
name = vendorName err = "Product description is required"
address = vendorAddress )
gstNumber = vendorGstNum )
} return@forEach
val quote = Quotation() }
quote.apply { if (pHsn.isEmpty()) {
quoteNum = quoteNumber resp.add(
quoteDate = quoteDt validateExcel(
reqForQuoteNum = rfqNum name = pName,
validTill = quoteValidTill description = pDesc,
products = mutableListOf(prod) hsnCode = pHsn,
vendor = v ok = false,
totalAmount = totalQuoteAmount err = "Product HSN is required"
} )
quotesMap.put(quoteNumber, quote) )
return@forEach
} }
} }
//docs, tncs h = true
// 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
}
} }
} }
return app_common_om.writeValueAsString(resp)
} }
fun excelToDb(): List<Product> {
val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\product-4.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

@@ -1,14 +1,15 @@
package com.restapi.controllers package com.restapi.controllers
import com.restapi.domain.* import com.restapi.domain.*
import com.restapi.domain.PurchaseOrder
import com.restapi.domain.Quotation import com.restapi.domain.Quotation
import com.restapi.domain.Session.database
import java.time.LocalDate import java.time.LocalDate
import com.restapi.domain.Session.database
//constants //constants
const val IGNORE = "%" const val IGNORE = "%"
val baseDate :LocalDate = LocalDate.of(1500, 1,1, ) val baseDate :LocalDate = LocalDate.MIN
val maxDate :LocalDate = LocalDate.of(3000, 1 ,1) val maxDate :LocalDate = LocalDate.MAX
const val RATING_MAX = 10.0 const val RATING_MAX = 10.0
const val RATING_MIN = 0.0 const val RATING_MIN = 0.0
//common filters would be used by most of the handlers //common filters would be used by most of the handlers
@@ -20,7 +21,6 @@ data class CommonFilters (
val sortAsc :Boolean = true, val sortAsc :Boolean = true,
val sortBy :String = IGNORE val sortBy :String = IGNORE
) )
interface CustomFilters{}
data class POFilters ( data class POFilters (
val poNumLike :String = IGNORE, val poNumLike :String = IGNORE,
val totalAmountExceeds :Long = Long.MIN_VALUE, val totalAmountExceeds :Long = Long.MIN_VALUE,
@@ -28,18 +28,16 @@ data class POFilters (
val validAfter: LocalDate = baseDate, val validAfter: LocalDate = baseDate,
val validBefore: LocalDate = maxDate, val validBefore: LocalDate = maxDate,
val refQuotation :String = IGNORE, val refQuotation :String = IGNORE,
) : CustomFilters )
data class ProductFilters ( data class ProductFilters (
val nameLike :String = IGNORE, val nameLike :String = IGNORE,
val hsnLike :String = IGNORE, val hsnLike :String = IGNORE,
val uom :UOM = UOM.ALL, val uom :UOM = UOM.ALL,
) : CustomFilters )
data class DocumentFilters ( data class DocumentFilters (
val nameLike :String = IGNORE, val nameLike :String = IGNORE,
val typeOfDoc :DocType = DocType.ALL, val typeOfDoc :DocType = DocType.ALL,
val docDateFrom :LocalDate = baseDate, )
val docDataTo :LocalDate = maxDate,
) :CustomFilters
data class RFQFilters ( data class RFQFilters (
val validBefore :LocalDate = maxDate, val validBefore :LocalDate = maxDate,
val validAfter :LocalDate = baseDate, val validAfter :LocalDate = baseDate,
@@ -47,11 +45,11 @@ data class RFQFilters (
) )
data class QuoteFilters ( data class QuoteFilters (
val quoteNumLike :String = IGNORE, val quoteNumLike :String = IGNORE,
val validBefore :LocalDate = maxDate, val validBefore :LocalDate = baseDate,
val validAfter :LocalDate = baseDate, val validAfter :LocalDate = maxDate,
val totalAmountExceeds :Long = Long.MIN_VALUE, val totalAmountExceeds :Long = Long.MIN_VALUE,
val totalAmountLessThan :Long = Long.MAX_VALUE, val totalAmountLessThan :Long = Long.MAX_VALUE,
) :CustomFilters )
data class VendorFilters ( data class VendorFilters (
val nameLike :String = IGNORE, val nameLike :String = IGNORE,
val msmeLike :String = IGNORE, val msmeLike :String = IGNORE,
@@ -59,7 +57,7 @@ data class VendorFilters (
val addressLike :String = IGNORE, val addressLike :String = IGNORE,
val ratingExceeds :Double = RATING_MIN, val ratingExceeds :Double = RATING_MIN,
val ratingLessThan :Double = RATING_MAX, val ratingLessThan :Double = RATING_MAX,
) :CustomFilters )
fun<T> applyVendorHelper(q :io.ebean.ExpressionList<T>, vids :List<Long>?) { fun<T> applyVendorHelper(q :io.ebean.ExpressionList<T>, vids :List<Long>?) {
if (vids.isNullOrEmpty()) return if (vids.isNullOrEmpty()) return
q.apply { q.apply {
@@ -71,10 +69,6 @@ fun<T> applySortHelper(q :io.ebean.ExpressionList<T>, sortBy :String, asc :Boole
val order = if (asc) "ASC" else "DESC" val order = if (asc) "ASC" else "DESC"
q.orderBy("$sortBy $order") q.orderBy("$sortBy $order")
} }
fun<T> applyFromToHelper(q :io.ebean.ExpressionList<T>, fromDate: LocalDate, toDate: LocalDate, colName :String) {
q.ge(colName, fromDate)
.le(colName, toDate)
}
fun<T> applyCommonFilters(q :io.ebean.ExpressionList<T>, commonFilters: CommonFilters) { fun<T> applyCommonFilters(q :io.ebean.ExpressionList<T>, commonFilters: CommonFilters) {
applyVendorHelper<T>(q, commonFilters.vendor) applyVendorHelper<T>(q, commonFilters.vendor)
applySortHelper<T>(q, commonFilters.sortBy, commonFilters.sortAsc) applySortHelper<T>(q, commonFilters.sortBy, commonFilters.sortAsc)
@@ -82,14 +76,17 @@ fun<T> applyCommonFilters(q :io.ebean.ExpressionList<T>, commonFilters: CommonFi
fun searchQuotes(commonFilters: CommonFilters, quoteFilters: QuoteFilters) : List<Quotation> { fun searchQuotes(commonFilters: CommonFilters, quoteFilters: QuoteFilters) : List<Quotation> {
val q = database.find(Quotation::class.java) val q = database.find(Quotation::class.java)
.where() .where()
.ge("quoteDate", commonFilters.fromDate) .between("quoteDate", commonFilters.fromDate, commonFilters.toDate)
.le("quoteDate", commonFilters.toDate) .ilike("quoteNum", quoteFilters.quoteNumLike )
.ge("validTill",quoteFilters.validAfter) .ge("validTill",quoteFilters.validAfter)
.le("validTill", quoteFilters.validBefore) .le("validTill", quoteFilters.validBefore)
.ge("totalAmount", quoteFilters.totalAmountExceeds)
.le("totalAmount", quoteFilters.totalAmountLessThan) .le("totalAmount", quoteFilters.totalAmountLessThan)
.ilike("quoteNum", "%" + quoteFilters.quoteNumLike + "%") .ge("totalAmount", quoteFilters.totalAmountExceeds)
applyVendorHelper(q, commonFilters.vendor) .apply {
if(!commonFilters.vendor?.isEmpty()!!){
commonFilters.vendor.let { this.`in`("vendor", it) }
}
}
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc) applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList() return q.findList()
} }
@@ -98,10 +95,10 @@ fun searchVendors(commonFilters: CommonFilters, vendorFilters: VendorFilters) :
.where() .where()
.ge("rating", vendorFilters.ratingExceeds) .ge("rating", vendorFilters.ratingExceeds)
.le("rating", vendorFilters.ratingLessThan) .le("rating", vendorFilters.ratingLessThan)
.ilike("name", "%" + vendorFilters.nameLike + "%") .ilike("name", vendorFilters.nameLike)
.ilike("msme", "%" + vendorFilters.msmeLike + "%") .ilike("msme", vendorFilters.msmeLike)
.ilike("gstNumber", "%" + vendorFilters.gstNumLike + "%") .ilike("gstNum", vendorFilters.gstNumLike)
.ilike("address", "%" + vendorFilters.addressLike + "%") .ilike("address", vendorFilters.addressLike)
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc) applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList() return q.findList()
} }
@@ -113,21 +110,17 @@ fun searchDocs(commonFilters: CommonFilters, documentFilters: DocumentFilters) :
this.eq("docType", documentFilters.typeOfDoc) this.eq("docType", documentFilters.typeOfDoc)
} }
} }
.ilike("name", "%" + documentFilters.nameLike + "%") .ilike("name", documentFilters.nameLike )
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc) applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
applyVendorHelper(q, commonFilters.vendor)
return q.findList() return q.findList()
} }
fun searchPos(commonFilters: CommonFilters, poFilters: POFilters?) : List<PurchaseOrder> { fun searchPos(commonFilters: CommonFilters, poFilters: POFilters) : List<PurchaseOrder> {
val poFilters = poFilters ?: POFilters()
val q = database.find(PurchaseOrder::class.java) val q = database.find(PurchaseOrder::class.java)
.where() .where()
.ge("totalAmount", poFilters.totalAmountExceeds) .between("totalAmount", poFilters.totalAmountExceeds, poFilters.totalAmountLessThan)
.le("totalAmount", poFilters.totalAmountLessThan) .between("validTill", poFilters.validAfter, poFilters.validBefore)
.ge("validTill", poFilters.validAfter) .ilike("poNum", poFilters.poNumLike )
.le("validTill", poFilters.validBefore) .ilike("referenceQuotation", poFilters.refQuotation )
.ilike("poNum", "%" + poFilters.poNumLike + "%")
.ilike("referenceQuotation", "%" + poFilters.refQuotation + "%")
applyVendorHelper(q, commonFilters.vendor) applyVendorHelper(q, commonFilters.vendor)
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc) applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList() return q.findList()
@@ -135,10 +128,18 @@ fun searchPos(commonFilters: CommonFilters, poFilters: POFilters?) : List<Purcha
fun searchRFQ(commonFilters: CommonFilters, rfqFilters: RFQFilters) : List<ReqForQuote> { fun searchRFQ(commonFilters: CommonFilters, rfqFilters: RFQFilters) : List<ReqForQuote> {
val q = database.find(ReqForQuote::class.java) val q = database.find(ReqForQuote::class.java)
.where() .where()
.ge("validTill", rfqFilters.validAfter) .between("validTill", rfqFilters.validAfter, rfqFilters.validBefore)
.le("validTill", rfqFilters.validBefore) .ilike("reqForQuoteNum", rfqFilters.reqForQuoteNumLike)
.ilike("reqForQuoteNum", "%" + rfqFilters.reqForQuoteNumLike + "%")
applyVendorHelper(q, commonFilters.vendor) applyVendorHelper(q, commonFilters.vendor)
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc) applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList() 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,12 +9,11 @@ import io.ebean.annotation.*
import io.ebean.annotation.Index import io.ebean.annotation.Index
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
import java.util.*
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 productName: String = "", val unitPrice :Double = 0.0, val quantity: Double = 0.0, val description :String = "") data class POProducts(val productId: 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
} }
@@ -243,7 +242,7 @@ class SafeStringDeserializer : JsonDeserializer<String>() {
} }
} }
data class ContactPerson(val name: String = "", val email: String = "", val mobile: String = "") data class ContactPerson(val name: String, val email: String, val mobile: String)
@Entity @Entity
open class Vendor :BaseTenantModel() { open class Vendor :BaseTenantModel() {
var name :String = "" var name :String = ""
@@ -260,23 +259,24 @@ open class PurchaseOrder :BaseTenantModel() {
var products :MutableList<POProducts> = mutableListOf() var products :MutableList<POProducts> = mutableListOf()
@ManyToOne @ManyToOne
var vendor :Vendor? = null var vendor :Vendor? = null
var referenceQuotation :String? = "" var referenceQuotation :String = ""
var totalAmount :Double = 0.0 var totalAmount :Int = 0
var poNum: String = "" var poNum: String = ""
var poDate: LocalDate? = null var poDate: LocalDate? = null
var validTill: LocalDate? = null var validTill: LocalDate? = null
@DbArray @DbArray
var tnc: List<String>? = arrayListOf() var tnc: List<String> = arrayListOf()
@DbArray @DbArray
var documents: MutableList<Long>? = arrayListOf() var documents: MutableList<Long> = arrayListOf()
} }
enum class UOM { enum class UOM {
NOS, LTR, MTR, ALL NOS, LTR, MTR, ALL
} }
@Entity @Entity
open class Product :BaseTenantModel() { open class Product :BaseTenantModel() {
var id: Long? = null var id: Int? = null
var name :String = "" var name :String = ""
var description :String = "" var description :String = ""
var hsnCode :String = "" var hsnCode :String = ""
@@ -290,9 +290,9 @@ 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 :Double = 0.0 var totalAmount :Long = 0
var reqForQuoteNum: String? = "" var reqForQuoteNum: String = ""
var quoteNum: String = "" var quoteNum: String = ""
var quoteDate: LocalDate? = null var quoteDate: LocalDate? = null
var validTill: LocalDate? = null var validTill: LocalDate? = null
@@ -311,12 +311,9 @@ open class Document :BaseTenantModel() {
var name :String = "" var name :String = ""
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
var typeOfDoc :DocType? = null var typeOfDoc :DocType? = null
//could be quoteNum, PoNum, InvoiceNum var refId: Long? = null
var refId: String? = null
var description :String = "" var description :String = ""
var url :String = "" var url :String = ""
var docDate :LocalDate? = null
var vendor :Vendor? = null
} }
enum class RFQStatus{ enum class RFQStatus{
@@ -328,10 +325,10 @@ open class ReqForQuote :BaseTenantModel() {
var potentialVendors :List<Long>? = null var potentialVendors :List<Long>? = null
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
var status :RFQStatus? = null var status :RFQStatus? = null
// @DbArray @DbArray
// var docs :List<Document>? = null var docs :List<Document>? = null
@DbJsonB @DbJsonB
var products :List<POProducts>? = null var products :List<POProducts>? = null
var reqForQuoteNum: String? = null var reqForQuoteNum: String = ""
var openTill: LocalDate? = null var openTill: LocalDate? = null
} }

View File

@@ -1,43 +0,0 @@
-- drop dependencies
alter table document drop constraint if exists ck_document_type_of_doc;
alter table product drop constraint if exists ck_product_uom;
-- apply changes
create table req_for_quote (
sys_pk bigint generated by default as identity not null,
deleted_on timestamp,
current_approval_level integer default 0 not null,
required_approval_levels integer default 0 not null,
potential_vendors bigint[],
open_till date,
deleted boolean default false not null,
version integer default 1 not null,
created_at timestamp default 'now()' not null,
modified_at timestamp default 'now()' not null,
deleted_by varchar(255),
approval_status varchar(8) default 'APPROVED' not null,
tags varchar[] default '{}' not null,
comments jsonb default '[]' not null,
tenant_id varchar(255) not null,
status varchar(9),
products jsonb,
req_for_quote_num varchar(255),
created_by varchar(255) not null,
modified_by varchar(255) not null,
constraint ck_req_for_quote_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
constraint ck_req_for_quote_status check ( status in ('DELIVERED','PO','QUOTE','CANCELLED')),
constraint pk_req_for_quote primary key (sys_pk)
);
-- apply alter tables
alter table document alter column type_of_doc type varchar(7) using type_of_doc::varchar(7);
alter table document alter column type_of_doc drop not null;
alter table document add column if not exists ref_id varchar(255);
alter table document add column if not exists doc_date date;
alter table product add column if not exists id bigint;
alter table purchase_order alter column reference_quotation drop not null;
alter table purchase_order alter column total_amount type float using total_amount::float;
alter table quotation alter column total_amount type float using total_amount::float;
alter table quotation add column if not exists req_for_quote_num varchar(255);
-- apply post alter
alter table document add constraint ck_document_type_of_doc check ( type_of_doc in ('PO','QUOTE','INVOICE','ALL'));
alter table product add constraint ck_product_uom check ( uom in ('NOS','LTR','MTR','ALL'));

View File

@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
<changeSet type="apply">
<alterColumn columnName="type_of_doc" tableName="document" type="varchar(7)" currentType="varchar" notnull="false" currentNotnull="true" checkConstraint="check ( type_of_doc in ('PO','QUOTE','INVOICE','ALL'))" checkConstraintName="ck_document_type_of_doc"/>
<addColumn tableName="document">
<column name="ref_id" type="varchar"/>
<column name="doc_date" type="date"/>
</addColumn>
<alterColumn columnName="uom" tableName="product" checkConstraint="check ( uom in ('NOS','LTR','MTR','ALL'))" checkConstraintName="ck_product_uom"/>
<addColumn tableName="product">
<column name="id" type="bigint"/>
</addColumn>
<alterColumn columnName="reference_quotation" tableName="purchase_order" currentType="varchar" notnull="false" currentNotnull="true"/>
<alterColumn columnName="total_amount" tableName="purchase_order" type="double" currentType="integer" currentNotnull="true"/>
<alterColumn columnName="total_amount" tableName="quotation" type="double" currentType="integer" currentNotnull="true"/>
<addColumn tableName="quotation">
<column name="req_for_quote_num" type="varchar"/>
</addColumn>
<createTable name="req_for_quote" pkName="pk_req_for_quote">
<column name="sys_pk" type="bigint" primaryKey="true"/>
<column name="deleted_on" type="localdatetime"/>
<column name="deleted_by" type="varchar"/>
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_req_for_quote_approval_status"/>
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
<column name="tenant_id" type="varchar" notnull="true"/>
<column name="potential_vendors" type="bigint[]"/>
<column name="status" type="varchar(9)" checkConstraint="check ( status in ('DELIVERED','PO','QUOTE','CANCELLED'))" checkConstraintName="ck_req_for_quote_status"/>
<column name="products" type="jsonb"/>
<column name="req_for_quote_num" type="varchar"/>
<column name="open_till" type="date"/>
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
<column name="version" type="integer" defaultValue="1" notnull="true"/>
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
<column name="created_by" type="varchar" notnull="true"/>
<column name="modified_by" type="varchar" notnull="true"/>
</createTable>
</changeSet>
</migration>