@@ -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}") | |||