diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderRepository.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderRepository.kt index feaa85f..a9b5c5d 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderRepository.kt @@ -55,4 +55,41 @@ interface JobOrderRepository : AbstractRepository { """ ) fun findJobOrderDetailById(id: Long): JobOrderDetailWithJsonString?; + @Query( + nativeQuery = true, + value = """ + select + jo.id, + jo.code, + b.name, + jo.reqQty, + uc2.udfudesc as uom, + json_arrayagg( + json_object( + 'id', jobm.id, + 'code', i.code, + 'name', i.name, + 'lotNo', il.lotNo, + 'reqQty', jobm.reqQty, + 'uom', uc.udfudesc, + 'status', jobm.status + ) + ) as pickLines, + jo.status + from job_order jo + left join bom b on b.id = jo.bomId + left join item_uom iu on b.itemId = iu.itemId and iu.salesUnit = true + left join uom_conversion uc2 on uc2.id = iu.uomId + left join job_order_bom_material jobm on jo.id = jobm.jobOrderId + left join items i on i.id = jobm.itemId + left join uom_conversion uc on uc.id = jobm.uomId + left join stock_out_line sol on sol.id = jobm.stockOutLineId + left join inventory_lot_line ill on ill.id = sol.inventoryLotLineId + left join inventory_lot il on il.id = ill.inventoryLotId + where jo.code = :code + group by jo.id, uc2.udfudesc + limit 1 + """ + ) + fun findJobOrderDetailByCode(code: String): JobOrderDetailWithJsonString?; } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt index c91459e..0b99164 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt @@ -67,6 +67,23 @@ open class JobOrderService( status = sqlResult.status ) } + + open fun jobOrderDetailByCode(code: String): JobOrderDetail { + val sqlResult = jobOrderRepository.findJobOrderDetailByCode(code) ?: throw NoSuchElementException("Job Order not found: $code"); + + val type = object : TypeToken>() {}.type + val jsonResult = sqlResult.pickLines?.let { GsonUtils.stringToJson>(it, type) } + return JobOrderDetail( + id = sqlResult.id, + code = sqlResult.code, + name = sqlResult.name, + reqQty = sqlResult.reqQty, + uom = sqlResult.uom, + pickLines = jsonResult, + status = sqlResult.status + ) + } + open fun assignJobNo(): String { val suffixFormat = "%03d" val pattern = "yyyyMMdd" diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt index 38717f1..0e9c7bd 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt @@ -37,6 +37,11 @@ class JobOrderController( return jobOrderService.jobOrderDetail(id); } + @GetMapping("/detailByCode/{code}") + fun jobOrderDetailByCode(@PathVariable code: String): JobOrderDetail { + return jobOrderService.jobOrderDetailByCode(code); + } + @PostMapping("/release") fun releaseJobOrder(@Valid @RequestBody request: JobOrderReleaseRequest): MessageResponse { return jobOrderService.releaseJobOrder(request) diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt index 9040e03..5e0fdab 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt @@ -37,10 +37,12 @@ open class ItemsService( + " i.id, " + " concat(i.code , ' - ' , i.name) as label, " + " uc.id as uomId, " - + " uc.code as uom " + + " uc.code as uom, " + + " COALESCE(inv.onHandQty, 0) - COALESCE(inv.onHoldQty, 0) - COALESCE(inv.unavailableQty, 0) as currentStockBalance " + " from items i " + " left join item_uom iu on iu.itemId = i.id and iu.deleted = false and iu.salesUnit = true " + " left join uom_conversion uc on uc.id = iu.uomId " + + " left join inventory inv on inv.itemId = i.id " + " where i.deleted = false " + " and i.type = :type " ) diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index 52d7f6a..5b52b12 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -127,7 +127,85 @@ open class PickOrderService( val total = response.totalElements return RecordsRes(records, total.toInt()) } + + + open fun getPickOrdersWithStockBalanceByPage(request: SearchPickOrderRequest): RecordsRes { + val pageable = PageRequest.of(request.pageNum ?: 0, request.pageSize ?: 10); + + // First get the basic pick order info for pagination + 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 pickOrderIds = records.mapNotNull { it.id } + + if (pickOrderIds.isEmpty()) { + return RecordsRes(emptyList(), 0) + } + + // Get full pick orders with relationships + val fullPickOrders = pickOrderRepository.findAllByIdIn(pickOrderIds) + + // Get all item IDs + val itemIds = fullPickOrders + .flatMap { it.pickOrderLines } + .mapNotNull { it.item?.id } + .distinct() + + // Get inventory data + val today = LocalDate.now() + val zero = BigDecimal.ZERO + + val inventories = if (itemIds.isNotEmpty()) { + inventoryLotLineService + .allInventoryLotLinesByItemIdIn(itemIds) + .filter { it.status == InventoryLotLineStatus.AVAILABLE.value } + .filter { (it.inQty ?: zero).minus(it.outQty ?: zero).minus(it.holdQty ?: zero) > zero } + .filter { it.expiryDate.isAfter(today) || it.expiryDate.isEqual(today) } + .groupBy { it.item?.id } + } else { + emptyMap() + } + + // Build response (removed suggestions) + val pickOrderInfos = fullPickOrders.map { po -> + val pickOrderLineInfos = po.pickOrderLines.map { pol -> + val inventory = pol.item?.id?.let { inventories[it] } + + GetPickOrderLineInfo( + id = pol.id, + itemId = pol.item?.id, + itemCode = pol.item?.code, + itemName = pol.item?.name, + availableQty = inventory?.sumOf { i -> (i.availableQty ?: zero) }, + requiredQty = pol.qty, + uomCode = pol.uom?.code, + uomDesc = pol.uom?.udfudesc, + suggestedList = emptyList() // Empty list since you don't need suggestions + ) + } + + GetPickOrderInfo( + id = po.id, + code = po.code, + targetDate = po.targetDate, + type = po.type?.value, + status = po.status?.value, + pickOrderLines = pickOrderLineInfos + ) + } + + val total = response.totalElements + return RecordsRes(pickOrderInfos, total.toInt()) + } open fun getConsoPickOrderList(args: MutableMap): List> { val sql = StringBuilder( "select" @@ -145,6 +223,9 @@ open class PickOrderService( if (args.containsKey("status")) { sql.append(" AND po.status = :status "); } + if (args.containsKey("assignTo")) { + sql.append(" AND po.assignTo = :assignTo "); + } sql.append(" group by po.consoCode, po.releasedDate, po.status, po.assignTo ") return jdbcDao.queryForList(sql.toString(), args); } diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt index fd999d0..9d927e5 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt @@ -45,11 +45,17 @@ class PickOrderController( fun allPickOrdersByPage(@ModelAttribute request: SearchPickOrderRequest): RecordsRes { return pickOrderService.allPickOrdersByPage(request); } + + @GetMapping("/getRecordByPageWithStock") + fun getPickOrdersWithStockBalanceByPage(@ModelAttribute request: SearchPickOrderRequest): RecordsRes { + return pickOrderService.getPickOrdersWithStockBalanceByPage(request); + } @GetMapping("/getRecordByPage-conso") fun allConsoPickOrdersByPage(request: HttpServletRequest): RecordsRes> { val criteriaArgs = CriteriaArgsBuilder.withRequest(request) .addStringLike("consoCode") .addString("status") + .addString("assignTo") .build() 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