| @@ -207,6 +207,7 @@ open class ProductionScheduleService( | |||
| val resultList = jdbcDao.queryForList(sql.toString(), args, ); | |||
| //TODO: From Global config | |||
| val DARK_MAX_VALUE = 1; | |||
| val FLOAT_MAX_VALUE = 5; | |||
| val DENSE_MAX_VALUE = 5; | |||
| @@ -1,6 +1,7 @@ | |||
| package com.ffii.fpsms.modules.pickOrder.service | |||
| import com.ffii.core.response.RecordsRes | |||
| import com.ffii.core.support.JdbcDao | |||
| import com.ffii.fpsms.modules.common.SecurityUtils | |||
| import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository | |||
| import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo | |||
| @@ -12,8 +13,11 @@ import com.ffii.fpsms.modules.stock.service.InventoryService | |||
| import com.ffii.fpsms.modules.stock.service.StockOutLineService | |||
| import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService | |||
| import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPoRequest | |||
| import com.ffii.fpsms.modules.user.entity.UserRepository | |||
| import com.ffii.fpsms.modules.user.service.UserService | |||
| import org.springframework.data.domain.PageRequest | |||
| import org.springframework.http.HttpStatus | |||
| import org.springframework.http.ResponseEntity | |||
| import org.springframework.stereotype.Service | |||
| import org.springframework.transaction.annotation.Transactional | |||
| import java.io.Serializable | |||
| @@ -25,10 +29,12 @@ import kotlin.jvm.optionals.getOrNull | |||
| @Service | |||
| open class PickOrderService( | |||
| private val jdbcDao: JdbcDao, | |||
| val pickOrderRepository: PickOrderRepository, | |||
| val stockOutLineService: StockOutLineService, | |||
| val suggestedPickLotService: SuggestedPickLotService, | |||
| val userService: UserService, private val inventoryLotLineRepository: InventoryLotLineRepository, | |||
| val userService: UserService, | |||
| private val inventoryLotLineRepository: InventoryLotLineRepository, | |||
| val inventoryService: InventoryService, | |||
| ) { | |||
| open fun localDateTimeParse(dateTime: String?, pattern: String? = "YYYY-MM-DD hh:mm:ss"): LocalDateTime? { | |||
| @@ -62,6 +68,25 @@ open class PickOrderService( | |||
| return RecordsRes<PickOrderInfo>(records, total.toInt()) | |||
| } | |||
| open fun getConsoPickOrderList(args: MutableMap<String, Any>): List<Map<String, Any>> { | |||
| val sql = StringBuilder( "select" | |||
| + " po.consoCode, " | |||
| + " po.releasedDate, " | |||
| + " po.status, " | |||
| + " po.assignTo " | |||
| + " from pick_order po " | |||
| + " where po.deleted = false " | |||
| + " and po.consoCode is not null " | |||
| ) | |||
| if (args.containsKey("consoCode")){ | |||
| sql.append(" AND po.consoCode like :consoCode "); | |||
| } | |||
| if (args.containsKey("status")){ | |||
| sql.append(" AND po.status = :status "); | |||
| } | |||
| sql.append(" group by po.consoCode, po.releasedDate, po.status, po.assignTo ") | |||
| return jdbcDao.queryForList(sql.toString(), args); | |||
| } | |||
| // Consolidating Pick Orders | |||
| open fun assignConsoCode(): String { | |||
| val suffixFormat = "%03d" | |||
| @@ -91,12 +116,14 @@ open class PickOrderService( | |||
| it.consoCode = newConsoCode | |||
| it.status = PickOrderStatus.CONSOLIDATED | |||
| } | |||
| println(newConsoCode) | |||
| println(pickOrders) | |||
| val updatedPickOrders = pickOrderRepository.saveAll(pickOrders) | |||
| val updatedPickOrderInfos = updatedPickOrders.map { po -> po.id as Serializable } | |||
| val savedPickOrders = pickOrderRepository.saveAll(pickOrders) | |||
| val savedPickOrderInfos = savedPickOrders.map { po -> po.id as Serializable } | |||
| .let { pickOrderRepository.findPickOrderInfoByIdIn(it) } | |||
| return updatedPickOrderInfos | |||
| return savedPickOrderInfos | |||
| } | |||
| open fun deconsoPickOrders(request: ConsoPickOrderRequest): List<PickOrderInfo> { | |||
| @@ -113,6 +140,32 @@ open class PickOrderService( | |||
| return updatedPickOrderInfos | |||
| } | |||
| open fun getPickOrderLine(args: MutableMap<String, Any>): List<Map<String, Any>> { | |||
| if (!args.containsKey("consoCode") || args["consoCode"] == null) { | |||
| throw IllegalArgumentException("consoCode must not be null") | |||
| } | |||
| val sql = StringBuilder("select" | |||
| + " pol.id, " | |||
| + " i.name as itemName, " | |||
| + " pol.qty as qty, " | |||
| + " max(uc.code) as uom, " | |||
| + " group_concat(w.name) as warehouse, " | |||
| + " group_concat(il.lotNo) as suggestedLotNo " | |||
| + " from pick_order po " | |||
| + " left join pick_order_line pol on pol.poId = po.id " | |||
| + " left join items i on i.id = pol.itemId " | |||
| + " left join suggested_pick_lot spl on spl.pickOrderLineId = pol.id " | |||
| + " left join inventory_lot_line ill on ill.id = spl.suggestedLotLineId " | |||
| + " left join warehouse w on w.id = ill.warehouseId " | |||
| + " left join inventory_lot il on il.id = ill.inventoryLotId " | |||
| + " left join uom_conversion uc on uc.id = pol.uomId " | |||
| + " where po.deleted = false " | |||
| + " and po.consoCode = :consoCode " | |||
| + " group by pol.id, i.name, pol.qty " | |||
| ) | |||
| return jdbcDao.queryForList(sql.toString(), args); | |||
| } | |||
| // TODO: Add actual pick lots | |||
| open fun consoPickOrderDetail(consoCode: String): ConsoPickOrderResponse { | |||
| val zero = BigDecimal.ZERO | |||
| @@ -128,7 +181,6 @@ open class PickOrderService( | |||
| // Mapping: PickOrder -> PickOrderInConso | |||
| val finalPos = pos.map { po -> | |||
| val pols = po.pickOrderLines | |||
| // Suggestions for Pick Order Line | |||
| // val suggestions = suggestedPickLotService.suggestionForPickOrderLines(pols) | |||
| @@ -253,7 +305,7 @@ open class PickOrderService( | |||
| open fun releaseConsoPickOrderInfo(consoCode: String): ReleasePickOrderInfoResponse { | |||
| val zero = BigDecimal.ZERO | |||
| val pos = pickOrderRepository.findAllByConsoCodeAndStatus(consoCode, PickOrderStatus.CONSOLIDATED) | |||
| println(pos) | |||
| // Get Inventory Data | |||
| val requiredItems = pos | |||
| .flatMap { it.pickOrderLines } | |||
| @@ -263,8 +315,10 @@ open class PickOrderService( | |||
| override val id: Long? = value[0].item?.id | |||
| override val code: String? = value[0].item?.code | |||
| override val name: String? = value[0].item?.name | |||
| override val uomDesc: String? = value[0].uom?.udfudesc | |||
| override var availableQty: BigDecimal? = zero | |||
| override val requiredQty: BigDecimal = value.sumOf { it.qty ?: zero } | |||
| } | |||
| } // itemId - requiredQty | |||
| @@ -322,15 +376,15 @@ open class PickOrderService( | |||
| } | |||
| @Transactional(rollbackFor = [java.lang.Exception::class]) | |||
| open fun releaseConsoPickOrderAction(request: ReleaseConsoPickOrderRequest) { | |||
| open fun releaseConsoPickOrderAction(request: ReleaseConsoPickOrderRequest): ResponseEntity<String> { | |||
| val releasedBy = SecurityUtils.getUser().getOrNull() | |||
| val assignTo = request.assignTo?.let { userService.find(it) }?.getOrNull() | |||
| val pos = pickOrderRepository.findAllByConsoCodeAndStatus(request.consoCode, PickOrderStatus.CONSOLIDATED) | |||
| pos.forEach { | |||
| it.apply { | |||
| this.releasedBy = releasedBy | |||
| this.assignTo = assignTo | |||
| status = PickOrderStatus.RELEASED | |||
| this.assignTo = assignTo | |||
| } | |||
| } | |||
| @@ -339,5 +393,6 @@ open class PickOrderService( | |||
| suggestedPickLotService.saveAll(suggestions.suggestedList) | |||
| pickOrderRepository.saveAll(pos) | |||
| return ResponseEntity("success", HttpStatus.OK) | |||
| } | |||
| } | |||
| @@ -1,14 +1,22 @@ | |||
| package com.ffii.fpsms.modules.pickOrder.web | |||
| import com.ffii.core.response.RecordsRes | |||
| import com.ffii.core.utils.CriteriaArgsBuilder | |||
| import com.ffii.core.utils.PagingUtils | |||
| 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.* | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderRequest | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderResponse | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.ReleaseConsoPickOrderRequest | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest | |||
| import jakarta.servlet.http.HttpServletRequest | |||
| 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.http.ResponseEntity | |||
| import org.springframework.web.bind.annotation.GetMapping | |||
| import org.springframework.web.bind.annotation.ModelAttribute | |||
| import org.springframework.web.bind.annotation.PathVariable | |||
| @@ -36,6 +44,30 @@ class PickOrderController( | |||
| fun allPickOrdersByPage(@ModelAttribute request: SearchPickOrderRequest): RecordsRes<PickOrderInfo> { | |||
| return pickOrderService.allPickOrdersByPage(request); | |||
| } | |||
| @GetMapping("/getRecordByPage-conso") | |||
| fun allConsoPickOrdersByPage(request: HttpServletRequest): RecordsRes<Map<String, Any>> { | |||
| val criteriaArgs = CriteriaArgsBuilder.withRequest(request) | |||
| .addStringLike("consoCode") | |||
| .addString("status") | |||
| .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 | |||
| val fullList = pickOrderService.getConsoPickOrderList(criteriaArgs) | |||
| val paginatedList = PagingUtils.getPaginatedList(fullList,pageSize, pageNum) | |||
| return RecordsRes(paginatedList, fullList.size) | |||
| } | |||
| @GetMapping("/get-pickorder-line-byPage") | |||
| fun getPickOrderLine(request: HttpServletRequest): RecordsRes<Map<String, Any>> { | |||
| val criteriaArgs = CriteriaArgsBuilder.withRequest(request) | |||
| .addString("consoCode") | |||
| .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 | |||
| val fullList = pickOrderService.getPickOrderLine(criteriaArgs) | |||
| val paginatedList = PagingUtils.getPaginatedList(fullList,pageSize, pageNum) | |||
| return RecordsRes(paginatedList, fullList.size) | |||
| } | |||
| // Consolidating Pick Orders | |||
| @PostMapping("/conso") | |||
| @@ -54,13 +86,13 @@ class PickOrderController( | |||
| } | |||
| // Release Pick Order | |||
| @GetMapping("/releaseConso/{consoCode}") | |||
| @GetMapping("/pre-release-info/{consoCode}") | |||
| fun releaseConsoPickOrderInfo(@PathVariable consoCode: String): ReleasePickOrderInfoResponse { | |||
| return pickOrderService.releaseConsoPickOrderInfo(consoCode); | |||
| } | |||
| @PostMapping("/releaseConso") | |||
| fun releaseConsoPickOrderAction(@Valid @RequestBody request: ReleaseConsoPickOrderRequest) { | |||
| pickOrderService.releaseConsoPickOrderAction(request) | |||
| fun releaseConsoPickOrderAction(@Valid @RequestBody request: ReleaseConsoPickOrderRequest): ResponseEntity<String> { | |||
| return pickOrderService.releaseConsoPickOrderAction(request) | |||
| } | |||
| } | |||
| @@ -43,6 +43,7 @@ interface CurrentInventoryItemInfo { | |||
| val id: Long? // item id | |||
| val code: String? | |||
| val name: String? | |||
| val uomDesc: String? | |||
| val availableQty: BigDecimal? | |||
| val requiredQty: BigDecimal? | |||
| } | |||
| @@ -69,8 +69,8 @@ open class SuggestedPickLotService( | |||
| // get current inventory lot line qty & grouped by item Id | |||
| val availableInventoryLotLines = inventoryLotLineService | |||
| .allInventoryLotLinesByItemIdIn(itemIds) | |||
| .filter { (it.inQty ?: zero).minus(it.outQty ?: zero).minus(it.holdQty ?: zero) > zero } | |||
| .filter { it.status == InventoryLotLineStatus.AVAILABLE.value } | |||
| .filter { (it.inQty ?: zero).minus(it.outQty ?: zero).minus(it.holdQty ?: zero) > zero } | |||
| .sortedBy { it.expiryDate } | |||
| .groupBy { it.item?.id } | |||
| @@ -2,18 +2,23 @@ package com.ffii.fpsms.modules.stock.web | |||
| import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderRequest | |||
| import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository | |||
| import com.ffii.fpsms.modules.stock.entity.StockInLineRepository | |||
| import com.ffii.fpsms.modules.stock.web.model.LotLineInfo | |||
| import jakarta.validation.Valid | |||
| 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.RequestBody | |||
| import org.springframework.web.bind.annotation.RequestMapping | |||
| import org.springframework.web.bind.annotation.RequestParam | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import java.math.BigDecimal | |||
| @RequestMapping("/inventoryLotLine") | |||
| @RestController | |||
| class InventoryLotLineController ( | |||
| private val inventoryLotLineRepository: InventoryLotLineRepository | |||
| private val inventoryLotLineRepository: InventoryLotLineRepository, | |||
| private val stockInLineRepository: StockInLineRepository, | |||
| ){ | |||
| // @PostMapping("/test") | |||
| @@ -24,4 +29,19 @@ class InventoryLotLineController ( | |||
| fun test(@Valid @RequestBody request: ConsoPickOrderRequest): Any { | |||
| return inventoryLotLineRepository.findCurrentInventoryByItems(request.ids) | |||
| } | |||
| @GetMapping("/lot-detail/{stockInLineId}") | |||
| fun getLotDetail(@Valid @PathVariable stockInLineId: Long): LotLineInfo { | |||
| val stockInLine = stockInLineRepository.findById(stockInLineId).orElseThrow() | |||
| val inventoryLotLine = stockInLine.inventoryLotLine!! | |||
| val zero = BigDecimal.ZERO | |||
| return LotLineInfo( | |||
| inventoryLotLineId = inventoryLotLine.id!!, | |||
| lotNo = stockInLine.lotNo!!, | |||
| remainingQty = (inventoryLotLine.inQty ?: zero) | |||
| .minus(inventoryLotLine.outQty ?: zero) | |||
| .minus(inventoryLotLine.holdQty ?: zero), | |||
| uom = inventoryLotLine.stockUom!!.uom!!.udfudesc!! | |||
| ) | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| package com.ffii.fpsms.modules.stock.web.model | |||
| import java.math.BigDecimal | |||
| data class LotLineInfo( | |||
| val inventoryLotLineId: Long, | |||
| val lotNo: String, | |||
| val remainingQty: BigDecimal, | |||
| val uom: String | |||
| ) | |||
| @@ -1,11 +1,14 @@ | |||
| package com.ffii.fpsms.modules.user.web; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import com.ffii.fpsms.modules.user.service.pojo.UserRecord; | |||
| import org.apache.commons.logging.Log; | |||
| import org.apache.commons.logging.LogFactory; | |||
| import org.hibernate.mapping.Any; | |||
| import org.springframework.http.HttpStatus; | |||
| import org.springframework.http.ResponseEntity; | |||
| import org.springframework.security.access.prepost.PreAuthorize; | |||
| @@ -69,6 +72,19 @@ public class UserController{ | |||
| return ResponseEntity.ok(userService.search(req)); | |||
| } | |||
| @GetMapping("/name-list") | |||
| public ResponseEntity<List<Map<String, Object>>> namelist() { | |||
| SearchUserReq req = new SearchUserReq(); | |||
| List<Map<String, Object>> namelist = userService.search(req).stream() | |||
| .map(user -> { | |||
| Map<String, Object> map = new HashMap<>(); | |||
| map.put("id", user.getId()); | |||
| map.put("name", user.getName()); | |||
| return map; | |||
| }) | |||
| .toList(); | |||
| return ResponseEntity.ok(namelist); | |||
| } | |||
| // @Operation(summary = "load user data", responses = { @ApiResponse(responseCode = "200"), | |||
| // @ApiResponse(responseCode = "404", content = @Content) }) | |||
| @GetMapping("/{id}") | |||