/* * Copyright (c) 2018-2025, ztt All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: ztt */ package com.chinaztt.mes.plan.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.chinaztt.mes.basic.entity.Part; import com.chinaztt.mes.basic.mapper.PartMapper; import com.chinaztt.mes.basic.service.DiscToolService; import com.chinaztt.mes.plan.dto.OperationTaskProduceDTO; import com.chinaztt.mes.plan.entity.CustomerOrder; import com.chinaztt.mes.plan.entity.CustomerOrderProduceTask; import com.chinaztt.mes.plan.entity.OperationTaskProduce; import com.chinaztt.mes.plan.excel.OperationTaskProduceData; import com.chinaztt.mes.plan.mapper.CustomerOrderMapper; import com.chinaztt.mes.plan.mapper.CustomerOrderProduceTaskMapper; import com.chinaztt.mes.plan.mapper.OperationTaskProduceMapper; import com.chinaztt.mes.plan.service.OperationTaskProduceService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; /** * 工单产出批次 * * @author xucg * @date 2022-07-20 */ @Service @AllArgsConstructor @Transactional(rollbackFor = Exception.class) public class OperationTaskProduceServiceImpl extends ServiceImpl implements OperationTaskProduceService { public static final String SUBMIT_TYPE_MERGE = "01merge"; public static final String SUBMIT_TYPE_SPLIT = "02split"; private CustomerOrderMapper customerOrderMapper; private CustomerOrderProduceTaskMapper customerOrderProduceTaskMapper; private PartMapper partMapper; private DiscToolService discToolService; @Override public IPage getPage(Page page, QueryWrapper gen) { gen.getExpression().getOrderBy().removeAll(gen.getExpression().getOrderBy()); return this.baseMapper.getPage(page, gen, null); } /** * 导入excel数据 * * @param list */ @Override public void importExcel(LinkedList list) { //查询当前时间 生成SN号需要 DateTimeFormatter snFormat = DateTimeFormatter.ofPattern("yyMMdd"); String snDate = snFormat.format(LocalDateTime.now()); //查询最新的SN号码 String otcCustomerOrderNo = list.get(0).getOtcCustomerOrderNo(); String number = baseMapper.getLastSnNumber(otcCustomerOrderNo.substring(otcCustomerOrderNo.length() - 8) + "%"); //号码的处理 int num = 0; if (StrUtil.isNotBlank(number)) { num = Integer.parseInt(number.substring(8)); } // < 客户订单号, List< 段长数据 >> LinkedHashMap> map = list.stream().collect(Collectors.groupingBy(OperationTaskProduceData::getOtcLineNo, LinkedHashMap::new, Collectors.toList())); for (String otcLineNo : map.keySet()) { List customerOrders = customerOrderMapper.selectList(Wrappers.lambdaQuery() .eq(CustomerOrder::getOtcLineNo, otcLineNo)); if (customerOrders.size() != 1) { throw new RuntimeException("OTC行项号重复或不存在相关OTC行项号的客户订单"); } CustomerOrder customerOrder = customerOrders.get(0); if (null == customerOrder.getBuyQtyDue()){ throw new RuntimeException("当前订单行缺少库存数量,请先判断是否查询销售件号"); } List dataList = map.get(otcLineNo); List insertList = new ArrayList<>(); BigDecimal total = BigDecimal.ZERO; // 算出已经导入的数据并求和段长 List operationTaskProduceListcheck = baseMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getCustomerOrderId, customerOrder.getId())); if (CollectionUtil.isNotEmpty(operationTaskProduceListcheck)) { total = total.add(operationTaskProduceListcheck.stream().map(OperationTaskProduce::getQty).reduce(BigDecimal.ZERO, BigDecimal::add)); } for (OperationTaskProduceData operationTaskProduceData : dataList) { OperationTaskProduce operationTaskProduce = new OperationTaskProduce(); operationTaskProduce.setOtcCustomerOrderNo(operationTaskProduceData.getOtcCustomerOrderNo()); operationTaskProduce.setOtcLineNo(operationTaskProduceData.getOtcLineNo()); // operationTaskProduce.setCustomerPartSpec(operationTaskProduceData.getCustomerPartSpec()); operationTaskProduce.setSnNo(otcCustomerOrderNo.substring(otcCustomerOrderNo.length() - 8) + String.format("%03d", num + 1)); operationTaskProduce.setSelfNo(operationTaskProduceData.getSelfNo()); operationTaskProduce.setPrint(operationTaskProduceData.getPrint()); operationTaskProduce.setSection(operationTaskProduceData.getSection()); operationTaskProduce.setBegining(operationTaskProduceData.getBegining()); operationTaskProduce.setEnding(operationTaskProduceData.getEnding()); operationTaskProduce.setDirection(operationTaskProduceData.getDirection()); operationTaskProduce.setPurpose(operationTaskProduceData.getPurpose()); operationTaskProduce.setOtcLineNo(customerOrder.getOtcLineNo()); operationTaskProduce.setEndClassification(operationTaskProduceData.getEndClassification()); operationTaskProduce.setCompany(operationTaskProduceData.getCompany()); operationTaskProduce.setCrccNumber(operationTaskProduceData.getCrccNumber()); operationTaskProduce.setCustomerOrderId(customerOrder.getId()); operationTaskProduce.setQty(operationTaskProduceData.getQty().divide(new BigDecimal(1000), 6, RoundingMode.HALF_UP)); operationTaskProduce.setFinishedProductSpecification(operationTaskProduceData.getFinishedProductSpecification()); operationTaskProduce.setYmd(operationTaskProduceData.getYmd()); operationTaskProduce.setMeterMark(operationTaskProduceData.getMeterMark()); operationTaskProduce.setOrderUploadRemark(operationTaskProduceData.getOrderUploadRemark()); operationTaskProduce.setIsGenerateTask(false); operationTaskProduce.setSort(num + 1); total = total.add(operationTaskProduceData.getQty().divide(new BigDecimal(1000), 6, RoundingMode.HALF_UP)); insertList.add(operationTaskProduce); num++; } if (customerOrder.getBuyQtyDue().compareTo(total) != 0) { throw new RuntimeException("客户订单号" + customerOrder.getCustomerOrderNo() + " 订单行号 " + customerOrder.getOtcLineNo() + " 数量不一致"); } saveBatch(insertList); } } /** * 导入模板下载 * * @param response * @throws IOException */ @Override public void export(HttpServletResponse response) throws IOException { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("UTF-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("工单批次模板", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); try { //新建ExcelWriter ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build(); //获取sheet0对象 WriteSheet mainSheet = EasyExcel.writerSheet(0, "导入模板").head(OperationTaskProduceData.class).build(); //向sheet0写入数据 传入空list这样只导出表头 List operationTaskProduceDataArrayList = new ArrayList<>(); excelWriter.write(operationTaskProduceDataArrayList, mainSheet); //关闭流 excelWriter.finish(); } catch (IOException e) { throw new RuntimeException("导出失败"); } } /** * 根据id list查询 * * @param ids * @return */ @Override public Map> getByIds(List ids, String idType) { Map> map = new HashMap<>(); for (Long id : ids) { List operationTaskProduceList = new ArrayList<>(); switch (idType) { case "customer": operationTaskProduceList = baseMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getCustomerOrderId, id)); map.put(id, operationTaskProduceList); break; case "mps": operationTaskProduceList = baseMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getMpsId, id)); map.put(id, operationTaskProduceList); break; case "mo": operationTaskProduceList = baseMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getMoId, id)); map.put(id, operationTaskProduceList); break; case "operationTask": operationTaskProduceList = baseMapper.selectList(Wrappers.lambdaQuery() .eq(OperationTaskProduce::getOperationTaskId, id)); break; } map.put(id, operationTaskProduceList); } return map; } @Override public boolean submit(List taskProduces, String type) { if (CollectionUtil.isEmpty(taskProduces)) { throw new RuntimeException("请选择需要提交的数据"); } List ids = taskProduces.stream().map(OperationTaskProduceDTO::getId).collect(Collectors.toList()); synchronized (ids.toString().intern()) { List operationTaskProduceList = this.baseMapper.selectBatchIds(ids); if (CollectionUtil.isNotEmpty(operationTaskProduceList)) { // 判断是否存在已生成工单 for (OperationTaskProduce operationTaskProduce : operationTaskProduceList) { if (operationTaskProduce.getIsGenerateTask() != null && operationTaskProduce.getIsGenerateTask()) { throw new RuntimeException("工单已生成,不能合并提交"); } } if (SUBMIT_TYPE_MERGE.equals(type)) { // 判断是否存在销售订单工艺文件不一致 List customerOrders = customerOrderMapper.selectBatchIds(operationTaskProduceList.stream() .map(OperationTaskProduce::getCustomerOrderId).collect(Collectors.toList())); Long count = customerOrders.stream().map(CustomerOrder::getTechnologyDocumentId).distinct().count(); if (count > 1) { throw new RuntimeException("存在销售订单工艺文件不一致,不能合并提交"); } long partCount = taskProduces.stream().map(OperationTaskProduceDTO::getPartId).distinct().count(); if (partCount > 1) { throw new RuntimeException("存在零件不一致,不能合并提交"); } } String mergeNoPrefix = "H" + operationTaskProduceList.get(0).getOtcCustomerOrderNo().substring(operationTaskProduceList.get(0).getOtcCustomerOrderNo().length() - 8); String lastMergeNo = this.customerOrderProduceTaskMapper.selectLastMergeNo(mergeNoPrefix + "%"); //号码的处理 int num = 0; if (StrUtil.isNotBlank(lastMergeNo)) { num = Integer.parseInt(lastMergeNo.substring(lastMergeNo.length() - 3)); } String mergeNo = mergeNoPrefix + String.format("%03d", num + 1); for (OperationTaskProduce operationTaskProduce : operationTaskProduceList) { CustomerOrderProduceTask produceTask = new CustomerOrderProduceTask(); BeanUtil.copyProperties(operationTaskProduce, produceTask); taskProduces.stream().filter(taskProduce -> taskProduce.getId().equals(operationTaskProduce.getId())).findFirst().ifPresent(taskProduce -> { produceTask.setOperationTaskProduceId(taskProduce.getId()); produceTask.setPartId(taskProduce.getPartId()); produceTask.setPartNo(taskProduce.getPartNo()); produceTask.setPartName(taskProduce.getPartName()); produceTask.setCustomerName(taskProduce.getCustomerName()); produceTask.setTechnologyDocumentId(taskProduce.getTechnologyDocumentId()); }); // 合并编号 if (SUBMIT_TYPE_MERGE.equals(type)) { produceTask.setMergeSnNo(mergeNo); } else { produceTask.setMergeSnNo(operationTaskProduce.getSnNo()); } produceTask.setStatus(CustomerOrderProduceTask.STATUS_DRAFT); this.customerOrderProduceTaskMapper.insert(produceTask); } } return this.update(Wrappers.lambdaUpdate() .set(OperationTaskProduce::getIsGenerateTask, true) .in(OperationTaskProduce::getId, ids)); } } @Override public boolean batchUpdate(List operationTaskProduces) { if (CollectionUtil.isEmpty(operationTaskProduces)) { throw new RuntimeException("请选择需要修改的数据"); } Integer count = this.baseMapper.selectCount(Wrappers.lambdaQuery() .in(OperationTaskProduce::getId, operationTaskProduces.stream().map(OperationTaskProduce::getId).collect(Collectors.toList())) .eq(OperationTaskProduce::getIsGenerateTask, true)); if (count > 0) { throw new RuntimeException("存在已生成工单的数据,不能修改"); } for (OperationTaskProduce operationTaskProduce : operationTaskProduces) { if (StrUtil.isNotBlank(operationTaskProduce.getDiscToolMeasurement())) { discToolService.checkMeasurementFormat(operationTaskProduce.getDiscToolMeasurement()); } } return this.updateBatchById(operationTaskProduces); } @Override public void exportData(HttpServletResponse response, String otcCustomerOrderNo) throws IOException { //新建ExcelWriter ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build(); try { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("UTF-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("产出批次明细导出", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); //获取sheet0对象 WriteSheet mainSheet = EasyExcel.writerSheet(0, "产出批次明细导出").head(OperationTaskProduceDTO.class).build(); //向sheet0写入数据 传入空list这样只导出表头 List operationTaskProduceDataArrayList = this.baseMapper.getListByOrderNo(otcCustomerOrderNo); excelWriter.write(operationTaskProduceDataArrayList, mainSheet); } catch (IOException e) { throw new RuntimeException("导出失败"); } finally { if (excelWriter != null) { excelWriter.finish(); } } } }