diff --git a/src/main/kotlin/com/restapi/Main.kt b/src/main/kotlin/com/restapi/Main.kt index 4778e2e..c8df441 100644 --- a/src/main/kotlin/com/restapi/Main.kt +++ b/src/main/kotlin/com/restapi/Main.kt @@ -187,6 +187,7 @@ fun main(args: Array) { PaymentCtrl::getAll, Roles(Role.Explicit("ROLE_PAYMENT_CREATE", "ROLE_PAYMENT_VIEW")) ) + delete("/{id}", PaymentCtrl::delete, Roles(Role.Explicit("ROLE_PAYMENT_CREATE"))) } path("/po") { get("/next", PurchaseOrderCtrl::getNextNum, Roles(Role.Explicit("ROLE_PO_CREATE"))) diff --git a/src/main/kotlin/com/restapi/controllers/Entities.kt b/src/main/kotlin/com/restapi/controllers/Entities.kt index 41ec164..eb497ae 100644 --- a/src/main/kotlin/com/restapi/controllers/Entities.kt +++ b/src/main/kotlin/com/restapi/controllers/Entities.kt @@ -904,42 +904,63 @@ object OutgoingInventoryCtrl { ctx.json(seq).status(HttpStatus.OK) } } + object PaymentCtrl { - fun create(ctx :Context){ + 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 + val invoices = searchInvoices( + CommonFilters(sortBy = "date", sortAsc = true), + InvoiceFilters(status = InvoiceStatus.PAID_NONE) + ) + println(invoices) + for (invoice in invoices) { + val deduct = Math.min(pmt.amount, invoice.totalAmount) + invoice.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) + if (invoice.totalAmount <= 0.0) { + invoice.status = InvoiceStatus.PAID_FULL + } else { + invoice.status = InvoiceStatus.PAID_SOME } + database.update(invoice) + pmt.invoicesAffected?.toMutableMap()?.put(invoice.sysPk, deduct) + if (pmt.amount <= 0.0) break } + pmt.excessAmount = pmt.amount + database.save(pmt) ctx.json(pmt).status(HttpStatus.CREATED) } - fun get(ctx : Context){ - val id = ctx.pathParam("id") + + fun delete(ctx: Context) { + val id = ctx.pathParam("id").toLong() val pmt = database.find(Payment::class.java, id) - ?: throw NotFoundResponse("No payment found for this id") + ?: throw NotFoundResponse("No payment found for this id $id") + val invoiceDeductMap = pmt.invoicesAffected + for (entry in invoiceDeductMap?.entries!!.iterator()) { + val inv = database.find(Invoice::class.java, entry.key) + ?: throw NotFoundResponse("No invoice found for $entry.key") + inv.totalAmount += entry.value + database.update(inv) + } + database.delete(pmt) ctx.json(pmt).status(HttpStatus.OK) } - data class PMTF(val common : CommonFilters, val paymentFilters: PaymentFilters) - fun getAll(ctx : Context){ + + 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 $id") + ctx.json(pmt).status(HttpStatus.OK) + } + + data class PMTF(val common: CommonFilters, val paymentFilters: PaymentFilters) + + fun getAll(ctx: Context) { val filters = ctx.bodyAsClass() val payments = searchPayments(filters.common, filters.paymentFilters) - println(payments) + println(payments) val excel = ctx.queryParam("excel") if (excel !== null) { // exportPayments(payments) @@ -949,7 +970,8 @@ object PaymentCtrl { ctx.json(payments).status(HttpStatus.OK) } } - fun update(ctx : Context){ + + 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") @@ -959,20 +981,24 @@ object PaymentCtrl { ctx.json(pmt).status(HttpStatus.OK) } } + object InvoiceCtrl { - fun create(ctx : Context){ - val invoice = ctx.bodyAsClass() - database.save(invoice) - ctx.json(invoice).status(HttpStatus.CREATED) + fun create(ctx: Context) { + val invoice = ctx.bodyAsClass() + database.save(invoice) + ctx.json(invoice).status(HttpStatus.CREATED) } - fun get(ctx : Context){ + + 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){ + + fun getAll(ctx: Context) { val filters = ctx.bodyAsClass() val invoices = searchInvoices(filters.common, filters.invoiceFilters) val excel = ctx.queryParam("excel") @@ -985,7 +1011,8 @@ object InvoiceCtrl { } } - fun update(ctx : Context){ + + 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") @@ -994,7 +1021,8 @@ object InvoiceCtrl { invoice.update() ctx.json(invoice).status(HttpStatus.OK) } - fun getNextNum(ctx : Context){ + + fun getNextNum(ctx: Context) { val prefix = "INV/" val cnt = database.find(Invoice::class.java) .findCount() diff --git a/src/main/kotlin/com/restapi/controllers/Filters.kt b/src/main/kotlin/com/restapi/controllers/Filters.kt index e8473c5..10561c2 100644 --- a/src/main/kotlin/com/restapi/controllers/Filters.kt +++ b/src/main/kotlin/com/restapi/controllers/Filters.kt @@ -2,7 +2,6 @@ package com.restapi.controllers import com.restapi.domain.* import com.restapi.domain.Session.database -import org.checkerframework.checker.index.qual.LessThan import java.time.LocalDate //constants diff --git a/src/main/kotlin/com/restapi/domain/models.kt b/src/main/kotlin/com/restapi/domain/models.kt index 90fc108..2939751 100644 --- a/src/main/kotlin/com/restapi/domain/models.kt +++ b/src/main/kotlin/com/restapi/domain/models.kt @@ -268,8 +268,8 @@ open class Vendor : BaseTenantModel() { var gstNumber: String = "" var address: String = "" var rating: Double = 0.0 - var outstanding: Double?=0.0 - var asOnWhichDate: LocalDate?=null + var outstanding: Double? = 0.0 + var asOnWhichDate: LocalDate? = null @DbJsonB var contacts: List = mutableListOf() @@ -370,7 +370,7 @@ open class Quotation : BaseTenantModel() { @DbArray var documents: List? = arrayListOf() - var taxesIncluded: Boolean ?= null + var taxesIncluded: Boolean? = null } enum class DocType { @@ -464,12 +464,13 @@ open class OutgoingInventory : BaseTenantModel() { var vehicle: String? = null } -enum class InvoiceStatus{ +enum class InvoiceStatus { PAID_FULL, PAID_SOME, PAID_NONE, ALL } + @Entity -open class Invoice : BaseTenantModel() { - fun patchValues(updated : Invoice) { +open class Invoice : BaseTenantModel() { + fun patchValues(updated: Invoice) { this.date = updated.date this.number = updated.number this.totalAmount = updated.totalAmount @@ -478,32 +479,40 @@ open class Invoice : BaseTenantModel() { this.vendor = updated.vendor this.status = updated.status } + var number: String = "" - var date: LocalDate?=null - var totalAmount : Double=0.0 - var poNum:String?=null + var date: LocalDate? = null + var totalAmount: Double = 0.0 + var poNum: String? = null + @DbJsonB - var products: List ?= null + var products: List? = null + @ManyToOne var vendor: Vendor? = null + @Enumerated(EnumType.STRING) - var status:InvoiceStatus?=null + var status: InvoiceStatus? = null } @Entity open class Payment : BaseTenantModel() { - fun patchValues(updated : Payment){ + 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 + var refNumber: String = "" + var amount: Double = 0.0 + var date: LocalDate? = null + var remark: String? = null + var excessAmount : Double ?= null + + @DbJsonB + var invoicesAffected: Map? = null @ManyToOne - var vendor:Vendor?=null + var vendor: Vendor? = null } \ No newline at end of file diff --git a/src/main/resources/dbmigration/1.13.sql b/src/main/resources/dbmigration/1.13.sql new file mode 100644 index 0000000..14bcec6 --- /dev/null +++ b/src/main/resources/dbmigration/1.13.sql @@ -0,0 +1,3 @@ +-- apply alter tables +alter table payment add column if not exists excess_amount float; +alter table payment add column if not exists invoices_affected jsonb; diff --git a/src/main/resources/dbmigration/model/1.13.model.xml b/src/main/resources/dbmigration/model/1.13.model.xml new file mode 100644 index 0000000..ce5afcf --- /dev/null +++ b/src/main/resources/dbmigration/model/1.13.model.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file