| @@ -2,10 +2,50 @@ package com.ffii.fpsms.modules.pickOrder.entity | |||
| import com.ffii.core.support.AbstractRepository | |||
| import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest | |||
| import org.springframework.data.domain.Page | |||
| import org.springframework.data.domain.Pageable | |||
| import org.springframework.data.jpa.repository.Query | |||
| import org.springframework.data.repository.query.Param | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| import java.time.LocalDateTime | |||
| @Repository | |||
| interface PickOrderRepository: AbstractRepository<PickOrder, Long> { | |||
| interface PickOrderRepository : AbstractRepository<PickOrder, Long> { | |||
| fun findPickOrderInfoByDeletedIsFalse(): List<PickOrderInfo> | |||
| @Query( | |||
| """ | |||
| select po from PickOrder po | |||
| where (lower(:code) = 'all' or lower(po.code) like concat('%',lower(:code),'%')) | |||
| and (:targetDateFrom is null or po.targetDate >= :targetDateFrom) | |||
| and (:targetDateTo is null or po.targetDate <= :targetDateTo) | |||
| and (lower(:type) = 'all' or lower(po.type) like concat('%',lower(:type),'%')) | |||
| and (lower(:status) = 'all' or lower(po.status) like concat('%',lower(:status),'%')) | |||
| and (lower(:itemName) = 'all' or exists ( | |||
| select 1 from PickOrderLine pol | |||
| where pol.pickOrder = po | |||
| and (lower(:itemName) = 'all' or lower(pol.item.name) like concat('%',lower(:itemName),'%')) | |||
| ) | |||
| ) | |||
| and po.consoCode = null | |||
| and po.deleted = false | |||
| """ | |||
| ) | |||
| fun findPickOrderInfoByConditionsAndPageable( | |||
| code: String, | |||
| targetDateFrom: LocalDateTime?, | |||
| targetDateTo: LocalDateTime?, | |||
| type: String, | |||
| status: String, | |||
| itemName: String, | |||
| pageable: Pageable, | |||
| ): Page<PickOrderInfo> | |||
| @Query(""" | |||
| select po.consoCode from PickOrder po where po.consoCode like :prefix% order by po.consoCode desc limit 1 | |||
| """) | |||
| fun findLatestConsoCodeByPrefix(prefix: String): String? | |||
| fun findAllByIdIn(id: List<Serializable>): List<PickOrder> | |||
| } | |||
| @@ -1,19 +1,76 @@ | |||
| package com.ffii.fpsms.modules.pickOrder.service | |||
| import com.ffii.core.response.RecordsRes | |||
| import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository | |||
| import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderRequest | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest | |||
| import org.springframework.data.domain.PageRequest | |||
| import org.springframework.stereotype.Service | |||
| import java.time.LocalDate | |||
| import java.time.LocalDateTime | |||
| import java.time.format.DateTimeFormatter | |||
| @Service | |||
| open class PickOrderService( | |||
| val pickOrderRepository: PickOrderRepository, | |||
| ) { | |||
| open fun LocalDateTimeParse(dateTime: String?, pattern: String? = "YYYY-MM-DD hh:mm:ss"): LocalDateTime? { | |||
| try { | |||
| val formatter = DateTimeFormatter.ofPattern(pattern) | |||
| return LocalDateTime.parse(dateTime, formatter) | |||
| } catch (e: Exception) { | |||
| return null | |||
| } | |||
| } | |||
| open fun allPickOrders(): List<PickOrderInfo> { | |||
| return pickOrderRepository.findPickOrderInfoByDeletedIsFalse() | |||
| } | |||
| open fun allPickOrdersByPage(request: SearchPickOrderRequest): RecordsRes<PickOrderInfo> { | |||
| val pageable = PageRequest.of(request.pageNum ?: 0, request.pageSize ?: 10); | |||
| val response = pickOrderRepository.findPickOrderInfoByConditionsAndPageable( | |||
| code = request.code ?: "all", | |||
| targetDateFrom = LocalDateTimeParse(request.targetDateFrom), | |||
| targetDateTo = LocalDateTimeParse(request.targetDateTo), | |||
| type = request.type ?: "all", | |||
| status = request.status ?: "all", | |||
| itemName = request.itemName ?: "all", | |||
| pageable = pageable | |||
| ) | |||
| val records = response.content | |||
| val total = response.totalElements | |||
| return RecordsRes<PickOrderInfo>(records, total.toInt()) | |||
| } | |||
| // Consolidating Pick Orders | |||
| open fun consoPickOrders() { | |||
| open fun assignConsoCode(): String { | |||
| val suffixFormat = "%03d" | |||
| val pattern = "YYYYMMDD" | |||
| val formatter = DateTimeFormatter.ofPattern(pattern) | |||
| val prefix = "PICK" | |||
| val midfix = LocalDate.now().format(formatter) | |||
| val suffix = String.format(suffixFormat, 1) | |||
| val latestConsoCode = pickOrderRepository.findLatestConsoCodeByPrefix("${prefix}-${midfix}") | |||
| if (latestConsoCode != null) { | |||
| val splitLatestConsoCode = latestConsoCode.split("-") | |||
| if (splitLatestConsoCode.size > 2) { | |||
| val latestNo = splitLatestConsoCode[2].toInt() | |||
| return listOf<String>(prefix, midfix, String.format(suffixFormat, latestNo + 1)).joinToString("-") | |||
| } | |||
| } | |||
| return listOf<String>(prefix, midfix, suffix).joinToString("-") | |||
| } | |||
| // open fun consoPickOrders(request: ConsoPickOrderRequest) { | |||
| // val assignConsoCode = assignConsoCode() | |||
| // val pickOrders = pickOrderRepository.findAllByIdIn(request.ids) | |||
| // pickOrders. | |||
| // } | |||
| } | |||
| @@ -1,18 +1,37 @@ | |||
| package com.ffii.fpsms.modules.pickOrder.web | |||
| import com.ffii.core.response.RecordsRes | |||
| import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository | |||
| import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo | |||
| import com.ffii.fpsms.modules.pickOrder.service.PickOrderService | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest | |||
| import jakarta.validation.Valid | |||
| import org.springframework.data.domain.Page | |||
| import org.springframework.data.domain.PageRequest | |||
| import org.springframework.data.domain.Pageable | |||
| 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.RequestMapping | |||
| import org.springframework.web.bind.annotation.RequestParam | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import java.time.DateTimeException | |||
| import java.time.LocalDateTime | |||
| import java.time.format.DateTimeFormatter | |||
| @RestController | |||
| @RequestMapping("/pickOrder") | |||
| class PickOrderController( | |||
| private val pickOrderService: PickOrderService, | |||
| private val pickOrderRepository: PickOrderRepository, | |||
| ) { | |||
| @GetMapping("/list") | |||
| fun allPickOrders(): List<PickOrderInfo> { | |||
| return pickOrderService.allPickOrders(); | |||
| } | |||
| @GetMapping("/getRecordByPage") | |||
| fun allPickOrdersByPage(@ModelAttribute request: SearchPickOrderRequest): RecordsRes<PickOrderInfo> { | |||
| return pickOrderService.allPickOrdersByPage(request); | |||
| } | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| package com.ffii.fpsms.modules.pickOrder.web.models | |||
| data class ConsoPickOrderRequest ( | |||
| val ids: List<Long> | |||
| ) | |||
| @@ -0,0 +1,14 @@ | |||
| package com.ffii.fpsms.modules.pickOrder.web.models | |||
| import org.springframework.web.bind.annotation.RequestParam | |||
| data class SearchPickOrderRequest ( | |||
| val code: String?, | |||
| val targetDateFrom: String?, | |||
| val targetDateTo: String?, | |||
| val type: String?, | |||
| val status: String?, | |||
| val itemName: String?, | |||
| val pageSize: Int?, | |||
| val pageNum: Int?, | |||
| ) | |||
| @@ -12,5 +12,6 @@ interface PurchaseOrderLineRepository : AbstractRepository<PurchaseOrderLine, Lo | |||
| fun findAllPurchaseOrderLineInfoByPurchaseOrderIdAndDeletedIsFalse(purchaseOrderId: Long): List<PurchaseOrderLineInfo> | |||
| fun findAllByPurchaseOrderIdAndDeletedIsFalse(purchaseOrderId: Long): List<PurchaseOrderLine> | |||
| fun findAllByPurchaseOrderIdAndStatusNotAndDeletedIsFalse(purchaseOrderId: Long, status: PurchaseOrderLineStatus): List<PurchaseOrderLine> | |||
| // fun findAllByPurchaseOrderIdAndDeletedIsFalse(purchaseOrderId: Long): List<PurchaseOrderLine> | |||
| // fun find | |||
| } | |||
| @@ -1,19 +1,20 @@ | |||
| package com.ffii.fpsms.modules.purchaseOrder.entity | |||
| import com.ffii.core.support.AbstractRepository | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderDataClass | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderInfo | |||
| import org.springframework.data.domain.Page | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| import java.util.Optional | |||
| import org.springframework.data.domain.Pageable | |||
| import org.springframework.data.jpa.repository.Query | |||
| import org.springframework.data.repository.query.Param | |||
| @Repository | |||
| interface PurchaseOrderRepository : AbstractRepository<PurchaseOrder, Long> { | |||
| fun findTopByM18DataLogIdAndDeletedIsFalseOrderByModifiedDesc(m18datalogId: Serializable): PurchaseOrder? | |||
| fun findPurchaseOrderInfoByDeletedIsFalse(): List<PurchaseOrderInfo> | |||
| fun findPurchaseOrderInfoByDeletedIsFalse(pageable: Pageable): Page<PurchaseOrderInfo> | |||
| fun findPurchaseOrderInfoByIdAndDeletedIsFalse(id: Long): PurchaseOrderInfo | |||
| fun findByIdAndDeletedFalse(id: Long): Optional<PurchaseOrder> | |||
| @@ -14,7 +14,7 @@ interface PurchaseOrderInfo { | |||
| val status: String | |||
| @get:Value("#{target.supplier?.name}") | |||
| val supplier: String? | |||
| // var escalated: Boolean? | |||
| var escalated: Boolean? | |||
| } | |||
| data class PurchaseOrderDataClass( | |||
| @@ -30,6 +30,7 @@ import org.springframework.data.domain.Pageable | |||
| import org.springframework.stereotype.Service | |||
| import org.springframework.transaction.annotation.Transactional | |||
| import java.io.IOException | |||
| import java.time.LocalDateTime | |||
| import java.util.HashMap | |||
| import java.util.Objects | |||
| import kotlin.jvm.optionals.getOrDefault | |||
| @@ -47,33 +48,69 @@ open class PurchaseOrderService( | |||
| private val currencyService: CurrencyService, | |||
| private val shopService: ShopService, | |||
| ) : AbstractBaseEntityService<PurchaseOrder, Long, PurchaseOrderRepository>(jdbcDao, purchaseOrderRepository) { | |||
| open fun getPoList(request: PagingRequest): RecordsRes<PurchaseOrderDataClass> { | |||
| println(request) | |||
| val totalCount = purchaseOrderRepository.count().toInt() | |||
| val list: List<PurchaseOrderInfo> = if (request.pageNum != null && request.pageSize != null) { | |||
| val pageable = PageRequest.of(request.pageNum!!, request.pageSize!!) | |||
| purchaseOrderRepository.findPurchaseOrderInfoByDeletedIsFalse(pageable).content | |||
| } else { | |||
| purchaseOrderRepository.findPurchaseOrderInfoByDeletedIsFalse() | |||
| // open fun getPurchaseOrderInfo(args: Map<String, Any>): List<Map<String, Any>> { | |||
| // val sql = StringBuilder( | |||
| // "SELECT " + | |||
| // "po.* " + | |||
| // "FROM purchase_order po " + | |||
| // "WHERE po.deleted = FALSE" | |||
| // ); | |||
| // if (args.containsKey("name")){ | |||
| // sql.append(" AND i.name like :name "); | |||
| // } | |||
| // } | |||
| open fun getPoList(args: MutableMap<String, Any>): List<PurchaseOrderDataClass> { | |||
| val sql = StringBuilder( | |||
| " select " | |||
| + " po.*, " | |||
| + " s.name as supplier, " | |||
| + " CASE " | |||
| + " WHEN sil.purchaseOrderId IS NOT NULL THEN 1 " | |||
| + " ELSE 0 " | |||
| + " END AS escalated " | |||
| + " from purchase_order po " | |||
| + " left join shop s on s.id = po.supplierId " | |||
| + " left join ( " | |||
| + " select " | |||
| + " sil.purchaseOrderId " | |||
| + " from stock_in_line sil " | |||
| + " where sil.status like 'determine%' " | |||
| + " ) sil on sil.purchaseOrderId = po.id " | |||
| + " where po.deleted = false " | |||
| ) | |||
| if (args.containsKey("code")){ | |||
| sql.append(" AND po.code like :code "); | |||
| } | |||
| if (args.containsKey("status")){ | |||
| sql.append(" AND po.status = :status "); | |||
| } | |||
| if (args.containsKey("escalated")) { | |||
| if (args["escalated"] == true) { | |||
| sql.append(" and sil.purchaseOrderId IS NOT NULL "); | |||
| } else { | |||
| sql.append(" and sil.purchaseOrderId IS NULL "); | |||
| } | |||
| } | |||
| val list = jdbcDao.queryForList(sql.toString(), args); | |||
| println(list) | |||
| val mappedList = list.map { | |||
| val escalated = stockInLineRepository.findAllStockInLineInfoByPurchaseOrderIdAndStatusStartsWithAndDeletedFalse( | |||
| purchaseOrderId = it.id, | |||
| status = "determine" | |||
| ) | |||
| PurchaseOrderDataClass( | |||
| id = it.id, | |||
| code = it.code, | |||
| orderDate = it.orderDate, | |||
| estimatedArrivalDate = it.estimatedArrivalDate, | |||
| completeDate = it.completeDate, | |||
| status = it.status, | |||
| supplier = it.supplier, | |||
| escalated = escalated.isNotEmpty(), | |||
| id = (it["id"] as Int).toLong(), | |||
| code = it["code"] as String, | |||
| orderDate = it["orderDate"] as LocalDateTime?, | |||
| estimatedArrivalDate = it["estimatedArrivalDate"] as LocalDateTime?, | |||
| completeDate = it["completeDate"] as LocalDateTime?, | |||
| status = it["status"] as String, | |||
| supplier = it["supplier"] as String?, | |||
| escalated = it["escalated"] == 1L, | |||
| ) | |||
| } | |||
| return RecordsRes(mappedList, totalCount) | |||
| // println(value1) | |||
| // println(value1 == 1L) | |||
| // println(value2) | |||
| println(mappedList) | |||
| return mappedList | |||
| } | |||
| open fun allPurchaseOrder(): List<PurchaseOrder> { | |||
| @@ -188,6 +225,13 @@ open class PurchaseOrderService( | |||
| @Transactional | |||
| open fun checkPolAndCompletePo(id: Long): MessageResponse { | |||
| val unfinishedLines = polRepository.findAllByPurchaseOrderIdAndStatusNotAndDeletedIsFalse(purchaseOrderId = id, status = PurchaseOrderLineStatus.COMPLETED) | |||
| // val unfinishedLines = polRepository.findAllByPurchaseOrderIdAndDeletedIsFalse(purchaseOrderId = id) | |||
| // .filter { | |||
| // it.status != PurchaseOrderLineStatus.COMPLETED | | |||
| // it.status != PurchaseOrderLineStatus. | |||
| // } | |||
| println("unfinishedLines") | |||
| println(unfinishedLines) | |||
| val po = purchaseOrderRepository.findById(id).orElseThrow() | |||
| if (unfinishedLines.isEmpty()) { | |||
| po.apply { | |||
| @@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.purchaseOrder.web | |||
| import com.ffii.core.response.RecordsRes | |||
| import com.ffii.core.support.JdbcDao | |||
| import com.ffii.core.utils.CriteriaArgsBuilder | |||
| import com.ffii.core.utils.PagingUtils | |||
| import com.ffii.fpsms.modules.master.entity.Items | |||
| import com.ffii.fpsms.modules.master.service.ItemsService | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| @@ -24,16 +25,24 @@ class PurchaseOrderController( | |||
| ) { | |||
| @GetMapping("/list") | |||
| fun getPoList( | |||
| request: HttpServletRequest | |||
| // @RequestParam(required = false) pageNum: Int, | |||
| // @RequestParam(required = false) pageSize: Int | |||
| ): RecordsRes<PurchaseOrderDataClass> { | |||
| // println("request") | |||
| // println(pageSize) | |||
| // println(pageNum - 1) | |||
| // request pageNum starts from 1, but pagingRequest starts with 0 | |||
| // val pageRequest = PagingRequest(pageSize = pageSize, pageNum = pageNum - 1,) // not start from 0 | |||
| val pageRequest = PagingRequest(pageSize = null, pageNum = null) // not start from 0 | |||
| return purchaseOrderService.getPoList(pageRequest) | |||
| println("request") | |||
| println(request) | |||
| val criteriaArgs = CriteriaArgsBuilder.withRequest(request) | |||
| .addStringLike("code") | |||
| .addString("status") | |||
| .addBoolean("escalated") | |||
| .build() | |||
| println(criteriaArgs) | |||
| val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10 // Default to 10 if not provided | |||
| val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1 // Default to 1 if not provided | |||
| val fullList = purchaseOrderService.getPoList(criteriaArgs) | |||
| val paginatedList = PagingUtils.getPaginatedList(fullList,pageSize, pageNum) | |||
| return RecordsRes(paginatedList, fullList.size) | |||
| } | |||
| @GetMapping("/testing") | |||
| @@ -41,6 +50,7 @@ class PurchaseOrderController( | |||
| val criteriaArgs = CriteriaArgsBuilder.withRequest(request) | |||
| .addStringLike("code") | |||
| .addStringLike("name") | |||
| .addBoolean("escalated") | |||
| .build() | |||
| println("criteriaArgs") | |||
| println(criteriaArgs) | |||
| @@ -13,6 +13,7 @@ interface StockInLineRepository : AbstractRepository<StockInLine, Long> { | |||
| fun findStockInLineInfoByIdAndDeletedFalse(id: Long): StockInLineInfo | |||
| fun findStockInLineInfoByIdInAndDeletedFalse(id: List<Long>): List<StockInLineInfo> | |||
| fun findStockInLineInfoByPurchaseOrderLineIdAndStatusNotAndDeletedFalse(purchaseOrderLineId: Long, status: String): List<StockInLineInfo> | |||
| fun findStockInLineInfoByPurchaseOrderLineIdAndDeletedFalse(purchaseOrderLineId: Long): List<StockInLineInfo> | |||
| fun findStockInLineInfoByIdAndStatusAndDeletedFalse(id: Long, status: String): Optional<StockInLineInfo> | |||
| fun findAllStockInLineInfoByPurchaseOrderIdAndStatusStartsWithAndDeletedFalse(purchaseOrderId: Long, status: String): List<Optional<StockInLineInfo>> | |||
| } | |||
| @@ -191,8 +191,16 @@ open class StockInLineService( | |||
| @Throws(IOException::class) | |||
| @Transactional | |||
| fun updatePurchaseOrderLineStatus(request: SaveStockInLineRequest) { | |||
| if (request.status == StockInLineStatus.COMPLETE.status) { | |||
| val unfinishedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndStatusNotAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId, status = request.status!!) | |||
| println(request.status) | |||
| if (request.status == StockInLineStatus.COMPLETE.status || request.status == StockInLineStatus.REJECT.status) { | |||
| // val unfinishedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndStatusNotAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId, status = request.status!!) | |||
| val unfinishedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId) | |||
| .filter { | |||
| it.status != StockInLineStatus.COMPLETE.status | |||
| && it.status != StockInLineStatus.REJECT.status | |||
| } | |||
| println("unfinishedLines") | |||
| println(unfinishedLines) | |||
| if (unfinishedLines.isEmpty()) { | |||
| // all stock in lines finished | |||
| // change status of purchase order line | |||