# Conflicts: # src/main/java/com/ffii/fpsms/modules/user/web/UserController.javamaster
| @@ -9,4 +9,6 @@ interface MailTemplateRepository : AbstractRepository<MailTemplate, Long> { | |||||
| fun findAllByDeletedIsFalse(): List<MailTemplate> | fun findAllByDeletedIsFalse(): List<MailTemplate> | ||||
| fun findByIdAndDeletedIsFalse(id: Serializable): MailTemplate? | fun findByIdAndDeletedIsFalse(id: Serializable): MailTemplate? | ||||
| fun findByCodeAndDeletedIsFalse(code: String): MailTemplate? | |||||
| } | } | ||||
| @@ -2,13 +2,29 @@ package com.ffii.fpsms.modules.common.mail.service | |||||
| import com.ffii.fpsms.modules.common.mail.entity.MailTemplate | import com.ffii.fpsms.modules.common.mail.entity.MailTemplate | ||||
| import com.ffii.fpsms.modules.common.mail.entity.MailTemplateRepository | import com.ffii.fpsms.modules.common.mail.entity.MailTemplateRepository | ||||
| import com.ffii.fpsms.modules.common.mail.web.models.DownloadMailTemplateResponse | |||||
| import com.ffii.fpsms.modules.common.mail.web.models.MailTemplateRequest | import com.ffii.fpsms.modules.common.mail.web.models.MailTemplateRequest | ||||
| import com.ffii.fpsms.modules.qc.service.QcResultService | |||||
| import com.ffii.fpsms.modules.stock.entity.StockInLineRepository | |||||
| import com.ffii.fpsms.modules.stock.service.InventoryLotService | |||||
| import com.itextpdf.html2pdf.ConverterProperties | |||||
| import com.itextpdf.html2pdf.HtmlConverter | |||||
| import com.itextpdf.layout.font.FontProvider | |||||
| import org.jsoup.Jsoup | |||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
| import java.io.ByteArrayOutputStream | |||||
| import java.math.BigDecimal | |||||
| import java.time.format.DateTimeFormatter | |||||
| import kotlin.jvm.optionals.getOrNull | |||||
| @Service | @Service | ||||
| open class MailTemplateService( | open class MailTemplateService( | ||||
| private val mailTemplateRepository: MailTemplateRepository, | private val mailTemplateRepository: MailTemplateRepository, | ||||
| private val stockInLineRepository: StockInLineRepository, | |||||
| private val inventoryLotService: InventoryLotService, | |||||
| private val qcResultService: QcResultService | |||||
| ) { | ) { | ||||
| val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") | |||||
| fun allMailTemplates(): List<MailTemplate> { | fun allMailTemplates(): List<MailTemplate> { | ||||
| return mailTemplateRepository.findAllByDeletedIsFalse(); | return mailTemplateRepository.findAllByDeletedIsFalse(); | ||||
| } | } | ||||
| @@ -17,6 +33,10 @@ open class MailTemplateService( | |||||
| return mailTemplateRepository.findByIdAndDeletedIsFalse(id); | return mailTemplateRepository.findByIdAndDeletedIsFalse(id); | ||||
| } | } | ||||
| fun findByCode(code: String): MailTemplate? { | |||||
| return mailTemplateRepository.findByCodeAndDeletedIsFalse(code); | |||||
| } | |||||
| fun saveMailTemplate(request: MailTemplateRequest): MailTemplate { | fun saveMailTemplate(request: MailTemplateRequest): MailTemplate { | ||||
| val mailTemplate = request.id?.let { findById(it) } ?: MailTemplate() | val mailTemplate = request.id?.let { findById(it) } ?: MailTemplate() | ||||
| @@ -59,4 +79,102 @@ open class MailTemplateService( | |||||
| mailTemplateRepository.saveAll(mailTemplates) | mailTemplateRepository.saveAll(mailTemplates) | ||||
| } | } | ||||
| fun getMailTemplateForStockInLine(stockInLineId: Long): DownloadMailTemplateResponse { | |||||
| val emailTemplate = findByCode("RM-01") ?: throw NoSuchElementException("No RP-01 Email Template") | |||||
| val stockInLine = stockInLineRepository.findById(stockInLineId).getOrNull() ?: throw NoSuchElementException("Cant find this stock in line.") | |||||
| // Value | |||||
| val zero = BigDecimal.ZERO | |||||
| val po = stockInLine.purchaseOrder | |||||
| 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 dnDate = formatter.format(stockInLine.dnDate) ?: "N/A" | |||||
| val poNo = po?.code ?: "N/A" | |||||
| val supplierId = po?.supplier?.code ?: "N/A" // Id? | |||||
| val itemNo = item?.code ?: "N/A" | |||||
| val itemQty = (pol?.qty ?: zero).toString() | |||||
| val uom = pol?.uom?.udfudesc ?: "N/A" | |||||
| val planDnDate = po?.estimatedArrivalDate?.let { formatter.format(it) } ?: "N/A" | |||||
| val unitPrice = (pol?.up ?: zero).toString() | |||||
| val receivedCompany = po?.shop?.name ?: "N/A" | |||||
| val lotNo = stockInLine.productLotNo ?: "N/A" | |||||
| var qcDate = "N/A" | |||||
| val qcResult = qcResultService.getAllQcResultInfoByStockInLineId(stockInLineId).let { qcResults -> | |||||
| val filteredResult = qcResults | |||||
| .groupBy { Pair(it.stockInLineId, it.qcItemId) } | |||||
| .mapValues { (_, group) -> | |||||
| group.maxByOrNull { it.recordDate } | |||||
| } | |||||
| .values | |||||
| .filterNotNull() | |||||
| .filter { !it.qcPassed } | |||||
| if (filteredResult.isNotEmpty()) { | |||||
| qcDate = formatter.format(filteredResult.maxOf { it.recordDate }) | |||||
| val tempDoc = Jsoup.parse("") | |||||
| val element = tempDoc.appendElement("ul") | |||||
| for (result in filteredResult) { | |||||
| element.appendElement("li") | |||||
| .text("${result.name} - ${result.description}") | |||||
| } | |||||
| tempDoc.outerHtml() | |||||
| } else { | |||||
| "N/A" | |||||
| } | |||||
| } ?: "N/A" | |||||
| val acceptedQty = (stockInLine.acceptedQty ?: zero).minus(stockInLine.demandQty ?: zero).toString() | |||||
| val rejectedQty = (stockInLine.demandQty ?: zero).toString() // reject? | |||||
| val nonDelieveredQty = (zero).toString() | |||||
| // HTML | |||||
| val to = 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 subjectHtmlStr = Jsoup.parse("").appendElement("p").text("Subject: $subject").outerHtml() | |||||
| val content = (emailTemplate.contentCht ?: "N/A") | |||||
| .replace("{supplierName}", supplierName) | |||||
| .replace("{dnDate}", dnDate) | |||||
| .replace("{poNo}", poNo) | |||||
| .replace("{supplierId}", supplierId) | |||||
| .replace("{itemNo}", itemNo) | |||||
| .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() | |||||
| // Result | |||||
| val resultHtmlStr = toHtmlStr + subjectHtmlStr + contentHtmlStr | |||||
| // println(resultHtmlStr) | |||||
| val resultPdf = ByteArrayOutputStream() | |||||
| val fp = FontProvider(); | |||||
| fp.addStandardPdfFonts() | |||||
| fp.addFont("/fonts/msjh_0.ttf") | |||||
| val converterProperties = ConverterProperties() | |||||
| converterProperties.apply { | |||||
| fontProvider = fp | |||||
| } | |||||
| HtmlConverter.convertToPdf(resultHtmlStr, resultPdf, converterProperties) | |||||
| return DownloadMailTemplateResponse( | |||||
| file = resultPdf.toByteArray(), | |||||
| fileName = subject ?: "N/A" | |||||
| ); | |||||
| } | |||||
| } | } | ||||
| @@ -3,10 +3,15 @@ package com.ffii.fpsms.modules.common.mail.web | |||||
| import com.ffii.fpsms.modules.common.mail.entity.MailTemplate | import com.ffii.fpsms.modules.common.mail.entity.MailTemplate | ||||
| import com.ffii.fpsms.modules.common.mail.web.models.MailTemplateRequest | import com.ffii.fpsms.modules.common.mail.web.models.MailTemplateRequest | ||||
| import com.ffii.fpsms.modules.common.mail.service.MailTemplateService | import com.ffii.fpsms.modules.common.mail.service.MailTemplateService | ||||
| import org.springframework.http.HttpHeaders | |||||
| import org.springframework.http.MediaType | |||||
| import org.springframework.http.ResponseEntity | |||||
| import org.springframework.web.bind.annotation.GetMapping | import org.springframework.web.bind.annotation.GetMapping | ||||
| import org.springframework.web.bind.annotation.PathVariable | |||||
| import org.springframework.web.bind.annotation.PostMapping | import org.springframework.web.bind.annotation.PostMapping | ||||
| import org.springframework.web.bind.annotation.RequestMapping | import org.springframework.web.bind.annotation.RequestMapping | ||||
| import org.springframework.web.bind.annotation.RestController | import org.springframework.web.bind.annotation.RestController | ||||
| import java.net.URLEncoder | |||||
| @RequestMapping("/mailTemplates") | @RequestMapping("/mailTemplates") | ||||
| @RestController | @RestController | ||||
| @@ -22,4 +27,18 @@ class MailTemplateController( | |||||
| fun saveMailTemplate(request: MailTemplateRequest): MailTemplate { | fun saveMailTemplate(request: MailTemplateRequest): MailTemplate { | ||||
| return mailTemplateService.saveMailTemplate(request); | return mailTemplateService.saveMailTemplate(request); | ||||
| } | } | ||||
| @GetMapping("/getMailTemplateForStockInLine/{stockInLineId}") | |||||
| fun getMailTemplateForStockInLine(@PathVariable stockInLineId: Long): ResponseEntity<ByteArray> { | |||||
| val response = mailTemplateService.getMailTemplateForStockInLine(stockInLineId) | |||||
| val headers = HttpHeaders().apply { | |||||
| contentType = MediaType.APPLICATION_PDF | |||||
| // add("Content-Disposition", "attachment; filename=${response.fileName}") | |||||
| add("filename", "${response.fileName}.pdf") | |||||
| } | |||||
| return ResponseEntity.ok() | |||||
| .headers(headers) | |||||
| .body(response.file) | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,24 @@ | |||||
| package com.ffii.fpsms.modules.common.mail.web.models | |||||
| data class DownloadMailTemplateResponse( | |||||
| val file: ByteArray, | |||||
| val fileName: String, | |||||
| ) { | |||||
| override fun equals(other: Any?): Boolean { | |||||
| if (this === other) return true | |||||
| if (javaClass != other?.javaClass) return false | |||||
| other as DownloadMailTemplateResponse | |||||
| if (!file.contentEquals(other.file)) return false | |||||
| if (fileName != other.fileName) return false | |||||
| return true | |||||
| } | |||||
| override fun hashCode(): Int { | |||||
| var result = file.contentHashCode() | |||||
| result = 31 * result + fileName.hashCode() | |||||
| return result | |||||
| } | |||||
| } | |||||
| @@ -37,4 +37,8 @@ open class QcResult: BaseEntity<Long>() { | |||||
| @Column(name = "remarks") | @Column(name = "remarks") | ||||
| open var remarks: String? = null | open var remarks: String? = null | ||||
| @NotNull | |||||
| @Column(name = "qcPassed") | |||||
| open var qcPassed: Boolean = true | |||||
| } | } | ||||
| @@ -1,18 +1,25 @@ | |||||
| package com.ffii.fpsms.modules.qc.entity.projection | package com.ffii.fpsms.modules.qc.entity.projection | ||||
| import org.springframework.beans.factory.annotation.Value | import org.springframework.beans.factory.annotation.Value | ||||
| import java.time.LocalDateTime | |||||
| interface QcResultInfo { | interface QcResultInfo { | ||||
| val id: Long | val id: Long | ||||
| @get:Value("#{target.qcItem.id}") | |||||
| val qcItemId: Long | |||||
| @get:Value("#{target.qcItem.name}") | |||||
| val name: String | |||||
| @get:Value("#{target.qcItem.code}") | |||||
| val code: String | |||||
| @get:Value("#{target.qcItem?.id}") | |||||
| val qcItemId: Long? | |||||
| @get:Value("#{target.qcItem?.code}") | |||||
| val code: String? | |||||
| @get:Value("#{target.qcItem?.name}") | |||||
| val name: String? | |||||
| @get:Value("#{target.qcItem?.description}") | |||||
| val description: String? | |||||
| val remarks: String? | |||||
| @get:Value("#{target.stockInLine?.id}") | @get:Value("#{target.stockInLine?.id}") | ||||
| val stockInLineId: Long? | val stockInLineId: Long? | ||||
| @get:Value("#{target.stockOutLine?.id}") | @get:Value("#{target.stockOutLine?.id}") | ||||
| val stockOutLineId: Long? | val stockOutLineId: Long? | ||||
| val failQty: Double | |||||
| val failQty: Double? | |||||
| val qcPassed: Boolean | |||||
| @get:Value("#{target.modified}") | |||||
| val recordDate: LocalDateTime | |||||
| } | } | ||||
| @@ -42,6 +42,7 @@ open class QcResultService( | |||||
| this.failQty = request.failQty | this.failQty = request.failQty | ||||
| this.type = request.type | this.type = request.type | ||||
| this.remarks = request.remarks | this.remarks = request.remarks | ||||
| this.qcPassed = request.qcPassed | |||||
| } | } | ||||
| val savedQcResult = saveAndFlush(qcResult) | val savedQcResult = saveAndFlush(qcResult) | ||||
| return MessageResponse( | return MessageResponse( | ||||
| @@ -7,6 +7,7 @@ data class SaveQcResultRequest( | |||||
| val stockInLineId: Long?, | val stockInLineId: Long?, | ||||
| val stockOutLineId: Long?, | val stockOutLineId: Long?, | ||||
| val failQty: Double, | val failQty: Double, | ||||
| val qcPassed: Boolean, | |||||
| val type: String?, | val type: String?, | ||||
| val remarks: String?, | val remarks: String?, | ||||
| ) | ) | ||||
| @@ -1,6 +1,8 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | package com.ffii.fpsms.modules.stock.entity | ||||
| import com.ffii.core.entity.BaseEntity | import com.ffii.core.entity.BaseEntity | ||||
| import com.ffii.fpsms.modules.stock.enums.EscalationLogStatus | |||||
| import com.ffii.fpsms.modules.stock.enums.EscalationLogStatusConverter | |||||
| import com.ffii.fpsms.modules.user.entity.User | import com.ffii.fpsms.modules.user.entity.User | ||||
| import jakarta.persistence.* | import jakarta.persistence.* | ||||
| import jakarta.validation.constraints.NotNull | import jakarta.validation.constraints.NotNull | ||||
| @@ -8,15 +10,14 @@ import jakarta.validation.constraints.Size | |||||
| import java.time.LocalDateTime | import java.time.LocalDateTime | ||||
| @Entity | @Entity | ||||
| @Table(name = "supervision_approval_log") | |||||
| open class SupervisionApprovalLog : BaseEntity<Long>() { | |||||
| @Table(name = "escalation_log") | |||||
| open class EscalationLog : BaseEntity<Long>() { | |||||
| @NotNull | @NotNull | ||||
| @ManyToOne | @ManyToOne | ||||
| @JoinColumn(name = "personInCharge", nullable = false, referencedColumnName = "id") | |||||
| open var personInCharge: User? = null | |||||
| @JoinColumn(name = "handlerId", nullable = false, referencedColumnName = "id") | |||||
| open var handler: User? = null | |||||
| @Size(max = 100) | @Size(max = 100) | ||||
| @NotNull | |||||
| @Column(name = "type", nullable = false, length = 100) | @Column(name = "type", nullable = false, length = 100) | ||||
| open var type: String? = null | open var type: String? = null | ||||
| @@ -31,13 +32,19 @@ open class SupervisionApprovalLog : BaseEntity<Long>() { | |||||
| @Column(name = "recordDate") | @Column(name = "recordDate") | ||||
| open var recordDate: LocalDateTime? = null | open var recordDate: LocalDateTime? = null | ||||
| @Size(max = 100) | |||||
| @NotNull | @NotNull | ||||
| @Convert(converter = EscalationLogStatusConverter::class) | |||||
| @Column(name = "status", nullable = false, length = 100) | @Column(name = "status", nullable = false, length = 100) | ||||
| open var status: String? = null | |||||
| open var status: EscalationLogStatus? = null | |||||
| @Size(max = 500) | @Size(max = 500) | ||||
| @NotNull | @NotNull | ||||
| @Column(name = "reason", nullable = false, length = 500) | @Column(name = "reason", nullable = false, length = 500) | ||||
| open var reason: String? = null | open var reason: String? = null | ||||
| @Column(name = "qcTotalCount") | |||||
| open var qcTotalCount: Int? = null | |||||
| @Column(name = "qcFailCount") | |||||
| open var qcFailCount: Int? = null | |||||
| } | } | ||||
| @@ -0,0 +1,71 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | |||||
| import org.springframework.beans.factory.annotation.Value | |||||
| import java.math.BigDecimal | |||||
| import java.time.LocalDateTime | |||||
| interface EscalationLogInfo { | |||||
| val id: Long? | |||||
| @get:Value("#{target.stockInLine?.stockIn?.purchaseOrder?.id}") | |||||
| val poId: Long? | |||||
| @get:Value("#{target.stockInLine?.purchaseOrderLine?.id}") | |||||
| val polId: Long? | |||||
| @get:Value("#{target.stockInLine?.stockIn?.code}") | |||||
| val poCode: String? | |||||
| @get:Value("#{target.stockInLine?.id}") | |||||
| val stockInLineId: Long? | |||||
| @get:Value("#{target.stockOutLine?.id}") | |||||
| val stockOutLineId: Long? | |||||
| @get:Value("#{target.stockInLine?.dnNo}") | |||||
| val dnNo: String? | |||||
| @get:Value("#{target.stockInLine?.dnDate}") | |||||
| val dnDate: LocalDateTime? | |||||
| @get:Value("#{target.stockInLine?.item?.code}") | |||||
| val itemCode: String? | |||||
| @get:Value("#{target.stockInLine?.item?.name}") | |||||
| val itemName: String? | |||||
| @get:Value("#{target.stockInLine?.demandQty}") | |||||
| val demandQty: BigDecimal? | |||||
| @get:Value("#{target.stockInLine?.acceptedQty}") | |||||
| val acceptedQty: BigDecimal? | |||||
| @get:Value("#{target.stockInLine?.item?.itemUoms.^[purchaseUnit == true && deleted == false]?.uom.code}") | |||||
| val purchaseUomCode: String? | |||||
| @get:Value("#{target.stockInLine?.item?.itemUoms.^[purchaseUnit == true && deleted == false]?.uom.udfudesc}") | |||||
| val purchaseUomDesc: String? | |||||
| @get:Value("#{target.stockInLine?.item?.itemUoms.^[stockUnit == true && deleted == false]?.uom.code}") | |||||
| val stockUomCode: String? | |||||
| @get:Value("#{target.stockInLine?.item?.itemUoms.^[stockUnit == true && deleted == false]?.uom.udfudesc}") | |||||
| val stockUomDesc: String? | |||||
| @get:Value("#{target.handler?.id}") | |||||
| val handlerId: Long? | |||||
| @get:Value("#{target.handler?.department} - #{target.handler?.title} - #{target.handler?.name}") | |||||
| val handler: String? | |||||
| @get:Value("#{target.handler?.name}") | |||||
| val handlerName: String? | |||||
| @get:Value("#{target.handler?.title}") | |||||
| val handlerTitle: String? | |||||
| @get:Value("#{target.handler?.department}") | |||||
| val handlerDepartment: String? | |||||
| // @get:Value("#{target.type}") | |||||
| // val escalationLevel: String | |||||
| val qcTotalCount: Int?; | |||||
| val qcFailCount: Int?; | |||||
| val reason: String?; | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | |||||
| import com.ffii.core.support.AbstractRepository | |||||
| import org.springframework.stereotype.Repository | |||||
| import java.io.Serializable | |||||
| @Repository | |||||
| interface EscalationLogRepository: AbstractRepository<EscalationLog, Long> { | |||||
| // fun findAllByHandler(handler: Long): List<SupervisionApprovalLog> | |||||
| fun findAllInfoByDeletedFalse(): List<EscalationLogInfo> | |||||
| fun findAllInfoByDeletedFalseAndStockInLineIdIn(stockInLineIds: List<Serializable>): List<EscalationLogInfo> | |||||
| fun findAllInfoByDeletedFalseAndHandlerIdIs(handlerId: Serializable): List<EscalationLogInfo> | |||||
| } | |||||
| @@ -2,7 +2,9 @@ package com.ffii.fpsms.modules.stock.entity | |||||
| import com.ffii.core.support.AbstractRepository | import com.ffii.core.support.AbstractRepository | ||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||
| import java.io.Serializable | |||||
| @Repository | @Repository | ||||
| interface InventoryLotRepository: AbstractRepository<InventoryLot, Long> { | interface InventoryLotRepository: AbstractRepository<InventoryLot, Long> { | ||||
| fun findByStockInLineIdAndDeletedFalse(stockInLineId: Serializable): InventoryLot? | |||||
| } | } | ||||
| @@ -1,20 +0,0 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | |||||
| import org.springframework.beans.factory.annotation.Value | |||||
| interface SupervisionApprovalLogInfo { | |||||
| val id: Long | |||||
| @get:Value("#{target.stockInLine?.stockIn.purchaseOrder.id}") | |||||
| val poId: Long | |||||
| @get:Value("#{target.stockInLine?.purchaseOrderLine.id}") | |||||
| val polId: Long | |||||
| @get:Value("#{target.stockInLine?.stockIn.code}") | |||||
| val poCode: String | |||||
| @get:Value("#{target.stockInLine?.id}") | |||||
| val stockInLineId: Long | |||||
| @get:Value("#{target.stockInLine?.item.name}") | |||||
| val itemName: String | |||||
| @get:Value("#{target.type}") | |||||
| val escalationLevel: String | |||||
| val reason: String | |||||
| } | |||||
| @@ -1,11 +0,0 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | |||||
| import com.ffii.core.support.AbstractRepository | |||||
| import com.ffii.fpsms.modules.user.entity.User | |||||
| import org.springframework.stereotype.Repository | |||||
| @Repository | |||||
| interface SupervisionApprovalLogRepository: AbstractRepository<SupervisionApprovalLog, Long> { | |||||
| // fun findAllByPersonInCharge(personInCharge: Long): List<SupervisionApprovalLog> | |||||
| fun findAllInfoByDeletedFalse(): List<SupervisionApprovalLogInfo> | |||||
| } | |||||
| @@ -14,17 +14,21 @@ interface InventoryInfo{ | |||||
| @get:Value("#{target.item.type}") | @get:Value("#{target.item.type}") | ||||
| val itemType: String? | val itemType: String? | ||||
| // @get:Value("#{target.qty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | // @get:Value("#{target.qty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | ||||
| @get:Value("#{target.onHandQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.onHandQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{target.onHandQty}") | |||||
| val onHandQty: BigDecimal? | val onHandQty: BigDecimal? | ||||
| @get:Value("#{target.onHoldQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.onHoldQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{target.onHoldQty}") | |||||
| val onHoldQty: BigDecimal? | val onHoldQty: BigDecimal? | ||||
| @get:Value("#{target.unavailableQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{target.unavailableQty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{target.unavailableQty}") | |||||
| val unavailableQty: BigDecimal? | val unavailableQty: BigDecimal? | ||||
| @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty) / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty) / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty)}") | |||||
| val availableQty: BigDecimal? | val availableQty: BigDecimal? | ||||
| @get:Value("#{target.item.itemUoms.^[purchaseUnit == true && deleted == false]?.uom.code}") | |||||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom.code}") | |||||
| val uomCode: String? | val uomCode: String? | ||||
| @get:Value("#{target.item.itemUoms.^[purchaseUnit == true && deleted == false]?.uom.udfudesc}") | |||||
| @get:Value("#{target.item.itemUoms.^[stockUnit == true && deleted == false]?.uom.udfudesc}") | |||||
| val uomUdfudesc: String? | val uomUdfudesc: String? | ||||
| // @get:Value("#{target.qty * target.uom.gramPerSmallestUnit}") | // @get:Value("#{target.qty * target.uom.gramPerSmallestUnit}") | ||||
| // val germPerSmallestUnit: BigDecimal? | // val germPerSmallestUnit: BigDecimal? | ||||
| @@ -26,13 +26,17 @@ interface InventoryLotLineInfo { | |||||
| @get:Value("#{target.inventoryLot.item}") | @get:Value("#{target.inventoryLot.item}") | ||||
| val item: InventoryLotLineItemInfo? | val item: InventoryLotLineItemInfo? | ||||
| val warehouse: InventoryLotLineWarehouseInfo? | val warehouse: InventoryLotLineWarehouseInfo? | ||||
| @get:Value("#{((target.inQty ?: 0) - (target.outQty ?: 0) - (target.holdQty ?: 0)) / (target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{((target.inQty ?: 0) - (target.outQty ?: 0) - (target.holdQty ?: 0)) / (target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{(target.inQty ?: 0) - (target.outQty ?: 0) - (target.holdQty ?: 0)}") | |||||
| var availableQty: BigDecimal? | var availableQty: BigDecimal? | ||||
| @get:Value("#{(target.inQty ?: 0)/ (target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{(target.inQty ?: 0)/ (target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{target.inQty ?: 0}") | |||||
| var inQty: BigDecimal? | var inQty: BigDecimal? | ||||
| @get:Value("#{(target.outQty ?: 0)/ (target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{(target.outQty ?: 0)/ (target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{(target.outQty ?: 0)}") | |||||
| var outQty: BigDecimal? | var outQty: BigDecimal? | ||||
| @get:Value("#{(target.holdQty ?: 0)/ (target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
| // @get:Value("#{(target.holdQty ?: 0)/ (target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.inventoryLot.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | |||||
| @get:Value("#{(target.holdQty ?: 0)}") | |||||
| var holdQty: BigDecimal? | var holdQty: BigDecimal? | ||||
| @get:Value("#{(target.inQty ?: 0) - (target.outQty ?: 0) - (target.holdQty ?: 0)}") | @get:Value("#{(target.inQty ?: 0) - (target.outQty ?: 0) - (target.holdQty ?: 0)}") | ||||
| val qtyPerSmallestUnit: BigDecimal? | val qtyPerSmallestUnit: BigDecimal? | ||||
| @@ -0,0 +1,7 @@ | |||||
| package com.ffii.fpsms.modules.stock.enums | |||||
| enum class EscalationLogStatus(val value: String) { | |||||
| PENDING("pending"), | |||||
| ACCEPTED("accepted"), | |||||
| REJECTED("rejected"), | |||||
| } | |||||
| @@ -0,0 +1,18 @@ | |||||
| package com.ffii.fpsms.modules.stock.enums | |||||
| import jakarta.persistence.AttributeConverter | |||||
| import jakarta.persistence.Converter | |||||
| // Escalation Log Status | |||||
| @Converter(autoApply = true) | |||||
| class EscalationLogStatusConverter : AttributeConverter<EscalationLogStatus, String>{ | |||||
| override fun convertToDatabaseColumn(status: EscalationLogStatus?): String? { | |||||
| return status?.value | |||||
| } | |||||
| override fun convertToEntityAttribute(value: String?): EscalationLogStatus? { | |||||
| return value?.let { v -> | |||||
| EscalationLogStatus.entries.find { it.value == v } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,88 @@ | |||||
| package com.ffii.fpsms.modules.stock.service | |||||
| import com.ffii.core.support.AbstractBaseEntityService | |||||
| import com.ffii.core.support.JdbcDao | |||||
| import com.ffii.fpsms.modules.common.SecurityUtils | |||||
| import com.ffii.fpsms.modules.stock.entity.* | |||||
| import com.ffii.fpsms.modules.stock.enums.EscalationLogStatus | |||||
| import com.ffii.fpsms.modules.stock.web.model.SaveEscalationLogRequest | |||||
| import com.ffii.fpsms.modules.stock.web.model.SaveEscalationLogResponse | |||||
| import com.ffii.fpsms.modules.user.service.UserService | |||||
| import org.springframework.stereotype.Service | |||||
| import kotlin.jvm.optionals.getOrNull | |||||
| @Service | |||||
| open class EscalationLogService( | |||||
| private val jdbcDao: JdbcDao, | |||||
| private val escalationLogRepository: EscalationLogRepository, | |||||
| private val userService: UserService, | |||||
| private val stockInLineService: StockInLineService, | |||||
| private val stockOutLineService: StockOutLineService, | |||||
| private val stockInLineRepository: StockInLineRepository, | |||||
| private val stockOutLIneRepository: StockOutLIneRepository, | |||||
| ): AbstractBaseEntityService<EscalationLog, Long, EscalationLogRepository>(jdbcDao, escalationLogRepository) { | |||||
| open fun getAllLogs(): List<EscalationLog> { | |||||
| return escalationLogRepository.findAll() | |||||
| } | |||||
| open fun getLogsByStockInLines(stockInLineIds: List<Long>?): List<EscalationLogInfo> { | |||||
| val logs = stockInLineIds?.let { escalationLogRepository.findAllInfoByDeletedFalseAndStockInLineIdIn(it) } ?: listOf() | |||||
| return logs | |||||
| } | |||||
| open fun getLogsByStockInLine(stockInLineId: Long?): List<EscalationLogInfo> { | |||||
| val logs = stockInLineId?.let { getLogsByStockInLines(listOf(it)) } ?: listOf() | |||||
| return logs | |||||
| } | |||||
| open fun getLogsByUser(): List<EscalationLogInfo> { | |||||
| val user = SecurityUtils.getUser().orElseThrow() | |||||
| val logs = user.id?.let { escalationLogRepository.findAllInfoByDeletedFalseAndHandlerIdIs(it) } ?: listOf() | |||||
| return logs | |||||
| } | |||||
| open fun saveEscalationLog(request: SaveEscalationLogRequest): SaveEscalationLogResponse{ | |||||
| val escalationLog = request.id?.let { escalationLogRepository.findById(it).getOrNull() } ?: EscalationLog() | |||||
| val handler = request.handlerId.let { userService.getUserById(it) } | |||||
| if (handler == null && escalationLog.handler == null) { | |||||
| throw NoSuchElementException("Person In Charge is null."); | |||||
| } | |||||
| val stockInLine = request.stockInLineId?.let { stockInLineRepository.findById(it).getOrNull() } | |||||
| val stockOutLine = request.stockOutLineId?.let { stockOutLIneRepository.findById(it).getOrNull() } | |||||
| if (stockInLine == null && stockOutLine == null) { | |||||
| throw NoSuchElementException("Both stock in line and stock out line are null."); | |||||
| } | |||||
| val status = request.status.let { status -> EscalationLogStatus.entries.find{ it.value == status} } | |||||
| escalationLog.apply { | |||||
| this.handler = handler | |||||
| type = request.type | |||||
| this.stockInLine = stockInLine | |||||
| this.stockOutLine = stockOutLine | |||||
| recordDate = request.recordDate | |||||
| this.status = status | |||||
| reason = request.reason | |||||
| qcTotalCount = request.qcTotalCount | |||||
| qcFailCount = request.qcFailCount | |||||
| } | |||||
| val response = escalationLogRepository.save(escalationLog).let { | |||||
| SaveEscalationLogResponse( | |||||
| id = it.id, | |||||
| stockInLineId = it.stockInLine?.id, | |||||
| stockOutLineId = it.stockOutLine?.id, | |||||
| handlerId = it.handler?.id, | |||||
| handlerName = it.handler?.name, | |||||
| handlerTitle = it.handler?.title, | |||||
| handlerDepartment = it.handler?.department, | |||||
| recordDate = it.recordDate, | |||||
| status = it.status?.value, | |||||
| reason = it.reason, | |||||
| ) | |||||
| } | |||||
| return response | |||||
| } | |||||
| } | |||||
| @@ -20,6 +20,10 @@ open class InventoryLotService( | |||||
| private val inventoryLotRepository: InventoryLotRepository, | private val inventoryLotRepository: InventoryLotRepository, | ||||
| ): AbstractBaseEntityService<InventoryLot, Long, InventoryLotRepository>(jdbcDao, inventoryLotRepository) { | ): AbstractBaseEntityService<InventoryLot, Long, InventoryLotRepository>(jdbcDao, inventoryLotRepository) { | ||||
| open fun findByStockInLineId(stockInLineId: Long): InventoryLot? { | |||||
| return inventoryLotRepository.findByStockInLineIdAndDeletedFalse(stockInLineId) | |||||
| } | |||||
| @Throws(IOException::class) | @Throws(IOException::class) | ||||
| @Transactional | @Transactional | ||||
| open fun createOrUpdate(request: SaveInventoryRequest): MessageResponse { | open fun createOrUpdate(request: SaveInventoryRequest): MessageResponse { | ||||
| @@ -171,6 +171,7 @@ open class StockInLineService( | |||||
| this.item = item | this.item = item | ||||
| this.stockInLine = stockInLine | this.stockInLine = stockInLine | ||||
| this.failQty = it.failQty | this.failQty = it.failQty | ||||
| this.qcPassed = it.qcPassed | |||||
| this.type = "qc" // default as qc for now | this.type = "qc" // default as qc for now | ||||
| this.remarks = it.remarks | this.remarks = it.remarks | ||||
| } | } | ||||
| @@ -1,38 +0,0 @@ | |||||
| package com.ffii.fpsms.modules.stock.service | |||||
| import com.ffii.core.support.AbstractBaseEntityService | |||||
| import com.ffii.core.support.JdbcDao | |||||
| import com.ffii.fpsms.modules.common.SecurityUtils | |||||
| import com.ffii.fpsms.modules.stock.entity.SupervisionApprovalLog | |||||
| import com.ffii.fpsms.modules.stock.entity.SupervisionApprovalLogInfo | |||||
| import com.ffii.fpsms.modules.stock.entity.SupervisionApprovalLogRepository | |||||
| import org.springframework.stereotype.Service | |||||
| @Service | |||||
| open class SupervisionApprovalLogService( | |||||
| private val jdbcDao: JdbcDao, | |||||
| private val supervisionApprovalLogRepository: SupervisionApprovalLogRepository | |||||
| ): AbstractBaseEntityService<SupervisionApprovalLog, Long, SupervisionApprovalLogRepository>(jdbcDao, supervisionApprovalLogRepository) { | |||||
| open fun getAllLogs(): List<SupervisionApprovalLog> { | |||||
| return supervisionApprovalLogRepository.findAll() | |||||
| } | |||||
| open fun getStockInLog(): List<SupervisionApprovalLog> { | |||||
| val stockInLog = getAllLogs().filter { | |||||
| it.stockInLine != null | |||||
| } | |||||
| return stockInLog | |||||
| } | |||||
| open fun getLogByUser(): List<SupervisionApprovalLogInfo> { | |||||
| val user = SecurityUtils.getUser().orElseThrow() | |||||
| val filterLog = supervisionApprovalLogRepository | |||||
| .findAllInfoByDeletedFalse() | |||||
| // .findAll() | |||||
| // .findAllByPersonInCharge(user.id!!).filter { | |||||
| // it.stockInLine != null | |||||
| // } | |||||
| println("filterLog") | |||||
| println(filterLog) | |||||
| return filterLog | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package com.ffii.fpsms.modules.stock.web | |||||
| import com.ffii.fpsms.modules.stock.entity.EscalationLogInfo | |||||
| import com.ffii.fpsms.modules.stock.service.EscalationLogService | |||||
| import com.ffii.fpsms.modules.stock.web.model.SaveEscalationLogRequest | |||||
| import com.ffii.fpsms.modules.stock.web.model.SaveEscalationLogResponse | |||||
| import com.ffii.fpsms.modules.stock.web.model.SearchEscalationLogRequest | |||||
| import jakarta.validation.Valid | |||||
| import org.springframework.web.bind.annotation.GetMapping | |||||
| import org.springframework.web.bind.annotation.ModelAttribute | |||||
| import org.springframework.web.bind.annotation.PostMapping | |||||
| import org.springframework.web.bind.annotation.RequestBody | |||||
| import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| @RestController | |||||
| @RequestMapping("/escalationLog") | |||||
| class EscalationLogController( | |||||
| private val escalationLogService: EscalationLogService | |||||
| ) { | |||||
| @GetMapping("/stockInLines") | |||||
| fun getLogsByStockInLines(@ModelAttribute request: SearchEscalationLogRequest): List<EscalationLogInfo> { | |||||
| return escalationLogService.getLogsByStockInLines(request.stockInLineIds); | |||||
| } | |||||
| @GetMapping("/stockInLine") | |||||
| fun getLogsByStockInLine(@ModelAttribute request: SearchEscalationLogRequest): List<EscalationLogInfo> { | |||||
| return escalationLogService.getLogsByStockInLine(request.stockInLineId); | |||||
| } | |||||
| @GetMapping("/user") | |||||
| fun getLogsByUser(): List<EscalationLogInfo> { | |||||
| return escalationLogService.getLogsByUser(); | |||||
| } | |||||
| @PostMapping("/save") | |||||
| fun saveEscalationLog(@Valid @RequestBody request: SaveEscalationLogRequest): SaveEscalationLogResponse { | |||||
| return escalationLogService.saveEscalationLog(request); | |||||
| } | |||||
| } | |||||
| @@ -1,19 +0,0 @@ | |||||
| package com.ffii.fpsms.modules.stock.web | |||||
| import com.ffii.fpsms.modules.stock.entity.SupervisionApprovalLog | |||||
| import com.ffii.fpsms.modules.stock.entity.SupervisionApprovalLogInfo | |||||
| import com.ffii.fpsms.modules.stock.service.SupervisionApprovalLogService | |||||
| import org.springframework.web.bind.annotation.GetMapping | |||||
| import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| @RestController | |||||
| @RequestMapping("/supervisionApprovalLog") | |||||
| class SupervisionApprovalLogController( | |||||
| private val supervisionApprovalLogService: SupervisionApprovalLogService | |||||
| ) { | |||||
| @GetMapping("/stock-in") | |||||
| fun getStockInQcLog(): List<SupervisionApprovalLogInfo> { | |||||
| return supervisionApprovalLogService.getLogByUser() | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| package com.ffii.fpsms.modules.stock.web.model | |||||
| import jakarta.validation.constraints.NotBlank | |||||
| import jakarta.validation.constraints.NotNull | |||||
| import java.time.LocalDateTime | |||||
| data class SaveEscalationLogRequest( | |||||
| val id: Long?, | |||||
| @field:NotNull(message = "Person In Charge cannot be empty") | |||||
| val handlerId: Long, | |||||
| val type: String?, | |||||
| val stockInLineId: Long?, | |||||
| val stockOutLineId: Long?, | |||||
| val recordDate: LocalDateTime?, | |||||
| @field:NotBlank(message = "Status cannot be empty") | |||||
| val status: String, | |||||
| val reason: String?, | |||||
| val qcTotalCount: Int?, | |||||
| val qcFailCount: Int?, | |||||
| ) | |||||
| @@ -0,0 +1,16 @@ | |||||
| package com.ffii.fpsms.modules.stock.web.model | |||||
| import java.time.LocalDateTime | |||||
| data class SaveEscalationLogResponse( | |||||
| val id: Long?, | |||||
| val stockInLineId: Long?, | |||||
| val stockOutLineId: Long?, | |||||
| val handlerId: Long?, | |||||
| val handlerName: String?, | |||||
| val handlerTitle: String?, | |||||
| val handlerDepartment: String?, | |||||
| val recordDate: LocalDateTime?, | |||||
| val status: String?, | |||||
| val reason: String?, | |||||
| ) | |||||
| @@ -0,0 +1,7 @@ | |||||
| package com.ffii.fpsms.modules.stock.web.model | |||||
| data class SearchEscalationLogRequest( | |||||
| val stockInLineIds: List<Long>?, | |||||
| val stockInLineId: Long?, | |||||
| val userId: Long?, | |||||
| ) | |||||
| @@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.user.entity; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Optional; | import java.util.Optional; | ||||
| import com.ffii.fpsms.modules.user.entity.projections.UserCombo; | |||||
| import org.springframework.data.repository.query.Param; | import org.springframework.data.repository.query.Param; | ||||
| import com.ffii.core.support.AbstractRepository; | import com.ffii.core.support.AbstractRepository; | ||||
| @@ -12,4 +13,6 @@ public interface UserRepository extends AbstractRepository<User, Long> { | |||||
| List<User> findByName(@Param("name") String name); | List<User> findByName(@Param("name") String name); | ||||
| Optional<User> findByUsernameAndDeletedFalse(String username); | Optional<User> findByUsernameAndDeletedFalse(String username); | ||||
| List<UserCombo> findUserComboByTitleNotNullAndDepartmentNotNull(); | |||||
| } | } | ||||
| @@ -0,0 +1,19 @@ | |||||
| package com.ffii.fpsms.modules.user.entity.projections; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| public interface UserCombo { | |||||
| Long getId(); | |||||
| @Value("#{target.id}") | |||||
| Long getValue(); | |||||
| @Value("#{target.department} - #{target.title} - #{target.name}") | |||||
| String getLabel(); | |||||
| String getName(); | |||||
| String getDepartment(); | |||||
| String getTitle(); | |||||
| } | |||||
| @@ -8,6 +8,7 @@ import java.util.Optional; | |||||
| import java.util.Set; | import java.util.Set; | ||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
| import com.ffii.fpsms.modules.user.entity.projections.UserCombo; | |||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| @@ -269,4 +270,8 @@ public class UserService extends AbstractBaseEntityService<User, Long, UserRepos | |||||
| instance = save(instance); | instance = save(instance); | ||||
| return randomPassword; | return randomPassword; | ||||
| } | } | ||||
| public List<UserCombo> getEscalationCombo() { | |||||
| return userRepository.findUserComboByTitleNotNullAndDepartmentNotNull(); | |||||
| } | |||||
| } | } | ||||
| @@ -5,6 +5,8 @@ import java.util.HashMap; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| import com.ffii.fpsms.modules.user.entity.projections.UserCombo; | |||||
| import com.ffii.fpsms.modules.user.service.pojo.UserRecord; | |||||
| import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
| import org.springframework.http.HttpStatus; | import org.springframework.http.HttpStatus; | ||||
| @@ -38,7 +40,6 @@ import com.ffii.fpsms.modules.user.req.NewUserReq; | |||||
| import com.ffii.fpsms.modules.user.req.SearchUserReq; | import com.ffii.fpsms.modules.user.req.SearchUserReq; | ||||
| import com.ffii.fpsms.modules.user.req.UpdateUserReq; | import com.ffii.fpsms.modules.user.req.UpdateUserReq; | ||||
| import com.ffii.fpsms.modules.user.service.UserService; | import com.ffii.fpsms.modules.user.service.UserService; | ||||
| import com.ffii.fpsms.modules.user.service.pojo.UserRecord; | |||||
| import com.ffii.fpsms.modules.user.service.res.LoadUserRes; | import com.ffii.fpsms.modules.user.service.res.LoadUserRes; | ||||
| import jakarta.validation.Valid; | import jakarta.validation.Valid; | ||||
| @@ -71,6 +72,11 @@ public class UserController{ | |||||
| return ResponseEntity.ok(userService.search(req)); | return ResponseEntity.ok(userService.search(req)); | ||||
| } | } | ||||
| @GetMapping("/escalation-combo") | |||||
| public ResponseEntity<List<UserCombo>> escalationCombo() { | |||||
| return ResponseEntity.ok(userService.getEscalationCombo()); | |||||
| } | |||||
| @GetMapping("/name-list") | @GetMapping("/name-list") | ||||
| public ResponseEntity<List<Map<String, Object>>> namelist() { | public ResponseEntity<List<Map<String, Object>>> namelist() { | ||||
| SearchUserReq req = new SearchUserReq(); | SearchUserReq req = new SearchUserReq(); | ||||
| @@ -0,0 +1,6 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset cyril:update_supervision_approval_log | |||||
| ALTER TABLE `supervision_approval_log` | |||||
| ADD COLUMN `qcFailCount` INT NULL AFTER `reason`, | |||||
| ADD COLUMN `qcTotalCount` INT NULL AFTER `qcFailCount`; | |||||
| @@ -0,0 +1,5 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset cyril:update_supervision_approval_log | |||||
| ALTER TABLE `supervision_approval_log` | |||||
| CHANGE COLUMN `type` `type` VARCHAR(100) NULL; | |||||
| @@ -0,0 +1,5 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset cyril:rename_supervision_approval_log | |||||
| ALTER TABLE `supervision_approval_log` | |||||
| RENAME TO `escalation_log` ; | |||||
| @@ -0,0 +1,4 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset kelvin:update qc result table | |||||
| ALTER TABLE `qc_result` | |||||
| ADD COLUMN `qcPassed` TINYINT(1) NOT NULL DEFAULT 1 AFTER `remarks`; | |||||
| @@ -0,0 +1,11 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset cyril:rename_escalation_log | |||||
| ALTER TABLE `escalation_log` | |||||
| DROP FOREIGN KEY `FK_SUPERVISION_APPROVAL_LOG_ON_PERSONINCHARGE`; | |||||
| ALTER TABLE `escalation_log` | |||||
| CHANGE COLUMN `personInCharge` `handlerId` INT NOT NULL ; | |||||
| ALTER TABLE `escalation_log` | |||||
| ADD CONSTRAINT `FK_SUPERVISION_APPROVAL_LOG_ON_PERSONINCHARGE` | |||||
| FOREIGN KEY (`handlerId`) | |||||
| REFERENCES `user` (`id`); | |||||