Compare commits

...

12 Commits

Author SHA1 Message Date
arsalan
d9dcda0724 add payments, invoice 2024-03-06 15:59:14 +05:30
arsalan
211e55a373 Merge branch 'arsalan'
# Conflicts:
#	src/main/kotlin/com/restapi/controllers/Excel.kt
#	src/main/kotlin/com/restapi/controllers/Filters.kt
#	src/main/kotlin/com/restapi/domain/models.kt
2024-03-05 10:29:30 +05:30
arsalan
e94928ae7f Merge branch 'master' of https://git.basuvaraj.com/gowthaman/readymixerp_modules_api
# Conflicts:
#	api.http
#	src/main/kotlin/com/restapi/Main.kt
#	src/main/kotlin/com/restapi/controllers/Entities.kt
2024-02-08 15:14:18 +05:30
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 345 additions and 7 deletions

View File

@@ -39,10 +39,9 @@ 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") 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

@@ -159,6 +159,35 @@ fun main(args: Array<String>) {
Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW")) Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
) )
} }
path("/invoice") {
post("", InvoiceCtrl::create, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
get("/next", InvoiceCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
get(
"/{id}",
InvoiceCtrl::get,
Roles(Role.Explicit("ROLE_INVOICE_VIEW", "ROLE_INVOICE_CREATE"))
)
put("/{id}", InvoiceCtrl::update, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
post(
"/getAll",
InvoiceCtrl::getAll,
Roles(Role.Explicit("ROLE_INVOICE_CREATE", "ROLE_INVOICE_VIEW"))
)
}
path("/payment") {
post("", PaymentCtrl::create, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
get(
"/{id}",
PaymentCtrl::get,
Roles(Role.Explicit("ROLE_PAYMENT_VIEW", "ROLE_PAYMENT_CREATE"))
)
put("/{id}", PaymentCtrl::update, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
post(
"/getAll",
PaymentCtrl::getAll,
Roles(Role.Explicit("ROLE_PAYMENT_CREATE", "ROLE_PAYMENT_VIEW"))
)
}
path("/po") { path("/po") {
get("/next", PurchaseOrderCtrl::getNextNum, Roles(Role.Explicit("ROLE_PO_CREATE"))) get("/next", PurchaseOrderCtrl::getNextNum, Roles(Role.Explicit("ROLE_PO_CREATE")))
post("", PurchaseOrderCtrl::create, Roles(Role.Explicit("ROLE_PO_CREATE"))) post("", PurchaseOrderCtrl::create, Roles(Role.Explicit("ROLE_PO_CREATE")))

View File

@@ -57,6 +57,7 @@ sealed class QueryParam {
return when (this) { return when (this) {
is Complex -> getValueComplex() is Complex -> getValueComplex()
is Simple -> simple is Simple -> simple
else -> {}
} }
} }
} }
@@ -894,7 +895,6 @@ object OutgoingInventoryCtrl {
} }
fun getNextNum(ctx: Context) { fun getNextNum(ctx: Context) {
println("inside next num")
val prefix = "MDN/" val prefix = "MDN/"
val cnt = database.find(OutgoingInventory::class.java) val cnt = database.find(OutgoingInventory::class.java)
.findCount() .findCount()
@@ -904,3 +904,103 @@ object OutgoingInventoryCtrl {
ctx.json(seq).status(HttpStatus.OK) ctx.json(seq).status(HttpStatus.OK)
} }
} }
object PaymentCtrl {
fun create(ctx :Context){
val pmt = ctx.bodyAsClass(Payment::class.java)
database.save(pmt)
//update the status of invoices pertaining to payment.vendor
val invcs = searchInvoices(CommonFilters(sortBy = "date", sortAsc = true), InvoiceFilters(status = InvoiceStatus.PAID_NONE))
val tot: Double = pmt.amount
for(inv in invcs){
val deduct = Math.min(pmt.amount, inv.totalAmount)
inv.totalAmount -= deduct
pmt.amount -= deduct
database.update(inv)
if(pmt.amount <= 0.0) break
}
if (pmt.amount > 0.0){
//balance left for this vendor
val v = pmt.vendor?.sysPk?.let { database.find(Vendor::class.java, it) }
v?.apply {
outstanding = outstanding?.minus(tot)
database.update(v)
}
}
ctx.json(pmt).status(HttpStatus.CREATED)
}
fun get(ctx : Context){
val id = ctx.pathParam("id")
val pmt = database.find(Payment::class.java, id)
?: throw NotFoundResponse("No payment found for this id")
ctx.json(pmt).status(HttpStatus.OK)
}
data class PMTF(val common : CommonFilters, val paymentFilters: PaymentFilters)
fun getAll(ctx : Context){
val filters = ctx.bodyAsClass<PMTF>()
val payments = searchPayments(filters.common, filters.paymentFilters)
println(payments)
val excel = ctx.queryParam("excel")
if (excel !== null) {
// exportPayments(payments)
val inputStream = FileInputStream("./excel/Payments.xls")
ctx.result(inputStream).status(HttpStatus.OK)
} else {
ctx.json(payments).status(HttpStatus.OK)
}
}
fun update(ctx : Context){
val id = ctx.pathParam("id").toLong()
val pmt =
database.find(Payment::class.java, id) ?: throw NotFoundResponse("payment not found for $id")
val updatedPayment = ctx.bodyAsClass<Payment>()
pmt.patchValues(updatedPayment)
pmt.update()
ctx.json(pmt).status(HttpStatus.OK)
}
}
object InvoiceCtrl {
fun create(ctx : Context){
val invoice = ctx.bodyAsClass<Invoice>()
database.save(invoice)
ctx.json(invoice).status(HttpStatus.CREATED)
}
fun get(ctx : Context){
val id = ctx.pathParam("id").toLong()
val invoice = database.find(Invoice::class.java, id)
?: throw NotFoundResponse("No invoice found with id $id")
ctx.json(invoice).status(HttpStatus.OK)
}
data class INVF(val common: CommonFilters, val invoiceFilters: InvoiceFilters)
fun getAll(ctx : Context){
val filters = ctx.bodyAsClass<INVF>()
val invoices = searchInvoices(filters.common, filters.invoiceFilters)
val excel = ctx.queryParam("excel")
if (excel !== null) {
// exportPayments(payments)
val inputStream = FileInputStream("./excel/Invoices.xls")
ctx.result(inputStream).status(HttpStatus.OK)
} else {
ctx.json(invoices).status(HttpStatus.OK)
}
}
fun update(ctx : Context){
val id = ctx.pathParam("id").toLong()
val invoice =
database.find(Invoice::class.java, id) ?: throw NotFoundResponse("invoice not found for $id")
val updatedPayment = ctx.bodyAsClass<Invoice>()
invoice.patchValues(updatedPayment)
invoice.update()
ctx.json(invoice).status(HttpStatus.OK)
}
fun getNextNum(ctx : Context){
val prefix = "INV/"
val cnt = database.find(Invoice::class.java)
.findCount()
.toString()
.padStart(6, '0')
val seq = SequenceNumber(prefix + cnt)
ctx.json(seq).status(HttpStatus.OK)
}
}

View File

@@ -2,6 +2,7 @@ package com.restapi.controllers
import com.restapi.domain.* import com.restapi.domain.*
import com.restapi.domain.Session.database import com.restapi.domain.Session.database
import org.checkerframework.checker.index.qual.LessThan
import java.time.LocalDate import java.time.LocalDate
//constants //constants
@@ -83,6 +84,20 @@ data class OutgoingInventoryFilters(
val outMode: OutMode = OutMode.ALL val outMode: OutMode = OutMode.ALL
) : CustomFilters ) : CustomFilters
data class InvoiceFilters(
val numLike: String = IGNORE,
val poNumLike: String = IGNORE,
val status: InvoiceStatus = InvoiceStatus.ALL,
val totalAmountExceeds: Double = Double.MIN_VALUE,
val totalAmountLessThan: Double = Double.MAX_VALUE
) : CustomFilters
data class PaymentFilters(
val refNumberLike: String = IGNORE,
val amountExceeds: Double = Double.MIN_VALUE,
val amountLessThan: Double = Double.MAX_VALUE
) : 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 {
@@ -216,8 +231,8 @@ fun searchOutgoingInventory(
.where() .where()
.ilike("mdn", "%" + outgoingInventoryFilters.mdnLike + "%") .ilike("mdn", "%" + outgoingInventoryFilters.mdnLike + "%")
.ilike("purpose", "%" + outgoingInventoryFilters.purposeLike + "%") .ilike("purpose", "%" + outgoingInventoryFilters.purposeLike + "%")
// .ilike("person", "%" + outgoingInventoryFilters.personLike + "%") // .ilike("person", "%" + outgoingInventoryFilters.personLike + "%")
//.ilike("vehicle", "%" + outgoingInventoryFilters.vehicleLike + "%") //.ilike("vehicle", "%" + outgoingInventoryFilters.vehicleLike + "%")
if (outgoingInventoryFilters.outMode != OutMode.ALL) { if (outgoingInventoryFilters.outMode != OutMode.ALL) {
q.eq("outMode", outgoingInventoryFilters.outMode) q.eq("outMode", outgoingInventoryFilters.outMode)
} }
@@ -226,3 +241,30 @@ fun searchOutgoingInventory(
return q.findList() return q.findList()
} }
fun searchInvoices(commonFilters: CommonFilters, invoiceFilters: InvoiceFilters): List<Invoice> {
val q = database.find(Invoice::class.java)
.where()
.ilike("number", "%" + invoiceFilters.numLike + "%")
if (invoiceFilters.status != InvoiceStatus.ALL) {
q.eq("status", invoiceFilters.status)
}
applyFromToHelper(q, commonFilters.from, commonFilters.to, "date")
applyVendorHelper(q, commonFilters.vendor)
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList()
}
fun searchPayments(commonFilters: CommonFilters, paymentFilters: PaymentFilters): List<Payment> {
val q = database.find(Payment::class.java)
.where()
.ilike("refNumber", "%" + paymentFilters.refNumberLike + "%")
.ge("amount", paymentFilters.amountExceeds)
.le("amount", paymentFilters.amountLessThan)
applyFromToHelper(q, commonFilters.from, commonFilters.to, "date")
applyVendorHelper(q, commonFilters.vendor)
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
return q.findList()
}
//if date is null then fromtoheper drops that///

View File

@@ -259,6 +259,8 @@ open class Vendor : BaseTenantModel() {
this.address = updatedVendor.address this.address = updatedVendor.address
this.rating = updatedVendor.rating this.rating = updatedVendor.rating
this.contacts = updatedVendor.contacts this.contacts = updatedVendor.contacts
this.outstanding = updatedVendor.outstanding
this.asOnWhichDate = updatedVendor.asOnWhichDate
} }
var name: String = "" var name: String = ""
@@ -266,9 +268,12 @@ open class Vendor : BaseTenantModel() {
var gstNumber: String = "" var gstNumber: String = ""
var address: String = "" var address: String = ""
var rating: Double = 0.0 var rating: Double = 0.0
var outstanding: Double?=0.0
var asOnWhichDate: LocalDate?=null
@DbJsonB @DbJsonB
var contacts: List<ContactPerson> = mutableListOf() var contacts: List<ContactPerson> = mutableListOf()
} }
@Entity @Entity
@@ -458,3 +463,47 @@ open class OutgoingInventory : BaseTenantModel() {
var person: String? = null var person: String? = null
var vehicle: String? = null var vehicle: String? = null
} }
enum class InvoiceStatus{
PAID_FULL, PAID_SOME, PAID_NONE, ALL
}
@Entity
open class Invoice : BaseTenantModel() {
fun patchValues(updated : Invoice) {
this.date = updated.date
this.number = updated.number
this.totalAmount = updated.totalAmount
this.poNum = updated.poNum
this.products = updated.products
this.vendor = updated.vendor
this.status = updated.status
}
var number: String = ""
var date: LocalDate?=null
var totalAmount : Double=0.0
var poNum:String?=null
@DbJsonB
var products: List<POProducts> ?= null
@ManyToOne
var vendor: Vendor? = null
@Enumerated(EnumType.STRING)
var status:InvoiceStatus?=null
}
@Entity
open class Payment : BaseTenantModel() {
fun patchValues(updated : Payment){
this.refNumber = updated.refNumber
this.amount = updated.amount
this.date = updated.date
this.remark = updated.remark
this.vendor = updated.vendor
}
var refNumber:String=""
var amount:Double=0.0
var date:LocalDate?=null
var remark:String?= null
@ManyToOne
var vendor:Vendor?=null
}

