/* * Copyright (c) 2018-2025, ztt All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: ztt */ package com.chinaztt.mes.production.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.chinaztt.mes.basic.entity.Location; import com.chinaztt.mes.basic.entity.Part; import com.chinaztt.mes.basic.entity.WorkstationLocation; import com.chinaztt.mes.basic.mapper.LocationMapper; import com.chinaztt.mes.basic.mapper.PartMapper; import com.chinaztt.mes.basic.mapper.WorkstationLocationMapper; import com.chinaztt.mes.common.numgen.NumberGenerator; import com.chinaztt.mes.common.wrapper.QueryWrapperUtil; import com.chinaztt.mes.production.dto.ProductOutputDTO; import com.chinaztt.mes.production.dto.SegmentationTaskRecordDTO; import com.chinaztt.mes.production.entity.*; import com.chinaztt.mes.production.mapper.*; import com.chinaztt.mes.production.service.SegmentationTaskRecordService; import com.chinaztt.mes.warehouse.dto.IfsMoveLibraryInfoDTO; import com.chinaztt.mes.warehouse.dto.StockAddDTO; import com.chinaztt.mes.warehouse.dto.StockDTO; import com.chinaztt.mes.warehouse.entity.Stock; import com.chinaztt.mes.warehouse.mapper.StockMapper; import com.chinaztt.mes.warehouse.service.StockService; import com.chinaztt.mes.warehouse.util.StockUtils; import com.chinaztt.mes.warehouse.util.TransactionType; import com.chinaztt.ztt.common.core.util.R; import com.chinaztt.ztt.common.sequence.sequence.Sequence; import lombok.AllArgsConstructor; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * 分割任务明细 * * @author shz * @date 2023-02-14 09:04:11 */ @Service @AllArgsConstructor @Transactional(rollbackFor = Exception.class) public class SegmentationTaskRecordServiceImpl extends ServiceImpl implements SegmentationTaskRecordService { private NumberGenerator segmentationTaskNumberGenerator; private SegmentationTaskMapper segmentationTaskMapper; private StockMapper stockMapper; private SegmentationTaskInputMapper segmentationTaskInputMapper; private StockUtils stockUtils; private PartMapper partMapper; private StockService stockService; private LocationMapper locationMapper; private ExaminerMapper examinerMapper; private WorkstationLocationMapper workstationLocationMapper; private Sequence segmentationSequence; @Override public IPage getPage(Page page, QueryWrapper gen,SegmentationTaskRecordDTO segmentationTaskRecordDTO) { SegmentationTaskRecordDTO searchSegmentationTaskRecordDTO = new SegmentationTaskRecordDTO(); BeanUtils.copyProperties(segmentationTaskRecordDTO,searchSegmentationTaskRecordDTO); segmentationTaskRecordDTO.setStartTime(null); segmentationTaskRecordDTO.setEndTime(null); return this.baseMapper.getPage(page,QueryWrapperUtil.gen(segmentationTaskRecordDTO),searchSegmentationTaskRecordDTO); } @Override public boolean fullSave(SegmentationTaskRecordDTO segmentationTaskRecord) { String taskNo = segmentationTaskNumberGenerator.generateNumberWithPrefix(SegmentationTask.DIGIT, SegmentationTask.PREFIX, SegmentationTask::getNo); // 投入总调整数量 BigDecimal totalInputNum = segmentationTaskRecord.getInputs().stream().map(SegmentationTaskInput::getAdjustQty).reduce(BigDecimal.ZERO, BigDecimal::add); // 生产总数量不能大于输入数量 BigDecimal totalProduceNum = segmentationTaskRecord.getProductQty().multiply(new BigDecimal(segmentationTaskRecord.getDiskNum())); // 占用库存 = 生产数量 + 报废数量 for (SegmentationTaskInput input : segmentationTaskRecord.getInputs()) { // 判断是否为工序库存 Stock stock = stockMapper.selectById(input.getStockId()); if (stock.getOperationStockStatus()) { throw new RuntimeException("工序库存不能作为分割投入"); } // 如果存在多余的库存,需要将多余的库存释放 if (segmentationTaskRecord.getReturnInputStockId() != null && input.getStockId().equals(segmentationTaskRecord.getReturnInputStockId())) { BigDecimal returnNum = totalInputNum.subtract(totalProduceNum); if (input.getAdjustQty().compareTo(returnNum) < 0) { throw new RuntimeException("需退回数量大于原输入数量"); } else { input.setAdjustQty(input.getAdjustQty().subtract(returnNum)); } } stockUtils.updateById(input.getStockId(), input.getAdjustQty().add(input.getScrapQty()).negate(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, taskNo, TransactionType.SEGMENTATION_IN.getValue()); } // 生成分割主表数据 SegmentationTask segmentationTask = SegmentationTask.builder() .no(taskNo) .taskType(segmentationTaskRecord.getTaskType()) .diskNum(segmentationTaskRecord.getDiskNum()) .partId(segmentationTaskRecord.getPartId()) .unit(segmentationTaskRecord.getUnit()) .productionUser(segmentationTaskRecord.getProductionUser()) .dutyRecordId(segmentationTaskRecord.getDutyRecordId()) .workstationId(segmentationTaskRecord.getWorkstationId()) .build(); segmentationTaskMapper.insert(segmentationTask); DateTimeFormatter snFormat = DateTimeFormatter.ofPattern("yyMMdd"); String snDate = snFormat.format(LocalDateTime.now()); /* SegmentationTaskRecord maxRecord = this.baseMapper.selectOne(Wrappers.lambdaQuery() .like(SegmentationTaskRecord::getPartBatchNo, "Q" + snDate) .orderByDesc(SegmentationTaskRecord::getPartBatchNo) .last("LIMIT 1")); int num = 1; if (maxRecord != null) { String partBatchNo = maxRecord.getPartBatchNo(); num = Integer.parseInt(partBatchNo.substring(partBatchNo.length() - 6)) + 1; }*/ Part part = this.partMapper.selectById(segmentationTaskRecord.getPartId()); WorkstationLocation workstationLocation = workstationLocationMapper.selectOne(Wrappers.lambdaQuery().eq(WorkstationLocation::getWorkstationId, segmentationTask.getWorkstationId()) .eq(WorkstationLocation::getLocationType, WorkstationLocation.QUALIFIED_LOCATION).last("limit 1")); Location qualifiedLocation = locationMapper.selectById(workstationLocation.getLocationId()); // 生成分割明细数据 for (int i = 0; i < segmentationTaskRecord.getDiskNum(); i++) { SegmentationTaskRecord record = new SegmentationTaskRecord(); BeanUtil.copyProperties(segmentationTaskRecord, record); record.setTaskId(segmentationTask.getId()); int num = Integer.parseInt(segmentationSequence.nextNo().substring(8)); record.setPartBatchNo("Q" + snDate + String.format("%06d", num)); record.setLocationId(qualifiedLocation.getId()); // 分盘IFS批次号不变,检号分盘和拼盘根据是否启用批次号来判断 if (SegmentationTask.TASK_TYPE_CENT_LINE.equals(segmentationTaskRecord.getTaskType())) { record.setIfsBatchNo(segmentationTaskRecord.getInputs().get(0).getIfsBatchNo()); } else { if (part.getLotTrackingIfs()) { record.setIfsBatchNo(record.getPartBatchNo()); } else { record.setIfsBatchNo("*"); } } record.setStatus(SegmentationTaskRecord.STATUS_DRAFT); this.baseMapper.insert(record); //num++; } BigDecimal totalNum = segmentationTaskRecord.getInputs().stream().map(SegmentationTaskInput::getAdjustQty).reduce(BigDecimal.ZERO, BigDecimal::add); // 生成分割输入数据 for (SegmentationTaskInput input : segmentationTaskRecord.getInputs()) { input.setTaskId(segmentationTask.getId()); input.setProportion(input.getAdjustQty().divide(totalNum, 2, RoundingMode.HALF_UP)); input.setUnit(segmentationTaskRecord.getUnit()); segmentationTaskInputMapper.insert(input); } return true; } @Override public synchronized boolean fullUpdate(List segmentationTaskRecords) { if (CollectionUtil.isNotEmpty(segmentationTaskRecords)) { for (SegmentationTaskRecordDTO segmentationTaskRecord : segmentationTaskRecords) { SegmentationTaskRecord record = this.baseMapper.selectById(segmentationTaskRecord.getId()); if (record == null) { throw new RuntimeException("分割任务不存在"); } if (SegmentationTaskRecord.STATUS_DRAFT.equals(record.getStatus())) { if (segmentationTaskRecord.getProductQty().compareTo(record.getProductQty()) != 0) { // 找出所有投入数据 List inputs = segmentationTaskInputMapper.selectList(Wrappers.lambdaQuery() .eq(SegmentationTaskInput::getTaskId, record.getTaskId())); BigDecimal totalInputNum = BigDecimal.ZERO; for (SegmentationTaskInput input : inputs) { totalInputNum = totalInputNum.add(input.getAdjustQty()).add(input.getScrapQty()); } BigDecimal totalProductQty = record.getProductQty(); // 找出所有明细数据 List records = this.baseMapper.selectList(Wrappers.lambdaQuery() .eq(SegmentationTaskRecord::getTaskId, record.getTaskId()).ne(SegmentationTaskRecord::getId, record.getId())); if (records.size() > 0) { totalProductQty = totalProductQty.add(records.stream().map(SegmentationTaskRecord::getProductQty).reduce(BigDecimal.ZERO, BigDecimal::add)); } if (totalProductQty.compareTo(totalInputNum) > 0) { throw new RuntimeException("分割数量大于投入数量"); } } // 校验分段描述 if (StrUtil.isNotBlank(segmentationTaskRecord.getSegmentDesc())) { checkSegmentDesc(segmentationTaskRecord.getProductQty(), segmentationTaskRecord.getSegmentDesc()); } // 如果生产数量减少,需要将多余数量退回 if (segmentationTaskRecord.getProductQty().compareTo(record.getProductQty()) != 0) { BigDecimal returnNum = record.getProductQty().subtract(segmentationTaskRecord.getProductQty()); SegmentationTask segmentationTask = this.segmentationTaskMapper.selectById(record.getTaskId()); if (segmentationTask.getTaskType().equals(SegmentationTask.TASK_TYPE_MERGE_DISH)) { SegmentationTaskInput input = this.segmentationTaskInputMapper.selectOne(Wrappers.lambdaQuery() .eq(SegmentationTaskInput::getTaskId, record.getTaskId()) .eq(SegmentationTaskInput::getStockId, segmentationTaskRecord.getReturnInputStockId())); if (returnNum.compareTo(BigDecimal.ZERO) > 0) { if (input.getAdjustQty().compareTo(returnNum) < 0) { throw new RuntimeException("退回数量无法大于该批次投入数量"); } } stockUtils.updateById(segmentationTaskRecord.getReturnInputStockId(), returnNum, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, segmentationTask.getNo(), TransactionType.SEGMENTATION_OUT.getValue()); // 更新投入数量 input.setAdjustQty(input.getAdjustQty().subtract(returnNum)); segmentationTaskInputMapper.updateById(input); } else { SegmentationTaskInput input = this.segmentationTaskInputMapper.selectOne(Wrappers.lambdaQuery().eq(SegmentationTaskInput::getTaskId, record.getTaskId())); if (returnNum.compareTo(BigDecimal.ZERO) > 0) { if (input.getAdjustQty().compareTo(returnNum) < 0) { throw new RuntimeException("退回数量无法大于该批次投入数量"); } } stockUtils.updateById(input.getStockId(), returnNum, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, segmentationTask.getNo(), TransactionType.SEGMENTATION_OUT.getValue()); // 更新投入数量 input.setAdjustQty(input.getAdjustQty().subtract(returnNum)); segmentationTaskInputMapper.updateById(input); } } record.setProductQty(segmentationTaskRecord.getProductQty()); record.setSegmentDesc(segmentationTaskRecord.getSegmentDesc()); } record.setReelNumber(segmentationTaskRecord.getReelNumber()); record.setRemark(segmentationTaskRecord.getRemark()); this.updateById(record); } } return true; } @Override public boolean delByIds(List ids) { synchronized (ids.toString().intern()) { for (Long id : ids) { SegmentationTaskRecord record = this.baseMapper.selectById(id); if (record == null) { throw new RuntimeException("分割任务不存在"); } if (!SegmentationTaskRecord.STATUS_DRAFT.equals(record.getStatus())) { throw new RuntimeException("分割任务状态不是草稿"); } SegmentationTask task = segmentationTaskMapper.selectById(record.getTaskId()); Integer count = this.baseMapper.selectCount(Wrappers.lambdaQuery() .eq(SegmentationTaskRecord::getTaskId, record.getTaskId()).ne(SegmentationTaskRecord::getId, record.getId())); // 查找所有投入数据 List inputs = segmentationTaskInputMapper.selectList(Wrappers.lambdaQuery() .eq(SegmentationTaskInput::getTaskId, record.getTaskId())); for (SegmentationTaskInput input : inputs) { // 计算该投入所需退回数量 BigDecimal summary = record.getProductQty().multiply(input.getProportion()); // 如果为最后一条明细,退回所有投入数量 if (count == 0) { // 退回库存 stockUtils.updateById(input.getStockId(), input.getAdjustQty().add(input.getScrapQty()), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, task.getNo(), TransactionType.SEGMENTATION_OUT.getValue()); // 删除投入数据 segmentationTaskInputMapper.deleteById(input.getId()); // 删除主表数据 segmentationTaskMapper.deleteById(task.getId()); // 投入数量小于退回数量 } else if (summary.compareTo(input.getAdjustQty()) < 0) { // 更新投入数量 input.setAdjustQty(input.getAdjustQty().subtract(summary)); segmentationTaskInputMapper.updateById(input); // 退回库存 stockUtils.updateById(input.getStockId(), summary, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, task.getNo(), TransactionType.SEGMENTATION_OUT.getValue()); } } // 删除分割明细数据 this.baseMapper.deleteById(id); } } return true; } @Override public boolean submit(List ids) { synchronized (ids.toString().intern()) { List records = this.baseMapper.selectBatchIds(ids); if (CollectionUtil.isEmpty(records)) { throw new RuntimeException("分割任务不存在"); } Long count = records.stream().map(SegmentationTaskRecord::getTaskId).distinct().count(); if (count.intValue() != 1) { throw new RuntimeException("只能提交同一个任务的明细"); } records.stream().filter(record -> !SegmentationTaskRecord.STATUS_DRAFT.equals(record.getStatus())).forEach(record -> { throw new RuntimeException("只能提交草稿状态的明细"); }); Integer checkCount = this.baseMapper.selectCount(Wrappers.lambdaQuery() .eq(SegmentationTaskRecord::getTaskId, records.get(0).getTaskId()) .notIn(SegmentationTaskRecord::getId, ids)); if (checkCount > 0) { throw new RuntimeException("该任务存在明细未提交"); } SegmentationTask task = segmentationTaskMapper.selectById(records.get(0).getTaskId()); // 查找所有投入数据 List segmentationTaskInputs = this.segmentationTaskInputMapper.selectList(Wrappers.lambdaQuery() .eq(SegmentationTaskInput::getTaskId, task.getId())); BigDecimal totalScrapQty = segmentationTaskInputs.stream().map(SegmentationTaskInput::getScrapQty).reduce(BigDecimal.ZERO, BigDecimal::add); // 如果类型为分盘 if (SegmentationTask.TASK_TYPE_CENT_LINE.equals(task.getTaskType())) { Stock inputStock = stockMapper.selectById(segmentationTaskInputs.get(0).getStockId()); Location inputLocation = locationMapper.selectById(inputStock.getLocationId()); Location nowLocation = locationMapper.selectById(records.get(0).getLocationId()); // 存在废料需要发放 if (totalScrapQty.compareTo(BigDecimal.ZERO) > 0) { List stocks = new ArrayList<>(); StockDTO stockDTO = new StockDTO(); stockDTO.setPartId(task.getPartId()); stockDTO.setLocationId(inputLocation.getId()); stockDTO.setLocationNo(inputLocation.getIfsLocation()); stockDTO.setPartBatchNo(segmentationTaskInputs.get(0).getPartBatchNo()); stockDTO.setIfsBatchNo(segmentationTaskInputs.get(0).getIfsBatchNo()); stockDTO.setManualInput(true); stockDTO.setAvailableStockQuantityMove(totalScrapQty); stockDTO.setAdjustType("Issue"); stockDTO.setAdjustMemo("库存发放"); stocks.add(stockDTO); stockService.inventAdjustForRfcable(stocks, "Issue", null); } // 判断投入库位和分割库位是否一致,不一致进行库存件移库 if (!records.get(0).getLocationId().equals(inputLocation.getId())) { Part part = partMapper.selectById(inputStock.getPartId()); List ifsMoveLibraryInfoDTOList = new ArrayList<>(); IfsMoveLibraryInfoDTO param = new IfsMoveLibraryInfoDTO(); param.setStartLocationNo(inputLocation.getIfsLocation()); param.setArriveLocationNo(nowLocation.getIfsLocation()); param.setMoveQty(segmentationTaskInputs.get(0).getAdjustQty()); param.setPartNo(segmentationTaskInputs.get(0).getPartNo()); param.setBatchNo(segmentationTaskInputs.get(0).getIfsBatchNo()); param.setSerialNo("*"); param.setEngChgLevel(part.getEngChgLevel()); if(part.getLotTrackingIfs() != null && part.getLotTrackingIfs()){ param.setWaivDevRejNo(segmentationTaskInputs.get(0).getPartBatchNo());//wdr号(把mes的sn号放里面) }else{ param.setWaivDevRejNo("*");//wdr号 } ifsMoveLibraryInfoDTOList.add(param); stockService.ifsMoveLibrary(ifsMoveLibraryInfoDTOList); } // 新增MES库存,调用更改wdr号接口 List stocks = new ArrayList<>(); for (SegmentationTaskRecord record : records) { StockAddDTO stockAddDTO = new StockAddDTO(); stockAddDTO.setPartsId(record.getPartId()); stockAddDTO.setNewLocationId(record.getLocationId()); stockAddDTO.setNewPartBatchNo(record.getPartBatchNo()); stockAddDTO.setReelNumber(record.getReelNumber()); stockAddDTO.setOperationStockStatus(false); stockAddDTO.setIfsBatchNo(record.getIfsBatchNo()); stockAddDTO.setManualInput(true); StockDTO stockDTO = BeanUtil.copyProperties(stockUtils.query(stockAddDTO), StockDTO.class); stockUtils.updateById(stockDTO.getId(), record.getProductQty(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, task.getNo(), TransactionType.SEGMENTATION_SUBMIT.getValue()); stockDTO.setAvailableStockQuantityMove(record.getProductQty()); stockDTO.setLocationNo(nowLocation.getIfsLocation()); stocks.add(stockDTO); } stockService.ifsImportChangeWdrStd(stocks, segmentationTaskInputs.get(0).getPartBatchNo()); // 检号分盘和拼盘 } else { // 投入发放 List inStocks = new ArrayList<>(); for (SegmentationTaskInput input : segmentationTaskInputs) { Stock inputStock = stockMapper.selectById(input.getStockId()); Location inputLocation = locationMapper.selectById(inputStock.getLocationId()); // 通过零件号、库位号、IFS批次号查询IFS库存数量查询接口,获取WDR号 JSONObject ifsStockQuery = new JSONObject(); ifsStockQuery.put("PART_NO", input.getPartNo()); ifsStockQuery.put("LOCATION_NO", inputLocation.getIfsLocation()); ifsStockQuery.put("LOT_BATCH_NO", input.getIfsBatchNo()); ifsStockQuery.put("QUANTITY_FLAG", ">0"); R ifsStock = stockService.getIfsStock(null, ifsStockQuery); String wdrNo; if (ifsStock.getCode() == 0) { JSONArray jsonArray = (JSONArray) ifsStock.getData(); if (jsonArray.size() == 0) { throw new RuntimeException("IFS库存未找到该投入,IFS批次号为:" + input.getIfsBatchNo()); } else { wdrNo = jsonArray.getJSONObject(0).getString("WAIV_DEV_REJ_NO"); } } else { throw new RuntimeException("IFS库存查询接口调用失败,原因:" + ifsStock.getMsg()); } StockDTO stockDTO = new StockDTO(); stockDTO.setPartId(inputStock.getPartId()); stockDTO.setPartNo(input.getPartNo()); stockDTO.setLocationNo(inputLocation.getIfsLocation()); stockDTO.setPartBatchNo(wdrNo); stockDTO.setIfsBatchNo(input.getIfsBatchNo()); stockDTO.setManualInput(true); stockDTO.setAvailableStockQuantityMove(input.getAdjustQty().add(input.getScrapQty())); stockDTO.setAdjustType("Issue"); stockDTO.setAdjustMemo("库存发放"); inStocks.add(stockDTO); } // stockService.inventAdjustForRfcable(inStocks, "Issue", "T03"); // 库存调整 List stocks = new ArrayList<>(); // 组装库存数据 for (SegmentationTaskRecord record : records) { Location location = locationMapper.selectById(record.getLocationId()); StockAddDTO stockAddDTO = new StockAddDTO(); stockAddDTO.setPartsId(record.getPartId()); stockAddDTO.setNewLocationId(record.getLocationId()); stockAddDTO.setNewPartBatchNo(record.getPartBatchNo()); stockAddDTO.setReelNumber(record.getReelNumber()); stockAddDTO.setOperationStockStatus(false); stockAddDTO.setIfsBatchNo(record.getIfsBatchNo()); stockAddDTO.setManualInput(true); StockDTO stockDTO = BeanUtil.copyProperties(stockUtils.query(stockAddDTO), StockDTO.class); stockUtils.updateById(stockDTO.getId(), record.getProductQty(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, task.getNo(), TransactionType.SEGMENTATION_SUBMIT.getValue()); stockDTO.setAvailableStockQuantityMove(record.getProductQty()); stockDTO.setLocationNo(location.getIfsLocation()); stockDTO.setAdjustType("Receive"); stockDTO.setAdjustMemo("库存接收"); inStocks.add(stockDTO); } stockService.inventAdjustForRfcable(inStocks, "", "T03"); } this.update(Wrappers.lambdaUpdate() .eq(SegmentationTaskRecord::getTaskId, task.getId()) .set(SegmentationTaskRecord::getStatus, SegmentationTaskRecord.STATUS_SUBMIT)); } return true; } @Override public List batchLabelPrint(List ids) { return this.baseMapper.batchLabelPrint(ids); } @Override public boolean check(SegmentationTaskRecordDTO segmentationTaskRecord) { // 分盘和检号分盘 if (segmentationTaskRecord.getDiskNum() == null || segmentationTaskRecord.getDiskNum() <= 0 || segmentationTaskRecord.getProductQty() == null || segmentationTaskRecord.getProductQty().compareTo(BigDecimal.ZERO) <= 0) { throw new RuntimeException("盘数和生产数量未填或填写错误"); } if (SegmentationTask.TASK_TYPE_CENT_LINE.equals(segmentationTaskRecord.getTaskType()) || SegmentationTask.TASK_TYPE_CHECK_CENT_LINE.equals(segmentationTaskRecord.getTaskType())) { if (segmentationTaskRecord.getInputs().size() > 1) { throw new RuntimeException("分盘任务只能有一个输入"); } } BigDecimal totalInputNum = BigDecimal.ZERO; // 检测输入数量是否正确 for (SegmentationTaskInput input : segmentationTaskRecord.getInputs()) { Stock stock = stockMapper.selectById(input.getStockId()); BigDecimal inputNum = input.getAdjustQty().add(input.getScrapQty()); if (stock.getAvailableStockQuantity().compareTo(inputNum) != 0) { throw new RuntimeException("库存可用数量与输入可用数量和报废数量之和不一致"); } totalInputNum = totalInputNum.add(input.getAdjustQty()); } // 校验分段描述 if (StrUtil.isNotBlank(segmentationTaskRecord.getSegmentDesc())) { checkSegmentDesc(segmentationTaskRecord.getProductQty(), segmentationTaskRecord.getSegmentDesc()); } // 生产总数量不能大于输入数量 BigDecimal totalProduceNum = segmentationTaskRecord.getProductQty().multiply(new BigDecimal(segmentationTaskRecord.getDiskNum())); if (totalProduceNum.compareTo(totalInputNum) > 0) { throw new RuntimeException("生产总数量不能大于输入数量"); } else if (totalProduceNum.compareTo(totalInputNum) < 0) { return false; } return true; } @Override public List checkEdit(List segmentationTaskRecords) { List listByIds = this.baseMapper.getListByIds(segmentationTaskRecords.stream().map(SegmentationTaskRecordDTO::getId).collect(Collectors.toList())); for (SegmentationTaskRecordDTO record : listByIds) { if (record.getStatus().equals(SegmentationTaskRecord.STATUS_SUBMIT)) { throw new RuntimeException("已提交的分盘任务不能修改"); } for (SegmentationTaskRecordDTO newRecord : segmentationTaskRecords) { // 拼盘需要判断是否需要选择退库 if (record.getId().equals(newRecord.getId()) && record.getTaskType().equals(SegmentationTask.TASK_TYPE_MERGE_DISH)) { if (record.getProductQty().compareTo(newRecord.getProductQty()) != 0) { return this.segmentationTaskInputMapper.selectList(Wrappers.lambdaQuery() .eq(SegmentationTaskInput::getTaskId, record.getTaskId())); } } } } return new ArrayList<>(); } private void checkSegmentDesc(BigDecimal productQty, String segmentDesc) { String[] split = segmentDesc.split("\\+"); if (split.length > 1) { for (String desc : split) { if (!NumberUtils.isCreatable(desc)) { throw new RuntimeException("分段描述只能用数字分段"); } } } else { throw new RuntimeException("分段描述格式不正确"); } List segmentList = Arrays.asList(split); BigDecimal totalSegment = segmentList.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(new BigDecimal(b)), BigDecimal::add); if (productQty.compareTo(totalSegment.divide(BigDecimal.valueOf(1000))) != 0) { throw new RuntimeException("分段描述与生产数量不一致"); } } }