# Conflicts: # src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.ktmaster
| @@ -64,11 +64,11 @@ class M18TestController ( | |||
| return schedulerService.getM18Pos(); | |||
| } | |||
| // --------------------------------------------- Scheduler --------------------------------------------- /// | |||
| @GetMapping("/schedule/po") // | |||
| fun schedulePo(@RequestParam @Valid newCron: String) { | |||
| settingsService.update(SettingNames.SCHEDULE_M18_PO, newCron); | |||
| schedulerService.scheduleM18PoTask() | |||
| } | |||
| // @GetMapping("/schedule/po") | |||
| // fun schedulePo(@RequestParam @Valid newCron: String) { | |||
| // settingsService.update(SettingNames.SCHEDULE_M18_PO, newCron); | |||
| // schedulerService.scheduleM18PoTask() | |||
| // } | |||
| // --------------------------------------------- Master Data --------------------------------------------- /// | |||
| @GetMapping("/all") | |||
| @@ -0,0 +1,30 @@ | |||
| package com.ffii.fpsms.modules.common.scheduler.web | |||
| import com.ffii.fpsms.modules.common.SettingNames | |||
| import com.ffii.fpsms.modules.common.scheduler.service.SchedulerService | |||
| import com.ffii.fpsms.modules.settings.service.SettingsService | |||
| import jakarta.validation.Valid | |||
| import org.springframework.web.bind.annotation.GetMapping | |||
| import org.springframework.web.bind.annotation.RequestMapping | |||
| import org.springframework.web.bind.annotation.RequestParam | |||
| import org.springframework.web.bind.annotation.RestController | |||
| @RestController | |||
| @RequestMapping("/scheduler") | |||
| class SchedulerController( | |||
| val schedulerService: SchedulerService, | |||
| val settingsService: SettingsService | |||
| ) { | |||
| @GetMapping("/testDetailedProd") | |||
| fun testDetailedProd(): Any { | |||
| schedulerService.getDetailedProdSchedule() | |||
| return 200 | |||
| } | |||
| // Cron Settings | |||
| @GetMapping("/updateSetting/poCron") | |||
| fun schedulePo(@RequestParam @Valid newCron: String) { | |||
| settingsService.update(SettingNames.SCHEDULE_M18_PO, newCron); | |||
| schedulerService.scheduleM18PoTask() | |||
| } | |||
| } | |||
| @@ -2,10 +2,12 @@ package com.ffii.fpsms.modules.deliveryOrder.entity | |||
| import com.ffii.core.support.AbstractRepository | |||
| import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo | |||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | |||
| import com.ffii.fpsms.modules.master.entity.projections.SearchId | |||
| import org.springframework.data.jpa.repository.Query | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| import java.time.LocalDateTime | |||
| @Repository | |||
| interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | |||
| @@ -17,9 +19,15 @@ interface DeliveryOrderRepository : AbstractRepository<DeliveryOrder, Long> { | |||
| fun findAllByCodeAndDeletedIsFalse(code: String): List<DeliveryOrderInfo> | |||
| fun findAllByShopNameAndDeletedIsFalse(shopName: String): List<DeliveryOrderInfo> | |||
| fun findAllByStatusAndDeletedIsFalse(status: DeliveryOrderStatus): List<DeliveryOrderInfo> | |||
| fun findByOrderDateBetweenAndDeletedIsFalse(start: LocalDateTime?, end: LocalDateTime?) : List<DeliveryOrderInfo> | |||
| fun findAllByCodeContainsAndShopNameContainsAndStatusAndOrderDateBetween(code: String?, shopName: String?, status: DeliveryOrderStatus?, startDate: LocalDateTime?, endDate: LocalDateTime?) : List<DeliveryOrderInfo> | |||
| fun findAllByCodeContainsAndShopNameContainsAndStatus(code: String?, shopName: String?, status: DeliveryOrderStatus?): List<DeliveryOrderInfo>; | |||
| fun findAllBy() : List<DeliveryOrderInfo>; | |||
| } | |||
| @@ -3,5 +3,5 @@ package com.ffii.fpsms.modules.deliveryOrder.enums | |||
| enum class DeliveryOrderStatus(val value: String) { | |||
| PENDING("pending"), | |||
| RECEIVING("receiving"), | |||
| COMPLETED("completed"); | |||
| COMPLETED("completed"), | |||
| } | |||
| @@ -28,6 +28,8 @@ import com.ffii.fpsms.modules.pickOrder.service.PickOrderService | |||
| import java.time.LocalDate | |||
| import java.math.BigDecimal | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| import java.time.LocalDateTime | |||
| @Service | |||
| open class DeliveryOrderService( | |||
| private val deliveryOrderRepository: DeliveryOrderRepository, | |||
| @@ -82,6 +84,26 @@ open class DeliveryOrderService( | |||
| return deliveryOrderRepository.findAllByCodeAndDeletedIsFalse(code); | |||
| } | |||
| open fun searchByShopName(shopName: String) : List<DeliveryOrderInfo> { | |||
| return deliveryOrderRepository.findAllByShopNameAndDeletedIsFalse(shopName); | |||
| } | |||
| open fun searchByStatus(status: DeliveryOrderStatus): List<DeliveryOrderInfo> { | |||
| return deliveryOrderRepository.findAllByStatusAndDeletedIsFalse(status); | |||
| } | |||
| open fun searchBetweenOrderDate(start: LocalDateTime?, end: LocalDateTime?): List<DeliveryOrderInfo> { | |||
| return deliveryOrderRepository.findByOrderDateBetweenAndDeletedIsFalse(start, end); | |||
| } | |||
| open fun searchDO(code: String?, shopName: String?, status: DeliveryOrderStatus?, startDate: LocalDateTime?, endDate: LocalDateTime?):List<DeliveryOrderInfo> { | |||
| if(status == null || startDate == null || endDate ==null){ | |||
| return deliveryOrderRepository.findAllBy(); | |||
| } | |||
| return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndOrderDateBetween(code, shopName, status, startDate, endDate); | |||
| } | |||
| open fun updateDeliveryOrderStatus(request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | |||
| val deliveryOrder = checkNotNull( | |||
| @@ -18,6 +18,8 @@ import com.ffii.fpsms.modules.deliveryOrder.web.models.DoDetailResponse | |||
| import com.ffii.fpsms.modules.deliveryOrder.web.models.ReleaseDoRequest | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| import jakarta.validation.Valid | |||
| import java.time.LocalDateTime | |||
| @RequestMapping("/do") | |||
| @RestController | |||
| class DeliveryOrderController( | |||
| @@ -34,10 +36,32 @@ class DeliveryOrderController( | |||
| } | |||
| @GetMapping("/search-code/{code}") | |||
| fun searchByCode(@PathVariable code: String): List<DeliveryOrderInfo>{ | |||
| fun searchByCode(@PathVariable code: String): List<DeliveryOrderInfo> { | |||
| return deliveryOrderService.searchByCode(code); | |||
| } | |||
| @GetMapping("/search-shopname/{shopName}") | |||
| fun searchByShopName(@PathVariable shopName: String): List<DeliveryOrderInfo> { | |||
| return deliveryOrderService.searchByShopName(shopName); | |||
| } | |||
| @GetMapping("/search-status/{status}") | |||
| fun searchByStatus(@PathVariable status: DeliveryOrderStatus): List<DeliveryOrderInfo> { | |||
| return deliveryOrderService.searchByStatus(status); | |||
| } | |||
| @GetMapping("/search-orderdate/{start}&{end}") | |||
| fun searchBetweenOrderDate(@PathVariable start: LocalDateTime?,@PathVariable end: LocalDateTime?): List<DeliveryOrderInfo> { | |||
| return deliveryOrderService.searchBetweenOrderDate(start, end); | |||
| } | |||
| @GetMapping("/search-DO/{code}&{shopName}&{status}&{startDate}&{endDate}") | |||
| fun searchDO(@PathVariable code: String?, @PathVariable shopName: String?, @PathVariable status: DeliveryOrderStatus?, @PathVariable startDate: LocalDateTime? , @PathVariable endDate: LocalDateTime?): List<DeliveryOrderInfo>{ | |||
| return deliveryOrderService.searchDO(code, shopName, status, startDate, endDate); | |||
| } | |||
| @PostMapping("/update-status") | |||
| fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse { | |||
| return deliveryOrderService.updateDeliveryOrderStatus(request); | |||
| @@ -24,7 +24,7 @@ open class JobOrderBomMaterialService( | |||
| open fun createJobOrderBomMaterialRequests(joId: Long): List<CreateJobOrderBomMaterialRequest> { | |||
| val zero = BigDecimal.ZERO | |||
| val jo = jobOrderRepository.findById(joId).getOrNull() ?: throw NoSuchElementException() | |||
| val proportion = (jo.reqQty ?: zero).divide(jo.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val proportion = BigDecimal.ONE //(jo.reqQty ?: zero).divide(jo.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val jobmRequests = jo.bom?.bomMaterials?.map { bm -> | |||
| val salesUnit = bm.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | |||
| @@ -14,7 +14,8 @@ interface ProductionScheduleLineRepository : AbstractRepository<ProductionSchedu | |||
| with prod_prop as ( | |||
| select | |||
| psl.id as pslId, | |||
| round(coalesce(psl.prodQty, 0) / coalesce(b.outputQty, 1), 5) as proportion | |||
| -- round(coalesce(psl.prodQty, 0) / coalesce(b.outputQty, 1), 5) as proportion | |||
| 1 as proportion | |||
| from production_schedule_line psl | |||
| left join bom b on b.itemId = psl.itemId | |||
| where psl.id = :id and b.id is not null | |||
| @@ -36,9 +36,17 @@ interface ProductionScheduleRepository : AbstractRepository<ProductionSchedule, | |||
| ps.totalFGType, | |||
| ps.`type` | |||
| from production_schedule ps | |||
| ), | |||
| ranked_prod as ( | |||
| select | |||
| *, | |||
| row_number() over (partition by date(schedulePeriod) and date(schedulePeriodTo) order by scheduleAt desc) as rn | |||
| from prod | |||
| where deleted = false | |||
| ) | |||
| select * from prod | |||
| select * from ranked_prod | |||
| where deleted = false | |||
| and rn = 1 | |||
| and (:scheduleAt = '' or datediff(scheduleAt, coalesce(:scheduleAt, scheduleAt)) = 0) | |||
| and (:schedulePeriod = '' or datediff(schedulePeriod, coalesce(:schedulePeriod, schedulePeriod)) = 0) | |||
| and (:schedulePeriodTo = '' or datediff(schedulePeriodTo, coalesce(:schedulePeriodTo, schedulePeriodTo)) = 0) | |||
| @@ -59,9 +67,17 @@ interface ProductionScheduleRepository : AbstractRepository<ProductionSchedule, | |||
| ps.totalFGType, | |||
| ps.`type` | |||
| from production_schedule ps | |||
| ), | |||
| ranked_prod as ( | |||
| select | |||
| *, | |||
| row_number() over (partition by date(schedulePeriod) and date(schedulePeriodTo) order by scheduleAt desc) as rn | |||
| from prod | |||
| where deleted = false | |||
| ) | |||
| select count(*) from prod | |||
| select count(*) from ranked_prod | |||
| where deleted = false | |||
| and rn = 1 | |||
| and (:scheduleAt = '' or datediff(scheduleAt, coalesce(:scheduleAt, scheduleAt)) = 0) | |||
| and (:schedulePeriod = '' or datediff(schedulePeriod, coalesce(:schedulePeriod, schedulePeriod)) = 0) | |||
| and (:schedulePeriodTo = '' or datediff(schedulePeriodTo, coalesce(:schedulePeriodTo, schedulePeriodTo)) = 0) | |||
| @@ -84,16 +100,21 @@ interface ProductionScheduleRepository : AbstractRepository<ProductionSchedule, | |||
| nativeQuery = true, | |||
| value = | |||
| """ | |||
| select | |||
| ps.id, | |||
| ps.deleted, | |||
| ps.scheduleAt, | |||
| ps.produceAt, | |||
| ps.totalEstProdCount, | |||
| ps.totalFGType, | |||
| ps.`type` | |||
| from production_schedule ps | |||
| where deleted = false | |||
| select * | |||
| from ( | |||
| select | |||
| ps.id, | |||
| ps.deleted, | |||
| ps.scheduleAt, | |||
| ps.produceAt, | |||
| ps.totalEstProdCount, | |||
| ps.totalFGType, | |||
| ps.`type`, | |||
| row_number() over (partition by date(ps.produceAt) order by ps.scheduleAt desc) as rn | |||
| from production_schedule ps | |||
| where deleted = false | |||
| ) ranked_prod | |||
| where rn = 1 | |||
| and produceAt is not null | |||
| and scheduleAt in (select max(ps2.scheduleAt) from production_schedule ps2 group by ps2.produceAt) | |||
| -- and (:scheduleAt = '' or datediff(scheduleAt, coalesce(:scheduleAt, scheduleAt)) = 0) | |||
| @@ -117,7 +138,8 @@ interface ProductionScheduleRepository : AbstractRepository<ProductionSchedule, | |||
| with prod_prop as ( | |||
| select | |||
| psl.id as pslId, | |||
| round(coalesce(psl.prodQty, 0) / coalesce(b.outputQty, 1), 5) as proportion | |||
| -- round(coalesce(psl.prodQty, 0) / coalesce(b.outputQty, 1), 5) as proportion | |||
| 1 as proportion | |||
| from production_schedule ps | |||
| left join production_schedule_line psl on psl.prodScheduleId = ps.id | |||
| left join bom b on b.itemId = psl.itemId | |||
| @@ -214,7 +236,7 @@ interface ProductionScheduleRepository : AbstractRepository<ProductionSchedule, | |||
| where psl.deleted is false and pe.prodTimeInMinute is not null and pm.bomMaterials is not null | |||
| and ps.id = :id | |||
| group by psl.id, jo.id, pp.proportion, pm.bomOutputQty, uc.udfudesc | |||
| ) prod group by prod.id limit 1 | |||
| ) prod group by prod.id limit 1; | |||
| """ | |||
| ) | |||
| fun findDetailedProdScheduleWithLine(id: Long): DetailedProdScheduleWithLineWithJsonString? | |||
| @@ -8,6 +8,7 @@ import java.time.LocalDateTime | |||
| interface ProdScheduleInfo { | |||
| val id: Long? | |||
| val scheduleAt: LocalDate? | |||
| val produceAt: LocalDate? | |||
| val schedulePeriod: LocalDate? | |||
| val schedulePeriodTo: LocalDate? | |||
| val totalEstProdCount: BigDecimal? | |||
| @@ -143,7 +143,7 @@ open class ProductionScheduleService( | |||
| // BigDecimal.ONE | |||
| // } | |||
| val proportion = BigDecimal(line.prodQty).divide(bm.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val proportion = BigDecimal.ONE // BigDecimal(line.prodQty).divide(bm.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val demandQty = bm.qty?.times(proportion) ?: zero | |||
| val saleUnit = bm.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | |||
| @@ -230,7 +230,7 @@ open class ProductionScheduleService( | |||
| // BigDecimal.ONE | |||
| // } | |||
| val proportion = BigDecimal(line.prodQty).divide(bm.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val proportion = BigDecimal.ONE //BigDecimal(line.prodQty).divide(bm.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val demandQty = bm.qty?.times(proportion) ?: zero | |||
| val saleUnit = bm.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | |||
| @@ -363,7 +363,7 @@ open class ProductionScheduleService( | |||
| val prodScheduleLine = request.id.let { productionScheduleLineRepository.findById(it).getOrNull() } ?: throw NoSuchElementException() | |||
| val bom = prodScheduleLine.item.id?.let { bomService.findByItemId(it) } | |||
| val approver = SecurityUtils.getUser().getOrNull() | |||
| val proportion = request.demandQty.divide(bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val proportion = BigDecimal.ONE // request.demandQty.divide(bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP) | |||
| val isSameQty = request.demandQty.equals(prodScheduleLine.prodQty) | |||
| // Update Prod Schedule Type | |||
| @@ -441,7 +441,7 @@ open class PickOrderService( | |||
| val salesUnit = inventoryLotLine?.inventoryLot?.item?.id?.let { _itemId -> | |||
| itemUomService.findSalesUnitByItemId(_itemId) | |||
| } | |||
| val ratio = BigDecimal.ONE | |||
| val ratio = BigDecimal.ONE //(salesUnit?.ratioN ?: zero).divide(salesUnit?.ratioD ?: one) | |||
| val remainingQty = (inventoryLotLine?.inQty ?: zero) | |||
| .minus(inventoryLotLine?.outQty ?: zero) | |||
| @@ -65,4 +65,8 @@ interface PutAwayLineForSil { | |||
| val warehouseCode: String?; | |||
| @get:Value("#{target.warehouse?.name}") | |||
| val warehouseName: String?; | |||
| @get:Value("#{target.created}") | |||
| val putawayDate: LocalDateTime?; | |||
| @get:Value("#{target.createdBy}") | |||
| val putawayUser: String?; | |||
| } | |||