View File

@@ -0,0 +1,64 @@
-- apply changes
create table invoice (
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,
date date,
total_amount float not null,
vendor_sys_pk bigint,
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,
number varchar(255) not null,
po_num varchar(255),
products jsonb,
status varchar(9),
created_by varchar(255) not null,
modified_by varchar(255) not null,
constraint ck_invoice_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
constraint ck_invoice_status check ( status in ('PAID_FULL','PAID_SOME','PAID_NONE','ALL')),
constraint pk_invoice primary key (sys_pk)
);
create table payment (
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,
amount float not null,
date date,
vendor_sys_pk bigint,
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,
ref_number varchar(255) not null,
remark varchar(255),
created_by varchar(255) not null,
modified_by varchar(255) not null,
constraint ck_payment_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
constraint pk_payment primary key (sys_pk)
);
-- apply alter tables
alter table vendor add column if not exists outstanding float;
alter table vendor add column if not exists as_on_which_date date;
-- foreign keys and indices
create index ix_invoice_vendor_sys_pk on invoice (vendor_sys_pk);
alter table invoice add constraint fk_invoice_vendor_sys_pk foreign key (vendor_sys_pk) references vendor (sys_pk) on delete restrict on update restrict;
create index ix_payment_vendor_sys_pk on payment (vendor_sys_pk);
alter table payment add constraint fk_payment_vendor_sys_pk foreign key (vendor_sys_pk) references vendor (sys_pk) on delete restrict on update restrict;

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
<changeSet type="apply">
<createTable name="invoice" pkName="pk_invoice">
<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_invoice_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="number" type="varchar" notnull="true"/>
<column name="date" type="date"/>
<column name="total_amount" type="double" notnull="true"/>
<column name="po_num" type="varchar"/>
<column name="products" type="jsonb"/>
<column name="vendor_sys_pk" type="bigint" references="vendor.sys_pk" foreignKeyName="fk_invoice_vendor_sys_pk" foreignKeyIndex="ix_invoice_vendor_sys_pk"/>
<column name="status" type="varchar(9)" checkConstraint="check ( status in ('PAID_FULL','PAID_SOME','PAID_NONE','ALL'))" checkConstraintName="ck_invoice_status"/>
<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>
<createTable name="payment" pkName="pk_payment">
<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_payment_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="ref_number" type="varchar" notnull="true"/>
<column name="amount" type="double" notnull="true"/>
<column name="date" type="date"/>
<column name="remark" type="varchar"/>
<column name="vendor_sys_pk" type="bigint" references="vendor.sys_pk" foreignKeyName="fk_payment_vendor_sys_pk" foreignKeyIndex="ix_payment_vendor_sys_pk"/>
<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>
<addColumn tableName="vendor">
<column name="outstanding" type="double"/>
<column name="as_on_which_date" type="date"/>
</addColumn>
</changeSet>
</migration>