package com.dy.pmsProduct.taskPlan; import cn.hutool.core.date.DateUtil; import com.alibaba.excel.util.StringUtils; import com.dy.common.webFilter.UserTokenContext; import com.dy.common.webUtil.QueryResultVo; import com.dy.pmsGlobal.daoPlt.PltProductMapper; import com.dy.pmsGlobal.daoPr.PrAssemblyPlanMapper; import com.dy.pmsGlobal.daoPr.PrBatchNumberMapper; import com.dy.pmsGlobal.daoPr.PrDeviceMapper; import com.dy.pmsGlobal.daoPr.PrProductionProcessMapper; import com.dy.pmsGlobal.pojoBa.BaUser; import com.dy.pmsGlobal.pojoPlt.PltProduct; import com.dy.pmsGlobal.pojoPr.PrAssemblyPlan; import com.dy.pmsGlobal.pojoPr.PrBatchNumber; import com.dy.pmsGlobal.pojoPr.PrDevice; import com.dy.pmsGlobal.pojoPr.PrProductionProcess; import com.dy.pmsGlobal.util.QrCodeConstant; import com.dy.pmsGlobal.util.QrCodeUtil; import com.dy.pmsGlobal.util.UserUtil; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.common.utils.PojoUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.List; import java.util.Map; @Slf4j @Service public class AssemblySv { private static final int BATCH_SIZE = 100; // 批量处理大小 private static final String CODE_FORMAT = "%03d"; private static final String CODE_FORMAT_7 = "%07d"; private PrAssemblyPlanMapper assemblyDao; private UserUtil userUtil; private PrBatchNumberMapper batchDao; private PrDeviceMapper deviceDao; private PltProductMapper productDao; private PrProductionProcessMapper processDao; @Autowired public void setAssemblyDao(PrAssemblyPlanMapper assemblyDao) { this.assemblyDao = assemblyDao; } @Autowired public void setBatchDao(PrBatchNumberMapper batchDao) { this.batchDao = batchDao; } @Autowired public void setUserUtil(UserUtil userUtil){ this.userUtil = userUtil; } @Autowired public void setDeviceDao(PrDeviceMapper deviceDao) { this.deviceDao = deviceDao; } @Autowired public void setProductDao(PltProductMapper productDao) { this.productDao = productDao; } @Autowired public void setProcessDao(PrProductionProcessMapper processDao) { this.processDao = processDao; } @Transactional public int save(PrAssemblyPlan plan){ //计划名称不能重复 if(assemblyDao.exists(plan.name,plan.id)){ throw new RuntimeException("计划名称不能重复"); } extractedCheck(plan); PrBatchNumber batch = new PrBatchNumber(); batch.batchNumber = getNextCode(); batch.proId = plan.proId; batch.remark = plan.content; BaUser loginUser = userUtil.getUser(UserTokenContext.get()); if(loginUser!=null){ batch.creator = loginUser.id; plan.creator = loginUser.id; } batchDao.insertSelective(batch); insertDevice(plan.proId,batch.id,batch.batchNumber,plan.number,1); plan.batchId = batch.id; plan.status =PlanStatusEnum.NORMAL.getCode(); plan.deleted = false; return assemblyDao.insertSelective(plan); } @Transactional public int update(PrAssemblyPlan plan){ //计划名称不能重复 if(assemblyDao.exists(plan.name,plan.id)){ throw new RuntimeException("计划名称不能重复"); } PrAssemblyPlan origPlan = assemblyDao.selectByPrimaryKey(plan.id); PrBatchNumber batch = batchDao.selectByPrimaryKey(origPlan.batchId); //如果有投入,产品和流程不能变更 if(origPlan.getInputNumber() > 0){ if(!origPlan.proId.equals(plan.proId) || !origPlan.processId.equals(plan.processId)){ throw new RuntimeException("计划已投入,产品与生产流程不能变更"); } } extractedCheck(plan); //产品改变则更新全部已生成设备号 if(origPlan.proId != plan.proId){ batch.proId = plan.proId; batchDao.updateByPrimaryKeySelective(batch); deviceDao.deleteByBatchId(origPlan.batchId); insertDevice(plan.proId,origPlan.batchId,batch.batchNumber,plan.number,1); }else if(origPlan.number < plan.number){ //数量增加则新增设备号 insertDevice(plan.proId,origPlan.batchId,batch.batchNumber,plan.number,origPlan.number+1); } return assemblyDao.updateByPrimaryKeySelective(plan); } private void extractedCheck(PrAssemblyPlan plan) { PrProductionProcess process = processDao.selectByPrimaryKey(plan.processId); if(process == null || !process.proId.equals(plan.proId)){ throw new RuntimeException("产品与生产流程不匹配"); } //开始日期要小于结束日期 if(plan.startDate.compareTo(plan.endDate) > 0){ throw new RuntimeException("开始日期不能大于结束日期"); } //Fancy add 2024/07/09 如果状态为执行 ,则结束日期必须大于等于当前日期 if(plan.status == PlanStatusEnum.NORMAL.getCode()){ String endDateStr = plan.getEndDate(); LocalDate endDate = LocalDate.parse(endDateStr, DateTimeFormatter.ISO_LOCAL_DATE); LocalDate nextDay = endDate.plusDays(1); LocalDate today = LocalDate.now(); // 获取当前日期 if (nextDay.isBefore(today)) { throw new RuntimeException("执行状态结束日期必须大于等于当前日期,请修改结束日期"); } } } @Transactional public int addDevice(Long planId,int num){ PrAssemblyPlan plan = assemblyDao.selectByPrimaryKey(planId); PrBatchNumber batch = batchDao.selectByPrimaryKey(plan.batchId); int count =insertDevice(plan.proId,plan.batchId,batch.batchNumber,num + plan.number,plan.number+1); // plan.number = plan.number + num; // assemblyDao.updateByPrimaryKeySelective (plan); return count; } /** * 批量插入 设备数据 * @param proId 产品id * @param batchId 批次id * @param batchCode 批次号 * @param number 数量 * @return 插入数量 */ private int insertDevice(Long proId,Long batchId,String batchCode,Integer number,int startIndex){ log.info("批量插入设备"); PltProduct product = productDao.selectByPrimaryKey(proId); List list = new java.util.ArrayList<>(); for(int i= startIndex ;i<= number;i++){ PrDevice device = new PrDevice(); device.proId = proId; device.batchId = batchId; device.deviceNo = getDeviceNo(product.code,batchCode,i); device.status = 0; list.add(device); } return insertBatchDevice(list); } private int insertBatchDevice(List list) { int count = 0; for (int i = 0; i < list.size(); i += BATCH_SIZE) { List subList = list.subList(i, Math.min(i + BATCH_SIZE, list.size())); // 调用MyBatis插入这批数据 count += deviceDao.insertBatch(subList); } return count; } public String getNextCode(){ log.info("获取批次编号"); String currentDay = getCurrentDay(); String maxCode = batchDao.selectMaxCode(currentDay); if (StringUtils.isBlank(maxCode)) { return currentDay + String.format(CODE_FORMAT, 1); } else { int nextCode = Integer.parseInt(maxCode.replace(currentDay, "")) + 1; // 检查溢出 if (nextCode > 999) { throw new RuntimeException("批次编号溢出"); } return currentDay + String.format(CODE_FORMAT, nextCode); } } private static String getDeviceNo(String proCode,String batchCode,int index){ String deviceNo = QrCodeConstant.TypeProduct + proCode + batchCode + String.format(CODE_FORMAT_7, index); return deviceNo; } public static void main(String[] args) { List list = new java.util.ArrayList<>(); for(int i= 1 ;i<= 10000;i++){ PrDevice device = new PrDevice(); device.proId = 2024052310512000003l; device.batchId = 2024053017154400004l; device.deviceNo = getDeviceNo("002","2024001",i); device.status = 0; list.add(device); } list.forEach(device->{ System.out.println(device.deviceNo); }); } /** * 获取当前日期 * @return yyMMdd */ private String getCurrentDay(){ return DateUtil.format(new Date(), "yyMMdd"); } public PrAssemblyPlan selectById(Long id){ return assemblyDao.selectByPrimaryKey(id); } public QueryResultVo> selectSome(QueryVo queryVo){ Map params = (Map) PojoUtils.generalize(queryVo); //查询符合条件的记录总数 Long itemTotal = assemblyDao.selectSomeCount(params); QueryResultVo> rsVo = new QueryResultVo<>(queryVo.pageSize, queryVo.pageCurr) ; //计算分页等信息 rsVo.calculateAndSet(itemTotal, params); //查询符合条件的记录 rsVo.obj = assemblyDao.selectSome(params); return rsVo ; } public QueryResultVo> selectSomeDevice(QueryVo queryVo) { Map params = (Map) PojoUtils.generalize(queryVo); //查询符合条件的记录总数 Long itemTotal = deviceDao.selectSomeCount(params); QueryResultVo> rsVo = new QueryResultVo<>(queryVo.pageSize, queryVo.pageCurr) ; //计算分页等信息 rsVo.calculateAndSet(itemTotal, params); //查询符合条件的记录 rsVo.obj = deviceDao.selectSome(params); rsVo.obj.forEach(device->{ device.qrCode = QrCodeUtil.genQrCodeString(device.deviceNo); }); return rsVo ; } public List selectDeviceByBatchId(Long batchId) { return deviceDao.selectByBatchId(batchId); } public PrAssemblyPlan selectByBatchId(Long batchId){ return assemblyDao.selectByBatchId(batchId); } /** * 只更新状态,不更新其他字段 * @param plan * @return */ @Transactional public int updateStatus(PrAssemblyPlan plan) { if(plan.status == PlanStatusEnum.NORMAL.getCode()){ PrAssemblyPlan assemblyPlan = assemblyDao.selectByPrimaryKey(plan.id); assemblyPlan.status = plan.status; extractedCheck(assemblyPlan); } PrAssemblyPlan param = new PrAssemblyPlan(); param.id =plan.id; param.status = plan.status; return assemblyDao.updateByPrimaryKeySelective(param); } }