| @@ -80,4 +80,6 @@ open class JobOrder : BaseEntity<Long>() { | |||||
| @Column(name = "jobTypeId") | @Column(name = "jobTypeId") | ||||
| open var jobTypeId: Long? = null | open var jobTypeId: Long? = null | ||||
| } | } | ||||
| @@ -16,4 +16,5 @@ import java.util.Optional | |||||
| interface JobTypeRepository : JpaRepository<JobType, Long> { | interface JobTypeRepository : JpaRepository<JobType, Long> { | ||||
| //fun findByName(name: String): Optional<JobType> | //fun findByName(name: String): Optional<JobType> | ||||
| //fun findByIdAndDeletedIsFalse(id: Long): Optional<JobType> | //fun findByIdAndDeletedIsFalse(id: Long): Optional<JobType> | ||||
| } | } | ||||
| @@ -38,8 +38,32 @@ interface JobOrderInfo { | |||||
| @get:Value("#{target.status.value}") | @get:Value("#{target.status.value}") | ||||
| val status: String; | val status: String; | ||||
| } | |||||
| @get:Value("#{target.jobTypeId}") | |||||
| val jobTypeId: Long?; | |||||
| } | |||||
| data class JobTypeResponse( | |||||
| val id: Long?, | |||||
| val name: String? | |||||
| ) | |||||
| data class JobOrderInfoWithTypeName( | |||||
| val id: Long, | |||||
| val code: String, | |||||
| val itemCode: String, | |||||
| val itemName: String, | |||||
| val name: String, | |||||
| val reqQty: BigDecimal, | |||||
| val item: JobOrderItemInfo, | |||||
| val stockInLineId: Long?, | |||||
| val stockInLineStatus: String?, | |||||
| val silHandlerId: Long?, | |||||
| val planStart: LocalDateTime?, | |||||
| val status: String, | |||||
| val jobTypeId: Long?, | |||||
| val jobTypeName: String? | |||||
| ) | |||||
| // Job Order | // Job Order | ||||
| interface JobOrderDetailWithJsonString { | interface JobOrderDetailWithJsonString { | ||||
| val id: Long?; | val id: Long?; | ||||
| @@ -14,6 +14,7 @@ import org.springframework.stereotype.Service | |||||
| import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||
| import java.time.LocalDate | import java.time.LocalDate | ||||
| import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus | import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus | ||||
| import com.ffii.fpsms.modules.pickOrder.enums.PickOrderLineStatus | |||||
| import java.time.LocalDateTime | import java.time.LocalDateTime | ||||
| import com.ffii.core.support.JdbcDao | import com.ffii.core.support.JdbcDao | ||||
| import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest | import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest | ||||
| @@ -29,6 +30,10 @@ import com.ffii.fpsms.modules.stock.entity.SuggestPickLotRepository | |||||
| import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository | import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository | ||||
| import com.ffii.fpsms.modules.stock.entity.InventoryLotRepository | import com.ffii.fpsms.modules.stock.entity.InventoryLotRepository | ||||
| import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository | import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository | ||||
| import com.ffii.fpsms.modules.jobOrder.web.model.AllJoPickOrderResponse | |||||
| import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository | |||||
| import com.ffii.fpsms.modules.jobOrder.entity.JobTypeRepository | |||||
| import com.ffii.fpsms.modules.master.entity.ItemsRepository | |||||
| @Service | @Service | ||||
| open class JoPickOrderService( | open class JoPickOrderService( | ||||
| private val joPickOrderRepository: JoPickOrderRepository, | private val joPickOrderRepository: JoPickOrderRepository, | ||||
| @@ -42,7 +47,11 @@ open class JoPickOrderService( | |||||
| private val suggestPickLotRepository: SuggestPickLotRepository, | private val suggestPickLotRepository: SuggestPickLotRepository, | ||||
| private val inventoryLotLineRepository: InventoryLotLineRepository, | private val inventoryLotLineRepository: InventoryLotLineRepository, | ||||
| private val inventoryLotRepository: InventoryLotRepository, | private val inventoryLotRepository: InventoryLotRepository, | ||||
| private val stockOutLineRepository: StockOutLIneRepository | |||||
| private val stockOutLineRepository: StockOutLIneRepository, | |||||
| private val jobOrderRepository: JobOrderRepository, | |||||
| private val jobTypeRepository: JobTypeRepository, | |||||
| private val itemsRepository: ItemsRepository | |||||
| ) { | ) { | ||||
| open fun save(record: JoPickOrder): JoPickOrder { | open fun save(record: JoPickOrder): JoPickOrder { | ||||
| @@ -1629,4 +1638,318 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo | |||||
| emptyList() | emptyList() | ||||
| } | } | ||||
| } | } | ||||
| open fun getAllJoPickOrders(): List<AllJoPickOrderResponse> { | |||||
| println("=== getAllJoPickOrders ===") | |||||
| return try { | |||||
| val releasedPickOrders = pickOrderRepository.findAllByStatusAndDeletedFalse( | |||||
| PickOrderStatus.RELEASED | |||||
| ).filter { pickOrder -> | |||||
| pickOrder.jobOrder != null | |||||
| } | |||||
| println("Found ${releasedPickOrders.size} released job order pick orders") | |||||
| val jobOrderPickOrders = releasedPickOrders.mapNotNull { pickOrder -> | |||||
| println("Processing pick order: ${pickOrder.id}, code: ${pickOrder.code}") | |||||
| val jobOrder = pickOrder.jobOrder | |||||
| if (jobOrder == null) { | |||||
| println("❌ Pick order ${pickOrder.id} has no job order") | |||||
| return@mapNotNull null | |||||
| } | |||||
| println("Job order found: ${jobOrder.id}, code: ${jobOrder.code}") | |||||
| val bom = jobOrder.bom | |||||
| println("BOM found: ${bom?.id}") | |||||
| val item = bom?.item | |||||
| if (item == null) { | |||||
| println("❌ BOM ${bom?.id} has no item") | |||||
| return@mapNotNull null | |||||
| } | |||||
| println("Item found: ${item.id}, name: ${item.name}") | |||||
| val uom = bom.outputQtyUom | |||||
| if (uom == null) { | |||||
| println("❌ BOM ${bom.id} has no uom") | |||||
| return@mapNotNull null | |||||
| } | |||||
| // println("UOM found: ${uom.id}, code: ${uom.code}") | |||||
| val pickOrderLines = pickOrderLineRepository.findAllByPickOrderId(pickOrder.id ?: return@mapNotNull null) | |||||
| val finishedLines = pickOrderLines.count { it.status == PickOrderLineStatus.COMPLETED } | |||||
| val jobOrderType = jobOrder.jobTypeId?.let { jobTypeRepository.findById(it).orElse(null) } | |||||
| println("✅ Building response for pick order ${pickOrder.id}") | |||||
| AllJoPickOrderResponse( | |||||
| id = pickOrder.id ?: 0L, | |||||
| pickOrderId = pickOrder.id, | |||||
| pickOrderCode = pickOrder.code, | |||||
| jobOrderId = jobOrder.id, | |||||
| jobOrderCode = jobOrder.code, | |||||
| jobOrderTypeId = jobOrder.jobTypeId, | |||||
| jobOrderType = jobOrderType?.name, | |||||
| itemId = item.id ?: 0L, | |||||
| itemName = item.name ?: "", | |||||
| reqQty = jobOrder.reqQty ?: BigDecimal.ZERO, | |||||
| //uomId = bom.outputQtyUom?.id : 0L, | |||||
| uomId = 0, | |||||
| uomName = bom?.outputQtyUom?: "", | |||||
| jobOrderStatus = jobOrder.status?.value ?: "", | |||||
| finishedPickOLineCount = finishedLines | |||||
| ) | |||||
| } | |||||
| println("Returning ${jobOrderPickOrders.size} released job order pick orders") | |||||
| jobOrderPickOrders | |||||
| } catch (e: Exception) { | |||||
| println("❌ Error in getAllJoPickOrders: ${e.message}") | |||||
| e.printStackTrace() | |||||
| emptyList() | |||||
| } | |||||
| } | |||||
| open fun getJobOrderLotsHierarchicalByPickOrderId(pickOrderId: Long): Map<String, Any?> { | |||||
| println("=== getJobOrderLotsHierarchicalByPickOrderId ===") | |||||
| println("pickOrderId: $pickOrderId") | |||||
| return try { | |||||
| val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) | |||||
| if (pickOrder == null || pickOrder.deleted == true) { | |||||
| println("❌ Pick order $pickOrderId not found or deleted") | |||||
| return mapOf( | |||||
| "pickOrder" to null as Any?, | |||||
| "pickOrderLines" to emptyList<Map<String, Any>>() as Any? | |||||
| ) | |||||
| } | |||||
| val jobOrder = pickOrder.jobOrder ?: return mapOf( | |||||
| "pickOrder" to null as Any?, | |||||
| "pickOrderLines" to emptyList<Map<String, Any>>() as Any? | |||||
| ) | |||||
| // 获取 pick order lines | |||||
| val pickOrderLines = pickOrderLineRepository.findAllByPickOrderId(pickOrder.id!!) | |||||
| .filter { it.deleted == false } | |||||
| // 获取所有 pick order line IDs | |||||
| val pickOrderLineIds = pickOrderLines.map { it.id!! } | |||||
| // 获取 suggested pick lots | |||||
| val suggestedPickLots = if (pickOrderLineIds.isNotEmpty()) { | |||||
| suggestPickLotRepository.findAllByPickOrderLineIdIn(pickOrderLineIds) | |||||
| .filter { it.deleted == false } | |||||
| } else { | |||||
| emptyList() | |||||
| } | |||||
| // 获取所有 inventory lot line IDs | |||||
| val inventoryLotLineIds = suggestedPickLots.mapNotNull { it.suggestedLotLine?.id } | |||||
| // 获取 inventory lot lines | |||||
| val inventoryLotLines = if (inventoryLotLineIds.isNotEmpty()) { | |||||
| inventoryLotLineRepository.findAllByIdIn(inventoryLotLineIds) | |||||
| .filter { it.deleted == false } | |||||
| } else { | |||||
| emptyList() | |||||
| } | |||||
| // 获取 inventory lots | |||||
| val inventoryLotIds = inventoryLotLines.mapNotNull { it.inventoryLot?.id }.distinct() | |||||
| val inventoryLots = if (inventoryLotIds.isNotEmpty()) { | |||||
| inventoryLotRepository.findAllByIdIn(inventoryLotIds) | |||||
| .filter { it.deleted == false } | |||||
| } else { | |||||
| emptyList() | |||||
| } | |||||
| // 获取 stock out lines | |||||
| val stockOutLines = if (pickOrderLineIds.isNotEmpty() && inventoryLotLineIds.isNotEmpty()) { | |||||
| pickOrderLineIds.flatMap { polId -> | |||||
| inventoryLotLineIds.flatMap { illId -> | |||||
| stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(polId, illId) | |||||
| } | |||||
| } | |||||
| } else { | |||||
| emptyList() | |||||
| } | |||||
| // 取得所有 stock out line(含無 lot 情況) | |||||
| val stockOutLinesByPickOrderLine = pickOrderLineIds.associateWith { polId -> | |||||
| stockOutLineRepository.findAllByPickOrderLineIdAndDeletedFalse(polId) | |||||
| } | |||||
| // 获取 jo_pick_order 记录 | |||||
| val joPickOrders = joPickOrderRepository.findByPickOrderId(pickOrder.id!!) | |||||
| // 构建 pick order info | |||||
| val pickOrderInfo = mapOf( | |||||
| "id" to pickOrder.id, | |||||
| "code" to pickOrder.code, | |||||
| "consoCode" to pickOrder.consoCode, | |||||
| "targetDate" to pickOrder.targetDate?.let { | |||||
| "${it.year}-${String.format("%02d", it.monthValue)}-${String.format("%02d", it.dayOfMonth)}" | |||||
| }, | |||||
| "type" to pickOrder.type?.value, | |||||
| "status" to pickOrder.status?.value, | |||||
| "assignTo" to pickOrder.assignTo?.id, | |||||
| "jobOrder" to mapOf( | |||||
| "id" to jobOrder.id, | |||||
| "code" to jobOrder.code, | |||||
| "name" to "Job Order ${jobOrder.code}" | |||||
| ) | |||||
| ) | |||||
| // 构建 pick order lines with lots | |||||
| val pickOrderLinesResult = pickOrderLines.map { pol -> | |||||
| val item = pol.item | |||||
| val uom = pol.uom | |||||
| val lineId = pol.id!! | |||||
| val suggestions = suggestedPickLots.filter { it.pickOrderLine?.id == lineId } | |||||
| val stockoutsForLine = stockOutLinesByPickOrderLine[lineId].orEmpty() | |||||
| // 获取该 line 的 suggested pick lots | |||||
| val lineSuggestedLots = suggestedPickLots.filter { it.pickOrderLine?.id == pol.id } | |||||
| // 构建 lots 数据 | |||||
| val lots = lineSuggestedLots.mapNotNull { spl -> | |||||
| val ill = spl.suggestedLotLine | |||||
| if (ill == null || ill.deleted == true) return@mapNotNull null | |||||
| val il = ill.inventoryLot | |||||
| if (il == null || il.deleted == true) return@mapNotNull null | |||||
| val warehouse = ill.warehouse | |||||
| // 获取对应的 stock out line | |||||
| val sol = stockOutLines.firstOrNull { | |||||
| it.pickOrderLine?.id == pol.id && it.inventoryLotLine?.id == ill.id | |||||
| } | |||||
| // 获取对应的 jo_pick_order | |||||
| val jpo = joPickOrders.firstOrNull { it.itemId == item?.id } | |||||
| // 计算 available quantity | |||||
| val availableQty = if (sol?.status == "rejected") { | |||||
| null | |||||
| } else { | |||||
| (ill.inQty ?: BigDecimal.ZERO) - (ill.outQty ?: BigDecimal.ZERO) - (ill.holdQty ?: BigDecimal.ZERO) | |||||
| } | |||||
| // 计算 total picked by all pick orders | |||||
| val totalPickedByAllPickOrders = stockOutLines | |||||
| .filter { it.inventoryLotLine?.id == ill.id && it.deleted == false } | |||||
| .filter { it.status in listOf("pending", "checked", "partially_completed", "completed") } | |||||
| .sumOf { it.qty?.toBigDecimal() ?: BigDecimal.ZERO } | |||||
| // 计算 lot availability | |||||
| val lotAvailability = when { | |||||
| il.expiryDate != null && il.expiryDate!!.isBefore(LocalDate.now()) -> "expired" | |||||
| sol?.status == "rejected" -> "rejected" | |||||
| availableQty != null && availableQty <= BigDecimal.ZERO -> "insufficient_stock" | |||||
| ill.status == InventoryLotLineStatus.UNAVAILABLE -> "status_unavailable" | |||||
| else -> "available" | |||||
| } | |||||
| // 计算 processing status | |||||
| val processingStatus = when (sol?.status) { | |||||
| "completed" -> "completed" | |||||
| "rejected" -> "rejected" | |||||
| "created" -> "pending" | |||||
| else -> "pending" | |||||
| } | |||||
| mapOf( | |||||
| "lotId" to ill.id, | |||||
| "lotNo" to il.lotNo, | |||||
| "expiryDate" to il.expiryDate?.let { | |||||
| "${it.year}-${String.format("%02d", it.monthValue)}-${String.format("%02d", it.dayOfMonth)}" | |||||
| }, | |||||
| "location" to warehouse?.name, | |||||
| "availableQty" to availableQty?.toDouble(), | |||||
| "requiredQty" to (spl.qty?.toDouble() ?: 0.0), | |||||
| "actualPickQty" to (sol?.qty ?: 0.0), | |||||
| "processingStatus" to processingStatus, | |||||
| "lotAvailability" to lotAvailability, | |||||
| "pickOrderId" to pickOrder.id, | |||||
| "pickOrderCode" to pickOrder.code, | |||||
| "pickOrderConsoCode" to pickOrder.consoCode, | |||||
| "pickOrderLineId" to pol.id, | |||||
| "stockOutLineId" to sol?.id, | |||||
| "suggestedPickLotId" to spl.id, | |||||
| "stockOutLineQty" to (sol?.qty ?: 0.0), | |||||
| "stockOutLineStatus" to sol?.status, | |||||
| "routerIndex" to warehouse?.order, | |||||
| "routerArea" to warehouse?.code, | |||||
| "routerRoute" to warehouse?.code, | |||||
| "uomShortDesc" to uom?.udfShortDesc, | |||||
| "matchStatus" to jpo?.matchStatus?.value, | |||||
| "matchBy" to jpo?.matchBy, | |||||
| "matchQty" to jpo?.matchQty | |||||
| ) | |||||
| } | |||||
| mapOf( | |||||
| "id" to pol.id, | |||||
| "itemId" to item?.id, | |||||
| "itemCode" to item?.code, | |||||
| "itemName" to item?.name, | |||||
| "requiredQty" to pol.qty?.toDouble(), | |||||
| "uomCode" to uom?.code, | |||||
| "uomDesc" to uom?.udfudesc, | |||||
| "lots" to lots | |||||
| ) | |||||
| } | |||||
| return mapOf( | |||||
| "pickOrder" to pickOrderInfo as Any?, | |||||
| "pickOrderLines" to pickOrderLinesResult as Any? | |||||
| ) | |||||
| } catch (e: Exception) { | |||||
| println("❌ Error in getJobOrderLotsHierarchicalByPickOrderId: ${e.message}") | |||||
| e.printStackTrace() | |||||
| return mapOf( | |||||
| "pickOrder" to null as Any?, | |||||
| "pickOrderLines" to emptyList<Map<String, Any>>() as Any? | |||||
| ) | |||||
| } | |||||
| } | |||||
| open fun updateHandledByForItem(pickOrderId: Long, itemId: Long, userId: Long): JoPickOrder? { | |||||
| val joPickOrderOpt = joPickOrderRepository.findByPickOrderIdAndItemId(pickOrderId, itemId) | |||||
| if (joPickOrderOpt.isEmpty) { | |||||
| println("⚠️ JoPickOrder not found for pickOrderId: $pickOrderId, itemId: $itemId") | |||||
| return null | |||||
| } | |||||
| val joPickOrder = joPickOrderOpt.get() | |||||
| joPickOrder.handledBy = userId | |||||
| // Don't update other fields - only handledBy | |||||
| return joPickOrderRepository.save(joPickOrder) | |||||
| } | |||||
| open fun updateRecordHandledByForItem(pickOrderId: Long, itemId: Long, userId: Long): JoPickOrderRecord? { | |||||
| val joPickOrderRecordOpt = joPickOrderRecordRepository.findByPickOrderIdAndItemId(pickOrderId, itemId) | |||||
| if (joPickOrderRecordOpt.isEmpty) { | |||||
| println("⚠️ JoPickOrderRecord not found for pickOrderId: $pickOrderId, itemId: $itemId") | |||||
| return null | |||||
| } | |||||
| val joPickOrderRecord = joPickOrderRecordOpt.get() | |||||
| joPickOrderRecord.handledBy = userId | |||||
| // Don't update other fields - only handledBy | |||||
| return joPickOrderRecordRepository.save(joPickOrderRecord) | |||||
| } | |||||
| } | } | ||||
| @@ -54,6 +54,8 @@ import org.springframework.core.io.ClassPathResource | |||||
| import java.io.File | import java.io.File | ||||
| import java.io.FileNotFoundException | import java.io.FileNotFoundException | ||||
| import java.io.IOException | import java.io.IOException | ||||
| import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfoWithTypeName | |||||
| import com.ffii.fpsms.modules.jobOrder.entity.projections.JobTypeResponse | |||||
| @Service | @Service | ||||
| @@ -82,7 +84,7 @@ open class JobOrderService( | |||||
| code = request.code ?: "", | code = request.code ?: "", | ||||
| bomName = request.itemName ?: "", | bomName = request.itemName ?: "", | ||||
| pageable = pageable | pageable = pageable | ||||
| ) | |||||
| ) | |||||
| val planStartFrom = request.planStart | val planStartFrom = request.planStart | ||||
| val planStartTo = request.planStartTo | val planStartTo = request.planStartTo | ||||
| @@ -97,7 +99,59 @@ open class JobOrderService( | |||||
| val total = response.totalElements | val total = response.totalElements | ||||
| return RecordsRes<JobOrderInfo>(records, total.toInt()); | return RecordsRes<JobOrderInfo>(records, total.toInt()); | ||||
| } | } | ||||
| open fun allJobOrdersByPageWithTypeName(request: SearchJobOrderInfoRequest): RecordsRes<JobOrderInfoWithTypeName> { | |||||
| val pageable = PageRequest.of(request.pageNum ?: 0, request.pageSize ?: 10); | |||||
| println("allJobOrdersByPage") | |||||
| println(request) | |||||
| val response = jobOrderRepository.findJobOrderInfoByCodeContainsAndBomNameContainsAndDeletedIsFalseOrderByIdDesc( | |||||
| code = request.code ?: "", | |||||
| bomName = request.itemName ?: "", | |||||
| pageable = pageable | |||||
| ) | |||||
| val jobTypeIds = response.content.mapNotNull { it.jobTypeId }.distinct() | |||||
| val jobTypes = if (jobTypeIds.isNotEmpty()) { | |||||
| jobTypeRepository.findAllById(jobTypeIds).associateBy { it.id } | |||||
| } else { | |||||
| emptyMap() | |||||
| } | |||||
| val planStartFrom = request.planStart | |||||
| val planStartTo = request.planStartTo | |||||
| val records = response.content | |||||
| .filter { | |||||
| (planStartFrom == null || (it.planStart != null && (planStartFrom.isEqual(it.planStart) || planStartFrom.isBefore(it.planStart)))) && | |||||
| (planStartTo == null || (it.planStart != null && (planStartTo.isEqual(it.planStart) || planStartTo.isAfter(it.planStart)))) | |||||
| } | |||||
| .map { info -> | |||||
| JobOrderInfoWithTypeName( | |||||
| id = info.id, | |||||
| code = info.code, | |||||
| itemCode = info.itemCode, | |||||
| itemName = info.itemName, | |||||
| name = info.name, | |||||
| reqQty = info.reqQty, | |||||
| item = info.item, | |||||
| stockInLineId = info.stockInLineId, | |||||
| stockInLineStatus = info.stockInLineStatus, | |||||
| silHandlerId = info.silHandlerId, | |||||
| planStart = info.planStart, | |||||
| status = info.status, | |||||
| jobTypeId = info.jobTypeId, | |||||
| jobTypeName = info.jobTypeId?.let { jobTypes[it]?.name } | |||||
| ) | |||||
| } | |||||
| .filter { info -> | |||||
| // Filter by jobTypeName if provided | |||||
| request.jobTypeName == null || | |||||
| request.jobTypeName.isBlank() || | |||||
| info.jobTypeName?.equals(request.jobTypeName, ignoreCase = true) == true || | |||||
| info.jobTypeName?.contains(request.jobTypeName, ignoreCase = true) == true | |||||
| } | |||||
| val total = response.totalElements | |||||
| return RecordsRes<JobOrderInfoWithTypeName>(records, total.toInt()); | |||||
| } | |||||
| open fun jobOrderDetail(id: Long): JobOrderDetail { | open fun jobOrderDetail(id: Long): JobOrderDetail { | ||||
| val sqlResult = jobOrderRepository.findJobOrderDetailById(id) ?: throw NoSuchElementException(); | val sqlResult = jobOrderRepository.findJobOrderDetailById(id) ?: throw NoSuchElementException(); | ||||
| @@ -594,6 +648,8 @@ open class JobOrderService( | |||||
| //tempPdfFile.delete | //tempPdfFile.delete | ||||
| } | } | ||||
| } | } | ||||
| open fun getAllJobTypes(): List<JobTypeResponse> { | |||||
| return jobTypeRepository.findAll().map { JobTypeResponse(it.id, it.name) } | |||||
| } | |||||
| } | } | ||||
| @@ -2,7 +2,7 @@ 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.service.JobOrderBomMaterialService | import com.ffii.fpsms.modules.jobOrder.service.JobOrderBomMaterialService | ||||
| import com.ffii.fpsms.modules.jobOrder.service.JobOrderProcessService | import com.ffii.fpsms.modules.jobOrder.service.JobOrderProcessService | ||||
| import com.ffii.fpsms.modules.jobOrder.service.JobOrderService | import com.ffii.fpsms.modules.jobOrder.service.JobOrderService | ||||
| @@ -10,6 +10,7 @@ import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderRequest | |||||
| import com.ffii.fpsms.modules.jobOrder.web.model.JobOrderCommonActionRequest | import com.ffii.fpsms.modules.jobOrder.web.model.JobOrderCommonActionRequest | ||||
| 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 | ||||
| import com.ffii.fpsms.modules.jobOrder.entity.projections.JobTypeResponse | |||||
| import jakarta.validation.Valid | import jakarta.validation.Valid | ||||
| import org.springframework.web.bind.annotation.GetMapping | import org.springframework.web.bind.annotation.GetMapping | ||||
| import org.springframework.web.bind.annotation.ModelAttribute | import org.springframework.web.bind.annotation.ModelAttribute | ||||
| @@ -35,6 +36,9 @@ import java.io.UnsupportedEncodingException | |||||
| import java.text.ParseException | import java.text.ParseException | ||||
| import org.springframework.web.bind.annotation.* | import org.springframework.web.bind.annotation.* | ||||
| import org.springframework.web.bind.annotation.RequestParam | import org.springframework.web.bind.annotation.RequestParam | ||||
| import com.ffii.fpsms.modules.jobOrder.web.model.UpdateJoPickOrderHandledByRequest | |||||
| import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo | |||||
| import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfoWithTypeName | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/jo") | @RequestMapping("/jo") | ||||
| class JobOrderController( | class JobOrderController( | ||||
| @@ -46,10 +50,11 @@ class JobOrderController( | |||||
| ) { | ) { | ||||
| @GetMapping("/getRecordByPage") | @GetMapping("/getRecordByPage") | ||||
| fun allJobOrdersByPage(@ModelAttribute request: SearchJobOrderInfoRequest): RecordsRes<JobOrderInfo> { | |||||
| fun allJobOrdersByPage(@ModelAttribute request: SearchJobOrderInfoRequest): RecordsRes<JobOrderInfoWithTypeName> { | |||||
| println("getRecordByPage") | println("getRecordByPage") | ||||
| println(request) | println(request) | ||||
| return jobOrderService.allJobOrdersByPage(request); | |||||
| //return jobOrderService.allJobOrdersByPage(request); | |||||
| return jobOrderService.allJobOrdersByPageWithTypeName(request); | |||||
| } | } | ||||
| @GetMapping("/detail/{id}") | @GetMapping("/detail/{id}") | ||||
| @@ -224,4 +229,64 @@ fun recordSecondScanIssue( | |||||
| fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(@PathVariable pickOrderId: Long): List<Map<String, Any?>> { | fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(@PathVariable pickOrderId: Long): List<Map<String, Any?>> { | ||||
| return joPickOrderService.getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId) | return joPickOrderService.getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId) | ||||
| } | } | ||||
| @GetMapping("/AllJoPickOrder") | |||||
| fun getAllJoPickOrder(): List<AllJoPickOrderResponse> { | |||||
| return joPickOrderService.getAllJoPickOrders() | |||||
| } | |||||
| @GetMapping("/all-lots-hierarchical-by-pick-order/{pickOrderId}") | |||||
| fun getJobOrderLotsHierarchicalByPickOrderId(@PathVariable pickOrderId: Long): Map<String, Any?> { | |||||
| return joPickOrderService.getJobOrderLotsHierarchicalByPickOrderId(pickOrderId) | |||||
| } | |||||
| @PostMapping("/update-jo-pick-order-handled-by") | |||||
| fun updateJoPickOrderHandledBy(@Valid @RequestBody request: UpdateJoPickOrderHandledByRequest): MessageResponse { | |||||
| try { | |||||
| val joPickOrder = joPickOrderService.updateHandledByForItem( | |||||
| request.pickOrderId, | |||||
| request.itemId, | |||||
| request.userId | |||||
| ) | |||||
| val joPickOrderRecord = joPickOrderService.updateRecordHandledByForItem( | |||||
| request.pickOrderId, | |||||
| request.itemId, | |||||
| request.userId | |||||
| ) | |||||
| if (joPickOrder == null) { | |||||
| return MessageResponse( | |||||
| id = null, | |||||
| code = "NOT_FOUND", | |||||
| name = null, | |||||
| type = null, | |||||
| message = "JoPickOrder not found for pickOrderId: ${request.pickOrderId}, itemId: ${request.itemId}", | |||||
| errorPosition = null | |||||
| ) | |||||
| } | |||||
| return MessageResponse( | |||||
| id = joPickOrder.id, | |||||
| code = "SUCCESS", | |||||
| name = null, | |||||
| type = null, | |||||
| message = "JoPickOrder handledBy updated successfully for item ${request.itemId}", | |||||
| errorPosition = null | |||||
| ) | |||||
| } catch (e: Exception) { | |||||
| println("Error updating JoPickOrder handledBy: ${e.message}") | |||||
| e.printStackTrace() | |||||
| return MessageResponse( | |||||
| id = null, | |||||
| code = "ERROR", | |||||
| name = null, | |||||
| type = null, | |||||
| message = "Failed to update JoPickOrder handledBy: ${e.message}", | |||||
| errorPosition = null | |||||
| ) | |||||
| } | |||||
| } | |||||
| @GetMapping("/jobTypes") | |||||
| fun getAllJobTypes(): List<JobTypeResponse> { | |||||
| return jobOrderService.getAllJobTypes() | |||||
| } | |||||
| } | } | ||||
| @@ -1,24 +0,0 @@ | |||||
| package com.ffii.fpsms.modules.jobOrder.web | |||||
| import OperatorRequest | |||||
| import com.ffii.core.response.RecordsRes | |||||
| import com.ffii.core.utils.CriteriaArgsBuilder | |||||
| import com.ffii.fpsms.modules.jobOrder.service.JobOrderProcessService | |||||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderDataClass | |||||
| import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderService | |||||
| import com.ffii.fpsms.modules.purchaseOrder.web.model.PagingRequest | |||||
| import jakarta.servlet.http.HttpServletRequest | |||||
| import org.springframework.web.bind.annotation.* | |||||
| @RestController | |||||
| @RequestMapping("/jop") | |||||
| class JobOrderProcessController( | |||||
| private val jobOrderProcessService: JobOrderProcessService | |||||
| ) { | |||||
| @PostMapping("/isOperatorExist") | |||||
| fun checkPolAndCompletePo(@RequestBody request: OperatorRequest): MessageResponse { | |||||
| println(request) | |||||
| return jobOrderProcessService.isOperatorExist(request) | |||||
| } | |||||
| } | |||||
| @@ -31,4 +31,38 @@ data class CreateJobOrderProcessRequest ( | |||||
| val seqNo: Long?, | val seqNo: Long?, | ||||
| val remarks: String? = null, | val remarks: String? = null, | ||||
| val status: String = "pending", | val status: String = "pending", | ||||
| ) | |||||
| data class AllJoPickOrderResponse( | |||||
| val id: Long, | |||||
| val pickOrderId: Long?, | |||||
| val pickOrderCode: String?, | |||||
| val jobOrderId: Long?, | |||||
| val jobOrderCode: String?, | |||||
| val jobOrderTypeId: Long?, | |||||
| val jobOrderType: String?, | |||||
| val itemId: Long, | |||||
| val itemName: String, | |||||
| val reqQty: BigDecimal, | |||||
| val uomId: Long, | |||||
| val uomName: String, | |||||
| val jobOrderStatus: String, | |||||
| val finishedPickOLineCount: Int, | |||||
| ) | |||||
| data class JobOrderLotsHierarchicalResponse( | |||||
| val id: Long, | |||||
| val lotId: Long?, | |||||
| val lotCode: String?, | |||||
| val lotName: String?, | |||||
| val lotQty: BigDecimal?, | |||||
| val lotUomId: Long?, | |||||
| val lotUomName: String?, | |||||
| ) | |||||
| data class UpdateJoPickOrderHandledByRequest( | |||||
| val pickOrderId: Long, | |||||
| val itemId: Long, | |||||
| val userId: Long | |||||
| ) | ) | ||||
| @@ -9,4 +9,5 @@ data class SearchJobOrderInfoRequest( | |||||
| val planStartTo: LocalDateTime?, | val planStartTo: LocalDateTime?, | ||||
| val pageSize: Int?, | val pageSize: Int?, | ||||
| val pageNum: Int?, | val pageNum: Int?, | ||||
| val jobTypeName: String?, | |||||
| ) | ) | ||||
| @@ -11,6 +11,6 @@ interface EquipmentDetailRepository : AbstractRepository<EquipmentDetail, Long> | |||||
| fun findByNameAndDeletedIsFalse(name: String): EquipmentDetail?; | fun findByNameAndDeletedIsFalse(name: String): EquipmentDetail?; | ||||
| fun findByDescriptionAndDeletedIsFalse(description: String): EquipmentDetail?; | fun findByDescriptionAndDeletedIsFalse(description: String): EquipmentDetail?; | ||||
| fun findByEquipmentTypeIdAndDeletedFalse(equipmentTypeId: Long): List<EquipmentDetail>; | |||||
| } | } | ||||
| @@ -78,4 +78,7 @@ interface PickOrderRepository : AbstractRepository<PickOrder, Long> { | |||||
| // 在 PickOrderRepository 中添加: | // 在 PickOrderRepository 中添加: | ||||
| fun findAllByStatusAndAssignToIsNullAndDeletedFalse(status: PickOrderStatus): List<PickOrder> | fun findAllByStatusAndAssignToIsNullAndDeletedFalse(status: PickOrderStatus): List<PickOrder> | ||||
| //fun findAllByJoid(jobOrderId: Long): List<PickOrder> | |||||
| fun findAllByJobOrder_Id(jobOrderId: Long): List<PickOrder> | |||||
| fun findTopByJobOrder_IdOrderByCreatedDesc(jobOrderId: Long): PickOrder? | |||||
| } | } | ||||
| @@ -26,6 +26,8 @@ open class ProductProcessLine : BaseEntity<Long>() { | |||||
| @Column(name = "equipmentDetailId") | @Column(name = "equipmentDetailId") | ||||
| open var equipmentDetailId: Long? = null | open var equipmentDetailId: Long? = null | ||||
| @Size(max = 100) | @Size(max = 100) | ||||
| @Column(name = "name", length = 100) | @Column(name = "name", length = 100) | ||||
| open var name: String? = null | open var name: String? = null | ||||
| @@ -52,6 +52,7 @@ data class ProductProcessLineInfo( | |||||
| val name: String?, | val name: String?, | ||||
| val description: String?, | val description: String?, | ||||
| val equipment_name: String?, | val equipment_name: String?, | ||||
| val equipmentDetailCode: String?, | |||||
| val status: String?, | val status: String?, | ||||
| val byproductId: Long?, | val byproductId: Long?, | ||||
| val byproductName: String?, | val byproductName: String?, | ||||
| @@ -7,6 +7,7 @@ import com.ffii.fpsms.modules.productProcess.enums.ProductProcessStatus | |||||
| import com.ffii.fpsms.modules.productProcess.web.model.* | import com.ffii.fpsms.modules.productProcess.web.model.* | ||||
| import org.springframework.data.domain.Page | import org.springframework.data.domain.Page | ||||
| import org.springframework.data.domain.Pageable | import org.springframework.data.domain.Pageable | ||||
| import com.ffii.fpsms.modules.master.entity.EquipmentDetailRepository | |||||
| import com.ffii.fpsms.modules.productProcess.entity.projections.jobOrderLineInfo | import com.ffii.fpsms.modules.productProcess.entity.projections.jobOrderLineInfo | ||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
| import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||
| @@ -38,7 +39,7 @@ import com.ffii.fpsms.modules.stock.service.StockInLineService | |||||
| import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest | import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest | ||||
| import com.ffii.fpsms.modules.master.entity.BomProcessMaterialRepository | import com.ffii.fpsms.modules.master.entity.BomProcessMaterialRepository | ||||
| import com.ffii.fpsms.modules.master.entity.BomMaterialRepository | import com.ffii.fpsms.modules.master.entity.BomMaterialRepository | ||||
| import com.ffii.fpsms.modules.master.entity.EquipmentDetailRepository | |||||
| import com.ffii.fpsms.modules.jobOrder.entity.JobTypeRepository | import com.ffii.fpsms.modules.jobOrder.entity.JobTypeRepository | ||||
| @Service | @Service | ||||
| @Transactional | @Transactional | ||||
| @@ -482,6 +483,7 @@ open class ProductProcessService( | |||||
| // get bom materials | // get bom materials | ||||
| val bomMaterials = jobOrderBomMaterialRepository.findAllByJobOrderId(jobOrder?.id?:0) | val bomMaterials = jobOrderBomMaterialRepository.findAllByJobOrderId(jobOrder?.id?:0) | ||||
| val bomProcessIds = bomProcess.mapNotNull { it.id } | val bomProcessIds = bomProcess.mapNotNull { it.id } | ||||
| val itemIds = bomMaterials.mapNotNull { it.item?.id } | val itemIds = bomMaterials.mapNotNull { it.item?.id } | ||||
| // calculate each item's available stock | // calculate each item's available stock | ||||
| @@ -559,6 +561,8 @@ open class ProductProcessService( | |||||
| return productProcesses.map { process -> | return productProcesses.map { process -> | ||||
| val jobType = jobTypeRepository.findById(process.jobOrder?.jobTypeId?:0L).orElse(null) | val jobType = jobTypeRepository.findById(process.jobOrder?.jobTypeId?:0L).orElse(null) | ||||
| println("jobType id ${process.jobOrder?.jobTypeId}") | |||||
| ProductProcessInfo( | ProductProcessInfo( | ||||
| id = process.id?:0, | id = process.id?:0, | ||||
| bomId = process.bom?.id?:0, | bomId = process.bom?.id?:0, | ||||
| @@ -586,6 +590,10 @@ open class ProductProcessService( | |||||
| insufficientStockQty = insufficientStockQty, | insufficientStockQty = insufficientStockQty, | ||||
| sufficientStockQty = sufficientStockQty, | sufficientStockQty = sufficientStockQty, | ||||
| productProcessLines = productProcessLineRepository.findByProductProcess_Id(process.id?:0).map { line -> | productProcessLines = productProcessLineRepository.findByProductProcess_Id(process.id?:0).map { line -> | ||||
| val equipmentDetail =equipmentDetailRepository.findById(line.equipmentDetailId?:0L).orElse(null) | |||||
| println("equipmentDetail ${equipmentDetail?.code}") | |||||
| println("equipmentDetail id${line.equipmentDetailId}") | |||||
| println("line id${line.id}") | |||||
| ProductProcessLineInfo( | ProductProcessLineInfo( | ||||
| id = line.id?:0, | id = line.id?:0, | ||||
| bomprocessId = line.bomProcess?.id?:0, | bomprocessId = line.bomProcess?.id?:0, | ||||
| @@ -597,6 +605,7 @@ open class ProductProcessService( | |||||
| name = line.name?:"", | name = line.name?:"", | ||||
| description = line.description?:"", | description = line.description?:"", | ||||
| equipment_name = line.equipmentType?:"", | equipment_name = line.equipmentType?:"", | ||||
| equipmentDetailCode = equipmentDetail?.code?:"", | |||||
| status = line.status?:"", | status = line.status?:"", | ||||
| durationInMinutes = line.bomProcess?.durationInMinute?:0, | durationInMinutes = line.bomProcess?.durationInMinute?:0, | ||||
| prepTimeInMinutes = line.bomProcess?.prepTimeInMinute?:0, | prepTimeInMinutes = line.bomProcess?.prepTimeInMinute?:0, | ||||
| @@ -693,7 +702,7 @@ open class ProductProcessService( | |||||
| this.seqNo = bomProcess.seqNo?:0 | this.seqNo = bomProcess.seqNo?:0 | ||||
| this.name = process?.name?:"" | this.name = process?.name?:"" | ||||
| this.description = bomProcess.description?:"" | this.description = bomProcess.description?:"" | ||||
| this.equipmentType = equipment?.name?:"" | |||||
| this.equipmentType = equipment?.code?:"" | |||||
| this.status = "Pending" | this.status = "Pending" | ||||
| } | } | ||||
| productProcessLineRepository.save(productProcessLine) | productProcessLineRepository.save(productProcessLine) | ||||
| @@ -710,6 +719,7 @@ open class ProductProcessService( | |||||
| } | } | ||||
| open fun UpdateProductProcessLineOperatorIdOrEquipmentId(request: UpdateProductProcessLineOperatorIdOrEquipmentIdRequest): MessageResponse { | open fun UpdateProductProcessLineOperatorIdOrEquipmentId(request: UpdateProductProcessLineOperatorIdOrEquipmentIdRequest): MessageResponse { | ||||
| val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) | val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) | ||||
| /* | |||||
| val equipmentId = request.equipmentId | val equipmentId = request.equipmentId | ||||
| val user = userRepository.findById(request.operatorId?:0L).orElse(null) | val user = userRepository.findById(request.operatorId?:0L).orElse(null) | ||||
| val bomProcess= bomProcessRepository.findById(productProcessLine?.bomProcess?.id?:0L).orElse(null) | val bomProcess= bomProcessRepository.findById(productProcessLine?.bomProcess?.id?:0L).orElse(null) | ||||
| @@ -753,6 +763,52 @@ open class ProductProcessService( | |||||
| productProcessLineRepository.save(productProcessLine) | productProcessLineRepository.save(productProcessLine) | ||||
| } | } | ||||
| */ | |||||
| val equipmentTypeSubTypeEquipmentNo = request.equipmentTypeSubTypeEquipmentNo | |||||
| println("equipmentTypeSubTypeEquipmentNo ${equipmentTypeSubTypeEquipmentNo}") | |||||
| val staffNo = request.staffNo | |||||
| println("staffNo ${staffNo}") | |||||
| val user = userRepository.findByStaffNo(staffNo?:"").orElse(null) | |||||
| println("user ${user?.id}") | |||||
| val equipmentDetail = equipmentDetailRepository.findByCode(equipmentTypeSubTypeEquipmentNo?:"") | |||||
| println("equipmentDetail ${equipmentDetail?.id}") | |||||
| val equipmentId = equipmentDetail?.equipmentTypeId | |||||
| println("equipmentId ${equipmentId}") | |||||
| val bomProcess= bomProcessRepository.findById(productProcessLine?.bomProcess?.id?:0L).orElse(null) | |||||
| val bomProcessEquipment=bomProcess?.equipment | |||||
| println("bomProcessEquipment ${bomProcessEquipment?.id}") | |||||
| if (equipmentId != null && user != null) { | |||||
| // 检查 equipmentId 是否与 bomProcessEquipment 匹配 | |||||
| if (equipmentId != bomProcessEquipment?.id) { | |||||
| println("productProcessLine id${request.productProcessLineId}") | |||||
| println("user ${user?.id}") | |||||
| println("bomProcess ${bomProcess?.id}") | |||||
| println("not match equipment id${equipmentId} and ${bomProcessEquipment?.id}") | |||||
| // 返回错误响应 | |||||
| return MessageResponse( | |||||
| id = request.productProcessLineId, | |||||
| code = "400", | |||||
| name = "Equipment Validation Failed", | |||||
| type = "error", | |||||
| message = "Input Equipment ID($equipmentId) and BOM Process Equipment ID(${bomProcessEquipment?.id}) not match", | |||||
| errorPosition = "equipmentId" | |||||
| ) | |||||
| } | |||||
| } | |||||
| if(equipmentId != null &&( equipmentId==bomProcessEquipment?.id)) { | |||||
| productProcessLine?.equipment = bomProcessEquipment | |||||
| productProcessLine?.equipmentDetailId = equipmentDetail?.id | |||||
| productProcessLineRepository.save(productProcessLine) | |||||
| } | |||||
| if(user != null) { | |||||
| productProcessLine.operator = user | |||||
| productProcessLineRepository.save(productProcessLine) | |||||
| } | |||||
| return MessageResponse( | return MessageResponse( | ||||
| id = null, | id = null, | ||||
| @@ -2,14 +2,18 @@ package com.ffii.fpsms.modules.productProcess.web.model | |||||
| import java.time.LocalDate | import java.time.LocalDate | ||||
| import java.time.LocalDateTime | import java.time.LocalDateTime | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | |||||
| data class SaveProductProcessRequest( | data class SaveProductProcessRequest( | ||||
| val bomId: Long, | val bomId: Long, | ||||
| val jobOrderId: Long?, | val jobOrderId: Long?, | ||||
| ) | ) | ||||
| data class UpdateProductProcessLineOperatorIdOrEquipmentIdRequest( | data class UpdateProductProcessLineOperatorIdOrEquipmentIdRequest( | ||||
| val productProcessLineId: Long, | val productProcessLineId: Long, | ||||
| val operatorId: Long?, | |||||
| val equipmentId: Long? | |||||
| //val operatorId: Long?, | |||||
| //val equipmentId: Long?, | |||||
| @JsonProperty("EquipmentType-SubType-EquipmentNo") | |||||
| val equipmentTypeSubTypeEquipmentNo: String?, | |||||
| val staffNo: String?, | |||||
| ) | ) | ||||
| data class UpdateProductProcessLineHandlerIdRequest( | data class UpdateProductProcessLineHandlerIdRequest( | ||||
| val productProcessLineId: Long, | val productProcessLineId: Long, | ||||
| @@ -3,18 +3,18 @@ package com.ffii.fpsms.modules.user.entity; | |||||
| import java.time.LocalDate; | import java.time.LocalDate; | ||||
| import java.util.Collection; | import java.util.Collection; | ||||
| import jakarta.persistence.Column; | |||||
| import jakarta.persistence.Entity; | |||||
| import jakarta.persistence.Table; | |||||
| import jakarta.persistence.Transient; | |||||
| import jakarta.validation.constraints.NotBlank; | |||||
| import org.springframework.security.core.GrantedAuthority; | import org.springframework.security.core.GrantedAuthority; | ||||
| import org.springframework.security.core.userdetails.UserDetails; | import org.springframework.security.core.userdetails.UserDetails; | ||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | import com.fasterxml.jackson.annotation.JsonIgnore; | ||||
| import com.ffii.core.entity.BaseEntity; | import com.ffii.core.entity.BaseEntity; | ||||
| import jakarta.persistence.Column; | |||||
| import jakarta.persistence.Entity; | |||||
| import jakarta.persistence.Table; | |||||
| import jakarta.persistence.Transient; | |||||
| import jakarta.validation.constraints.NotBlank; | |||||
| /** @author Terence */ | /** @author Terence */ | ||||
| @Entity | @Entity | ||||
| @Table(name = "user") | @Table(name = "user") | ||||
| @@ -77,6 +77,17 @@ public class User extends BaseEntity<Long> implements UserDetails { | |||||
| @Column | @Column | ||||
| private boolean lotusNotesUser = false; | private boolean lotusNotesUser = false; | ||||
| @Column | |||||
| private String staffNo; | |||||
| public String getStaffNo() { | |||||
| return staffNo; | |||||
| } | |||||
| public void setStaffNo(String staffNo) { | |||||
| this.staffNo = staffNo; | |||||
| } | |||||
| public boolean isLocked() { | public boolean isLocked() { | ||||
| return this.locked == null ? false : this.locked; | return this.locked == null ? false : this.locked; | ||||
| } | } | ||||
| @@ -15,4 +15,6 @@ public interface UserRepository extends AbstractRepository<User, Long> { | |||||
| Optional<User> findByUsernameAndDeletedFalse(String username); | Optional<User> findByUsernameAndDeletedFalse(String username); | ||||
| List<UserCombo> findUserComboByTitleNotNullAndDepartmentNotNullAndNameNotNullAndDeletedFalse(); | List<UserCombo> findUserComboByTitleNotNullAndDepartmentNotNullAndNameNotNullAndDeletedFalse(); | ||||
| Optional<User> findByStaffNo(@Param("staffNo") String staffNo); | |||||
| } | } | ||||
| @@ -0,0 +1,6 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset enson:altertable_enson | |||||
| ALTER TABLE `fpsmsdb`.`equipment_detail` | |||||
| MODIFY COLUMN `equipmentTypeID` INT NULL; | |||||