feat:添加生产计划单换线及换线记录表相关接口

main
HuangHuiKang 4 days ago
parent f8b097b4b7
commit 7b17c21c71

@ -697,6 +697,22 @@ public class PlanController {
return success(planService.getPlanProductCapacityPage(reqVO));
}
@PutMapping("/change-line")
@Operation(summary = "生产计划换线")
@PreAuthorize("@ss.hasPermission('mes:plan:update')")
public CommonResult<Boolean> changeLine(@Valid @RequestBody PlanLineChangeReqVO reqVO) {
planService.changeLine(reqVO);
return success(true);
}
@GetMapping("/line-change-record/list")
@Operation(summary = "获得生产计划换线记录列表")
@Parameter(name = "planId", description = "生产计划 ID", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('mes:plan:query')")
public CommonResult<List<PlanLineChangeRecordRespVO>> getLineChangeRecordList(@RequestParam("planId") Long planId) {
return success(planService.getLineChangeRecordList(planId));
}
}

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 生产计划换线记录 Response VO")
@Data
public class PlanLineChangeRecordRespVO {
@Schema(description = "编号", example = "1")
private Long id;
@Schema(description = "生产计划编号", example = "1")
private Long planId;
@Schema(description = "计划工艺流程明细编号", example = "1")
private Long planProcessRouteItemId;
@Schema(description = "工艺参数编号", example = "100")
private Long processParameterId;
@Schema(description = "工艺参数名称")
private String processParameterName;
@Schema(description = "换线前设备 ID", example = "10")
private Long beforeDeviceId;
@Schema(description = "换线前设备名称")
private String beforeDeviceName;
@Schema(description = "换线后设备 ID", example = "11")
private Long afterDeviceId;
@Schema(description = "换线后设备名称")
private String afterDeviceName;
@Schema(description = "换线时间")
private LocalDateTime changeTime;
@Schema(description = "操作人 ID", example = "1")
private Long operatorUserId;
@Schema(description = "当前计划合格数量", example = "100")
private Long passNumber;
@Schema(description = "备注")
private String remark;
}

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 生产计划换线 Request VO")
@Data
public class PlanLineChangeReqVO {
@Schema(description = "生产计划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "生产计划 ID 不能为空")
private Long planId;
@Schema(description = "计划工艺流程明细 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "计划工艺流程明细 ID 不能为空")
private Long planProcessRouteItemId;
@Schema(description = "换线后的设备 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "换线后的设备 ID 不能为空")
private Long deviceId;
@Schema(description = "备注")
private String remark;
}

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 生产计划工艺流程 Response VO")
@Data
public class PlanProcessRouteItemRespVO {
@Schema(description = "编号", example = "1")
private Long id;
@Schema(description = "生产计划编号", example = "1")
private Long planId;
@Schema(description = "工艺路线编号", example = "1")
private Long processRouteId;
@Schema(description = "工艺路线明细编号", example = "1")
private Long processRouteItemId;
@Schema(description = "排序,从 1 开始", example = "1")
private Integer sort;
@Schema(description = "工艺参数编号", example = "100")
private Long processParameterId;
@Schema(description = "工艺参数编码")
private String processParameterCode;
@Schema(description = "工艺参数名称")
private String processParameterName;
@Schema(description = "设备 ID", example = "10")
private Long deviceId;
@Schema(description = "设备名称")
private String deviceName;
@Schema(description = "备注")
private String remark;
}

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 生产计划工艺流程新增/修改 Request VO")
@Data
public class PlanProcessRouteItemSaveReqVO {
@Schema(description = "工艺路线明细 ID对应 /mes/process-route 的 items.id", example = "1")
private Long processRouteItemId;
@Schema(description = "排序,从 1 开始。不传时使用工艺路线明细排序", example = "1")
private Integer sort;
@Schema(description = "设备 ID对应 /mes/device-ledger", example = "10")
private Long deviceId;
@Schema(description = "备注")
private String remark;
}

@ -9,6 +9,7 @@ import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 生产计划 Response VO")
@Data
@ -156,10 +157,19 @@ public class PlanRespVO {
@Schema(description = "设备名称")
private String deviceName;
@Schema(description = "工艺路线 ID")
private Long processRouteId;
@Schema(description = "工艺路线名称")
private String processRouteName;
@Schema(description = "工艺流程明细")
private List<PlanProcessRouteItemRespVO> processRouteItems;
@Schema(description = "最晚开工时间")
private LocalDateTime latestStartTime;
@Schema(description = "交货日期")
private LocalDateTime deliveryDate;
}
}

@ -7,6 +7,7 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 生产计划新增/修改 Request VO")
@Data
@ -102,6 +103,12 @@ public class PlanSaveReqVO {
@Schema(description = "设备Id")
private Long deviceId;
@Schema(description = "工艺路线 ID对应 /mes/process-route", example = "1")
private Long processRouteId;
@Schema(description = "工艺流程明细。传入每个流程选择的设备 ID不传时按工艺路线 items 自动生成空设备明细", implementation = PlanProcessRouteItemSaveReqVO.class)
private List<PlanProcessRouteItemSaveReqVO> processRouteItems;
@Schema(description = "订单优先级")
private Integer orderPriority;

@ -148,6 +148,16 @@ public class PlanDO extends BaseDO {
*/
private Long deviceId;
/**
* 线 ID
*/
private Long processRouteId;
/**
* 线
*/
private String processRouteName;
/**
*
@ -161,4 +171,4 @@ public class PlanDO extends BaseDO {
}
}

@ -0,0 +1,78 @@
package cn.iocoder.yudao.module.mes.dal.dataobject.planlinechange;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.time.LocalDateTime;
/**
* 线 DO
*/
@TableName("mes_plan_line_change_record")
@KeySequence("mes_plan_line_change_record_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PlanLineChangeRecordDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private Long planId;
/**
*
*/
private Long planProcessRouteItemId;
/**
*
*/
private Long processParameterId;
/**
*
*/
private String processParameterName;
/**
* 线 ID
*/
private Long beforeDeviceId;
/**
* 线
*/
private String beforeDeviceName;
/**
* 线 ID
*/
private Long afterDeviceId;
/**
* 线
*/
private String afterDeviceName;
/**
* 线
*/
private LocalDateTime changeTime;
/**
* ID
*/
private Long operatorUserId;
/**
*
*/
private Long passNumber;
/**
*
*/
private String remark;
}

@ -0,0 +1,68 @@
package cn.iocoder.yudao.module.mes.dal.dataobject.planroute;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 线 DO
*/
@TableName("mes_plan_process_route_item")
@KeySequence("mes_plan_process_route_item_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PlanProcessRouteItemDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private Long planId;
/**
* 线
*/
private Long processRouteId;
/**
* 线
*/
private Long processRouteItemId;
/**
* 1
*/
private Integer sort;
/**
*
*/
private Long processParameterId;
/**
*
*/
private String processParameterCode;
/**
*
*/
private String processParameterName;
/**
*
*/
private Long deviceId;
/**
*
*/
private String deviceName;
/**
*
*/
private String remark;
}

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.mes.dal.mysql.planlinechange;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mes.dal.dataobject.planlinechange.PlanLineChangeRecordDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface PlanLineChangeRecordMapper extends BaseMapperX<PlanLineChangeRecordDO> {
default List<PlanLineChangeRecordDO> selectListByPlanId(Long planId) {
return selectList(new LambdaQueryWrapperX<PlanLineChangeRecordDO>()
.eq(PlanLineChangeRecordDO::getPlanId, planId)
.orderByDesc(PlanLineChangeRecordDO::getChangeTime)
.orderByDesc(PlanLineChangeRecordDO::getId));
}
}

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.mes.dal.mysql.planroute;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mes.dal.dataobject.planroute.PlanProcessRouteItemDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface PlanProcessRouteItemMapper extends BaseMapperX<PlanProcessRouteItemDO> {
default List<PlanProcessRouteItemDO> selectListByPlanId(Long planId) {
return selectList(new LambdaQueryWrapperX<PlanProcessRouteItemDO>()
.eq(PlanProcessRouteItemDO::getPlanId, planId)
.orderByAsc(PlanProcessRouteItemDO::getSort)
.orderByAsc(PlanProcessRouteItemDO::getId));
}
default void deleteByPlanId(Long planId) {
delete(new LambdaQueryWrapperX<PlanProcessRouteItemDO>()
.eq(PlanProcessRouteItemDO::getPlanId, planId));
}
}

@ -115,5 +115,9 @@ public interface PlanService {
PageResult<PlanProductCapacityRespVO> getPlanProductCapacityPage(PlanProductCapacityPageReqVO reqVO);
void changeLine(@Valid PlanLineChangeReqVO reqVO);
List<PlanLineChangeRecordRespVO> getLineChangeRecordList(Long planId);
}

@ -23,22 +23,30 @@ import cn.iocoder.yudao.module.mes.controller.admin.itemrequisition.vo.ItemRequi
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.*;
import cn.iocoder.yudao.module.mes.controller.admin.planrecord.vo.PlanRecordRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.task.vo.TaskStatusEnum;
import cn.iocoder.yudao.module.mes.dal.dataobject.bom.BomDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.bom.BomDetailDO;
// import cn.iocoder.yudao.module.mes.dal.dataobject.bom.BomDO;
// import cn.iocoder.yudao.module.mes.dal.dataobject.bom.BomDetailDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.itemrequisition.ItemRequisitionDetailDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.organization.OrganizationDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.paigongrecord.PaigongRecordDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.planlinechange.PlanLineChangeRecordDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.planroute.PlanProcessRouteItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.planrecord.PlanRecordDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.processroute.ProcessRouteDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.processroute.ProcessRouteItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDetailDO;
import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.bom.BomMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.bom.BomDetailMapper;
// import cn.iocoder.yudao.module.mes.dal.mysql.bom.BomMapper;
// import cn.iocoder.yudao.module.mes.dal.mysql.bom.BomDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.paigongrecord.PaigongRecordMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.planlinechange.PlanLineChangeRecordMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.planroute.PlanProcessRouteItemMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.planrecord.PlanRecordMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.processroute.ProcessRouteItemMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.processroute.ProcessRouteMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.stockindetail.StockInDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper;
import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO;
@ -76,6 +84,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PLAN_CODE_EXISTS;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PLAN_NOT_EXISTS;
@ -130,9 +139,17 @@ public class PlanServiceImpl implements PlanService {
@Resource
private PlanRecordMapper planRecordMapper;
@Resource
private BomMapper bomMapper;
private ProcessRouteMapper processRouteMapper;
@Resource
private BomDetailMapper bomDetailMapper;
private ProcessRouteItemMapper processRouteItemMapper;
@Resource
private PlanProcessRouteItemMapper planProcessRouteItemMapper;
@Resource
private PlanLineChangeRecordMapper planLineChangeRecordMapper;
// @Resource
// private BomMapper bomMapper;
// @Resource
// private BomDetailMapper bomDetailMapper;
@ -158,9 +175,10 @@ public class PlanServiceImpl implements PlanService {
}
if (plan.getIsEnable() == null) plan.setIsEnable(true);
if(plan.getPriorityNum()==null) plan.setPriorityNum(1L);
if (createReqVO.getIsCalculateLoss() == null) {
createReqVO.setIsCalculateLoss(true);
}
fillProcessRouteSnapshot(plan);
// if (createReqVO.getIsCalculateLoss() == null) {
// createReqVO.setIsCalculateLoss(true);
// }
// todo
// planMapper.insert(plan);
// 返回
@ -169,34 +187,38 @@ public class PlanServiceImpl implements PlanService {
taskDO.setStatus(TaskStatusEnum..getValue());
taskService.updateTask(taskDO);
}
List<ItemRequisitionAndStock> list = analysisService.getItemAnalysis(plan); // 产品 num
Map<Long, BigDecimal> bomYieldRateMap = buildBomYieldRateMap(plan.getProductId(), createReqVO.getIsCalculateLoss());
List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>();
for (ItemRequisitionAndStock item : list) {
ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO()
.setProductId(item.getItemId())
.setUnitId(item.getUnitId())
.setNumber(calculateLossNumber(item.getItemId(), item.getNumber(), bomYieldRateMap, createReqVO.getIsCalculateLoss()))
.setIsEnable(true);
itemRequisitionDetails.add(detailDO);
}
ItemRequisitionSaveReqVO saveReqVO = new ItemRequisitionSaveReqVO();
saveReqVO.setFeedingPipeline(createReqVO.getFeedingPipeline());
saveReqVO.setWorkerId(createReqVO.getWorkerId());
saveReqVO.setItemRequisitionDetails(itemRequisitionDetails);
saveReqVO.setStatus(ItemRequisitionStatusEnum..getValue());
if (saveReqVO.getRequisitionDate() == null)
saveReqVO.setRequisitionDate(LocalDateTime.now());
// // 创建领料单
Long id = itemRequisitionService.createItemRequisition(saveReqVO);
// 不再根据产品 BOM 自动生成领料单。analysisService.getItemAnalysis(plan) 内部会查询 BomDetailDO
// 产品没有 BOM 时会抛出“产品BOM不存在”所以 /mes/plan/create 暂时跳过该链路。
// List<ItemRequisitionAndStock> list = analysisService.getItemAnalysis(plan); // 产品 num
//// Map<Long, BigDecimal> bomYieldRateMap = buildBomYieldRateMap(plan.getProductId(), createReqVO.getIsCalculateLoss());
// List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>();
// for (ItemRequisitionAndStock item : list) {
// ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO().builder()
// .productId(item.getItemId())
// .unitId(item.getUnitId())
// .number(item.getNumber())
// .isEnable(true)
// .build();
// itemRequisitionDetails.add(detailDO);
// }
// ItemRequisitionSaveReqVO saveReqVO = new ItemRequisitionSaveReqVO();
// saveReqVO.setFeedingPipeline(createReqVO.getFeedingPipeline());
// saveReqVO.setWorkerId(createReqVO.getWorkerId());
// saveReqVO.setItemRequisitionDetails(itemRequisitionDetails);
// saveReqVO.setStatus(ItemRequisitionStatusEnum.下达.getValue());
// if (saveReqVO.getRequisitionDate() == null)
// saveReqVO.setRequisitionDate(LocalDateTime.now());
//// // 创建领料单
// Long id = itemRequisitionService.createItemRequisition(saveReqVO);
//更新计划状态
plan.setStatus(PlanStatusEnum..getValue());
plan.setIsEnable(true);
plan.setProductionManagerId(createReqVO.getWorkerId());
plan.setFeedingPipeline(createReqVO.getFeedingPipeline());
plan.setStartTime(LocalDateTime.now());
plan.setRequisitionId(id);
// plan.setRequisitionId(id);
planMapper.insert(plan);
savePlanProcessRouteItems(plan.getId(), plan.getProcessRouteId(), createReqVO.getProcessRouteItems());
//添加计划操作记录
PlanRecordDO planRecordDO = new PlanRecordDO();
planRecordDO.setTaskId(plan.getTaskId());
@ -256,71 +278,71 @@ public class PlanServiceImpl implements PlanService {
saveReqVO.setPlanId(plan.getId());
saveReqVO.setId(id);
itemRequisitionService.updateItemRequisition(saveReqVO);
// 创建入领料出库单
ErpStockOutSaveReqVO stockOut = new ErpStockOutSaveReqVO();
List<ErpStockOutSaveReqVOItem> itemList = new ArrayList<>();
stockOut.setOutTime(LocalDateTime.now());
stockOut.setOutType("领料出库");
ErpWarehouseDO warehouse = erpWarehouseMapper.selectOne(
Wrappers.<ErpWarehouseDO>lambdaQuery()
.orderByDesc(ErpWarehouseDO::getCreateTime)
.last("limit 1")
);
for (ItemRequisitionAndStock requisition : list) {
ErpStockOutSaveReqVOItem item = new ErpStockOutSaveReqVOItem();
item.setWarehouseId(warehouse.getId());
item.setProductId(requisition.getItemId());
item.setCount(calculateLossNumber(requisition.getItemId(), requisition.getNumber(), bomYieldRateMap, createReqVO.getIsCalculateLoss()));
itemList.add(item);
}
stockOut.setItems(itemList);
stockOut.setPlanCode(StringUtils.isEmpty(plan.getCode()) ? code : plan.getCode());
stockOutService.createStockOut(stockOut);
// saveReqVO.setPlanId(plan.getId());
// saveReqVO.setId(id);
// itemRequisitionService.updateItemRequisition(saveReqVO);
// // 创建入领料出库单
// ErpStockOutSaveReqVO stockOut = new ErpStockOutSaveReqVO();
// List<ErpStockOutSaveReqVOItem> itemList = new ArrayList<>();
// stockOut.setOutTime(LocalDateTime.now());
// stockOut.setOutType("领料出库");
//
// ErpWarehouseDO warehouse = erpWarehouseMapper.selectOne(
// Wrappers.<ErpWarehouseDO>lambdaQuery()
// .orderByDesc(ErpWarehouseDO::getCreateTime)
// .last("limit 1")
// );
// for (ItemRequisitionAndStock requisition : list) {
// ErpStockOutSaveReqVOItem item = new ErpStockOutSaveReqVOItem();
// item.setWarehouseId(warehouse.getId());
// item.setProductId(requisition.getItemId());
// item.setCount(requisition.getNumber());
// itemList.add(item);
// }
// stockOut.setItems(itemList);
// stockOut.setPlanCode(StringUtils.isEmpty(plan.getCode()) ? code : plan.getCode());
// stockOutService.createStockOut(stockOut);
return plan.getId();
}
private Map<Long, BigDecimal> buildBomYieldRateMap(Long productId, Boolean isCalculateLoss) {
if (!Boolean.TRUE.equals(isCalculateLoss) || productId == null) {
return Collections.emptyMap();
}
BomDO bomDO = bomMapper.selectByProductId(productId);
if (bomDO == null || bomDO.getId() == null) {
return Collections.emptyMap();
}
List<BomDetailDO> bomDetails = bomDetailMapper.selectList(
Wrappers.<BomDetailDO>lambdaQuery()
.eq(BomDetailDO::getBomId, bomDO.getId())
.eq(BomDetailDO::getIsEnable, true)
);
if (CollUtil.isEmpty(bomDetails)) {
return Collections.emptyMap();
}
return bomDetails.stream()
.filter(detail -> detail.getProductId() != null)
.collect(Collectors.toMap(
BomDetailDO::getProductId,
BomDetailDO::getYieldRate,
(first, second) -> first
));
}
private BigDecimal calculateLossNumber(Long itemId, BigDecimal originalNumber,
Map<Long, BigDecimal> bomYieldRateMap,
Boolean isCalculateLoss) {
if (!Boolean.TRUE.equals(isCalculateLoss) || itemId == null || originalNumber == null) {
return originalNumber;
}
BigDecimal yieldRate = bomYieldRateMap.get(itemId);
if (yieldRate == null) {
return originalNumber;
}
BigDecimal rate = yieldRate.divide(BigDecimal.valueOf(100), 8, RoundingMode.HALF_UP);
return originalNumber.multiply(BigDecimal.ONE.add(rate)).stripTrailingZeros();
}
// private Map<Long, BigDecimal> buildBomYieldRateMap(Long productId, Boolean isCalculateLoss) {
// if (!Boolean.TRUE.equals(isCalculateLoss) || productId == null) {
// return Collections.emptyMap();
// }
// BomDO bomDO = bomMapper.selectByProductId(productId);
// if (bomDO == null || bomDO.getId() == null) {
// return Collections.emptyMap();
// }
// List<BomDetailDO> bomDetails = bomDetailMapper.selectList(
// Wrappers.<BomDetailDO>lambdaQuery()
// .eq(BomDetailDO::getBomId, bomDO.getId())
// .eq(BomDetailDO::getIsEnable, true)
// );
// if (CollUtil.isEmpty(bomDetails)) {
// return Collections.emptyMap();
// }
// return bomDetails.stream()
// .filter(detail -> detail.getProductId() != null)
// .collect(Collectors.toMap(
// BomDetailDO::getProductId,
// BomDetailDO::getYieldRate,
// (first, second) -> first
// ));
// }
// private BigDecimal calculateLossNumber(Long itemId, BigDecimal originalNumber,
// Map<Long, BigDecimal> bomYieldRateMap,
// Boolean isCalculateLoss) {
// if (!Boolean.TRUE.equals(isCalculateLoss) || itemId == null || originalNumber == null) {
// return originalNumber;
// }
// BigDecimal yieldRate = bomYieldRateMap.get(itemId);
// if (yieldRate == null) {
// return originalNumber;
// }
// BigDecimal rate = yieldRate.divide(BigDecimal.valueOf(100), 8, RoundingMode.HALF_UP);
// return originalNumber.multiply(BigDecimal.ONE.add(rate)).stripTrailingZeros();
// }
@Override
@Transactional(rollbackFor = Exception.class)
@ -354,7 +376,65 @@ public class PlanServiceImpl implements PlanService {
TaskDetailDO taskDetailDO = taskService.getTaskDetail(updateObj.getTaskDetailId());
updateObj.setProductId(taskDetailDO.getProductId());
}
fillProcessRouteSnapshot(updateObj);
planMapper.updateById(updateObj);
if (updateReqVO.getProcessRouteItems() != null || updateReqVO.getProcessRouteId() != null) {
planProcessRouteItemMapper.deleteByPlanId(updateReqVO.getId());
savePlanProcessRouteItems(updateReqVO.getId(), updateObj.getProcessRouteId(), updateReqVO.getProcessRouteItems());
}
}
private void fillProcessRouteSnapshot(PlanDO plan) {
if (plan.getProcessRouteId() == null) {
plan.setProcessRouteName(null);
return;
}
ProcessRouteDO processRoute = processRouteMapper.selectById(plan.getProcessRouteId());
plan.setProcessRouteName(processRoute == null ? null : processRoute.getName());
}
private void savePlanProcessRouteItems(Long planId, Long processRouteId, List<PlanProcessRouteItemSaveReqVO> reqItems) {
if (planId == null || processRouteId == null) {
return;
}
List<ProcessRouteItemDO> routeItems = processRouteItemMapper.selectListByRouteId(processRouteId);
if (CollUtil.isEmpty(routeItems)) {
return;
}
Map<Long, PlanProcessRouteItemSaveReqVO> reqItemMap = Optional.ofNullable(reqItems)
.orElse(Collections.emptyList())
.stream()
.filter(item -> item.getProcessRouteItemId() != null)
.collect(Collectors.toMap(PlanProcessRouteItemSaveReqVO::getProcessRouteItemId, item -> item, (first, second) -> second));
Set<Long> deviceIds = Optional.ofNullable(reqItems)
.orElse(Collections.emptyList())
.stream()
.map(PlanProcessRouteItemSaveReqVO::getDeviceId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map<Long, DeviceLedgerDO> deviceMap = CollUtil.isEmpty(deviceIds) ? Collections.emptyMap()
: deviceLedgerMapper.selectBatchIds(deviceIds).stream()
.collect(Collectors.toMap(DeviceLedgerDO::getId, item -> item, (first, second) -> first));
for (ProcessRouteItemDO routeItem : routeItems) {
PlanProcessRouteItemSaveReqVO reqItem = reqItemMap.get(routeItem.getId());
DeviceLedgerDO device = reqItem == null || reqItem.getDeviceId() == null ? null : deviceMap.get(reqItem.getDeviceId());
PlanProcessRouteItemDO planRouteItem = new PlanProcessRouteItemDO();
planRouteItem.setPlanId(planId);
planRouteItem.setProcessRouteId(processRouteId);
planRouteItem.setProcessRouteItemId(routeItem.getId());
planRouteItem.setSort(reqItem != null && reqItem.getSort() != null ? reqItem.getSort() : routeItem.getSort());
planRouteItem.setProcessParameterId(routeItem.getProcessParameterId());
planRouteItem.setProcessParameterCode(routeItem.getProcessParameterCode());
planRouteItem.setProcessParameterName(routeItem.getProcessParameterName());
planRouteItem.setDeviceId(reqItem == null ? null : reqItem.getDeviceId());
planRouteItem.setDeviceName(device == null ? null : device.getDeviceName());
planRouteItem.setRemark(reqItem == null ? routeItem.getRemark() : reqItem.getRemark());
planProcessRouteItemMapper.insert(planRouteItem);
}
}
@Override
@ -411,6 +491,8 @@ public class PlanServiceImpl implements PlanService {
} else {
planRespVO.setDeviceName(null);
}
planRespVO.setProcessRouteItems(BeanUtils.toBean(
planProcessRouteItemMapper.selectListByPlanId(planDO.getId()), PlanProcessRouteItemRespVO.class));
return planRespVO;
}
@ -619,7 +701,7 @@ public class PlanServiceImpl implements PlanService {
convertSet(list, PlanDO::getTaskId));
Map<Long, OrganizationDO> organizationMap = organizationService.getMap(
convertSet(list, PlanDO::getFeedingPipeline));
return BeanUtils.toBean(list, PlanRespVO.class, item -> {
List<PlanRespVO> respList = BeanUtils.toBean(list, PlanRespVO.class, item -> {
MapUtils.findAndThen(map, item.getProductId(),
product -> item.setProductName(product.getName()));
@ -632,6 +714,27 @@ public class PlanServiceImpl implements PlanService {
MapUtils.findAndThen(organizationMap, item.getFeedingPipeline(),
organization -> item.setFeedingPipelineName(organization.getName()));
});
fillPlanProcessRouteItems(respList);
return respList;
}
private void fillPlanProcessRouteItems(List<PlanRespVO> list) {
if (CollUtil.isEmpty(list)) {
return;
}
Set<Long> planIds = list.stream().map(PlanRespVO::getId).filter(Objects::nonNull).collect(Collectors.toSet());
if (CollUtil.isEmpty(planIds)) {
return;
}
List<PlanProcessRouteItemDO> routeItems = planProcessRouteItemMapper.selectList(
Wrappers.<PlanProcessRouteItemDO>lambdaQuery()
.in(PlanProcessRouteItemDO::getPlanId, planIds)
.orderByAsc(PlanProcessRouteItemDO::getSort)
.orderByAsc(PlanProcessRouteItemDO::getId));
Map<Long, List<PlanProcessRouteItemRespVO>> routeItemMap = routeItems.stream()
.collect(Collectors.groupingBy(PlanProcessRouteItemDO::getPlanId, LinkedHashMap::new,
Collectors.mapping(item -> BeanUtils.toBean(item, PlanProcessRouteItemRespVO.class), Collectors.toList())));
list.forEach(item -> item.setProcessRouteItems(routeItemMap.getOrDefault(item.getId(), Collections.emptyList())));
}
@Override
public List<PlanDO> buildProgress(List<PlanDO> list){
@ -672,11 +775,12 @@ public class PlanServiceImpl implements PlanService {
List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>();
for (ItemRequisitionAndStock item : list) {
ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO()
.setProductId(item.getItemId())
.setUnitId(item.getUnitId())
.setNumber(item.getNumber())
.setIsEnable(true);
ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO().builder()
.productId(item.getItemId())
.unitId(item.getUnitId())
.number(item.getNumber())
.isEnable(true)
.build();
itemRequisitionDetails.add(detailDO);
}
saveReqVO.setItemRequisitionDetails(itemRequisitionDetails);
@ -700,12 +804,13 @@ public class PlanServiceImpl implements PlanService {
@Transactional(rollbackFor = Exception.class)
public Boolean arrangePlanNum(ItemRequisitionSaveReqVO saveReqVO, PlanDO planDO) {
// 创建派工记录
PaigongRecordDO paigongRecordDO = new PaigongRecordDO()
.setPaigongNum(saveReqVO.getPaigongNum())
.setPipeline(saveReqVO.getPipeline())
.setIsPreProduction(saveReqVO.getIsPreProduction())
.setPlanId(planDO.getId())
.setPaigongTime(LocalDateTime.now());
PaigongRecordDO paigongRecordDO = new PaigongRecordDO().builder()
.paigongNum(saveReqVO.getPaigongNum())
.pipeline(saveReqVO.getPipeline())
.isPreProduction(saveReqVO.getIsPreProduction())
.planId(planDO.getId())
.paigongTime(LocalDateTime.now())
.build();
paigongRecordMapper.insert(paigongRecordDO);
// 更新未派工数量
planDO.setNoPaigongNumber(planDO.getPlanNumber()-saveReqVO.getPaigongNum());
@ -877,6 +982,44 @@ public class PlanServiceImpl implements PlanService {
return new PageResult<>(page.getRecords(), page.getTotal());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void changeLine(PlanLineChangeReqVO reqVO) {
PlanDO plan = planMapper.selectById(reqVO.getPlanId());
if (plan == null) {
throw exception(PLAN_NOT_EXISTS);
}
PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(reqVO.getPlanProcessRouteItemId());
if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), reqVO.getPlanId())) {
throw exception(PLAN_NOT_EXISTS);
}
DeviceLedgerDO afterDevice = deviceLedgerMapper.selectById(reqVO.getDeviceId());
PlanLineChangeRecordDO record = new PlanLineChangeRecordDO();
record.setPlanId(plan.getId());
record.setPlanProcessRouteItemId(planRouteItem.getId());
record.setProcessParameterId(planRouteItem.getProcessParameterId());
record.setProcessParameterName(planRouteItem.getProcessParameterName());
record.setBeforeDeviceId(planRouteItem.getDeviceId());
record.setBeforeDeviceName(planRouteItem.getDeviceName());
record.setAfterDeviceId(reqVO.getDeviceId());
record.setAfterDeviceName(afterDevice == null ? null : afterDevice.getDeviceName());
record.setChangeTime(LocalDateTime.now());
record.setOperatorUserId(getLoginUserId());
record.setPassNumber(plan.getPassNumber());
record.setRemark(reqVO.getRemark());
planLineChangeRecordMapper.insert(record);
planRouteItem.setDeviceId(reqVO.getDeviceId());
planRouteItem.setDeviceName(afterDevice == null ? null : afterDevice.getDeviceName());
planProcessRouteItemMapper.updateById(planRouteItem);
}
@Override
public List<PlanLineChangeRecordRespVO> getLineChangeRecordList(Long planId) {
return BeanUtils.toBean(planLineChangeRecordMapper.selectListByPlanId(planId), PlanLineChangeRecordRespVO.class);
}
}

Loading…
Cancel
Save