Browse Source

[Job Order] Can manual create job order now

master
cyril.tsui 4 weeks ago
parent
commit
0eeacf5c16
11 changed files with 87 additions and 13 deletions
  1. +5
    -2
      src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderRepository.kt
  2. +3
    -3
      src/main/java/com/ffii/fpsms/modules/jobOrder/entity/projections/JobOrderInfo.kt
  3. +29
    -1
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderBomMaterialService.kt
  4. +5
    -4
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt
  5. +14
    -0
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt
  6. +2
    -2
      src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt
  7. +2
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/BomMaterialRepository.kt
  8. +3
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/BomRepository.kt
  9. +11
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/projections/BomCombo.kt
  10. +5
    -0
      src/main/java/com/ffii/fpsms/modules/master/service/BomMaterialService.kt
  11. +8
    -1
      src/main/java/com/ffii/fpsms/modules/master/web/BomController.kt

+ 5
- 2
src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderRepository.kt View File

@@ -25,7 +25,8 @@ interface JobOrderRepository : AbstractRepository<JobOrder, Long> {
jo.code, jo.code,
b.name, b.name,
jo.reqQty, jo.reqQty,
b.outputQtyUom,
-- b.outputQtyUom,
uc2.udfudesc as uom,
json_arrayagg( json_arrayagg(
json_object( json_object(
'id', jobm.id, 'id', jobm.id,
@@ -40,6 +41,8 @@ interface JobOrderRepository : AbstractRepository<JobOrder, Long> {
jo.status jo.status
from job_order jo from job_order jo
left join bom b on b.id = jo.bomId 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 job_order_bom_material jobm on jo.id = jobm.jobOrderId
left join items i on i.id = jobm.itemId left join items i on i.id = jobm.itemId
left join uom_conversion uc on uc.id = jobm.uomId left join uom_conversion uc on uc.id = jobm.uomId
@@ -47,7 +50,7 @@ interface JobOrderRepository : AbstractRepository<JobOrder, Long> {
left join inventory_lot_line ill on ill.id = sol.inventoryLotLineId left join inventory_lot_line ill on ill.id = sol.inventoryLotLineId
left join inventory_lot il on il.id = ill.inventoryLotId left join inventory_lot il on il.id = ill.inventoryLotId
where jo.id = :id where jo.id = :id
group by jo.id
group by jo.id, uc2.udfudesc
limit 1 limit 1
""" """
) )


+ 3
- 3
src/main/java/com/ffii/fpsms/modules/jobOrder/entity/projections/JobOrderInfo.kt View File

@@ -12,7 +12,7 @@ interface JobOrderInfo {
val name: String; val name: String;
val reqQty: BigDecimal; val reqQty: BigDecimal;


@get:Value("#{target.bom.outputQtyUom}")
@get:Value("#{target.bom.item.itemUoms.^[salesUnit == true && deleted == false]?.uom.udfudesc}")
val uom: String; val uom: String;
val status: String; val status: String;
} }
@@ -23,7 +23,7 @@ interface JobOrderDetailWithJsonString {
val code: String?; val code: String?;
val name: String?; val name: String?;
val reqQty: BigDecimal?; val reqQty: BigDecimal?;
val outputQtyUom: String?;
val uom: String?;
val pickLines: String?; val pickLines: String?;
val status: String?; val status: String?;
} }
@@ -33,7 +33,7 @@ data class JobOrderDetail(
val code: String?, val code: String?,
val name: String?, val name: String?,
val reqQty: BigDecimal?, val reqQty: BigDecimal?,
val outputQtyUom: String?,
val uom: String?,
val pickLines: List<JobOrderDetailPickLine>?, val pickLines: List<JobOrderDetailPickLine>?,
val status: String? val status: String?
) )


+ 29
- 1
src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderBomMaterialService.kt View File

@@ -6,16 +6,40 @@ import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository
import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderBomMaterialRequest import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderBomMaterialRequest
import com.ffii.fpsms.modules.master.entity.ItemsRepository import com.ffii.fpsms.modules.master.entity.ItemsRepository
import com.ffii.fpsms.modules.master.entity.UomConversionRepository import com.ffii.fpsms.modules.master.entity.UomConversionRepository
import com.ffii.fpsms.modules.master.service.ItemUomService
import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.master.web.models.MessageResponse
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.math.RoundingMode
import kotlin.jvm.optionals.getOrNull import kotlin.jvm.optionals.getOrNull


@Service @Service
open class JobOrderBomMaterialService( open class JobOrderBomMaterialService(
val jobOrderBomMaterialRepository: JobOrderBomMaterialRepository, private val jobOrderRepository: JobOrderRepository,
val jobOrderBomMaterialRepository: JobOrderBomMaterialRepository,
private val jobOrderRepository: JobOrderRepository,
private val itemsRepository: ItemsRepository, private val itemsRepository: ItemsRepository,
val itemUomService: ItemUomService,
private val uomConversionRepository: UomConversionRepository private val uomConversionRepository: UomConversionRepository
) { ) {
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 jobmRequests = jo.bom?.bomMaterials?.map { bm ->
val salesUnit = bm.item?.id?.let { itemUomService.findSalesUnitByItemId(it) }

CreateJobOrderBomMaterialRequest(
joId = joId,
itemId = bm.item?.id,
reqQty = bm.qty?.times(proportion) ?: zero,
uomId = salesUnit?.uom?.id
)
} ?: listOf()

return jobmRequests
}

fun createJobOrderBomMaterials(request: List<CreateJobOrderBomMaterialRequest>): MessageResponse { fun createJobOrderBomMaterials(request: List<CreateJobOrderBomMaterialRequest>): MessageResponse {
val joBomMaterials = request.map { req -> val joBomMaterials = request.map { req ->
val jo = req.joId?.let { jobOrderRepository.findById(it).getOrNull() } val jo = req.joId?.let { jobOrderRepository.findById(it).getOrNull() }
@@ -42,4 +66,8 @@ open class JobOrderBomMaterialService(
errorPosition = null errorPosition = null
) )
} }

fun createJobOrderBomMaterialsByJoId(joId: Long): MessageResponse {
return createJobOrderBomMaterials(createJobOrderBomMaterialRequests(joId))
}
} }

+ 5
- 4
src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt View File

@@ -2,6 +2,7 @@ package com.ffii.fpsms.modules.jobOrder.service


import com.ffii.core.response.RecordsRes import com.ffii.core.response.RecordsRes
import com.ffii.core.utils.GsonUtils import com.ffii.core.utils.GsonUtils
import com.ffii.fpsms.modules.common.SecurityUtils
import com.ffii.fpsms.modules.jobOrder.entity.JobOrder import com.ffii.fpsms.modules.jobOrder.entity.JobOrder
import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderDetail import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderDetail
@@ -61,7 +62,7 @@ open class JobOrderService(
code = sqlResult.code, code = sqlResult.code,
name = sqlResult.name, name = sqlResult.name,
reqQty = sqlResult.reqQty, reqQty = sqlResult.reqQty,
outputQtyUom = sqlResult.outputQtyUom,
uom = sqlResult.uom,
pickLines = jsonResult, pickLines = jsonResult,
status = sqlResult.status status = sqlResult.status
) )
@@ -90,7 +91,7 @@ open class JobOrderService(
open fun createJobOrder(request: CreateJobOrderRequest): MessageResponse { open fun createJobOrder(request: CreateJobOrderRequest): MessageResponse {
val jo = JobOrder() val jo = JobOrder()
val bom = request.bomId?.let { bomService.findById(it) } val bom = request.bomId?.let { bomService.findById(it) }
val approver = request.approverId?.let { userService.find(it).getOrNull() }
val approver = request.approverId?.let { userService.find(it).getOrNull() } ?: SecurityUtils.getUser().getOrNull()
val prodScheduleLine = request.prodScheduleLineId?.let { productionScheduleLineRepository.findById(it).getOrNull() } val prodScheduleLine = request.prodScheduleLineId?.let { productionScheduleLineRepository.findById(it).getOrNull() }
val code = assignJobNo() val code = assignJobNo()


@@ -98,8 +99,8 @@ open class JobOrderService(
this.code = code this.code = code
this.bom = bom this.bom = bom
//TODO: planStart & planEnd //TODO: planStart & planEnd
planStart = LocalDateTime.now()
planEnd = LocalDateTime.now()
planStart = request.planStart ?: LocalDateTime.now()
planEnd = request.planEnd ?: LocalDateTime.now()
reqQty = request.reqQty reqQty = request.reqQty
status = request.status status = request.status
type = request.type type = request.type


+ 14
- 0
src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt View File

@@ -3,7 +3,9 @@ package com.ffii.fpsms.modules.jobOrder.web
import com.ffii.core.response.RecordsRes import com.ffii.core.response.RecordsRes
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderDetail import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderDetail
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo
import com.ffii.fpsms.modules.jobOrder.service.JobOrderBomMaterialService
import com.ffii.fpsms.modules.jobOrder.service.JobOrderService import com.ffii.fpsms.modules.jobOrder.service.JobOrderService
import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderRequest
import com.ffii.fpsms.modules.jobOrder.web.model.JobOrderReleaseRequest import com.ffii.fpsms.modules.jobOrder.web.model.JobOrderReleaseRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SearchJobOrderInfoRequest import com.ffii.fpsms.modules.jobOrder.web.model.SearchJobOrderInfoRequest
import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.master.web.models.MessageResponse
@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController
@RequestMapping("/jo") @RequestMapping("/jo")
class JobOrderController( class JobOrderController(
private val jobOrderService: JobOrderService, private val jobOrderService: JobOrderService,
private val jobOrderBomMaterialService: JobOrderBomMaterialService,
) { ) {


@GetMapping("/getRecordByPage") @GetMapping("/getRecordByPage")
@@ -36,4 +39,15 @@ class JobOrderController(
fun releaseJobOrder(@Valid @RequestBody request: JobOrderReleaseRequest): MessageResponse { fun releaseJobOrder(@Valid @RequestBody request: JobOrderReleaseRequest): MessageResponse {
return jobOrderService.releaseJobOrder(request) return jobOrderService.releaseJobOrder(request)
} }

@PostMapping("/manualCreate")
fun manualCreateJobOrder(@Valid @RequestBody request: CreateJobOrderRequest): MessageResponse {
val jo = jobOrderService.createJobOrder(request)
if (jo.id == null) {
throw NoSuchElementException()
}
jobOrderBomMaterialService.createJobOrderBomMaterialsByJoId(jo.id)

return jo
}
} }

+ 2
- 2
src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt View File

@@ -9,8 +9,8 @@ data class CreateJobOrderRequest (
val planEnd: LocalDateTime? = null, val planEnd: LocalDateTime? = null,
val reqQty: BigDecimal?, val reqQty: BigDecimal?,
val type: String? = "detailed", val type: String? = "detailed",
val approverId: Long?,
val prodScheduleLineId: Long?,
val approverId: Long? = null,
val prodScheduleLineId: Long? = null,
val status: String = "planning", val status: String = "planning",
) )




+ 2
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/BomMaterialRepository.kt View File

@@ -11,4 +11,6 @@ interface BomMaterialRepository : AbstractRepository<BomMaterial, Long> {
fun findByM18IdAndDeletedIsFalse(m18Id: Long): BomMaterial? fun findByM18IdAndDeletedIsFalse(m18Id: Long): BomMaterial?


fun findAllByBomItemIdAndDeletedIsFalse(itemId: Long): List<BomMaterial> fun findAllByBomItemIdAndDeletedIsFalse(itemId: Long): List<BomMaterial>

fun findAllByBomIdAndDeletedIsFalse(bomId: Long): List<BomMaterial>
} }

+ 3
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/BomRepository.kt View File

@@ -1,6 +1,7 @@
package com.ffii.fpsms.modules.master.entity package com.ffii.fpsms.modules.master.entity


import com.ffii.core.support.AbstractRepository import com.ffii.core.support.AbstractRepository
import com.ffii.fpsms.modules.master.entity.projections.BomCombo
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import java.io.Serializable import java.io.Serializable


@@ -13,4 +14,6 @@ interface BomRepository : AbstractRepository<Bom, Long> {
fun findByM18IdAndDeletedIsFalse(m18Id: Long): Bom? fun findByM18IdAndDeletedIsFalse(m18Id: Long): Bom?


fun findByItemIdAndDeletedIsFalse(itemId: Serializable): Bom? fun findByItemIdAndDeletedIsFalse(itemId: Serializable): Bom?

fun findBomComboByDeletedIsFalse(): List<BomCombo>
} }

+ 11
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/projections/BomCombo.kt View File

@@ -0,0 +1,11 @@
package com.ffii.fpsms.modules.master.entity.projections

import org.springframework.beans.factory.annotation.Value

interface BomCombo {
val id: Long;
@get:Value("#{target.id}")
val value: Long;
@get:Value("#{target.code} - #{target.name} - #{target.item.itemUoms.^[salesUnit == true && deleted == false]?.uom.udfudesc}")
val label: String;
}

+ 5
- 0
src/main/java/com/ffii/fpsms/modules/master/service/BomMaterialService.kt View File

@@ -1,5 +1,6 @@
package com.ffii.fpsms.modules.master.service package com.ffii.fpsms.modules.master.service


import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderBomMaterialRequest
import com.ffii.fpsms.modules.master.entity.* import com.ffii.fpsms.modules.master.entity.*
import com.ffii.fpsms.modules.master.web.models.SaveBomMaterialRequest import com.ffii.fpsms.modules.master.web.models.SaveBomMaterialRequest
import com.ffii.fpsms.modules.master.web.models.SaveBomMaterialResponse import com.ffii.fpsms.modules.master.web.models.SaveBomMaterialResponse
@@ -20,6 +21,10 @@ open class BomMaterialService(
return bomMaterialRepository.findByM18IdAndDeletedIsFalse(m18Id); return bomMaterialRepository.findByM18IdAndDeletedIsFalse(m18Id);
} }


open fun findAllByBomId(bomId: Long): List<BomMaterial> {
return bomMaterialRepository.findAllByBomIdAndDeletedIsFalse(bomId);
}

open fun saveBomMaterial(request: SaveBomMaterialRequest): SaveBomMaterialResponse { open fun saveBomMaterial(request: SaveBomMaterialRequest): SaveBomMaterialResponse {
val bomMaterial = request.m18Id?.let { findByM18Id(it) } val bomMaterial = request.m18Id?.let { findByM18Id(it) }
?: request.id?.let { findById(it) } ?: request.id?.let { findById(it) }


+ 8
- 1
src/main/java/com/ffii/fpsms/modules/master/web/BomController.kt View File

@@ -1,6 +1,8 @@
package com.ffii.fpsms.modules.master.web package com.ffii.fpsms.modules.master.web


import com.ffii.fpsms.modules.master.entity.Bom import com.ffii.fpsms.modules.master.entity.Bom
import com.ffii.fpsms.modules.master.entity.BomRepository
import com.ffii.fpsms.modules.master.entity.projections.BomCombo
import com.ffii.fpsms.modules.master.service.BomService import com.ffii.fpsms.modules.master.service.BomService
import org.springframework.core.io.ByteArrayResource import org.springframework.core.io.ByteArrayResource
import org.springframework.core.io.Resource import org.springframework.core.io.Resource
@@ -16,13 +18,18 @@ import java.time.LocalDate
@RestController @RestController
@RequestMapping("/bom") @RequestMapping("/bom")
class BomController ( class BomController (
val bomService: BomService,
val bomService: BomService, private val bomRepository: BomRepository,
) { ) {
@GetMapping @GetMapping
fun getBoms(): List<Bom> { fun getBoms(): List<Bom> {
return bomService.findAll() return bomService.findAll()
} }


@GetMapping("/combo")
fun getCombo(): List<BomCombo> {
return bomRepository.findBomComboByDeletedIsFalse();
}

@PostMapping("/import-bom") @PostMapping("/import-bom")
fun importBom(): ResponseEntity<Resource> { fun importBom(): ResponseEntity<Resource> {
val reportResult = bomService.importBOM() val reportResult = bomService.importBOM()


Loading…
Cancel
Save