| @@ -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") | @JoinColumn(name = "personInCharge", nullable = false, referencedColumnName = "id") | ||||
| open var personInCharge: User? = null | open var personInCharge: 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,57 @@ | |||||
| 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.personInCharge?.id}") | |||||
| val personInChargeId: Long? | |||||
| @get:Value("#{target.personInCharge?.name}") | |||||
| val personInChargeName: String? | |||||
| @get:Value("#{target.personInCharge?.title}") | |||||
| val personInChargeTitle: String? | |||||
| @get:Value("#{target.personInCharge?.department}") | |||||
| val personInChargeDepartment: 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 findAllByPersonInCharge(personInCharge: Long): List<SupervisionApprovalLog> | |||||
| fun findAllInfoByDeletedFalse(): List<EscalationLogInfo> | |||||
| fun findAllInfoByDeletedFalseAndStockInLineIdIn(stockInLineIds: List<Serializable>): List<EscalationLogInfo> | |||||
| fun findAllInfoByDeletedFalseAndPersonInChargeIdIs(personInChargeId: Serializable): List<EscalationLogInfo> | |||||
| } | |||||
| @@ -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> | |||||
| } | |||||
| @@ -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.findAllInfoByDeletedFalseAndPersonInChargeIdIs(it) } ?: listOf() | |||||
| return logs | |||||
| } | |||||
| open fun saveEscalationLog(request: SaveEscalationLogRequest): SaveEscalationLogResponse{ | |||||
| val escalationLog = request.id?.let { escalationLogRepository.findById(it).getOrNull() } ?: EscalationLog() | |||||
| val personInCharge = request.personInChargeId.let { userService.getUserById(it) } | |||||
| if (personInCharge == null && escalationLog.personInCharge == 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.personInCharge = personInCharge | |||||
| 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, | |||||
| personInChargeId = it.personInCharge?.id, | |||||
| personInChargeName = it.personInCharge?.name, | |||||
| personInChargeTitle = it.personInCharge?.title, | |||||
| personInChargeDepartment = it.personInCharge?.department, | |||||
| recordDate = it.recordDate, | |||||
| status = it.status?.value, | |||||
| reason = it.reason, | |||||
| ) | |||||
| } | |||||
| return response | |||||
| } | |||||
| } | |||||
| @@ -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 personInChargeId: 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 personInChargeId: Long?, | |||||
| val personInChargeName: String?, | |||||
| val personInChargeTitle: String?, | |||||
| val personInChargeDepartment: 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?, | |||||
| ) | |||||
| @@ -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` ; | |||||