package com.ruoyi.production.service.impl;
|
|
import cn.hutool.core.bean.BeanUtil;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
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.ruoyi.basic.dto.StorageBlobVO;
|
import com.ruoyi.basic.mapper.StorageAttachmentMapper;
|
import com.ruoyi.basic.mapper.StorageBlobMapper;
|
import com.ruoyi.basic.pojo.StorageAttachment;
|
import com.ruoyi.basic.pojo.StorageBlob;
|
import com.ruoyi.basic.utils.FileUtil;
|
import com.ruoyi.common.constant.StorageAttachmentConstants;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
|
import com.ruoyi.production.bean.dto.ProductionOrderDto;
|
import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
|
import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
|
import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
|
import com.ruoyi.production.bean.vo.ProductionOrderVo;
|
import com.ruoyi.production.bean.vo.ProductionPlanVo;
|
import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo;
|
import com.ruoyi.production.enums.ProductOrderStatusEnum;
|
import com.ruoyi.production.mapper.*;
|
import com.ruoyi.production.pojo.*;
|
import com.ruoyi.quality.mapper.QualityInspectFileMapper;
|
import com.ruoyi.quality.mapper.QualityInspectMapper;
|
import com.ruoyi.quality.mapper.QualityInspectParamMapper;
|
import com.ruoyi.quality.pojo.QualityInspect;
|
import com.ruoyi.quality.pojo.QualityInspectFile;
|
import com.ruoyi.quality.pojo.QualityInspectParam;
|
import com.ruoyi.production.service.ProductionOrderService;
|
import com.ruoyi.sales.mapper.SalesLedgerMapper;
|
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
|
import com.ruoyi.stock.mapper.StockInventoryMapper;
|
import com.ruoyi.stock.pojo.StockInventory;
|
import com.ruoyi.technology.mapper.*;
|
import com.ruoyi.technology.pojo.*;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.format.DateTimeFormatter;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
@Service
|
@Transactional(rollbackFor = Exception.class)
|
@RequiredArgsConstructor
|
public class ProductionOrderServiceImpl extends ServiceImpl<ProductionOrderMapper, ProductionOrder> implements ProductionOrderService {
|
|
private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
|
private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
|
private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
|
private final ProductionOperationTaskMapper productionOperationTaskMapper;
|
private final ProductionOrderBomMapper productionOrderBomMapper;
|
private final ProductionBomStructureMapper productionBomStructureMapper;
|
private final ProductionProductMainMapper productionProductMainMapper;
|
private final ProductionProductOutputMapper productionProductOutputMapper;
|
private final ProductionOrderPickMapper productionOrderPickMapper;
|
private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
|
private final QualityInspectMapper qualityInspectMapper;
|
private final QualityInspectParamMapper qualityInspectParamMapper;
|
private final QualityInspectFileMapper qualityInspectFileMapper;
|
private final ProductionPlanMapper productionPlanMapper;
|
private final StockInventoryMapper stockInventoryMapper;
|
private final StorageAttachmentMapper storageAttachmentMapper;
|
private final StorageBlobMapper storageBlobMapper;
|
private final SalesLedgerMapper salesLedgerMapper;
|
private final SalesLedgerProductMapper salesLedgerProductMapper;
|
private final TechnologyRoutingMapper technologyRoutingMapper;
|
private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
|
private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper;
|
private final TechnologyOperationMapper technologyOperationMapper;
|
private final TechnologyBomMapper technologyBomMapper;
|
private final TechnologyBomStructureMapper technologyBomStructureMapper;
|
private final FileUtil fileUtil;
|
|
@Override
|
public IPage<ProductionOrderVo> pageProductionOrder(Page<ProductionOrderDto> page, ProductionOrderDto dto) {
|
Page<ProductionOrderVo> result = (Page<ProductionOrderVo>) baseMapper.pageProductionOrder(page, dto);
|
fillProductImages(result.getRecords());
|
return result;
|
}
|
|
@Override
|
public List<ProductionOrderVo> listProductionOrder(ProductionOrderDto dto) {
|
List<ProductionOrderVo> records = baseMapper.listProductionOrder(dto);
|
fillProductImages(records);
|
return records;
|
}
|
|
@Override
|
public ProductionOrderVo getProductionOrderInfo(Long id) {
|
ProductionOrderVo item = baseMapper.getProductionOrderInfo(id);
|
if (item == null) {
|
return null;
|
}
|
fillProductImages(java.util.Collections.singletonList(item));
|
return item;
|
}
|
|
@Override
|
public boolean saveProductionOrder(ProductionOrder productionOrder) {
|
ProductionOrder oldOrder = productionOrder.getId() == null ? null : this.getById(productionOrder.getId());
|
// 下单入口统一补齐来源单据、计划和工艺信息,避免前端分别传多套字段。
|
validateAndFillOrder(productionOrder, oldOrder);
|
if (productionOrder.getNpsNo() == null || productionOrder.getNpsNo().trim().isEmpty()) {
|
productionOrder.setNpsNo(generateNextOrderNo());
|
}
|
if (productionOrder.getCompleteQuantity() == null) {
|
productionOrder.setCompleteQuantity(BigDecimal.ZERO);
|
}
|
if (productionOrder.getStatus() == null) {
|
productionOrder.setStatus(ProductOrderStatusEnum.WAIT.getCode());
|
}
|
boolean saved = this.saveOrUpdate(productionOrder);
|
if (!saved) {
|
return false;
|
}
|
boolean needSync = productionOrder.getTechnologyRoutingId() != null
|
&& (oldOrder == null
|
|| !Objects.equals(oldOrder.getTechnologyRoutingId(), productionOrder.getTechnologyRoutingId())
|
|| !Objects.equals(oldOrder.getProductModelId(), productionOrder.getProductModelId())
|
|| compareDecimal(oldOrder.getQuantity(), productionOrder.getQuantity()) != 0
|
|| productionOrderRoutingMapper.selectCount(Wrappers.<ProductionOrderRouting>lambdaQuery()
|
.eq(ProductionOrderRouting::getProductionOrderId, productionOrder.getId())) == 0);
|
if (needSync) {
|
syncProductionOrderSnapshot(productionOrder.getId());
|
}
|
return true;
|
}
|
|
@Override
|
public boolean removeProductionOrder(List<Long> ids) {
|
if (ids == null || ids.isEmpty()) {
|
return false;
|
}
|
for (Long id : ids) {
|
ProductionOrder productionOrder = this.getById(id);
|
clearProductionSnapshot(id);
|
releaseProductionPlanIssueStatus(productionOrder);
|
}
|
return this.removeByIds(ids);
|
}
|
|
@Override
|
public Integer bindingRoute(ProductionOrderDto productionOrderDto) {
|
if (productionOrderDto == null || productionOrderDto.getId() == null) {
|
throw new ServiceException("生产订单ID不能为空");
|
}
|
ProductionOrder productionOrder = this.getById(productionOrderDto.getId());
|
if (productionOrder == null) {
|
throw new ServiceException("生产订单不存在");
|
}
|
|
Long targetRoutingId = productionOrderDto.getTechnologyRoutingId() == null
|
? productionOrder.getTechnologyRoutingId()
|
: productionOrderDto.getTechnologyRoutingId();
|
if (targetRoutingId == null) {
|
throw new ServiceException("工艺路线ID不能为空");
|
}
|
TechnologyRouting targetRouting = technologyRoutingMapper.selectById(targetRoutingId);
|
if (targetRouting == null) {
|
throw new ServiceException("工艺路线不存在");
|
}
|
if (productionOrder.getProductModelId() != null
|
&& !Objects.equals(productionOrder.getProductModelId(), targetRouting.getProductModelId())) {
|
throw new ServiceException("工艺路线与生产订单产品规格不匹配");
|
}
|
|
if (ProductOrderStatusEnum.isStarted(productionOrder.getStatus())
|
&& !Objects.equals(productionOrder.getTechnologyRoutingId(), targetRoutingId)) {
|
throw new ServiceException("生产订单已开工,不能修改工艺路线");
|
}
|
|
if (!Objects.equals(productionOrder.getTechnologyRoutingId(), targetRoutingId)) {
|
ProductionOrder update = new ProductionOrder();
|
update.setId(productionOrder.getId());
|
update.setTechnologyRoutingId(targetRoutingId);
|
if (!this.updateById(update)) {
|
throw new ServiceException("绑定工艺路线失败");
|
}
|
}
|
|
// 绑定路线仅重建订单侧快照数据
|
return syncProductionOrderSnapshot(productionOrder.getId());
|
}
|
|
@Override
|
public List<ProductionPlanVo> getSource(Long id) {
|
ProductionOrder productionOrder = baseMapper.selectById(id);
|
if (productionOrder != null && productionOrder.getProductionPlanIds() != null) {
|
List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds());
|
return productionPlanMapper.getSource(planIds);
|
}
|
return null;
|
}
|
|
@Override
|
public int syncProductionOrderSnapshot(Long productionOrderId) {
|
ProductionOrder productionOrder = this.getById(productionOrderId);
|
if (productionOrder == null) {
|
throw new ServiceException("生产订单不存在");
|
}
|
if (productionOrder.getTechnologyRoutingId() == null) {
|
throw new ServiceException("工艺路线ID不能为空");
|
}
|
TechnologyRouting technologyRouting = technologyRoutingMapper.selectById(productionOrder.getTechnologyRoutingId());
|
if (technologyRouting == null) {
|
throw new ServiceException("工艺路线不存在");
|
}
|
// 订单快照按“先清后建”处理,保证工艺路线、工序、参数、BOM 全部来自同一版本。
|
clearProductionSnapshot(productionOrderId);
|
ProductionOrderBom orderBom = syncProductionOrderBomSnapshot(productionOrder, technologyRouting);
|
|
ProductionOrderRouting orderRouting = new ProductionOrderRouting();
|
orderRouting.setProductionOrderId(productionOrder.getId());
|
orderRouting.setTechnologyRoutingId(technologyRouting.getId());
|
orderRouting.setProductModelId(technologyRouting.getProductModelId());
|
orderRouting.setProcessRouteCode(technologyRouting.getProcessRouteCode());
|
orderRouting.setDescription(technologyRouting.getDescription());
|
orderRouting.setBomId(technologyRouting.getBomId());
|
orderRouting.setOrderBomId(orderBom == null ? null : orderBom.getId());
|
productionOrderRoutingMapper.insert(orderRouting);
|
|
int syncedParamCount = 0;
|
List<TechnologyRoutingOperation> routingOperations = technologyRoutingOperationMapper.selectList(
|
Wrappers.<TechnologyRoutingOperation>lambdaQuery()
|
.eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId())
|
.orderByDesc(TechnologyRoutingOperation::getDragSort)
|
.orderByDesc(TechnologyRoutingOperation::getId));
|
Map<Long, String> operationNameMap = technologyOperationMapper.selectBatchIds(
|
routingOperations.stream()
|
.map(TechnologyRoutingOperation::getTechnologyOperationId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toSet()))
|
.stream()
|
.collect(Collectors.toMap(TechnologyOperation::getId, TechnologyOperation::getName, (a, b) -> a));
|
Integer lastDragSort = routingOperations.stream()
|
.map(TechnologyRoutingOperation::getDragSort)
|
.filter(Objects::nonNull)
|
.max(Integer::compareTo)
|
.orElse(null);
|
for (TechnologyRoutingOperation sourceOperation : routingOperations) {
|
// 订单工序保存的是工艺工序快照,后续报工只依赖快照,不再直接引用工艺主数据。
|
ProductionOrderRoutingOperation targetOperation = new ProductionOrderRoutingOperation();
|
targetOperation.setProductionOrderId(productionOrder.getId());
|
targetOperation.setTechnologyRoutingOperationId(sourceOperation.getId());
|
targetOperation.setOrderRoutingId(orderRouting.getId());
|
targetOperation.setProductModelId(sourceOperation.getProductModelId());
|
targetOperation.setDragSort(sourceOperation.getDragSort());
|
targetOperation.setIsProduction(sourceOperation.getIsProduction());
|
targetOperation.setIsQuality(sourceOperation.getIsQuality());
|
targetOperation.setOperationName(operationNameMap.get(sourceOperation.getTechnologyOperationId()));
|
targetOperation.setTechnologyOperationId(sourceOperation.getTechnologyOperationId());
|
productionOrderRoutingOperationMapper.insert(targetOperation);
|
|
boolean isLastOperation = lastDragSort != null && Objects.equals(sourceOperation.getDragSort(), lastDragSort);
|
if (isLastOperation || Boolean.TRUE.equals(targetOperation.getIsProduction())) {
|
ProductionOperationTask task = new ProductionOperationTask();
|
task.setProductionOrderRoutingOperationId(targetOperation.getId());
|
task.setProductionOrderId(productionOrder.getId());
|
task.setPlanQuantity(defaultDecimal(productionOrder.getQuantity()));
|
task.setCompleteQuantity(BigDecimal.ZERO);
|
task.setWorkOrderNo(generateNextTaskNo());
|
task.setStatus(2);
|
productionOperationTaskMapper.insert(task);
|
}
|
|
List<TechnologyRoutingOperationParam> sourceParams = technologyRoutingOperationParamMapper.selectList(
|
Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
|
.eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, sourceOperation.getId())
|
.orderByAsc(TechnologyRoutingOperationParam::getId));
|
for (TechnologyRoutingOperationParam sourceParam : sourceParams) {
|
// 工序执行参数同样做快照,避免工艺参数调整影响已下达订单。
|
ProductionOrderRoutingOperationParam targetParam = new ProductionOrderRoutingOperationParam();
|
targetParam.setProductionOrderId(productionOrder.getId());
|
targetParam.setProductionOrderRoutingOperationId(targetOperation.getId());
|
targetParam.setTechnologyRoutingOperationParamId(sourceParam.getId());
|
targetParam.setParamId(sourceParam.getParamId());
|
targetParam.setTechnologyOperationId(sourceParam.getTechnologyOperationId());
|
targetParam.setTechnologyOperationParamId(sourceParam.getTechnologyOperationParamId());
|
targetParam.setParamCode(sourceParam.getParamCode());
|
targetParam.setParamName(sourceParam.getParamName());
|
targetParam.setParamType(sourceParam.getParamType());
|
targetParam.setParamFormat(sourceParam.getParamFormat());
|
targetParam.setUnit(sourceParam.getUnit());
|
targetParam.setIsRequired(sourceParam.getIsRequired());
|
targetParam.setRemark(sourceParam.getRemark());
|
targetParam.setStandardValue(sourceParam.getStandardValue());
|
productionOrderRoutingOperationParamMapper.insert(targetParam);
|
syncedParamCount++;
|
}
|
}
|
return syncedParamCount;
|
}
|
|
private ProductionOrderBom syncProductionOrderBomSnapshot(ProductionOrder productionOrder, TechnologyRouting technologyRouting) {
|
if (technologyRouting.getBomId() == null) {
|
return null;
|
}
|
TechnologyBom technologyBom = technologyBomMapper.selectById(technologyRouting.getBomId());
|
if (technologyBom == null) {
|
throw new ServiceException("工艺BOM不存在");
|
}
|
List<TechnologyBomStructure> structureList = technologyBomStructureMapper.selectList(
|
Wrappers.<TechnologyBomStructure>lambdaQuery()
|
.eq(TechnologyBomStructure::getBomId, technologyBom.getId())
|
.orderByAsc(TechnologyBomStructure::getId));
|
TechnologyBomStructure root = structureList.stream().filter(item -> item.getParentId() == null).findFirst().orElse(null);
|
BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity());
|
|
ProductionOrderBom orderBom = new ProductionOrderBom();
|
orderBom.setProductionOrderId(productionOrder.getId());
|
orderBom.setBomId(Long.valueOf(technologyBom.getId()));
|
orderBom.setProductModelId(root != null ? root.getProductModelId() : productionOrder.getProductModelId());
|
orderBom.setRemark(technologyBom.getRemark());
|
orderBom.setBomNo(technologyBom.getBomNo());
|
orderBom.setVersion(technologyBom.getVersion());
|
productionOrderBomMapper.insert(orderBom);
|
|
Map<Long, Long> idMap = new HashMap<>();
|
for (TechnologyBomStructure source : structureList) {
|
// 子节点 parentId 需要映射成新快照节点 id,才能保留原始 BOM 层级。
|
ProductionBomStructure target = new ProductionBomStructure();
|
target.setProductionOrderId(productionOrder.getId());
|
target.setProductionOrderBomId(orderBom.getId());
|
target.setParentId(source.getParentId() == null ? null : idMap.get(source.getParentId()));
|
target.setProductModelId(source.getProductModelId());
|
target.setTechnologyOperationId(source.getOperationId());
|
target.setUnitQuantity(source.getUnitQuantity());
|
target.setDemandedQuantity(source.getUnitQuantity().multiply(orderQuantity));
|
target.setUnit(source.getUnit());
|
productionBomStructureMapper.insert(target);
|
idMap.put(source.getId(), target.getId());
|
}
|
return orderBom;
|
}
|
|
private void clearProductionSnapshot(Long productionOrderId) {
|
// 已产生领料记录后禁止重建,避免备料/投料依据与订单快照脱节。
|
boolean hasPickRecord = productionOrderPickRecordMapper.selectCount(
|
Wrappers.<ProductionOrderPickRecord>lambdaQuery()
|
.eq(ProductionOrderPickRecord::getProductionOrderId, productionOrderId)) > 0;
|
if (hasPickRecord) {
|
throw new ServiceException("生产订单已存在领料记录,不能重新生成快照");
|
}
|
List<Long> taskIds = productionOperationTaskMapper.selectList(
|
Wrappers.<ProductionOperationTask>lambdaQuery()
|
.eq(ProductionOperationTask::getProductionOrderId, productionOrderId))
|
.stream().map(ProductionOperationTask::getId).collect(Collectors.toList());
|
if (!taskIds.isEmpty()) {
|
// 已有报工记录说明订单已开工,此时不允许再重建快照。
|
boolean started = productionProductMainMapper.selectCount(
|
Wrappers.<ProductionProductMain>lambdaQuery()
|
.in(ProductionProductMain::getProductionOperationTaskId, taskIds)) > 0;
|
if (started) {
|
throw new ServiceException("生产订单已开工,不能重新生成快照");
|
}
|
productionOperationTaskMapper.delete(Wrappers.<ProductionOperationTask>lambdaQuery()
|
.eq(ProductionOperationTask::getProductionOrderId, productionOrderId));
|
}
|
productionOrderRoutingOperationParamMapper.delete(Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
|
.eq(ProductionOrderRoutingOperationParam::getProductionOrderId, productionOrderId));
|
productionOrderRoutingOperationMapper.delete(Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
|
.eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId));
|
productionOrderRoutingMapper.delete(Wrappers.<ProductionOrderRouting>lambdaQuery()
|
.eq(ProductionOrderRouting::getProductionOrderId, productionOrderId));
|
productionBomStructureMapper.delete(Wrappers.<ProductionBomStructure>lambdaQuery()
|
.eq(ProductionBomStructure::getProductionOrderId, productionOrderId));
|
productionOrderBomMapper.delete(Wrappers.<ProductionOrderBom>lambdaQuery()
|
.eq(ProductionOrderBom::getProductionOrderId, productionOrderId));
|
productionOrderPickMapper.delete(Wrappers.<ProductionOrderPick>lambdaQuery()
|
.eq(ProductionOrderPick::getProductionOrderId, productionOrderId));
|
}
|
|
private LambdaQueryWrapper<ProductionOrder> buildQueryWrapper(ProductionOrderDto dto) {
|
ProductionOrder query = dto == null ? new ProductionOrder() : dto;
|
return Wrappers.<ProductionOrder>lambdaQuery()
|
.eq(query.getId() != null, ProductionOrder::getId, query.getId())
|
.eq(query.getProductModelId() != null, ProductionOrder::getProductModelId, query.getProductModelId())
|
.eq(query.getTechnologyRoutingId() != null, ProductionOrder::getTechnologyRoutingId, query.getTechnologyRoutingId())
|
.like(query.getNpsNo() != null && !query.getNpsNo().trim().isEmpty(), ProductionOrder::getNpsNo, query.getNpsNo())
|
.orderByDesc(ProductionOrder::getId);
|
}
|
|
private String generateNextOrderNo() {
|
String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
String prefix = "SC" + datePrefix;
|
ProductionOrder latestOrder = this.getOne(Wrappers.<ProductionOrder>lambdaQuery()
|
.likeRight(ProductionOrder::getNpsNo, prefix)
|
.orderByDesc(ProductionOrder::getNpsNo)
|
.last("limit 1"));
|
int sequence = 1;
|
if (latestOrder != null && latestOrder.getNpsNo() != null && latestOrder.getNpsNo().startsWith(prefix)) {
|
try {
|
sequence = Integer.parseInt(latestOrder.getNpsNo().substring(prefix.length())) + 1;
|
} catch (NumberFormatException ignored) {
|
sequence = 1;
|
}
|
}
|
return prefix + String.format("%04d", sequence);
|
}
|
|
private String generateNextTaskNo() {
|
String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
String prefix = "GD" + datePrefix;
|
ProductionOperationTask lastTask = productionOperationTaskMapper.selectOne(
|
Wrappers.<ProductionOperationTask>lambdaQuery()
|
.likeRight(ProductionOperationTask::getWorkOrderNo, prefix)
|
.orderByDesc(ProductionOperationTask::getWorkOrderNo)
|
.last("limit 1"));
|
int sequence = 1;
|
if (lastTask != null && lastTask.getWorkOrderNo() != null && lastTask.getWorkOrderNo().startsWith(prefix)) {
|
try {
|
sequence = Integer.parseInt(lastTask.getWorkOrderNo().substring(prefix.length())) + 1;
|
} catch (NumberFormatException ignored) {
|
sequence = 1;
|
}
|
}
|
return prefix + String.format("%03d", sequence);
|
}
|
|
private BigDecimal defaultDecimal(BigDecimal value) {
|
return value == null ? BigDecimal.ZERO : value;
|
}
|
|
private void validateAndFillOrder(ProductionOrder productionOrder, ProductionOrder oldOrder) {
|
if (productionOrder == null) {
|
throw new ServiceException("生产订单不能为空");
|
}
|
fillFromProductionPlans(productionOrder);
|
if (productionOrder.getProductModelId() == null) {
|
throw new ServiceException("产品规格ID不能为空");
|
}
|
if (defaultDecimal(productionOrder.getQuantity()).compareTo(BigDecimal.ZERO) <= 0) {
|
throw new ServiceException("下单数量必须大于0");
|
}
|
if (productionOrder.getTechnologyRoutingId() == null) {
|
// 未显式指定工艺路线时,按产品规格选最新一条工艺作为默认路线。
|
TechnologyRouting technologyRouting = technologyRoutingMapper.selectOne(
|
Wrappers.<TechnologyRouting>lambdaQuery()
|
.eq(TechnologyRouting::getProductModelId, productionOrder.getProductModelId())
|
.orderByDesc(TechnologyRouting::getId)
|
.last("limit 1"));
|
if (technologyRouting != null) {
|
productionOrder.setTechnologyRoutingId(technologyRouting.getId());
|
}
|
}
|
if (oldOrder != null && ProductOrderStatusEnum.isStarted(oldOrder.getStatus())) {
|
// 开工后只允许修正非核心字段,核心生产依据锁定。
|
if (!Objects.equals(oldOrder.getProductModelId(), productionOrder.getProductModelId())
|
|| !Objects.equals(oldOrder.getTechnologyRoutingId(), productionOrder.getTechnologyRoutingId())
|
|| compareDecimal(oldOrder.getQuantity(), productionOrder.getQuantity()) != 0) {
|
throw new ServiceException("生产订单已开工,不能修改产品、工艺路线或数量");
|
}
|
}
|
}
|
|
private void fillFromProductionPlans(ProductionOrder productionOrder) {
|
List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds());
|
if (planIds.isEmpty()) {
|
return;
|
}
|
// 多计划合并转单时,所有计划必须属于同一规格,且只能下发一次。
|
List<ProductionPlan> productionPlans = productionPlanMapper.selectBatchIds(planIds);
|
if (productionPlans.size() != planIds.size()) {
|
throw new ServiceException("部分生产计划不存在");
|
}
|
Map<Long, ProductionPlan> planMap = productionPlans.stream()
|
.collect(Collectors.toMap(ProductionPlan::getId, item -> item, (left, right) -> left));
|
ProductionPlan mainPlan = planMap.get(planIds.get(0));
|
if (mainPlan == null) {
|
throw new ServiceException("主生产计划不存在");
|
}
|
Set<Long> productModelIds = productionPlans.stream()
|
.map(ProductionPlan::getProductModelId)
|
.collect(Collectors.toSet());
|
if (productModelIds.size() > 1) {
|
throw new ServiceException("所选生产计划必须属于同一产品规格");
|
}
|
if (productionPlans.stream().anyMatch(item -> item.getStatus() != null && item.getStatus() == 2)) {
|
throw new ServiceException("所选生产计划已下发");
|
}
|
ProductionPlan firstPlan = mainPlan;
|
if (productionOrder.getProductModelId() == null) {
|
productionOrder.setProductModelId(firstPlan.getProductModelId());
|
} else if (!Objects.equals(productionOrder.getProductModelId(), firstPlan.getProductModelId())) {
|
throw new ServiceException("产品规格ID与生产计划不一致");
|
}
|
if (productionOrder.getQuantity() == null || productionOrder.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
|
productionOrder.setQuantity(productionPlans.stream()
|
.map(ProductionPlan::getQtyRequired)
|
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
}
|
if (productionOrder.getPlanCompleteTime() == null) {
|
LocalDate planCompleteTime = productionPlans.stream()
|
.map(this::resolvePlanCompleteDate)
|
.filter(Objects::nonNull)
|
.min(Comparator.naturalOrder())
|
.orElse(null);
|
productionOrder.setPlanCompleteTime(planCompleteTime);
|
}
|
productionOrder.setProductionPlanIds(formatPlanIds(planIds));
|
}
|
|
private void releaseProductionPlanIssueStatus(ProductionOrder productionOrder) {
|
if (productionOrder == null) {
|
return;
|
}
|
List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds());
|
if (!planIds.isEmpty()) {
|
// 生产订单删除--对应的生产计划的已下发数量要减去
|
updatePlanIssuedFlag(planIds, productionOrder.getQuantity());
|
}
|
}
|
|
//生产订单删除,生产计划的已下发数量对应变更
|
private void updatePlanIssuedFlag(List<Long> planIds, BigDecimal remainingAssignedQuantity) {
|
if (planIds == null || planIds.isEmpty()) {
|
return;
|
}
|
List<ProductionPlan> plans = productionPlanMapper.selectBatchIds(planIds);
|
//下发数量减去
|
List<ProductionPlan> updates = new ArrayList<>();
|
for (ProductionPlan plan : plans) {
|
BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO);
|
if (requiredQuantity.compareTo(BigDecimal.ZERO) < 0) {
|
requiredQuantity = BigDecimal.ZERO;
|
}
|
BigDecimal remainingQuantity = resolveRemainingQuantity(plan);
|
BigDecimal historicalIssuedQuantity = requiredQuantity.subtract(remainingQuantity);
|
BigDecimal issuedQuantity = remainingAssignedQuantity.min(historicalIssuedQuantity);
|
remainingAssignedQuantity = remainingAssignedQuantity.subtract(issuedQuantity);
|
BigDecimal totalIssuedQuantity = historicalIssuedQuantity.subtract(issuedQuantity);
|
int planStatus = resolvePlanStatus(requiredQuantity, totalIssuedQuantity);
|
ProductionPlan update = new ProductionPlan();
|
update.setId(plan.getId());
|
update.setStatus(planStatus);
|
update.setQuantityIssued(totalIssuedQuantity);
|
updates.add(update);
|
}
|
if (!updates.isEmpty()) {
|
productionPlanMapper.updateById(updates);
|
}
|
}
|
|
private BigDecimal resolveRemainingQuantity(ProductionPlan plan) {
|
if (plan == null) {
|
return BigDecimal.ZERO;
|
}
|
BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO);
|
if (requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
|
return BigDecimal.ZERO;
|
}
|
BigDecimal issuedQuantity = Optional.ofNullable(plan.getQuantityIssued()).orElse(BigDecimal.ZERO);
|
if (issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
|
return requiredQuantity;
|
}
|
if (issuedQuantity.compareTo(requiredQuantity) >= 0) {
|
return BigDecimal.ZERO;
|
}
|
return requiredQuantity.subtract(issuedQuantity);
|
}
|
|
private int resolvePlanStatus(BigDecimal requiredQuantity, BigDecimal issuedQuantity) {
|
if (requiredQuantity == null || requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
|
return 0;
|
}
|
if (issuedQuantity == null || issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
|
return 0;
|
}
|
return issuedQuantity.compareTo(requiredQuantity) < 0 ? 1 : 2;
|
}
|
|
private List<Long> parsePlanIds(String productionPlanIds) {
|
if (productionPlanIds == null || productionPlanIds.trim().isEmpty()) {
|
return new ArrayList<>();
|
}
|
String normalized = productionPlanIds.replace("[", "").replace("]", "").trim();
|
if (normalized.isEmpty()) {
|
return new ArrayList<>();
|
}
|
return java.util.Arrays.stream(normalized.split(","))
|
.map(String::trim)
|
.filter(item -> !item.isEmpty())
|
.map(Long::valueOf)
|
.distinct()
|
.collect(Collectors.toList());
|
}
|
|
private String formatPlanIds(List<Long> planIds) {
|
if (planIds == null || planIds.isEmpty()) {
|
return null;
|
}
|
return planIds.stream()
|
.distinct()
|
.map(String::valueOf)
|
.collect(Collectors.joining(",", "[", "]"));
|
}
|
|
private LocalDate resolvePlanCompleteDate(ProductionPlan productionPlan) {
|
if (productionPlan == null) {
|
return null;
|
}
|
if (productionPlan.getPromisedDeliveryDate() != null) {
|
return productionPlan.getPromisedDeliveryDate();
|
}
|
if (productionPlan.getRequiredDate() != null) {
|
return productionPlan.getRequiredDate();
|
}
|
return null;
|
}
|
|
private int compareDecimal(BigDecimal left, BigDecimal right) {
|
return defaultDecimal(left).compareTo(defaultDecimal(right));
|
}
|
|
private void fillProductImages(List<ProductionOrderVo> records) {
|
if (records == null || records.isEmpty()) {
|
return;
|
}
|
List<Long> productModelIds = records.stream()
|
.map(ProductionOrderVo::getProductModelId)
|
.filter(Objects::nonNull)
|
.distinct()
|
.collect(Collectors.toList());
|
if (productModelIds.isEmpty()) {
|
return;
|
}
|
|
List<StorageAttachment> attachments = storageAttachmentMapper.selectList(
|
Wrappers.<StorageAttachment>lambdaQuery()
|
.in(StorageAttachment::getRecordId, productModelIds)
|
.eq(StorageAttachment::getApplication, StorageAttachmentConstants.StorageAttachmentImage)
|
.eq(StorageAttachment::getDeleted, 0L)
|
.orderByAsc(StorageAttachment::getId));
|
if (attachments == null || attachments.isEmpty()) {
|
return;
|
}
|
|
Map<Long, List<StorageAttachment>> attachmentMap = attachments.stream()
|
.collect(Collectors.groupingBy(StorageAttachment::getRecordId, java.util.LinkedHashMap::new, Collectors.toList()));
|
List<Long> blobIds = attachments.stream()
|
.map(StorageAttachment::getStorageBlobId)
|
.filter(Objects::nonNull)
|
.distinct()
|
.collect(Collectors.toList());
|
if (blobIds.isEmpty()) {
|
return;
|
}
|
|
Map<Long, StorageBlob> blobMap = storageBlobMapper.selectBatchIds(blobIds).stream()
|
.filter(Objects::nonNull)
|
.collect(Collectors.toMap(StorageBlob::getId, item -> item));
|
for (ProductionOrderVo record : records) {
|
List<StorageAttachment> modelAttachments = attachmentMap.get(record.getProductModelId());
|
if (modelAttachments == null || modelAttachments.isEmpty()) {
|
continue;
|
}
|
List<StorageBlobVO> images = modelAttachments.stream()
|
.map(StorageAttachment::getStorageBlobId)
|
.map(blobMap::get)
|
.filter(Objects::nonNull)
|
.map(this::toStorageBlobVO)
|
.collect(Collectors.toList());
|
if (!images.isEmpty()) {
|
record.setProductImages(images);
|
}
|
}
|
}
|
|
private StorageBlobVO toStorageBlobVO(StorageBlob blob) {
|
StorageBlobVO vo = BeanUtil.copyProperties(blob, StorageBlobVO.class);
|
vo.setPreviewURL(fileUtil.buildSignedPreviewUrl(vo));
|
vo.setDownloadURL(fileUtil.buildSignedDownloadUrl(vo));
|
return vo;
|
}
|
|
@Override
|
public ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(ProductionOrderDto dto) {
|
Long productionOrderId = resolveProductionOrderId(dto);
|
ProductionOrderVo orderInfo = getProductionOrderInfo(productionOrderId);
|
if (orderInfo == null) {
|
throw new ServiceException("生产订单不存在");
|
}
|
|
ProductionOrderWorkOrderDetailVo detailVo = new ProductionOrderWorkOrderDetailVo();
|
detailVo.setProductionOrder(orderInfo);
|
|
ProductionOperationTaskDto taskQuery = new ProductionOperationTaskDto();
|
taskQuery.setProductionOrderId(productionOrderId);
|
IPage<ProductionOperationTaskVo> workOrderPage = productionOperationTaskMapper.pageProductionOperationTask(
|
new Page<ProductionOperationTaskVo>(1, -1), taskQuery);
|
List<ProductionOperationTaskVo> workOrderList = workOrderPage == null || workOrderPage.getRecords() == null
|
? Collections.emptyList()
|
: workOrderPage.getRecords().stream()
|
.filter(Objects::nonNull)
|
.sorted(Comparator.comparing(ProductionOperationTaskVo::getId, Comparator.nullsLast(Comparator.naturalOrder())))
|
.collect(Collectors.toList());
|
if (workOrderList == null || workOrderList.isEmpty()) {
|
detailVo.setWorkOrderList(Collections.emptyList());
|
return detailVo;
|
}
|
|
List<Long> workOrderIdList = workOrderList.stream()
|
.map(ProductionOperationTaskVo::getId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toList());
|
List<ProductionProductMain> reportMainList = workOrderIdList.isEmpty()
|
? Collections.emptyList()
|
: productionProductMainMapper.selectList(
|
Wrappers.<ProductionProductMain>lambdaQuery()
|
.in(ProductionProductMain::getProductionOperationTaskId, workOrderIdList)
|
.orderByAsc(ProductionProductMain::getId));
|
Map<Long, List<ProductionProductMain>> reportMainByWorkOrderMap = new LinkedHashMap<>();
|
for (ProductionProductMain reportMain : reportMainList) {
|
if (reportMain == null || reportMain.getProductionOperationTaskId() == null) {
|
continue;
|
}
|
reportMainByWorkOrderMap.computeIfAbsent(reportMain.getProductionOperationTaskId(), key -> new ArrayList<>()).add(reportMain);
|
}
|
|
List<Long> reportMainIdList = reportMainList.stream()
|
.map(ProductionProductMain::getId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toList());
|
Map<Long, List<ProductionProductOutput>> reportOutputMap = new LinkedHashMap<>();
|
Map<Long, List<ProductionOrderRoutingOperationParam>> reportParamMap = new LinkedHashMap<>();
|
Map<Long, List<QualityInspect>> inspectMap = new LinkedHashMap<>();
|
Map<Long, List<QualityInspectParam>> inspectParamMap = new LinkedHashMap<>();
|
Map<Long, List<QualityInspectFile>> inspectFileMap = new LinkedHashMap<>();
|
if (!reportMainIdList.isEmpty()) {
|
List<ProductionProductOutput> reportOutputList = productionProductOutputMapper.selectList(
|
Wrappers.<ProductionProductOutput>lambdaQuery()
|
.in(ProductionProductOutput::getProductionProductMainId, reportMainIdList)
|
.orderByAsc(ProductionProductOutput::getId));
|
for (ProductionProductOutput reportOutput : reportOutputList) {
|
if (reportOutput == null) {
|
continue;
|
}
|
Long reportMainId = reportOutput.getProductionProductMainId() != null
|
? reportOutput.getProductionProductMainId()
|
: reportOutput.getProductMainId();
|
if (reportMainId == null) {
|
continue;
|
}
|
reportOutputMap.computeIfAbsent(reportMainId, k -> new ArrayList<>()).add(reportOutput);
|
}
|
|
List<ProductionOrderRoutingOperationParam> reportParamList = productionOrderRoutingOperationParamMapper.selectList(
|
Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
|
.in(ProductionOrderRoutingOperationParam::getProductionProductMainId, reportMainIdList)
|
.orderByAsc(ProductionOrderRoutingOperationParam::getId));
|
for (ProductionOrderRoutingOperationParam reportParam : reportParamList) {
|
if (reportParam == null || reportParam.getProductionProductMainId() == null) {
|
continue;
|
}
|
reportParamMap.computeIfAbsent(reportParam.getProductionProductMainId(), k -> new ArrayList<>()).add(reportParam);
|
}
|
|
List<QualityInspect> inspectList = qualityInspectMapper.selectList(
|
Wrappers.<QualityInspect>lambdaQuery()
|
.in(QualityInspect::getProductMainId, reportMainIdList)
|
.orderByAsc(QualityInspect::getId));
|
for (QualityInspect inspect : inspectList) {
|
if (inspect == null || inspect.getProductMainId() == null) {
|
continue;
|
}
|
inspectMap.computeIfAbsent(inspect.getProductMainId(), key -> new ArrayList<>()).add(inspect);
|
}
|
|
List<Long> inspectIdList = inspectList.stream()
|
.map(QualityInspect::getId)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toList());
|
if (!inspectIdList.isEmpty()) {
|
List<QualityInspectParam> inspectParamList = qualityInspectParamMapper.selectList(
|
Wrappers.<QualityInspectParam>lambdaQuery()
|
.in(QualityInspectParam::getInspectId, inspectIdList)
|
.orderByAsc(QualityInspectParam::getId));
|
for (QualityInspectParam inspectParam : inspectParamList) {
|
if (inspectParam == null || inspectParam.getInspectId() == null) {
|
continue;
|
}
|
inspectParamMap.computeIfAbsent(inspectParam.getInspectId(), k -> new ArrayList<>()).add(inspectParam);
|
}
|
|
List<QualityInspectFile> inspectFileList = qualityInspectFileMapper.selectList(
|
Wrappers.<QualityInspectFile>lambdaQuery()
|
.in(QualityInspectFile::getInspectId, inspectIdList)
|
.orderByAsc(QualityInspectFile::getId));
|
for (QualityInspectFile inspectFile : inspectFileList) {
|
if (inspectFile == null || inspectFile.getInspectId() == null) {
|
continue;
|
}
|
inspectFileMap.computeIfAbsent(inspectFile.getInspectId(), k -> new ArrayList<>()).add(inspectFile);
|
}
|
}
|
}
|
|
List<ProductionOrderWorkOrderDetailVo.WorkOrderDetail> workOrderDetailList = new ArrayList<>();
|
for (ProductionOperationTaskVo workOrder : workOrderList) {
|
ProductionOrderWorkOrderDetailVo.WorkOrderDetail workOrderDetail = new ProductionOrderWorkOrderDetailVo.WorkOrderDetail();
|
workOrderDetail.setWorkOrder(workOrder);
|
|
List<ProductionProductMain> workOrderReportMainList = reportMainByWorkOrderMap.getOrDefault(workOrder.getId(), Collections.emptyList());
|
if (workOrderReportMainList.isEmpty()) {
|
workOrderDetail.setReportList(Collections.emptyList());
|
workOrderDetail.setInspectList(Collections.emptyList());
|
workOrderDetailList.add(workOrderDetail);
|
continue;
|
}
|
|
List<ProductionOrderWorkOrderDetailVo.ReportDetail> reportDetailList = new ArrayList<>();
|
List<ProductionOrderWorkOrderDetailVo.InspectDetail> inspectDetailList = new ArrayList<>();
|
for (ProductionProductMain reportMain : workOrderReportMainList) {
|
Long reportMainId = reportMain.getId();
|
|
ProductionOrderWorkOrderDetailVo.ReportDetail reportDetail = new ProductionOrderWorkOrderDetailVo.ReportDetail();
|
reportDetail.setReportMain(reportMain);
|
reportDetail.setReportOutputList(reportOutputMap.getOrDefault(reportMainId, Collections.emptyList()));
|
reportDetail.setReportParamList(reportParamMap.getOrDefault(reportMainId, Collections.emptyList()));
|
reportDetailList.add(reportDetail);
|
|
List<QualityInspect> reportInspectList = inspectMap.getOrDefault(reportMainId, Collections.emptyList());
|
for (QualityInspect inspect : reportInspectList) {
|
ProductionOrderWorkOrderDetailVo.InspectDetail inspectDetail = new ProductionOrderWorkOrderDetailVo.InspectDetail();
|
inspectDetail.setReportId(reportMainId);
|
inspectDetail.setReportNo(reportMain.getProductNo());
|
inspectDetail.setReportMain(reportMain);
|
inspectDetail.setInspect(inspect);
|
inspectDetail.setInspectParamList(inspectParamMap.getOrDefault(inspect.getId(), Collections.emptyList()));
|
inspectDetail.setInspectFileList(inspectFileMap.getOrDefault(inspect.getId(), Collections.emptyList()));
|
inspectDetailList.add(inspectDetail);
|
}
|
}
|
|
workOrderDetail.setReportList(reportDetailList);
|
workOrderDetail.setInspectList(inspectDetailList);
|
workOrderDetailList.add(workOrderDetail);
|
}
|
|
detailVo.setWorkOrderList(workOrderDetailList);
|
return detailVo;
|
}
|
|
private Long resolveProductionOrderId(ProductionOrderDto dto) {
|
if (dto == null) {
|
throw new ServiceException("请传入生产订单ID或生产订单号");
|
}
|
if (dto.getId() != null) {
|
return dto.getId();
|
}
|
if (dto.getNpsNo() == null || dto.getNpsNo().trim().isEmpty()) {
|
throw new ServiceException("请传入生产订单ID或生产订单号");
|
}
|
ProductionOrder productionOrder = baseMapper.selectOne(
|
Wrappers.<ProductionOrder>lambdaQuery()
|
.eq(ProductionOrder::getNpsNo, dto.getNpsNo().trim())
|
.last("limit 1"));
|
if (productionOrder == null || productionOrder.getId() == null) {
|
throw new ServiceException("生产订单不存在");
|
}
|
return productionOrder.getId();
|
}
|
|
@Override
|
public List<ProductionOrderPickVo> pick(Long productionOrderId) {
|
if (productionOrderId == null) {
|
return Collections.emptyList();
|
}
|
|
ProductionOrderBom orderBom = productionOrderBomMapper.selectOne(
|
Wrappers.<ProductionOrderBom>lambdaQuery()
|
.eq(ProductionOrderBom::getProductionOrderId, productionOrderId)
|
.orderByDesc(ProductionOrderBom::getId)
|
.last("limit 1"));
|
if (orderBom == null || orderBom.getId() == null) {
|
return Collections.emptyList();
|
}
|
|
List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.pickByBomId(orderBom.getId());
|
if (bomStructureList == null || bomStructureList.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
List<Long> productModelIds = bomStructureList.stream()
|
.map(ProductionBomStructureVo::getProductModelId)
|
.filter(Objects::nonNull)
|
.distinct()
|
.collect(Collectors.toList());
|
Map<Long, BigDecimal> stockQuantityMap = new HashMap<>();
|
Map<Long, LinkedHashSet<String>> stockBatchNoMap = new HashMap<>();
|
if (!productModelIds.isEmpty()) {
|
List<StockInventory> stockList = stockInventoryMapper.selectList(
|
Wrappers.<StockInventory>lambdaQuery()
|
.in(StockInventory::getProductModelId, productModelIds));
|
for (StockInventory stockItem : stockList) {
|
if (stockItem == null || stockItem.getProductModelId() == null) {
|
continue;
|
}
|
Long productModelId = stockItem.getProductModelId();
|
stockQuantityMap.merge(productModelId, defaultDecimal(stockItem.getQualitity()), BigDecimal::add);
|
String batchNo = stockItem.getBatchNo();
|
if (batchNo != null && !batchNo.trim().isEmpty()) {
|
stockBatchNoMap.computeIfAbsent(productModelId, key -> new LinkedHashSet<>()).add(batchNo);
|
}
|
}
|
}
|
|
Map<String, ProductionOrderPickVo> mergedPickMap = new LinkedHashMap<>();
|
for (ProductionBomStructureVo structure : bomStructureList) {
|
if (structure == null || structure.getProductModelId() == null) {
|
continue;
|
}
|
Long productModelId = structure.getProductModelId();
|
String mergeKey = String.valueOf(structure.getTechnologyOperationId()) + "#" + productModelId;
|
ProductionOrderPickVo vo = mergedPickMap.get(mergeKey);
|
if (vo == null) {
|
vo = new ProductionOrderPickVo();
|
vo.setProductModelId(productModelId);
|
vo.setOperationName(structure.getOperationName());
|
vo.setTechnologyOperationId(structure.getTechnologyOperationId());
|
vo.setProductName(structure.getProductName());
|
vo.setModel(structure.getModel());
|
vo.setDemandedQuantity(BigDecimal.ZERO);
|
vo.setUnit(structure.getUnit());
|
List<String> batchNoList = stockBatchNoMap.get(productModelId) == null
|
? Collections.emptyList()
|
: new ArrayList<>(stockBatchNoMap.get(productModelId));
|
vo.setBatchNoList(batchNoList);
|
vo.setStockQuantity(stockQuantityMap.getOrDefault(productModelId, BigDecimal.ZERO));
|
vo.setBom(true);
|
mergedPickMap.put(mergeKey, vo);
|
}
|
vo.setDemandedQuantity(defaultDecimal(vo.getDemandedQuantity()).add(defaultDecimal(structure.getDemandedQuantity())));
|
}
|
return new ArrayList<>(mergedPickMap.values());
|
}
|
|
@Override
|
public int updateOrder(ProductionOrderDto productionOrderDto) {
|
productionOrderDto.setStatus(5);
|
return baseMapper.updateById(productionOrderDto);
|
}
|
}
|