From 63548f3203f56cce13242418440774d6b3cc00cc Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Sat, 14 Mar 2026 17:27:51 +0800 Subject: [PATCH] product process list and warehouse --- .../master/service/WarehouseService.kt | 42 ++++++++++++++++++- .../modules/master/web/WarehouseController.kt | 23 +++++++++- .../master/web/models/SaveWarehouseRequest.kt | 11 +++++ .../service/ProductProcessService.kt | 7 +++- .../web/ProductProcessController.kt | 6 ++- .../web/model/SaveProductProcessRequest.kt | 1 + .../stock/web/model/StockTakeRecordReponse.kt | 7 ++++ 7 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/WarehouseService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/WarehouseService.kt index cba4b38..0abb4a3 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/WarehouseService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/WarehouseService.kt @@ -25,6 +25,9 @@ import org.springframework.stereotype.Service import java.math.BigDecimal import kotlin.jvm.optionals.getOrNull import com.ffii.fpsms.modules.master.web.models.ExcelWarehouseData +import com.ffii.core.exception.BadRequestException +import com.ffii.fpsms.modules.master.web.models.StockTakeSectionInfo +import com.ffii.fpsms.modules.master.web.models.UpdateSectionDescriptionRequest @Service open class WarehouseService( private val jdbcDao: JdbcDao, @@ -58,7 +61,18 @@ open class WarehouseService( open fun saveWarehouse(request: SaveWarehouseRequest): Warehouse { val warehouse = request.id?.let { warehouseRepository.findById(it).getOrNull() } ?: Warehouse(); - + val section = request.stockTakeSection?.takeIf { it.isNotBlank() } + if (section != null) { + val existingList = warehouseRepository.findAllByStockTakeSectionAndDeletedIsFalse(section) + .filter { it.id != request.id } // exclude current record when edit + if (existingList.isNotEmpty()) { + val existingDesc = existingList.mapNotNull { it.stockTakeSectionDescription }.firstOrNull()?.trim() ?: "" + val inputDesc = request.stockTakeSectionDescription?.trim() ?: "" + if (existingDesc != inputDesc) { + throw BadRequestException("stockTakeSectionDescription not same") + } + } + } warehouse.apply { // Generate code, name, description if not provided but store_id, warehouse, area, slot are provided if (request.code == null && request.store_id != null && request.warehouse != null && request.area != null && request.slot != null) { @@ -100,6 +114,7 @@ open class WarehouseService( if (request.area != null) area = request.area if (request.slot != null) slot = request.slot if (request.stockTakeSection != null) stockTakeSection = request.stockTakeSection + if (request.stockTakeSectionDescription != null) stockTakeSectionDescription = request.stockTakeSectionDescription }; return warehouseRepository.save(warehouse); @@ -390,4 +405,29 @@ open class WarehouseService( // calculate total sort value: floor * 10000 + letter * 100 + slot return floorOrder * 10000L + letterOrder * 100L + slot } + + open fun getStockTakeSections(): List { + val all = warehouseRepository.findAllByDeletedIsFalse() + .filter { it.stockTakeSection != null && it.stockTakeSection!!.isNotBlank() } + val grouped = all.groupBy { it.stockTakeSection!! } + return grouped.map { (section, list) -> + val desc = list.mapNotNull { it.stockTakeSectionDescription }.firstOrNull()?.trim() + StockTakeSectionInfo(section, desc, list.size.toLong()) + }.sortedBy { it.stockTakeSection } + } + + open fun updateSectionDescription(section: String, newDescription: String?) { + val list = warehouseRepository.findAllByStockTakeSectionAndDeletedIsFalse(section) + list.forEach { w -> + w.stockTakeSectionDescription = newDescription?.takeIf { it.isNotBlank() } + warehouseRepository.save(w) + } + } + + open fun clearWarehouseSection(warehouseId: Long) { + val w = warehouseRepository.findById(warehouseId).orElseThrow() + w.stockTakeSection = null + w.stockTakeSectionDescription = null + warehouseRepository.save(w) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/WarehouseController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/WarehouseController.kt index 190a387..3e7658c 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/web/WarehouseController.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/web/WarehouseController.kt @@ -25,7 +25,8 @@ import org.springframework.web.multipart.MultipartHttpServletRequest import net.sf.jasperreports.engine.JasperExportManager import net.sf.jasperreports.engine.JasperPrint import java.io.OutputStream - +import com.ffii.fpsms.modules.master.web.models.StockTakeSectionInfo +import com.ffii.fpsms.modules.master.web.models.UpdateSectionDescriptionRequest @RestController @RequestMapping("/warehouse") class WarehouseController( @@ -97,4 +98,24 @@ class WarehouseController( out.write(JasperExportManager.exportReportToPdf(jasperPrint)) out.flush() } + @GetMapping("/stockTakeSections") +fun getStockTakeSections(): List { + return warehouseService.getStockTakeSections() +} + +// PATCH /warehouse/section/{section}/description (body: { "stockTakeSectionDescription": "demo1" }) +@org.springframework.web.bind.annotation.PatchMapping("/section/{section}/description") +fun updateSectionDescription( + @PathVariable section: String, + @RequestBody body: UpdateSectionDescriptionRequest +): Unit { + warehouseService.updateSectionDescription(section, body.stockTakeSectionDescription) +} + +// POST /warehouse/{id}/clearSection +@PostMapping("/{id}/clearSection") +fun clearWarehouseSection(@PathVariable id: Long): Warehouse { + warehouseService.clearWarehouseSection(id) + return warehouseService.findById(id)!! +} } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/models/SaveWarehouseRequest.kt b/src/main/java/com/ffii/fpsms/modules/master/web/models/SaveWarehouseRequest.kt index 6d6d26c..bd042c4 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/web/models/SaveWarehouseRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/web/models/SaveWarehouseRequest.kt @@ -14,6 +14,7 @@ data class SaveWarehouseRequest( val slot: String? = null, val order: String? = null, val stockTakeSection: String? = null, + val stockTakeSectionDescription: String? = null, ) data class NewWarehouseRequest( @@ -37,3 +38,13 @@ data class NewWarehouseRequest( val slot: String, val rowIndex: String ) +data class StockTakeSectionInfo( + val stockTakeSection: String, + val stockTakeSectionDescription: String?, + val warehouseCount: Long +) + + +data class UpdateSectionDescriptionRequest( + val stockTakeSectionDescription: String? +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt index a763685..b6acaa1 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt @@ -1376,7 +1376,7 @@ open class ProductProcessService( ) } - open fun getAllJoborderProductProcessInfo(): List { + open fun getAllJoborderProductProcessInfo(isDrink: Boolean?): List { val productProcesses = productProcessRepository.findAllByDeletedIsFalse() val productProcessIds = productProcesses.map { it.id } @@ -1397,12 +1397,14 @@ open class ProductProcessService( val timeNeedToComplete = bomProcessRepository.findByBomId(productProcesses.bom?.id ?: 0L) .filter { !it.deleted } .sumOf { it.durationInMinute ?: 0 } + val bomIsDrink = productProcesses.bom?.isDrink AllJoborderProductProcessInfoResponse( id = productProcesses.id ?: 0L, productProcessCode = productProcesses.productProcessCode, status = productProcesses.status.value, startTime = productProcesses.startTime, endTime = productProcesses.endTime, + isDrink = bomIsDrink, matchStatus = if (joPickOrdersList.isNotEmpty() && joPickOrdersList.all { it.matchStatus == JoPickOrderStatus.completed } ) { @@ -1445,6 +1447,9 @@ open class ProductProcessService( ) }.filter { response -> // 过滤掉已完成上架的 job order + if (isDrink != null && response.isDrink != isDrink) { + return@filter false + } val jobOrder = jobOrderRepository.findById(response.jobOrderId ?: 0L).orElse(null) val stockInLineStatus = jobOrder?.stockInLines?.firstOrNull()?.status stockInLineStatus != "completed" diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt index a3b241f..82c58a4 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt @@ -193,8 +193,10 @@ class ProductProcessController( } @GetMapping("/Demo/Process/all") - fun demoprocessall(): List { - return productProcessService.getAllJoborderProductProcessInfo() + fun demoprocessall( + @RequestParam(required = false) isDrink: Boolean? + ): List { + return productProcessService.getAllJoborderProductProcessInfo(isDrink) } @PostMapping("/Demo/ProcessLine/start/{lineId}") fun startProductProcessLine(@PathVariable lineId: Long): MessageResponse { diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt index 283af9a..85cd247 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt @@ -180,6 +180,7 @@ data class AllJoborderProductProcessInfoResponse( val FinishedProductProcessLineCount: Int, val stockInLineId: Long?, val TimeNeedToComplete: Int?, + val isDrink: Boolean?, val lines: List ) data class ProductProcessInfoResponse( diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt index ab74363..02c4dc0 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt @@ -25,6 +25,7 @@ data class AllPickedStockTakeListReponse( val ReStockTakeTrueFalse: Boolean, @JsonFormat(pattern = "yyyy-MM-dd") val planStartDate: LocalDate?, + val stockTakeSectionDescription: String?, ) data class InventoryLotDetailResponse( val id: Long, @@ -99,6 +100,12 @@ data class BatchSaveApproverStockTakeRecordRequest( val variancePercentTolerance: BigDecimal? = null, ) +data class BatchSaveApproverStockTakeAllRequest( + val stockTakeId: Long, + val approverId: Long, + val variancePercentTolerance: BigDecimal? = null, +) + data class BatchSaveApproverStockTakeRecordResponse( val successCount: Int, val errorCount: Int,