diff --git a/src/main/java/com/gaotao/modules/notify/controller/IssureNotifyController.java b/src/main/java/com/gaotao/modules/notify/controller/IssureNotifyController.java index 8be2cea..1f48e1a 100644 --- a/src/main/java/com/gaotao/modules/notify/controller/IssureNotifyController.java +++ b/src/main/java/com/gaotao/modules/notify/controller/IssureNotifyController.java @@ -12,9 +12,17 @@ import com.gaotao.modules.notify.entity.dto.NoOrderNotifyDto; import com.gaotao.modules.notify.entity.vo.*; import com.gaotao.modules.notify.service.IssureNotifyService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.List; @@ -466,4 +474,65 @@ public class IssureNotifyController { return R.error("Excel导入失败: " + e.getMessage()); } } + + @GetMapping("/downloadPartNoTemplate") + public ResponseEntity downloadPartNoTemplate() { + + try { + // 模板文件路径 + String templatePath = "D:\\wms-file\\NoorderPartNoTemplate.xlsx"; + File templateFile = new File(templatePath); + + if (!templateFile.exists()) { + return ResponseEntity.notFound().build(); + } + + Resource resource = new FileSystemResource(templateFile); + + String fileName = "无订单物料Excel模板.xlsx"; + String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()) + .replaceAll("\\+", "%20"); + + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename*=UTF-8''" + encodedFileName) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .body(resource); + + } catch (Exception e) { + return ResponseEntity.internalServerError().build(); + } + } + + + @GetMapping("/downloadShoporderTemplate") + public ResponseEntity downloadShoporderTemplate() { + + try { + // 模板文件路径 + String templatePath = "D:\\wms-file\\NoorderShoporderTemplate.xlsx"; + File templateFile = new File(templatePath); + + if (!templateFile.exists()) { + return ResponseEntity.notFound().build(); + } + + Resource resource = new FileSystemResource(templateFile); + + String fileName = "无订单订单号Excel模板.xlsx"; + String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()) + .replaceAll("\\+", "%20"); + + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename*=UTF-8''" + encodedFileName) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .body(resource); + + } catch (Exception e) { + return ResponseEntity.internalServerError().build(); + } + } } diff --git a/src/main/java/com/gaotao/modules/notify/service/impl/IssureNotifyServiceImpl.java b/src/main/java/com/gaotao/modules/notify/service/impl/IssureNotifyServiceImpl.java index a2fc0f4..bcdc122 100644 --- a/src/main/java/com/gaotao/modules/notify/service/impl/IssureNotifyServiceImpl.java +++ b/src/main/java/com/gaotao/modules/notify/service/impl/IssureNotifyServiceImpl.java @@ -10,18 +10,18 @@ import com.gaotao.common.utils.ExcelUtil; import com.gaotao.common.utils.HttpUtils; import com.gaotao.common.utils.PageUtils; import com.gaotao.modules.api.entity.IfsInventoryPart; +import com.gaotao.modules.api.entity.IfsShopOrder; +import com.gaotao.modules.api.service.IfsApiIssueAndReturnService; import com.gaotao.modules.api.service.IfsApiService; import com.gaotao.modules.api.service.impl.IfsApiServiceImpl; import com.gaotao.modules.base.entity.SOScheduledRoutingData; import com.gaotao.modules.customer.entity.dto.ShipmentIssueDto; import com.gaotao.modules.notify.entity.*; -import com.gaotao.modules.notify.entity.dto.GroupKey; -import com.gaotao.modules.notify.entity.dto.NewSoIssueNotifyDto; -import com.gaotao.modules.notify.entity.dto.NoOrderNotifyDto; -import com.gaotao.modules.notify.entity.dto.ShoporderAndMaterialDto; +import com.gaotao.modules.notify.entity.dto.*; import com.gaotao.modules.notify.entity.vo.*; import com.gaotao.modules.notify.mapper.IssureNotifyMapper; import com.gaotao.modules.notify.service.IssureNotifyService; +import com.gaotao.modules.notify.service.NewIssureService; import com.gaotao.modules.sys.entity.SysUserEntity; import com.gaotao.modules.trans.entity.TransNoControl; import com.gaotao.modules.trans.service.Consts; @@ -32,6 +32,7 @@ import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.shiro.SecurityUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -72,6 +73,11 @@ public class IssureNotifyServiceImpl implements IssureNotifyService { @Value("${ldap-control.control-flag:false}") private Boolean ldapFlag; + @Autowired + private NewIssureService newIssureService; + @Autowired + private IfsApiIssueAndReturnService ifsApiIssueAndReturnService; + /** * 获取当前用户的域控账号,如果开启了域控账号则获取用户的域控账号,否则使用配置的默认值 */ @@ -1037,56 +1043,148 @@ public class IssureNotifyServiceImpl implements IssureNotifyService { throw new RuntimeException("文件格式不正确,只支持.xls和.xlsx格式的Excel文件"); } - // 使用ExcelUtil读取Excel文件 + // 使用ExcelUtil读取Excel文件(数据部分,从第二行开始) List> excelDataList = ExcelUtil.readExcelToMapList(file); if (excelDataList.isEmpty()) { throw new RuntimeException("Excel文件中没有有效数据"); } - // 转换为ImportPartAttrVo列表 - List importPartAttrVoList = new ArrayList<>(); + // 读取表头行,准确获取模板的列数(第 0 行) + int columnCount; + try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) { + Sheet sheet = workbook.getSheetAt(0); + Row headerRow = sheet.getRow(0); + columnCount = (headerRow != null) ? headerRow.getLastCellNum() : 0; + } - for (int i = 0; i < excelDataList.size(); i++) { - Map rowData = excelDataList.get(i); - int rowIndex = i + 2; // Excel行号(考虑表头) + // 根据列数区分两种模板: + // 2 列:第一列料号 partNo,第二列数量 qty(原逻辑) + // 3 列:订单号 orderNo + releaseNo + sequenceNo - try { - ShopOrderAndMaterialVo importPartAttrVo = new ShopOrderAndMaterialVo(); + List resultList = new ArrayList<>(); - // 设置站点 - importPartAttrVo.setSite(site); + List orderNoList = new ArrayList<>(); - // 第一列:料号(A列,索引0) - Object partNoObj = rowData.get("0"); - if (partNoObj == null || StringUtils.isBlank(partNoObj.toString())) { - throw new RuntimeException("第" + rowIndex + "行的料号不能为空"); - } - importPartAttrVo.setComponentPartNo(partNoObj.toString().trim()); + if (columnCount <= 2) { + // 两列及以上:保留原逻辑,A 列料号,B 列数量 + for (int i = 0; i < excelDataList.size(); i++) { + Map rowData = excelDataList.get(i); + int rowIndex = i + 2; // Excel行号(考虑表头) - // 第二列:数量(B列,索引1) - Object qtyObj = rowData.get("1"); - if (qtyObj == null || StringUtils.isBlank(qtyObj.toString())) { - throw new RuntimeException("第" + rowIndex + "行的数量不能为空"); - } try { - BigDecimal qty = new BigDecimal(qtyObj.toString().trim()); - if (qty.compareTo(BigDecimal.ZERO) <= 0) { - throw new RuntimeException("第" + rowIndex + "行的数量必须大于0"); + ShopOrderAndMaterialVo vo = new ShopOrderAndMaterialVo(); + // 设置站点 + vo.setSite(site); + + // 第一列:料号(A列,索引0) + Object partNoObj = rowData.get("0"); + if (partNoObj == null || StringUtils.isBlank(partNoObj.toString())) { + throw new RuntimeException("第" + rowIndex + "行的料号不能为空"); + } + vo.setComponentPartNo(partNoObj.toString().trim()); + + // 第二列:数量(B列,索引1) + Object qtyObj = rowData.get("1"); + if (qtyObj == null || StringUtils.isBlank(qtyObj.toString())) { + throw new RuntimeException("第" + rowIndex + "行的数量不能为空"); + } + try { + BigDecimal qty = new BigDecimal(qtyObj.toString().trim()); + if (qty.compareTo(BigDecimal.ZERO) <= 0) { + throw new RuntimeException("第" + rowIndex + "行的数量必须大于0"); + } + vo.setQtyRequired(qty); + } catch (NumberFormatException e) { + throw new RuntimeException("第" + rowIndex + "行的数量必须是有效的数字"); } - importPartAttrVo.setQtyIssued(qty); - } catch (NumberFormatException e) { - throw new RuntimeException("第" + rowIndex + "行的数量必须是有效的数字"); + + resultList.add(vo); + } catch (Exception e) { + throw new RuntimeException("第" + rowIndex + "行数据处理异常: " + e.getMessage()); } + } - importPartAttrVoList.add(importPartAttrVo); + } else { + // 单列表头:A 列为工单号 orderNo + for (int i = 0; i < excelDataList.size(); i++) { + Map rowData = excelDataList.get(i); + int rowIndex = i + 2; // Excel行号(考虑表头) + + Object orderNoObj = rowData.get("0"); + if (orderNoObj == null || StringUtils.isBlank(orderNoObj.toString())) { + throw new RuntimeException("第" + rowIndex + "行的订单号不能为空"); + } + String orderNo = orderNoObj.toString().trim(); - } catch (Exception e) { - throw new RuntimeException("第" + rowIndex + "行数据处理异常: " + e.getMessage()); + Object releaseNoObj = rowData.get("1"); + if (releaseNoObj == null || StringUtils.isBlank(releaseNoObj.toString())) { + throw new RuntimeException("第" + rowIndex + "行的releaseNo不能为空"); + } + String releaseNo = releaseNoObj.toString().trim(); + + Object sequenceNoObj = rowData.get("2"); + if (sequenceNoObj == null || StringUtils.isBlank(sequenceNoObj.toString())) { + throw new RuntimeException("第" + rowIndex + "行的sequenceNo不能为空"); + } + String sequenceNo = sequenceNoObj.toString().trim(); + + IfsShopOrder shopOrder = new IfsShopOrder(); + shopOrder.setOrderNo(orderNo); + shopOrder.setSite(site); + shopOrder.setReleaseNo(releaseNo); + shopOrder.setSequenceNo(sequenceNo); + + orderNoList.add(shopOrder); + } + List orderNoListDistinct = orderNoList.stream() + .collect(Collectors.collectingAndThen( + Collectors.toMap( + vo -> Arrays.asList(vo.getOrderNo(), vo.getSite(), vo.getReleaseNo(), vo.getSequenceNo()), + vo -> vo, + (existing, replacement) -> existing + ), + map -> new ArrayList<>(map.values()) + )); + List orderAndMaterialVoList = new ArrayList<>(); + for (IfsShopOrder order:orderNoListDistinct){ + List shopOrderAndMaterialByShoporder = ifsApiIssueAndReturnService.getShopOrderMaterial(order.getOrderNo(),order.getSite(),order.getReleaseNo(),order.getSequenceNo()); + orderAndMaterialVoList.addAll(shopOrderAndMaterialByShoporder); + } + + // 对相同 contract、componentPartNo 的记录,汇总 + List groupedList = orderAndMaterialVoList.stream() + .collect(Collectors.groupingBy( + vo -> Arrays.asList( + vo.getContract(), + vo.getComponentPartNo() + ), + Collectors.reducing( + BigDecimal.ZERO, + ShopOrderMaterialVo::getQtyRequired, + BigDecimal::add + ) + ) + ).entrySet().stream() + .map(entry -> { + ShopOrderMaterialVo vo = new ShopOrderMaterialVo(); + vo.setContract((String) entry.getKey().get(0)); + vo.setComponentPartNo((String) entry.getKey().get(1)); + vo.setQtyRequired(entry.getValue()); + return vo; + }).collect(Collectors.toList()); + /*vo.setOrderNo((String) entry.getKey().get(0)); + vo.setReleaseNo((String) entry.getKey().get(1)); + vo.setSequenceNo((String) entry.getKey().get(2));*/ + for(ShopOrderMaterialVo vo:groupedList){ + ShopOrderAndMaterialVo shopOrderAndMaterialVo = new ShopOrderAndMaterialVo(); + BeanUtils.copyProperties(vo, shopOrderAndMaterialVo); + shopOrderAndMaterialVo.setSite(site); + resultList.add(shopOrderAndMaterialVo); } } - return importPartAttrVoList; + return resultList; } @Override