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

main
HuangHuiKang 3 weeks ago
parent f8b097b4b7
commit 7b17c21c71

@ -697,6 +697,22 @@ public class PlanController {
return success(planService.getPlanProductCapacityPage(reqVO)); 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.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 生产计划 Response VO") @Schema(description = "管理后台 - 生产计划 Response VO")
@Data @Data
@ -156,6 +157,15 @@ public class PlanRespVO {
@Schema(description = "设备名称") @Schema(description = "设备名称")
private String deviceName; private String deviceName;
@Schema(description = "工艺路线 ID")
private Long processRouteId;
@Schema(description = "工艺路线名称")
private String processRouteName;
@Schema(description = "工艺流程明细")
private List<PlanProcessRouteItemRespVO> processRouteItems;
@Schema(description = "最晚开工时间") @Schema(description = "最晚开工时间")
private LocalDateTime latestStartTime; private LocalDateTime latestStartTime;

@ -7,6 +7,7 @@ import lombok.Data;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 生产计划新增/修改 Request VO") @Schema(description = "管理后台 - 生产计划新增/修改 Request VO")
@Data @Data
@ -102,6 +103,12 @@ public class PlanSaveReqVO {
@Schema(description = "设备Id") @Schema(description = "设备Id")
private Long deviceId; 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 = "订单优先级") @Schema(description = "订单优先级")
private Integer orderPriority; private Integer orderPriority;

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

@ -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); 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.plan.vo.*;
import cn.iocoder.yudao.module.mes.controller.admin.planrecord.vo.PlanRecordRespVO; 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.controller.admin.task.vo.TaskStatusEnum;
import cn.iocoder.yudao.module.mes.dal.dataobject.bom.BomDO; // 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.BomDetailDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO; 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.itemrequisition.ItemRequisitionDetailDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.organization.OrganizationDO; 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.paigongrecord.PaigongRecordDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO; 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.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.TaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDetailDO; 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.deviceledger.DeviceLedgerMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.bom.BomMapper; // 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.BomDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.paigongrecord.PaigongRecordMapper; 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.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.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.stockindetail.StockInDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper; import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper;
import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO; 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.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 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_CODE_EXISTS;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PLAN_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PLAN_NOT_EXISTS;
@ -130,9 +139,17 @@ public class PlanServiceImpl implements PlanService {
@Resource @Resource
private PlanRecordMapper planRecordMapper; private PlanRecordMapper planRecordMapper;
@Resource @Resource
private BomMapper bomMapper; private ProcessRouteMapper processRouteMapper;
@Resource @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.getIsEnable() == null) plan.setIsEnable(true);
if(plan.getPriorityNum()==null) plan.setPriorityNum(1L); if(plan.getPriorityNum()==null) plan.setPriorityNum(1L);
if (createReqVO.getIsCalculateLoss() == null) { fillProcessRouteSnapshot(plan);
createReqVO.setIsCalculateLoss(true); // if (createReqVO.getIsCalculateLoss() == null) {
} // createReqVO.setIsCalculateLoss(true);
// }
// todo // todo
// planMapper.insert(plan); // planMapper.insert(plan);
// 返回 // 返回
@ -169,34 +187,38 @@ public class PlanServiceImpl implements PlanService {
taskDO.setStatus(TaskStatusEnum..getValue()); taskDO.setStatus(TaskStatusEnum..getValue());
taskService.updateTask(taskDO); taskService.updateTask(taskDO);
} }
List<ItemRequisitionAndStock> list = analysisService.getItemAnalysis(plan); // 产品 num // 不再根据产品 BOM 自动生成领料单。analysisService.getItemAnalysis(plan) 内部会查询 BomDetailDO
Map<Long, BigDecimal> bomYieldRateMap = buildBomYieldRateMap(plan.getProductId(), createReqVO.getIsCalculateLoss()); // 产品没有 BOM 时会抛出“产品BOM不存在”所以 /mes/plan/create 暂时跳过该链路。
List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>(); // List<ItemRequisitionAndStock> list = analysisService.getItemAnalysis(plan); // 产品 num
for (ItemRequisitionAndStock item : list) { //// Map<Long, BigDecimal> bomYieldRateMap = buildBomYieldRateMap(plan.getProductId(), createReqVO.getIsCalculateLoss());
ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO() // List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>();
.setProductId(item.getItemId()) // for (ItemRequisitionAndStock item : list) {
.setUnitId(item.getUnitId()) // ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO().builder()
.setNumber(calculateLossNumber(item.getItemId(), item.getNumber(), bomYieldRateMap, createReqVO.getIsCalculateLoss())) // .productId(item.getItemId())
.setIsEnable(true); // .unitId(item.getUnitId())
itemRequisitionDetails.add(detailDO); // .number(item.getNumber())
} // .isEnable(true)
ItemRequisitionSaveReqVO saveReqVO = new ItemRequisitionSaveReqVO(); // .build();
saveReqVO.setFeedingPipeline(createReqVO.getFeedingPipeline()); // itemRequisitionDetails.add(detailDO);
saveReqVO.setWorkerId(createReqVO.getWorkerId()); // }
saveReqVO.setItemRequisitionDetails(itemRequisitionDetails); // ItemRequisitionSaveReqVO saveReqVO = new ItemRequisitionSaveReqVO();
saveReqVO.setStatus(ItemRequisitionStatusEnum..getValue()); // saveReqVO.setFeedingPipeline(createReqVO.getFeedingPipeline());
if (saveReqVO.getRequisitionDate() == null) // saveReqVO.setWorkerId(createReqVO.getWorkerId());
saveReqVO.setRequisitionDate(LocalDateTime.now()); // saveReqVO.setItemRequisitionDetails(itemRequisitionDetails);
// // 创建领料单 // saveReqVO.setStatus(ItemRequisitionStatusEnum.下达.getValue());
Long id = itemRequisitionService.createItemRequisition(saveReqVO); // if (saveReqVO.getRequisitionDate() == null)
// saveReqVO.setRequisitionDate(LocalDateTime.now());
//// // 创建领料单
// Long id = itemRequisitionService.createItemRequisition(saveReqVO);
//更新计划状态 //更新计划状态
plan.setStatus(PlanStatusEnum..getValue()); plan.setStatus(PlanStatusEnum..getValue());
plan.setIsEnable(true); plan.setIsEnable(true);
plan.setProductionManagerId(createReqVO.getWorkerId()); plan.setProductionManagerId(createReqVO.getWorkerId());
plan.setFeedingPipeline(createReqVO.getFeedingPipeline()); plan.setFeedingPipeline(createReqVO.getFeedingPipeline());
plan.setStartTime(LocalDateTime.now()); plan.setStartTime(LocalDateTime.now());
plan.setRequisitionId(id); // plan.setRequisitionId(id);
planMapper.insert(plan); planMapper.insert(plan);
savePlanProcessRouteItems(plan.getId(), plan.getProcessRouteId(), createReqVO.getProcessRouteItems());
//添加计划操作记录 //添加计划操作记录
PlanRecordDO planRecordDO = new PlanRecordDO(); PlanRecordDO planRecordDO = new PlanRecordDO();
planRecordDO.setTaskId(plan.getTaskId()); planRecordDO.setTaskId(plan.getTaskId());
@ -256,71 +278,71 @@ public class PlanServiceImpl implements PlanService {
saveReqVO.setPlanId(plan.getId()); // saveReqVO.setPlanId(plan.getId());
saveReqVO.setId(id); // saveReqVO.setId(id);
itemRequisitionService.updateItemRequisition(saveReqVO); // itemRequisitionService.updateItemRequisition(saveReqVO);
// 创建入领料出库单 // // 创建入领料出库单
ErpStockOutSaveReqVO stockOut = new ErpStockOutSaveReqVO(); // ErpStockOutSaveReqVO stockOut = new ErpStockOutSaveReqVO();
List<ErpStockOutSaveReqVOItem> itemList = new ArrayList<>(); // List<ErpStockOutSaveReqVOItem> itemList = new ArrayList<>();
stockOut.setOutTime(LocalDateTime.now()); // stockOut.setOutTime(LocalDateTime.now());
stockOut.setOutType("领料出库"); // stockOut.setOutType("领料出库");
//
ErpWarehouseDO warehouse = erpWarehouseMapper.selectOne( // ErpWarehouseDO warehouse = erpWarehouseMapper.selectOne(
Wrappers.<ErpWarehouseDO>lambdaQuery() // Wrappers.<ErpWarehouseDO>lambdaQuery()
.orderByDesc(ErpWarehouseDO::getCreateTime) // .orderByDesc(ErpWarehouseDO::getCreateTime)
.last("limit 1") // .last("limit 1")
); // );
for (ItemRequisitionAndStock requisition : list) { // for (ItemRequisitionAndStock requisition : list) {
ErpStockOutSaveReqVOItem item = new ErpStockOutSaveReqVOItem(); // ErpStockOutSaveReqVOItem item = new ErpStockOutSaveReqVOItem();
item.setWarehouseId(warehouse.getId()); // item.setWarehouseId(warehouse.getId());
item.setProductId(requisition.getItemId()); // item.setProductId(requisition.getItemId());
item.setCount(calculateLossNumber(requisition.getItemId(), requisition.getNumber(), bomYieldRateMap, createReqVO.getIsCalculateLoss())); // item.setCount(requisition.getNumber());
itemList.add(item); // itemList.add(item);
} // }
stockOut.setItems(itemList); // stockOut.setItems(itemList);
stockOut.setPlanCode(StringUtils.isEmpty(plan.getCode()) ? code : plan.getCode()); // stockOut.setPlanCode(StringUtils.isEmpty(plan.getCode()) ? code : plan.getCode());
stockOutService.createStockOut(stockOut); // stockOutService.createStockOut(stockOut);
return plan.getId(); return plan.getId();
} }
private Map<Long, BigDecimal> buildBomYieldRateMap(Long productId, Boolean isCalculateLoss) { // private Map<Long, BigDecimal> buildBomYieldRateMap(Long productId, Boolean isCalculateLoss) {
if (!Boolean.TRUE.equals(isCalculateLoss) || productId == null) { // if (!Boolean.TRUE.equals(isCalculateLoss) || productId == null) {
return Collections.emptyMap(); // return Collections.emptyMap();
} // }
BomDO bomDO = bomMapper.selectByProductId(productId); // BomDO bomDO = bomMapper.selectByProductId(productId);
if (bomDO == null || bomDO.getId() == null) { // if (bomDO == null || bomDO.getId() == null) {
return Collections.emptyMap(); // return Collections.emptyMap();
} // }
List<BomDetailDO> bomDetails = bomDetailMapper.selectList( // List<BomDetailDO> bomDetails = bomDetailMapper.selectList(
Wrappers.<BomDetailDO>lambdaQuery() // Wrappers.<BomDetailDO>lambdaQuery()
.eq(BomDetailDO::getBomId, bomDO.getId()) // .eq(BomDetailDO::getBomId, bomDO.getId())
.eq(BomDetailDO::getIsEnable, true) // .eq(BomDetailDO::getIsEnable, true)
); // );
if (CollUtil.isEmpty(bomDetails)) { // if (CollUtil.isEmpty(bomDetails)) {
return Collections.emptyMap(); // return Collections.emptyMap();
} // }
return bomDetails.stream() // return bomDetails.stream()
.filter(detail -> detail.getProductId() != null) // .filter(detail -> detail.getProductId() != null)
.collect(Collectors.toMap( // .collect(Collectors.toMap(
BomDetailDO::getProductId, // BomDetailDO::getProductId,
BomDetailDO::getYieldRate, // BomDetailDO::getYieldRate,
(first, second) -> first // (first, second) -> first
)); // ));
} // }
private BigDecimal calculateLossNumber(Long itemId, BigDecimal originalNumber, // private BigDecimal calculateLossNumber(Long itemId, BigDecimal originalNumber,
Map<Long, BigDecimal> bomYieldRateMap, // Map<Long, BigDecimal> bomYieldRateMap,
Boolean isCalculateLoss) { // Boolean isCalculateLoss) {
if (!Boolean.TRUE.equals(isCalculateLoss) || itemId == null || originalNumber == null) { // if (!Boolean.TRUE.equals(isCalculateLoss) || itemId == null || originalNumber == null) {
return originalNumber; // return originalNumber;
} // }
BigDecimal yieldRate = bomYieldRateMap.get(itemId); // BigDecimal yieldRate = bomYieldRateMap.get(itemId);
if (yieldRate == null) { // if (yieldRate == null) {
return originalNumber; // return originalNumber;
} // }
BigDecimal rate = yieldRate.divide(BigDecimal.valueOf(100), 8, RoundingMode.HALF_UP); // BigDecimal rate = yieldRate.divide(BigDecimal.valueOf(100), 8, RoundingMode.HALF_UP);
return originalNumber.multiply(BigDecimal.ONE.add(rate)).stripTrailingZeros(); // return originalNumber.multiply(BigDecimal.ONE.add(rate)).stripTrailingZeros();
} // }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -354,7 +376,65 @@ public class PlanServiceImpl implements PlanService {
TaskDetailDO taskDetailDO = taskService.getTaskDetail(updateObj.getTaskDetailId()); TaskDetailDO taskDetailDO = taskService.getTaskDetail(updateObj.getTaskDetailId());
updateObj.setProductId(taskDetailDO.getProductId()); updateObj.setProductId(taskDetailDO.getProductId());
} }
fillProcessRouteSnapshot(updateObj);
planMapper.updateById(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 @Override
@ -411,6 +491,8 @@ public class PlanServiceImpl implements PlanService {
} else { } else {
planRespVO.setDeviceName(null); planRespVO.setDeviceName(null);
} }
planRespVO.setProcessRouteItems(BeanUtils.toBean(
planProcessRouteItemMapper.selectListByPlanId(planDO.getId()), PlanProcessRouteItemRespVO.class));
return planRespVO; return planRespVO;
} }
@ -619,7 +701,7 @@ public class PlanServiceImpl implements PlanService {
convertSet(list, PlanDO::getTaskId)); convertSet(list, PlanDO::getTaskId));
Map<Long, OrganizationDO> organizationMap = organizationService.getMap( Map<Long, OrganizationDO> organizationMap = organizationService.getMap(
convertSet(list, PlanDO::getFeedingPipeline)); 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(), MapUtils.findAndThen(map, item.getProductId(),
product -> item.setProductName(product.getName())); product -> item.setProductName(product.getName()));
@ -632,6 +714,27 @@ public class PlanServiceImpl implements PlanService {
MapUtils.findAndThen(organizationMap, item.getFeedingPipeline(), MapUtils.findAndThen(organizationMap, item.getFeedingPipeline(),
organization -> item.setFeedingPipelineName(organization.getName())); 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 @Override
public List<PlanDO> buildProgress(List<PlanDO> list){ public List<PlanDO> buildProgress(List<PlanDO> list){
@ -672,11 +775,12 @@ public class PlanServiceImpl implements PlanService {
List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>(); List<ItemRequisitionDetailDO> itemRequisitionDetails = new ArrayList<>();
for (ItemRequisitionAndStock item : list) { for (ItemRequisitionAndStock item : list) {
ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO() ItemRequisitionDetailDO detailDO = new ItemRequisitionDetailDO().builder()
.setProductId(item.getItemId()) .productId(item.getItemId())
.setUnitId(item.getUnitId()) .unitId(item.getUnitId())
.setNumber(item.getNumber()) .number(item.getNumber())
.setIsEnable(true); .isEnable(true)
.build();
itemRequisitionDetails.add(detailDO); itemRequisitionDetails.add(detailDO);
} }
saveReqVO.setItemRequisitionDetails(itemRequisitionDetails); saveReqVO.setItemRequisitionDetails(itemRequisitionDetails);
@ -700,12 +804,13 @@ public class PlanServiceImpl implements PlanService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean arrangePlanNum(ItemRequisitionSaveReqVO saveReqVO, PlanDO planDO) { public Boolean arrangePlanNum(ItemRequisitionSaveReqVO saveReqVO, PlanDO planDO) {
// 创建派工记录 // 创建派工记录
PaigongRecordDO paigongRecordDO = new PaigongRecordDO() PaigongRecordDO paigongRecordDO = new PaigongRecordDO().builder()
.setPaigongNum(saveReqVO.getPaigongNum()) .paigongNum(saveReqVO.getPaigongNum())
.setPipeline(saveReqVO.getPipeline()) .pipeline(saveReqVO.getPipeline())
.setIsPreProduction(saveReqVO.getIsPreProduction()) .isPreProduction(saveReqVO.getIsPreProduction())
.setPlanId(planDO.getId()) .planId(planDO.getId())
.setPaigongTime(LocalDateTime.now()); .paigongTime(LocalDateTime.now())
.build();
paigongRecordMapper.insert(paigongRecordDO); paigongRecordMapper.insert(paigongRecordDO);
// 更新未派工数量 // 更新未派工数量
planDO.setNoPaigongNumber(planDO.getPlanNumber()-saveReqVO.getPaigongNum()); planDO.setNoPaigongNumber(planDO.getPlanNumber()-saveReqVO.getPaigongNum());
@ -877,6 +982,44 @@ public class PlanServiceImpl implements PlanService {
return new PageResult<>(page.getRecords(), page.getTotal()); 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