src/main/java/org/jeecg/modules/cms/controller/CuttingInboundController.java
@@ -10,10 +10,7 @@ import io.micrometer.core.annotation.Timed; import org.jeecg.common.api.vo.Result; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.modules.cms.entity.CuttingInbound; import org.jeecg.modules.cms.entity.CuttingInboundDetail; import org.jeecg.modules.cms.entity.CuttingInboundInventory; import org.jeecg.modules.cms.entity.CuttingInventory; import org.jeecg.modules.cms.entity.*; import org.jeecg.modules.cms.mapper.CuttingInboundMapper; import org.jeecg.modules.cms.service.ICuttingInboundDetailService; import org.jeecg.modules.cms.service.ICuttingInboundInventoryService; @@ -142,6 +139,9 @@ @DeleteMapping(value = "/delete") public Result<String> delete(@RequestParam(name = "id", required = true) String id) { cuttingInboundService.removeById(id); //删除刀具领用明细表的数据 cuttingInboundDetailService.remove (new QueryWrapper<CuttingInboundDetail>().eq("order_id", id)); return Result.OK("删除成功!"); } @@ -289,64 +289,7 @@ @GetMapping("/submit") @Timed(value = "cutting.inbound.submit", description = "刀具入库提交耗时") public Result<?> submit(@RequestParam("orderId") String orderId) { // long startTime = System.currentTimeMillis(); // try { // // 1. 更新入库单状态 // CuttingInbound cuttingInbound = cuttingInboundService.getById(orderId); // if (cuttingInbound == null) { // return Result.error("未找到对应的入库单"); // } // cuttingInbound.setOrderStatus("2"); // cuttingInboundService.updateById(cuttingInbound); // // // 2. 获取入库明细 // List<CuttingInboundDetail> detailList = cuttingInboundDetailService.lambdaQuery() // .eq(CuttingInboundDetail::getOrderId, orderId) // .list(); // // // 3. 收集所有需要保存的数据 // List<CuttingInventory> inventoryList = new ArrayList<>(); // List<CuttingInboundInventory> inboundInventoryList = new ArrayList<>(); // // for (CuttingInboundDetail detail : detailList) { // int quantity = detail.getReceiveNumber() != null ? detail.getReceiveNumber().intValue() : 0; // // for (int i = 0; i < quantity; i++) { // // 生成库存记录 // CuttingInventory cuttingInventory = new CuttingInventory(); // cuttingInventory.setCuttingId(detail.getCuttingId()); // cuttingInventory.setCuttingBarcode(generateUniqueBarcode(detail.getCuttingId(), i)); // cuttingInventory.setInventoryStatus("正常"); // cuttingInventory.setCurrentLife(BigDecimal.valueOf(100)); // inventoryList.add(cuttingInventory); // } // } // // // 4. 批量保存库存记录(一次性操作) // if (!inventoryList.isEmpty()) { // cuttingInventoryService.saveBatch(inventoryList); // // // 5. 为每个保存的库存记录创建关联关系 // for (CuttingInventory inventory : inventoryList) { // CuttingInboundInventory cuttingInboundInventory = new CuttingInboundInventory(); // cuttingInboundInventory.setOrderId(orderId); // cuttingInboundInventory.setInventoryId(inventory.getId()); // inboundInventoryList.add(cuttingInboundInventory); // } // // // 6. 批量保存关联关系(一次性操作) // cuttingInboundInventoryService.saveBatch(inboundInventoryList); // } // // long endTime = System.currentTimeMillis(); // log.info("刀具入库提交完成,耗时: {} s", (endTime - startTime)/1000); // return Result.ok("提交成功"); // // } catch (Exception e) { // long endTime = System.currentTimeMillis(); // log.error("提交入库单失败,orderId: " + orderId + ",耗时: " + (endTime - startTime) + " ms", e); // return Result.error("提交失败: " + e.getMessage()); // } return cuttingInboundService.submit(orderId); } } src/main/java/org/jeecg/modules/cms/controller/CuttingReceiveController.java
@@ -159,6 +159,11 @@ cuttingInventoryService.restoreStatus(inventoryIds); } //删除刀具领用明细表的数据 cuttingReceiveDetailService.remove (new QueryWrapper<CuttingReceiveDetail>().eq("order_id", id)); return Result.OK("删除成功!"); } @@ -171,7 +176,6 @@ @DeleteMapping(value = "/deleteBatch") public Result<String> deleteBatch(@RequestParam(name = "ids") String ids) { this.cuttingReceiveService.removeByIds(Arrays.asList(ids.split(","))); //FIXME: 批量删除时,库存状态未恢复。也需要批量恢复库存状态。 return Result.OK("批量删除成功!"); } src/main/java/org/jeecg/modules/cms/controller/CuttingScrapController.java
@@ -107,25 +107,40 @@ JSONArray jsonArray = jSONObject.getJSONArray("detailData"); List<CuttingScrapDetail> list = jsonArray.toJavaList(CuttingScrapDetail.class); //做判断,申请报废的时候一个刀具只能申请一次 for (CuttingScrapDetail temp : list) { //判断刀具是否已经申请报废 QueryWrapper<CuttingScrapDetail> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("inventory_id", temp.getInventoryId()); // 检查数据库中是否已存在相同inventoryId的报废申请 if (cuttingScrapDetailService.count(queryWrapper) > 0) { cuttingScrapService.removeById(cuttingScrap.getId());//同时删除本表单 return Result.error("刀具" + temp.getInventoryId() + "已经申请报废,请不要重复申请"); } } // 所有检查通过后,保存所有明细数据 for (CuttingScrapDetail temp : list) { temp.setOrderId(cuttingScrap.getId()); cuttingScrapDetailService.save(temp); } // 更新库存刀具状态为"已出库" if (!list.isEmpty()) { // 收集所有需要更新状态的库存ID List<String> inventoryIds = list.stream() .map(CuttingScrapDetail::getInventoryId) // 假设CuttingScrapDetail中有inventoryId字段 .filter(id -> id != null && !id.isEmpty()) .collect(Collectors.toList()); if (!inventoryIds.isEmpty()) { // 更新库存状态为"已出库" cuttingInventoryService.updateStatus(inventoryIds, "待报废"); } } return Result.OK("添加成功!"); // // 更新库存刀具状态为"待报废" // if (!list.isEmpty()) { // // 收集所有需要更新状态的库存ID // List<String> inventoryIds = list.stream() // .map(CuttingScrapDetail::getInventoryId) // 假设CuttingScrapDetail中有inventoryId字段 // .filter(id -> id != null && !id.isEmpty()) // .collect(Collectors.toList()); // // if (!inventoryIds.isEmpty()) { // // 更新库存状态为"待报废" // cuttingInventoryService.updateStatus(inventoryIds, "待报废"); // } // } } /** @@ -154,7 +169,10 @@ //@RequiresPermissions("org.jeecg.modules:cms_cutting_scrap:delete") @DeleteMapping(value = "/delete") public Result<String> delete(@RequestParam(name = "id", required = true) String id) { cuttingScrapService.removeById(id); cuttingScrapService.removeById(id);//删除主表数据 //删除刀具报废明细表的数据 cuttingScrapDetailService.remove (new QueryWrapper<CuttingScrapDetail>().eq("order_id", id)); return Result.OK("删除成功!"); } @@ -238,4 +256,9 @@ return Result.ok(inventoryTooList); } @GetMapping("/submit") public Result<?> submit(@RequestParam("orderId") String orderId) { return cuttingScrapService.submit(orderId); } } src/main/java/org/jeecg/modules/cms/entity/CuttingInventory.java
@@ -78,8 +78,8 @@ @TableField(exist = false) // 表示这不是数据库字段 private String cuttingBarcodeSearch; @TableField(exist = false) // 表示这不是数据库字段 private String workpieceMaterial; // @TableField(exist = false) // 表示这不是数据库字段 // private String workpieceMaterial; @TableField(exist = false) // 表示这不是数据库字段 private BigDecimal ratedLife; src/main/java/org/jeecg/modules/cms/mapper/xml/CuttingReceiveMapper.xml
@@ -15,7 +15,7 @@ FROM cms_cutting_inventory t1 LEFT JOIN cms_cutting_tool t2 ON t1.cutting_id = t2.id LEFT JOIN (select * from v_sys_dict where dict_code = 'cutting_category') t3 on t3.item_value = t2.cutting_category WHERE t1.inventory_status = '正常' WHERE t1.inventory_status = '在库' AND t2.del_flag = 0 </select> src/main/java/org/jeecg/modules/cms/service/ICuttingReceiveService.java
@@ -16,6 +16,7 @@ public interface ICuttingReceiveService extends IService<CuttingReceive> { IPage<Map<String, Object>> getInventoryToolList(Integer pageNo, Integer pageSize, Map<String, Object> params); Result<?> submit(String orderId); Result<?> handleBack(String orderId); src/main/java/org/jeecg/modules/cms/service/ICuttingScrapDetailService.java
@@ -1,8 +1,10 @@ package org.jeecg.modules.cms.service; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; import org.jeecg.modules.cms.entity.CuttingScrapDetail; import com.baomidou.mybatisplus.extension.service.IService; import java.io.Serializable; import java.util.List; import java.util.Map; @@ -15,4 +17,5 @@ public interface ICuttingScrapDetailService extends IService<CuttingScrapDetail> { public List<Map<String, Object>> detailList(String orderId); } src/main/java/org/jeecg/modules/cms/service/ICuttingScrapService.java
@@ -1,6 +1,7 @@ package org.jeecg.modules.cms.service; import com.baomidou.mybatisplus.core.metadata.IPage; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.cms.entity.CuttingScrap; import com.baomidou.mybatisplus.extension.service.IService; @@ -15,5 +16,6 @@ public interface ICuttingScrapService extends IService<CuttingScrap> { IPage<Map<String, Object>> getInventoryToolList(Integer pageNo, Integer pageSize, Map<String, Object> params); Result<?> submit(String orderId); } src/main/java/org/jeecg/modules/cms/service/impl/CuttingInboundServiceImpl.java
@@ -135,7 +135,7 @@ CuttingInventory cuttingInventory = new CuttingInventory(); cuttingInventory.setCuttingId(detail.getCuttingId()); cuttingInventory.setCuttingBarcode(generateUniqueBarcode(detail.getCuttingId(), i)); cuttingInventory.setInventoryStatus("正常"); cuttingInventory.setInventoryStatus("在库"); cuttingInventory.setCurrentLife(BigDecimal.valueOf(100)); inventoryList.add(cuttingInventory); } src/main/java/org/jeecg/modules/cms/service/impl/CuttingInventoryServiceImpl.java
@@ -67,14 +67,13 @@ // 方式1: 查询当前状态并根据状态决定恢复到哪个状态 List<CuttingInventory> inventoryList = this.listByIds(ids); List<String> toRestoreIds = inventoryList.stream() .filter(inv -> "待出库".equals(inv.getInventoryStatus())) // 只处理"待出库"状态的 .filter(inv -> "待出库".equals(inv.getInventoryStatus())) // 出库单作废的情况下,只会有待出库退回正常状态的情况。 .map(CuttingInventory::getId) .collect(Collectors.toList()); //FIXME:在报废前有多个状态,如果报废作废,刀具库存状态如何退回原来的状态。 if (!toRestoreIds.isEmpty()) { UpdateWrapper<CuttingInventory> updateWrapper = new UpdateWrapper<>(); updateWrapper.in("id", toRestoreIds); updateWrapper.set("inventory_status", "正常"); updateWrapper.set("inventory_status", "在库"); updateWrapper.set("update_time", new Date()); updateWrapper.set("update_by", username); this.update(updateWrapper); src/main/java/org/jeecg/modules/cms/service/impl/CuttingReceiveServiceImpl.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.micrometer.core.annotation.Timed; import liquibase.pro.packaged.C; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.cms.entity.CuttingInventory; @@ -20,6 +21,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -95,8 +97,10 @@ } } @Override public synchronized Result<?> handleBack(String orderId) { //FIXME:刀具归还 目前设计的是以领用单为维度进行还库;若是需要以刀具为维度进行归还的则需要另行设计 long startTime = System.currentTimeMillis(); try { // 1. 更新领用单状态为已归还 @@ -129,32 +133,35 @@ } } // 4. 批量更新库存状态为"正常" if (!inventoryIds.isEmpty()) { cuttingInventoryService.updateStatus(inventoryIds, "正常"); } // 5. 寿命扣减 // 4. 寿命扣减 for (CuttingReceiveDetail detail : detailList) { if (detail.getInventoryId() != null && !detail.getInventoryId().isEmpty()) { CuttingReceiveDetail cuttingReceiveDetail = cuttingReceiveDetailService.getById(detail.getInventoryId()); CuttingInventory inventory = cuttingInventoryService.getById(detail.getInventoryId()); //FIXME:ratedLife空指针 RatedLife ratedLife = ratedLifeService.lambdaQuery() //额定寿命 .eq(RatedLife::getCuttingId, inventory.getCuttingId()) .eq(RatedLife::getWorkpieceMaterial, inventory.getWorkpieceMaterial()) .one(); BigDecimal currentLife = inventory.getCurrentLife().divide(BigDecimal.valueOf(100),java.math.RoundingMode.HALF_UP);//当前寿命百分比 RatedLife ratedLife = ratedLifeService.lambdaQuery() .eq(RatedLife::getCuttingId, detail.getCuttingId()) .eq(RatedLife::getWorkpieceMaterial, detail.getWorkpieceMaterial()) .one();//额定寿命 Integer useLife = detail.getUsedLife();//使用寿命 //计算公式: (ratedLife * currentLife - useLife) * 100 BigDecimal newLife = ratedLife.getRatedLife() .multiply(currentLife) .subtract(BigDecimal.valueOf(useLife)) .multiply(BigDecimal.valueOf(100)); //优化:(1-使用寿命/额定寿命)*100 BigDecimal usageRatio = BigDecimal.valueOf(useLife).divide(ratedLife.getRatedLife(), 4, RoundingMode.HALF_UP); BigDecimal newLife = BigDecimal.valueOf(1) .subtract(usageRatio) .multiply(BigDecimal.valueOf(100)) .setScale(2, RoundingMode.HALF_UP); // 更新库存寿命 inventory.setCurrentLife(newLife); cuttingInventoryService.updateById(inventory); } } // 5. 批量更新库存状态为"正常" if (!inventoryIds.isEmpty()) { cuttingInventoryService.updateStatus(inventoryIds, "在库"); } long endTime = System.currentTimeMillis(); log.info("刀具归还处理完成,耗时: {} ms", (endTime - startTime)); return Result.ok("归还成功"); src/main/java/org/jeecg/modules/cms/service/impl/CuttingScrapServiceImpl.java
@@ -2,13 +2,22 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.jeecg.modules.cms.entity.CuttingScrap; import io.micrometer.core.annotation.Timed; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.cms.entity.*; import org.jeecg.modules.cms.mapper.CuttingScrapMapper; import org.jeecg.modules.cms.service.ICuttingInventoryService; import org.jeecg.modules.cms.service.ICuttingScrapDetailService; import org.jeecg.modules.cms.service.ICuttingScrapService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; /** @@ -17,12 +26,70 @@ * @Date: 2025-07-28 * @Version: V1.0 */ @Slf4j @Service public class CuttingScrapServiceImpl extends ServiceImpl<CuttingScrapMapper, CuttingScrap> implements ICuttingScrapService { @Autowired private ICuttingScrapDetailService cuttingScarpDetailService; @Autowired private ICuttingInventoryService cuttingInventoryService; @Override public IPage<Map<String, Object>> getInventoryToolList(Integer pageNo, Integer pageSize, Map<String, Object> params) { IPage<Map> pageData = new Page<Map>(pageNo, pageSize); return super.getBaseMapper().getInventoryToolList(pageData,params); } @Override @Timed(value = "cutting.scrap.submit", description = "刀具领用提交耗时") public synchronized Result<?> submit(String orderId) { long startTime = System.currentTimeMillis(); try { // 1. 更新领用单状态 CuttingScrap cuttingScrap = this.getById(orderId); if (cuttingScrap == null) { return Result.error("未找到对应的领用单"); } // 检查领用单状态,只允许状态为"1"的领用单提交 if (!"1".equals(cuttingScrap.getOrderStatus())) { return Result.error("只有状态为未提交的领用单才能执行提交操作"); } cuttingScrap.setOrderStatus("2"); // 报废申请单变为 已提交 状态 boolean updateResult = this.updateById(cuttingScrap); if (!updateResult) { return Result.error("更新领用单状态失败,可能已被其他用户处理"); } // 2. 获取领用明细 List<CuttingScrapDetail> detailList = cuttingScarpDetailService.lambdaQuery() .eq(CuttingScrapDetail::getOrderId, orderId) .list(); // 3. 收集所有需要更新状态的库存ID List<String> inventoryIds = new ArrayList<>(); for (CuttingScrapDetail detail : detailList) { if (detail.getInventoryId() != null && !detail.getInventoryId().isEmpty()) { inventoryIds.add(detail.getInventoryId()); } } // 4. 批量更新库存状态为"已报废" if (!inventoryIds.isEmpty()) { cuttingInventoryService.updateStatus(inventoryIds, "已报废"); } long endTime = System.currentTimeMillis(); log.info("刀具领用提交完成,耗时: {} ms", (endTime - startTime)); return Result.ok("提交成功"); } catch (Exception e) { long endTime = System.currentTimeMillis(); log.error("提交领用单失败,orderId: " + orderId + ",耗时: " + (endTime - startTime) + " ms", e); return Result.error("提交失败: " + e.getMessage()); } } }