diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailTemplateService.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailTemplateService.kt index f4348da..3261d7a 100644 --- a/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailTemplateService.kt +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailTemplateService.kt @@ -24,7 +24,15 @@ open class MailTemplateService( private val inventoryLotService: InventoryLotService, private val qcResultService: QcResultService ) { + data class MailTemplateHtml ( + val to: String = "", + val subject: String = "", + val content: String = "", + val filename: String = "", + ) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + fun allMailTemplates(): List { return mailTemplateRepository.findAllByDeletedIsFalse(); } @@ -80,8 +88,57 @@ open class MailTemplateService( mailTemplateRepository.saveAll(mailTemplates) } - fun getMailTemplateForStockInLine(stockInLineId: Long): DownloadMailTemplateResponse { - val emailTemplate = findByCode("RM-01") ?: throw NoSuchElementException("No RP-01 Email Template") + // ------------------------------------------- Stock In Line - Mail Template ------------------------------------------- // + data class MailTemplateForStockInLineArgs( + val supplierEmail: String = "", + val supplierName: String = "", + val dnNo: String = "", + val dnDate: String = "", + val poNo: String = "", + val supplierId: String = "", + val itemNo: String = "", + val itemName: String = "", + val itemQty: String = "", + val uom: String = "", + val planDnDate: String = "", + val unitPrice: String = "", + val receivedCompany: String = "", + val lotNo: String = "", + val qcResult: String = "", + val receivedQty: String = "", + val nonDelieveredQty: String = "", + val rejectedQty: String = "", + val qcDate: String = "" + ) { + fun applyToTemplate(template: String?): String { + val content = template ?: "N/A" + val args = mapOf( + "\${supplierName}" to supplierName, + "\${dnNo}" to dnNo, + "\${dnDate}" to dnDate, + "\${poNo}" to poNo, + "\${supplierId}" to supplierId, + "\${itemNo}" to itemNo, + "\${itemName}" to itemName, + "\${itemQty}" to itemQty, + "\${uom}" to uom, + "\${planDnDate}" to planDnDate, + "\${unitPrice}" to unitPrice, + "\${receivedCompany}" to receivedCompany, + "\${lotNo}" to lotNo, + "\${qcResult}" to qcResult, + "\${receivedQty}" to receivedQty, + "\${nonDelieveredQty}" to nonDelieveredQty, + "\${rejectedQty}" to rejectedQty, + "\${qcDate}" to qcDate + ) + return args.entries.fold(content) { acc, (key, value) -> + acc.replace(key, value) + } + } + } + + fun getMailTemplateArgsForStockInLine(stockInLineId: Long): MailTemplateForStockInLineArgs { val stockInLine = stockInLineRepository.findById(stockInLineId).getOrNull() ?: throw NoSuchElementException("Cant find this stock in line.") // Value @@ -90,7 +147,7 @@ open class MailTemplateService( val pol = stockInLine.purchaseOrderLine val item = stockInLine.item val supplierName = po?.supplier?.name ?: "N/A" - val supplierEmail = if((po?.supplier?.contactEmail).isNullOrEmpty()) "N/A" else po?.supplier?.contactEmail + val supplierEmail = (if((po?.supplier?.contactEmail).isNullOrEmpty()) "N/A" else po?.supplier?.contactEmail) ?: "N/A" val dnNo = stockInLine.dnNo ?: "N/A" val dnDate = formatter.format(stockInLine.dnDate) ?: "N/A" val poNo = po?.code ?: "N/A" @@ -120,50 +177,92 @@ open class MailTemplateService( val element = tempDoc.appendElement("ul") for (result in filteredResult) { element.appendElement("li") - .text("${result.name} - ${result.description}") + .text("${result.code} - ${result.name}") } tempDoc.outerHtml() } else { "N/A" } } ?: "N/A" - val rejectedQty = (stockInLine.acceptedQty ?: zero).minus(stockInLine.demandQty ?: zero).toString() // reject? - val acceptedQty = (stockInLine.acceptedQty ?: zero).toString() + val rejectedQty = (stockInLine.acceptedQty ?: zero).minus(stockInLine.demandQty ?: zero).toString() // = reject qty + val receivedQty = (stockInLine.acceptedQty ?: zero).toString() // = received qty val nonDelieveredQty = (zero).toString() + // Final + val args = MailTemplateForStockInLineArgs( + supplierEmail = supplierEmail, + supplierName = supplierName, + dnNo = dnNo, + dnDate = dnDate, + poNo = poNo, + supplierId = supplierId, + itemNo = itemNo, + itemName = itemName, + itemQty = itemQty, + uom = uom, + planDnDate = planDnDate, + unitPrice = unitPrice, + receivedCompany = receivedCompany, + lotNo = lotNo, + qcResult = qcResult, + receivedQty = receivedQty, + nonDelieveredQty = nonDelieveredQty, + rejectedQty = rejectedQty, + qcDate = qcDate + ); + + return args; + } + + fun getMailTemplateHtmlForStockInLine(stockInLineId: Long): MailTemplateHtml { + val emailTemplate = findByCode("RM-01") ?: throw NoSuchElementException("No RM-01 Email Template"); + val args = getMailTemplateArgsForStockInLine(stockInLineId); + // HTML - val to = supplierEmail + val to = args.supplierEmail val toHtmlStr = Jsoup.parse("").appendElement("p").text("To: $to").outerHtml() - val subject = (emailTemplate.subjectCht ?: "N/A") -// .replace("{supplierName}", supplierName) - .replace("{poNo}", poNo) - .replace("{itemNo}", itemNo) + val subject = args.applyToTemplate(emailTemplate.subjectCht ?: "N/A") +// .replace("\${supplierName}", supplierName) +// .replace("\${poNo}", poNo) +// .replace("\${itemNo}", itemNo) val subjectHtmlStr = Jsoup.parse("").appendElement("p").text("Subject: $subject").outerHtml() - val content = (emailTemplate.contentCht ?: "N/A") - .replace("{supplierName}", supplierName) - .replace("{dnNo}", dnNo) - .replace("{dnDate}", dnDate) - .replace("{poNo}", poNo) - .replace("{supplierId}", supplierId) - .replace("{itemNo}", itemNo) - .replace("{itemName}", itemName) - .replace("{itemQty}", itemQty) - .replace("{uom}", uom) - .replace("{planDnDate}", planDnDate) - .replace("{unitPrice}", unitPrice) - .replace("{receivedCompany}", receivedCompany) - .replace("{lotNo}", lotNo) - .replace("{qcResult}", qcResult) - .replace("{acceptedQty}", acceptedQty) - .replace("{nonDelieveredQty}", nonDelieveredQty) - .replace("{rejectedQty}", rejectedQty) - .replace("{qcDate}", qcDate) - val contentHtmlStr = Jsoup.parse("").appendElement("p").append("Content: $content").outerHtml() + val content = args.applyToTemplate(emailTemplate.contentCht ?: "N/A") +// .replace("\${supplierName}", supplierName) +// .replace("\${dnNo}", dnNo) +// .replace("\${dnDate}", dnDate) +// .replace("\${poNo}", poNo) +// .replace("\${supplierId}", supplierId) +// .replace("\${itemNo}", itemNo) +// .replace("\${itemName}", itemName) +// .replace("\${itemQty}", itemQty) +// .replace("\${uom}", uom) +// .replace("\${planDnDate}", planDnDate) +// .replace("\${unitPrice}", unitPrice) +// .replace("\${receivedCompany}", receivedCompany) +// .replace("\${lotNo}", lotNo) +// .replace("\${qcResult}", qcResult) +// .replace("\${acceptedQty}", receivedQty) +// .replace("\${nonDelieveredQty}", nonDelieveredQty) +// .replace("\${rejectedQty}", rejectedQty) +// .replace("\${qcDate}", qcDate) + val contentHtmlStr = Jsoup.parse("").appendElement("p").append("Content: $content").outerHtml(); // Result - val resultHtmlStr = toHtmlStr + subjectHtmlStr + contentHtmlStr + val resultHtmlStr = toHtmlStr + subjectHtmlStr + contentHtmlStr; + + return MailTemplateHtml( + to = toHtmlStr, + subject = subjectHtmlStr, + content = contentHtmlStr, + filename = subject, + ); + } + + fun getMailTemplatePdfForStockInLine(stockInLineId: Long): DownloadMailTemplateResponse { + val htmlMailTemplate = getMailTemplateHtmlForStockInLine(stockInLineId) + val resultHtmlStr = htmlMailTemplate.to + htmlMailTemplate.subject + htmlMailTemplate.content // println(resultHtmlStr) val resultPdf = ByteArrayOutputStream() @@ -178,7 +277,7 @@ open class MailTemplateService( return DownloadMailTemplateResponse( file = resultPdf.toByteArray(), - fileName = subject + fileName = htmlMailTemplate.filename ); } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailTemplateController.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailTemplateController.kt index 63b80f2..ab034c2 100644 --- a/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailTemplateController.kt +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailTemplateController.kt @@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -import java.net.URLEncoder @RequestMapping("/mailTemplates") @RestController @@ -28,9 +27,9 @@ class MailTemplateController( return mailTemplateService.saveMailTemplate(request); } - @GetMapping("/getMailTemplateForStockInLine/{stockInLineId}") - fun getMailTemplateForStockInLine(@PathVariable stockInLineId: Long): ResponseEntity { - val response = mailTemplateService.getMailTemplateForStockInLine(stockInLineId) + @GetMapping("/getMailTemplatePdfForStockInLine/{stockInLineId}") + fun getMailTemplatePdfForStockInLine(@PathVariable stockInLineId: Long): ResponseEntity { + val response = mailTemplateService.getMailTemplatePdfForStockInLine(stockInLineId) val headers = HttpHeaders().apply { contentType = MediaType.APPLICATION_PDF // add("Content-Disposition", "attachment; filename=${response.fileName}") diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt index be5ab3e..8d34fd4 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderRepository.kt @@ -2,6 +2,8 @@ package com.ffii.fpsms.modules.deliveryOrder.entity import com.ffii.core.support.AbstractRepository import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo +import com.ffii.fpsms.modules.master.entity.projections.SearchId +import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository import java.io.Serializable @@ -12,4 +14,12 @@ interface DeliveryOrderRepository : AbstractRepository { fun findDeliveryOrderInfoByDeletedIsFalse(): List fun findByIdAndDeletedIsFalse(id: Serializable): DeliveryOrder? + + fun findAllByCodeAndDeletedIsFalse(code: String): List + + + + + + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt index b8a98be..4d51b86 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/models/DeliveryOrderInfo.kt @@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.deliveryOrder.entity.models import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderLine import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatusConverter +import com.ffii.fpsms.modules.master.entity.Shop import jakarta.persistence.Convert import org.springframework.beans.factory.annotation.Value import java.time.LocalDateTime @@ -11,6 +12,7 @@ interface DeliveryOrderInfo{ val id: Long val code: String val orderDate: LocalDateTime? + val estimatedArrivalDate: LocalDateTime? @get:Value("#{target.status.value}") val status: String? @@ -18,6 +20,11 @@ interface DeliveryOrderInfo{ @get:Value("#{target.shop?.name}") val shopName: String? + @get:Value("#{target.supplier?.name}") + val supplierName: String? + val deliveryOrderLines: List + + } diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt index 2ef0a3a..5a53eee 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt @@ -11,8 +11,6 @@ import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderResponse import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderStatusRequest import com.ffii.fpsms.modules.master.service.CurrencyService import com.ffii.fpsms.modules.master.service.ShopService -import com.ffii.fpsms.modules.master.web.models.MessageResponse -import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus import com.ffii.fpsms.modules.user.entity.UserRepository import com.ffii.fpsms.modules.user.service.UserService import org.springframework.stereotype.Service @@ -44,6 +42,11 @@ open class DeliveryOrderService( return deliveryOrderRepository.findByIdAndDeletedIsFalse(id); } + open fun searchByCode(code: String) : List { + return deliveryOrderRepository.findAllByCodeAndDeletedIsFalse(code); + } + + open fun updateDeliveryOrderStatus(request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { val deliveryOrder = checkNotNull( request.id?.let { deliveryOrderRepository.findById(it).getOrNull() } diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt index ca14dfe..cf855f3 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt @@ -30,6 +30,11 @@ class DeliveryOrderController( return deliveryOrderService.getDetailedDo(id); } + @GetMapping("/search-code/{code}") + fun searchByCode(@PathVariable code: String): List{ + return deliveryOrderService.searchByCode(code); + } + @PostMapping("/update-status") fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { return deliveryOrderService.updateDeliveryOrderStatus(request); diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockInLineInfo.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockInLineInfo.kt index a7bd82a..cb99d02 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockInLineInfo.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockInLineInfo.kt @@ -44,6 +44,7 @@ interface StockInLineInfo { val itemType: String val dnNo: String val dnDate: LocalDateTime? + val qcDecision: LocalDateTime? @get:Value("#{target.escalationLog.^[status.value == 'pending']?.handler?.id}") val handlerId: Long? @get:Value("#{target.inventoryLot?.inventoryLotLines ?: new java.util.ArrayList()}") diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt index 0d0a9a4..4b90c05 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt @@ -378,8 +378,7 @@ open class StockInLineService( BigDecimal.ONE } -// if (inventoryLotLines.sumOf { it.inQty ?: BigDecimal.ZERO } >= request.acceptQty?.times(ratio)) { - if (request.inventoryLotLines?.isEmpty() == true) { // Clicked proceed in PO Modal -- TODO improve + if (inventoryLotLines.sumOf { it.inQty ?: BigDecimal.ZERO } >= request.acceptQty?.times(ratio)) { stockInLine.apply { this.status = if (request.acceptQty?.compareTo(request.acceptedQty) == 0) StockInLineStatus.COMPLETE.status else StockInLineStatus.PARTIALLY_COMPLETE.status diff --git a/src/main/resources/application-db-local.yml b/src/main/resources/application-db-local.yml index a9c01bf..4fa8584 100644 --- a/src/main/resources/application-db-local.yml +++ b/src/main/resources/application-db-local.yml @@ -1,5 +1,5 @@ spring: datasource: - jdbc-url: jdbc:mysql://127.0.0.1:3308/fpsmsdb?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2B8 + jdbc-url: jdbc:mysql://127.0.0.1:3306/fpsmsdb?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2B8 username: root password: secret \ No newline at end of file