evoToK3Cloud/ruoyi-system/src/main/java/com/ruoyi/system/controller/ProcessRouteController.java
2026-04-12 10:11:15 +08:00

1058 lines
51 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.config.DingTalkProperties;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.dingding.util.DingUtil;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.excel.DefaultExcelListener;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.FtpUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.SmbUtil;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.ProcessRouteBo;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.domain.vo.PcRigidChainVo;
import com.ruoyi.system.domain.vo.PlannedProcessVo;
import com.ruoyi.system.domain.vo.ProcessRouteVo;
import com.ruoyi.system.domain.vo.ProductionOrderVo;
import com.ruoyi.system.jdmain.rouplan.Model;
import com.ruoyi.system.mapper.BomDetailsMapper;
import com.ruoyi.system.mapper.MaterialBomMapper;
import com.ruoyi.system.mapper.ProcessOrderProMapper;
import com.ruoyi.system.mapper.ProcessRouteMapper;
import com.ruoyi.system.runner.JdUtil;
import com.ruoyi.system.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* 工艺路线
*
* @date 2024-10-09
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/route")
@Slf4j
public class ProcessRouteController extends BaseController {
private final ProcessRouteMapper baseMapper;
private final IProcessRouteService iProcessRouteService;
private final IBomDetailsService iBomDetailsService;
private final ProcessOrderProMapper proMapper;
private final IImMaterialService materialService;
@Autowired
BomDetailsMapper bomDetailsMapper;
@Autowired
MaterialBomMapper materialBomMapper;
@Autowired
private DingTalkProperties dingTalkProperties;
@Autowired
private ISysOssService iSysOssService;
@Autowired
private IProcessOrderProService processOrderProService;
@Autowired
private ISysUserService userService;
@Autowired
private com.ruoyi.common.dingding.robot.RobotGroupService robotGroupService;
@Autowired
private com.ruoyi.common.dingding.media.MediaService mediaService;
private Long generateUniqueParentId(Long originalId) {
return originalId + 1000;
}
@Log(title = "查看BOM上传状态")
@SaCheckPermission("system:route:viewGetBomUploadStatus")
@PostMapping("/viewGetBomUploadStatus")
public R<String> viewGetBomUploadStatus(@RequestParam String rooteProdet) {
return iProcessRouteService.viewGetBomUploadStatus(rooteProdet);
}
/**
* 主动更新可用库存
*/
@SaCheckPermission("system:route:list")
@GetMapping("/list2")
public TableDataInfo<ProcessRouteVo> list2(ProcessRouteBo bo, PageQuery pageQuery) {
try {
// 查询工艺路线数据
TableDataInfo<ProcessRouteVo> processRouteVoTableDataInfo = iProcessRouteService.queryPageList2(bo, pageQuery);
// 用于存储父子关系的Mapkey为"物料编码_物料名称"值为父级ProcessRouteVo
Map<String, ProcessRouteVo> routeMap = new HashMap<>();
// 存储顶级列表
List<ProcessRouteVo> topLevelList = new ArrayList<>();
// 获取查询返回的行数据
List<ProcessRouteVo> rows = processRouteVoTableDataInfo.getRows();
// 遍历所有工艺路线记录
for (ProcessRouteVo processRouteVo : rows) {
// 组合父级键值,物料编码 + 物料名称
String parentCodeAndName = String.format("%s_%s", processRouteVo.getMaterialCode(), processRouteVo.getMaterialName());
// 查找是否已存在父节点
ProcessRouteVo parent = routeMap.get(parentCodeAndName);
if (parent == null) {
// 如果父节点不存在,创建并初始化
parent = new ProcessRouteVo();
parent.setId(generateUniqueParentId(processRouteVo.getId()));
parent.setRouteDescription(processRouteVo.getRouteDescription());
// parent.setParentId((Long.valueOf(generateUniqueParentId(processRouteVo.getId()))));
parent.setMaterialCode(processRouteVo.getMaterialCode());
parent.setMaterialName(processRouteVo.getMaterialName());
parent.setMaterial(processRouteVo.getMaterial());
parent.setDiscWeight(processRouteVo.getDiscWeight());
parent.setFirstBatchQuantity(processRouteVo.getFirstBatchQuantity());
// 初始化子节点列表
parent.setChildren(new ArrayList<>());
// 将父节点放入Map中
routeMap.put(parentCodeAndName, parent);
// 将父节点加入顶级列表
topLevelList.add(parent);
}
// 创建子节点,并将其添加到父节点的子集
ProcessRouteVo child = createChildVo(processRouteVo, parent.getId(), parent.getMaterialCode(), parent.getMaterialName());
parent.getChildren().add(child);
}
// 设置返回的rows为顶级节点列表
processRouteVoTableDataInfo.setRows(topLevelList);
// 返回构建后的数据
return processRouteVoTableDataInfo;
} catch (Exception e) {
e.printStackTrace();
return new TableDataInfo<>();
}
}
/**
* 查询工艺路线列表
*/
@SaCheckPermission("system:route:list")
@GetMapping("/list")
public TableDataInfo<ProcessRouteVo> list(ProcessRouteBo bo, PageQuery pageQuery) {
try {
// 查询工艺路线数据
TableDataInfo<ProcessRouteVo> processRouteVoTableDataInfo = iProcessRouteService.queryPageList(bo, pageQuery);
// 用于存储父子关系的Mapkey为"物料编码_物料名称"值为父级ProcessRouteVo
Map<String, ProcessRouteVo> routeMap = new HashMap<>();
// 存储顶级列表
List<ProcessRouteVo> topLevelList = new ArrayList<>();
// 获取查询返回的行数据
List<ProcessRouteVo> rows = processRouteVoTableDataInfo.getRows();
// 遍历所有工艺路线记录
for (ProcessRouteVo processRouteVo : rows) {
// 组合父级键值,物料编码 + 物料名称
String parentCodeAndName = String.format("%s_%s", processRouteVo.getMaterialCode(), processRouteVo.getMaterialName());
// 查找是否已存在父节点
ProcessRouteVo parent = routeMap.get(parentCodeAndName);
if (parent == null) {
// 如果父节点不存在,创建并初始化
parent = new ProcessRouteVo();
parent.setId(generateUniqueParentId(processRouteVo.getId()));
parent.setRouteDescription(processRouteVo.getRouteDescription());
// parent.setParentId((Long.valueOf(generateUniqueParentId(processRouteVo.getId()))));
parent.setMaterialCode(processRouteVo.getMaterialCode());
parent.setMaterialName(processRouteVo.getMaterialName());
parent.setMaterial(processRouteVo.getMaterial());
parent.setDiscWeight(processRouteVo.getDiscWeight());
parent.setBatchQuantity(processRouteVo.getBatchQuantity());
parent.setFirstBatchQuantity(processRouteVo.getFirstBatchQuantity());
// 初始化子节点列表
parent.setChildren(new ArrayList<>());
// 将父节点放入Map中
routeMap.put(parentCodeAndName, parent);
// 将父节点加入顶级列表
topLevelList.add(parent);
}
// 创建子节点,并将其添加到父节点的子集
ProcessRouteVo child = createChildVo(processRouteVo, parent.getId(), parent.getMaterialCode(), parent.getMaterialName());
parent.getChildren().add(child);
}
// 设置返回的rows为顶级节点列表
processRouteVoTableDataInfo.setRows(topLevelList);
// 返回构建后的数据
return processRouteVoTableDataInfo;
} catch (Exception e) {
e.printStackTrace();
return new TableDataInfo<>();
}
}
/**
* 创建子节点的辅助方法
*
* @param processRouteVo 原始数据
* @return ProcessRouteVo 子节点
*/
private ProcessRouteVo createChildVo(ProcessRouteVo processRouteVo, Long parentId, String materialCode, String materialName) {
ProcessRouteVo child = new ProcessRouteVo();
child.setId(processRouteVo.getId());
child.setParentId(parentId);
child.setProcessNo(processRouteVo.getProcessNo());
child.setWorkCenter(processRouteVo.getWorkCenter());
child.setProcessName(processRouteVo.getProcessName());
child.setProcessDescription(processRouteVo.getProcessDescription());
child.setProcessControl(processRouteVo.getProcessControl());
child.setActivityDuration(processRouteVo.getActivityDuration());
child.setActivityUnit(processRouteVo.getActivityUnit());
child.setUnitQuantity(processRouteVo.getUnitQuantity());
child.setPlanStartTime(processRouteVo.getPlanStartTime());
child.setPlanEndTime(processRouteVo.getPlanEndTime());
child.setXuStartTime(processRouteVo.getXuStartTime());
child.setXuEndTime(processRouteVo.getXuEndTime());
return child;
}
/**
* 导出工艺路线列表
*/
@SaCheckPermission("system:route:export2")
@Log(title = "工艺路线", businessType = BusinessType.EXPORT)
@PostMapping("/export2")
public void export2(ProcessRouteBo bo, HttpServletResponse response) {
log.info("获取项目生产数据表:{}", bo);
List<ProcessRoute> list = iProcessRouteService.queryList(bo);
List<MaterialUsageDTO2> bomlist = JdUtil.getPRD_PPBOM(bo.getRouteDescription());
//过滤bomlist 只要009开头的标准件
bomlist = bomlist.stream().filter(bom -> bom.getMaterialCode().startsWith("009")).collect(Collectors.toList());
if (list.isEmpty() && bomlist.isEmpty()) {
throw new ServiceException("没有数据");
}
try {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("工艺路线", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
ServletOutputStream os = response.getOutputStream();
// 创建ExcelWriter
try (com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(os).autoCloseStream(false) // 防止自动关闭流
.build()) {
// 写入工艺路线sheet
if (!list.isEmpty()) {
WriteSheet writeSheet1 = EasyExcel.writerSheet(0, "工艺路线").head(ProcessRoute.class).build();
excelWriter.write(list, writeSheet1);
}
// 写入标准件清单sheet
if (!bomlist.isEmpty()) {
WriteSheet writeSheet2 = EasyExcel.writerSheet(1, "标准件清单").head(MaterialUsageDTO2.class).build();
excelWriter.write(bomlist, writeSheet2);
}
}
} catch (Exception e) {
throw new RuntimeException("导出Excel异常: " + e.getMessage(), e);
}
}
@SaCheckPermission("system:route:export")
@Log(title = "工艺路线", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ProcessRouteBo bo, HttpServletResponse response) {
log.info("获取项目生产数据表:{}", bo);
// 下载Excel模板
SmbUtil.downloadExcelFiles(bo.getRouteDescription());
// 构建Excel文件路径
String ExcelName = "D:\\file\\" + bo.getRouteDescription() + "汇总表.xlsx";
File file = new File(ExcelName);
if (!file.exists()) {
throw new ServiceException("文件不存在,请确认路径是否正确");
}
//读取file的所有的物料编码
try {
if (file.exists()) {
// 读取Excel的sheet6 从第三行开始 读取到第4列 无数据的跳过
DefaultExcelListener<ProcessRoute> listener = new DefaultExcelListener<>(true);
EasyExcel.read(ExcelName, ProcessRoute.class, listener).sheet(6).headRowNumber(3).doRead();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
// 查询要写入的数据是否
List<ProcessRoute> list = iProcessRouteService.queryList(bo);
try {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("工艺路线", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
ServletOutputStream os = response.getOutputStream();
// 使用 EasyExcel 写入已有Excel的第七个sheetindex=6
try (ExcelWriter excelWriter = EasyExcel.write(os).withTemplate(file) // 指定模板文件
.autoCloseStream(true).build()) {
// 写入到第七个 sheetindex=6并命名为“工艺路线”
WriteSheet writeSheet = EasyExcel.writerSheet("已有工艺路线").head(ProcessRoute.class).needHead(true).build();
excelWriter.write(list, writeSheet);
}
os.flush();
} catch (Exception e) {
log.error("导出Excel异常", e);
throw new RuntimeException("导出Excel异常: " + e.getMessage(), e);
}
}
/**
* 获取工艺路线详细信息
*
* @param id 主键
*/
@SaCheckPermission("system:route:query")
@GetMapping("/{id}")
public R<ProcessRouteVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(iProcessRouteService.queryById(id));
}
/**
* 新增工艺路线
*/
@SaCheckPermission("system:route:add")
@Log(title = "工艺路线", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ProcessRouteBo bo) {
return toAjax(iProcessRouteService.insertByBo(bo));
}
/**
* 导出
* 修改工艺路线
*/
@SaCheckPermission("system:route:edit")
@Log(title = "工艺路线", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProcessRouteBo bo) {
return toAjax(iProcessRouteService.updateByBo(bo));
}
/**
* 删除工艺路线
*
* @param ids 主键串
*/
@SaCheckPermission("system:route:remove")
@Log(title = "工艺路线", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
return toAjax(iProcessRouteService.deleteWithValidByIds(Arrays.asList(ids), true));
}
@Log(title = "生产工艺计划表导入", businessType = BusinessType.IMPORT)
@SaCheckPermission("system:route:importRoute")
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R importData(@RequestParam("file") MultipartFile file) throws Exception {
String originalFilename = file.getOriginalFilename();
log.info("读取文件名: " + originalFilename);
// 读取工艺部分sheet
ExcelResult<ProcessRouteVo> result = ExcelUtil.importExcelSheet6(file.getInputStream(), ProcessRouteVo.class, true);
List<ProcessRouteVo> list1 = result.getList();
// 读取总装部分sheet
ExcelResult<ProductionOrderVo> result1 = ExcelUtil.importExcelSheet1(file.getInputStream(), ProductionOrderVo.class, true);
List<ProductionOrderVo> list = result1.getList();
String productionOrderNo = list1.get(0).getRouteDescription();
List<BomDetails> bomDetails = iBomDetailsService.selectByProjectNumber(list1.get(0).getRouteDescription());
List<ProcessRoute> route = iProcessRouteService.selectByProjectNumber(list1.get(0).getRouteDescription());
if (list1.isEmpty()) {
return R.fail("项目 " + productionOrderNo + "工艺生产计划表为空,请检查此表或将sheet移动至第七个!");
}
if (!bomDetails.isEmpty()) {
return R.fail("项目 " + productionOrderNo + "已导入过BOM,请先清空再上传");
}
if (!route.isEmpty()) {
return R.fail("项目 " + productionOrderNo + "已导入过工艺 ,请先清空再上传");
}
if (iProcessRouteService.saveData(list1, list)) {
// 保存临时文件用于发送给指定用户
File tempFile = null;
try {
String tempDirPath = "D:/file/";
File tempDir = new File(tempDirPath);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
tempFile = new File(tempDirPath + System.currentTimeMillis() + "_" + originalFilename);
file.transferTo(tempFile);
} catch (Exception e) {
log.error("保存上传临时文件失败", e);
}
final File uploadFile = tempFile;
// 获取当前登录用户昵称(需要在异步线程前获取)
String currentUserNickName = "未知用户";
try {
Long userId = LoginHelper.getUserId();
if (userId != null) {
SysUser user = userService.selectUserById(userId);
if (user != null && StringUtils.isNotEmpty(user.getNickName())) {
currentUserNickName = user.getNickName();
}
}
} catch (Exception e) {
log.warn("获取当前登录用户昵称失败", e);
}
// 异步发送钉钉卡片和文件
String finalNickName = currentUserNickName;
CompletableFuture.runAsync(() -> {
try {
if (uploadFile != null && uploadFile.exists()) {
String planUserIds = dingTalkProperties.getPlanUserId();
if (StringUtils.isNotBlank(planUserIds)) {
String mediaId = mediaService.uploadMedia("file", uploadFile.getAbsolutePath());
// 支持多人推送,假设多个 userId 以逗号分隔
String[] userIds = planUserIds.split(",");
for (String userId : userIds) {
String cleanUserId = userId.trim();
if (StringUtils.isNotBlank(cleanUserId)) {
try {
robotGroupService.sendFileToUser(cleanUserId, mediaId, originalFilename);
log.info("上传的工艺计划表已成功发送给用户: {}", cleanUserId);
} catch (Exception e) {
log.error("发送文件给用户 {} 异常", cleanUserId, e);
}
}
}
} else {
log.warn("未配置钉钉工艺计划接收人(planUserId),跳过发送文件");
}
}
} catch (Exception e) {
log.error("发送文件给工艺计划接收人异常", e);
} finally {
if (uploadFile != null && uploadFile.exists()) {
uploadFile.delete();
}
}
try {
ProcessOrderPro order = processOrderProService.selectByProjectNumber(productionOrderNo);
if (order != null) {
// 获取 AccessToken
String accessToken = DingUtil.getAccessToken(dingTalkProperties.getAppKey(), dingTalkProperties.getAppSecret());
// 构造卡片数据
Map<String, String> cardDataMap = new HashMap<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
cardDataMap.put("pro_number", StringUtils.defaultIfEmpty(order.getProductionOrderNo(), ""));
cardDataMap.put("createTime", order.getRouteUptime() != null ? sdf.format(new Date()) : "");
cardDataMap.put("title", finalNickName + "提交工艺审核");
cardDataMap.put("lastMessage", "请尽快处理");
cardDataMap.put("status", StringUtils.defaultIfEmpty("待审批", "待审批"));
String outTrackId = "audit-card-" + System.currentTimeMillis();
// 调用发送给工艺负责人的方法 createAndDeliverCardToUser
DingUtil.createAndDeliverCardToUser(
accessToken,
dingTalkProperties.getRouteCardTemplateId(),
Collections.singletonList(dingTalkProperties.getRouteApprovalId()),
outTrackId,
cardDataMap,
dingTalkProperties.getCallbackRouteKey()
);
// 统一存入带 userId 后缀的完整 outTrackId以便和钉钉回调保持一致
String fullOutTrackId = outTrackId + "_" + dingTalkProperties.getRouteApprovalId();
// 更新数据库中的AuditCardId
ProcessOrderPro update = new ProcessOrderPro();
update.setId(order.getId());
update.setUpdateBy("Dingding");
update.setAuditCardId(fullOutTrackId);
update.setBomStatus(2L);
// 更新审核状态为1已审核/提交审核)
update.setRouteStatus(0L);
proMapper.updateById(update);
}
} catch (Exception e) {
log.error("发送钉钉卡片异常", e);
}
});
return R.ok("上传物料成功");
} else {
return R.fail("导入失败");
}
}
/**
* 查询组焊件集合
*/
@Log(title = "查询组焊件集合")
@SaCheckPermission("system:route:pushGroupWeldments")
@PostMapping("/pushGroupWeldments")
public List<ProcessRoute> pushGroupWeldments(@RequestBody ProcessRoute processRoute) {
return iProcessRouteService.pushGroupWeldments(processRoute);
}
/**
* 查询需要单独生成BOm 的原材料集合
*/
@Log(title = "查询需要单独生成BOM的原材料集合")
@SaCheckPermission("system:route:getRawBom")
@PostMapping("/getRawBom")
public List<ProcessRoute> getRawBom(@RequestParam String rooteProdet) {
return iProcessRouteService.getRawBom(rooteProdet);
}
/**
* 查询工艺表中所有的需要做工艺的物料
*
* @return RequestBody List<ProcessRouteVo> routeVoList
*/
public List<ProcessRoute> getProcessRouteList(@RequestParam String rooteProdet) {
List<ProcessRoute> list = iProcessRouteService.pushRawMater(rooteProdet);
return list;
}
@Log(title = "查询工艺工序集合")
@SaCheckPermission("system:route:getProcessRoute")
@PostMapping("/getProcessRoute")
public List<ProcessRouteXuDTO> getProcessRoute(@RequestParam String rooteProdet) {
return iProcessRouteService.getProcessRoute(rooteProdet);
}
@Log(title = "推送工艺工序")
@SaCheckPermission("system:route:pushRouteBom")
@PostMapping("/pushRouteBom")
public R<ProcessRoutePushResultDTO> pushRouteBom(@RequestParam String rooteProdet, @RequestParam String groupName) {
return iProcessRouteService.pushRouteBom(rooteProdet, groupName);
}
/**
* 查询项目列表
*/
@Log(title = "获取所有的项目令号")
@SaCheckPermission("system:route:getDistinctProjectCodes")
@GetMapping("/getDistinctProjectCodes")
public ResponseEntity<List<String>> getDistinctProjectCodes(String query) {
return ResponseEntity.ok(iProcessRouteService.getDistinctProjectCodes(query));
}
@Log(title = "获取工序列表")
@SaCheckPermission("system:route:getProcessInfoList")
@GetMapping("/getProcessInfoList")
public ResponseEntity<List<String>> getProcessInfoList(String query) {
return ResponseEntity.ok(iProcessRouteService.getProcessInfoList(query));
}
@Log(title = "根据生产令号获取生产编号==》获取计划编号")
@SaCheckPermission("system:route:getSelecPlanRouteList")
@PostMapping("/getSelecPlanRouteList")
public List<CombinedDTO> getSelecPlanRouteList(@RequestParam String rooteProdet) {
return iProcessRouteService.getSelecPlanRouteList(rooteProdet);
}
@Log(title = "生成项目图纸PDF")
@SaCheckPermission("system:route:generatePDFs")
@GetMapping("/generatePDFs")
public void generatePDFs(String rooteProdet, HttpServletResponse response) throws IOException {
// 调用服务层方法生成 ZIP 文件并获取其路径
String zipFilePath = iProcessRouteService.generatePDFs(rooteProdet);
ProcessOrderPro processOrderPro = proMapper.selectByProjectNumber(rooteProdet);
processOrderPro.setBomStatus(5L);
proMapper.updateById(processOrderPro);
// 读取文件为字节数组
File zipFile = new File(zipFilePath);
if (!zipFile.exists()) {
throw new FileNotFoundException("ZIP 文件未找到: " + zipFilePath);
}
FileInputStream fis = new FileInputStream(zipFile);
OutputStream outputStreams = response.getOutputStream();
response.setContentType("application/zip");
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
outputStreams.write(buffer, 0, len);
}
outputStreams.flush();
fis.close();
outputStreams.close();
}
@Log(title = "更新计划时间")
@SaCheckPermission("system:route:updateProcessPlan")
@PostMapping("/updateProcessPlan")
public List<Model> updateProcessPlan(@RequestParam String rooteProdet) throws Exception {
return iProcessRouteService.updateProcessPlan(rooteProdet);
}
/**
* 更新生产订单的时间
*/
@Log(title = "更新生产订单时间")
@SaCheckPermission("system:route:updateProcesTime")
@PostMapping("/updateProcesTime")
public List<Model> updateProcesTime(@RequestParam String rooteProdet) throws Exception {
return iProcessRouteService.updateProcesTime(rooteProdet);
}
/**
* 保存工艺路线
*/
@SaCheckPermission("system:route:addRoute")
@Log(title = "保存工艺路线", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/addRoute")
public R<Void> addRoute(@RequestBody List<ProcessRouteVo> list) {
return iProcessRouteService.addRoute(list);
}
@SaCheckPermission("system:route:deleteRoute")
@Log(title = "删除工艺路线", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/deleteRoute")
public List<ProcessRoute> deleteRoute(@RequestBody ProcessRoute processRoute) {
return iProcessRouteService.deleteRoute(processRoute);
}
@Log(title = "获取材料bom列表")
@SaCheckPermission("system:route:getBomInfo")
@PostMapping("/getBomInfo")
public ResponseEntity<List<MaterialBom>> getProcessMaterialList(@RequestParam(value = "materialCode") String materialCode, @RequestParam(value = "materialName") String materialName, @RequestParam(value = "productionOrderNo") String productionOrderNo) {
return ResponseEntity.ok(iProcessRouteService.getProcessMaterialList(materialCode, materialName, productionOrderNo));
}
@Log(title = "获取金蝶列表")
@SaCheckPermission("system:route:getProcessRouteList")
@GetMapping("/getProcessRouteList")
public ResponseEntity<List<ProcessRouteJdDTO>> getProcessRouteList(@RequestParam(value = "materialCode") String materialCode, @RequestParam(value = "materialName") String materialName, @RequestParam(value = "productionOrderNo") String productionOrderNo) {
return ResponseEntity.ok(iProcessRouteService.getProcessRouteList(materialCode, materialName, productionOrderNo));
}
@Log(title = "导入时间", businessType = BusinessType.IMPORT)
@SaCheckPermission("system:route:importDataTime")
@PostMapping(value = "/importDataTime", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importDataTime(@RequestParam("file") MultipartFile file) throws Exception {
String originalFilename = file.getOriginalFilename();
log.info("读取文件名: " + originalFilename);
ExcelResult<ProcessRouteVo> result = ExcelUtil.importExcelSheet6(file.getInputStream(), ProcessRouteVo.class, true);
List<ProcessRouteVo> list = result.getList();
List<ProcessRoute> list1 = iProcessRouteService.importDataTime(list);
return R.ok("更新成功");
}
@Log(title = "导入时间", businessType = BusinessType.IMPORT)
@SaCheckPermission("system:route:importDataTime123")
@PostMapping(value = "/importDataTime123", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importDataTime123(@RequestParam("file") MultipartFile file) throws Exception {
DefaultExcelListener<PcRigidChainVo> listener = new DefaultExcelListener<>(true);
EasyExcel.read(file.getInputStream(), PcRigidChainVo.class, listener).excelType(ExcelTypeEnum.XLS).sheet(1).headRowNumber(4).doRead();
List<PcRigidChainVo> list1 = listener.getExcelResult().getList();
for (PcRigidChainVo pcRigidChainVO : list1) {
log.info("数据 ===============>: " + JSONUtil.toJsonStr(pcRigidChainVO));
}
return R.ok("更新成功");
}
@Log(title = "获取金蝶工艺路线")
@SaCheckPermission("system:route:getSelectProcessRout1e")
@PostMapping("/getSelectProcessRout1e")
public List<ProcessRouteSelectDTO> getSelectProcessRoute1(@RequestParam String materilCode) {
return iProcessRouteService.getSelectProcessRoute(materilCode);
}
private void processCombinedDTO(CombinedDTO combinedDTO, List<BomDetails> bomDetailsList, List<ProcessRoute> routeList, List<MaterialBom> materialBoms, String productionOrderNo) {
// 处理工序列表
combinedDTO.getProcesses().forEach(process -> {
ProcessRoute processRoute = createProcessRoute(process, combinedDTO, productionOrderNo);
routeList.add(processRoute);
});
// 处理物料清单
combinedDTO.getMaterialUsageDTOList().forEach(materialUsageDTO -> {
BomDetails bomDetails = createBomDetails(materialUsageDTO, combinedDTO, productionOrderNo);
bomDetailsList.add(bomDetails);
});
// 处理材料BOM
combinedDTO.getMaterialUsageDTOList().forEach(materialUsageDTO -> {
MaterialBom materialBom = creatBomMaterial(materialUsageDTO, combinedDTO, productionOrderNo);
materialBoms.add(materialBom);
});
}
private void processMaterAndRoute(JDMaterialAndRoute materialAndRoute, List<BomDetails> bomDetailsList, List<ProcessRoute> routeList, List<MaterialBom> materialBoms, String productionOrderNo) {
// 处理工序列表
materialAndRoute.getPlannedProcessVos().forEach(processRouteDTO -> {
ProcessRoute processRoute = createProcessRoute1(processRouteDTO, materialAndRoute, productionOrderNo);
routeList.add(processRoute);
});
// 处理物料清单
materialAndRoute.getMaterialUseDTOS().forEach(materialUsageDTO -> {
BomDetails bomDetails = createBomDetails1(materialUsageDTO, materialAndRoute, productionOrderNo);
bomDetailsList.add(bomDetails);
});
// 处理材料BOM
materialAndRoute.getMaterialUseDTOS().forEach(materialUsageDTO -> {
MaterialBom materialBom = creatBomMaterial1(materialUsageDTO, materialAndRoute, productionOrderNo);
materialBoms.add(materialBom);
});
}
private MaterialBom creatBomMaterial1(MaterialUseDTO materialUsageDTO, JDMaterialAndRoute materialAndRoute, String productionOrderNo) {
MaterialBom materialBom = new MaterialBom();
materialBom.setProjectNumber(productionOrderNo);
materialBom.setParentMaterialCode(materialAndRoute.getMaterialCode());
materialBom.setParentMaterialName(materialAndRoute.getMaterialName());
materialBom.setMaterialCode(materialUsageDTO.getMaterialCode());
materialBom.setMaterialName(materialUsageDTO.getMaterialName());
materialBom.setUnit(materialUsageDTO.getChildUnit());
materialBom.setMaterialType(materialUsageDTO.getCaizhi());
//保留四位小数
materialBom.setQuantity(String.valueOf(BigDecimal.valueOf(materialUsageDTO.getFenzi()).divide(new BigDecimal(materialUsageDTO.getFenmu()), 4, RoundingMode.HALF_UP)));
return materialBom;
}
private BomDetails createBomDetails1(MaterialUseDTO materialUsageDTO, JDMaterialAndRoute materialAndRoute, String productionOrderNo) {
BomDetails bomDetails = new BomDetails();
bomDetails.setTotalWeight(productionOrderNo);
bomDetails.setFNumber(materialAndRoute.getMaterialCode());
bomDetails.setFName(materialAndRoute.getMaterialName());
bomDetails.setPartNumber(materialUsageDTO.getMaterialCode());
bomDetails.setUnitWeight("");
bomDetails.setWareHouse(materialUsageDTO.getChildUnit());
//子项分子
bomDetails.setQuantity(String.valueOf(materialUsageDTO.getFenzi()));
//子项分母
bomDetails.setDenominator(Double.valueOf(materialUsageDTO.getFenmu()));
bomDetails.setName(materialUsageDTO.getMaterialName());
bomDetails.setMaterial(materialUsageDTO.getCaizhi());
return bomDetails;
}
private ProcessRoute createProcessRoute1(ProcessRouteDTO processRouteDTO, JDMaterialAndRoute materialAndRoute, String productionOrderNo) {
ProcessRoute processRoute = new ProcessRoute();
// 设置路线描述为生产订单号
processRoute.setRouteDescription(productionOrderNo);
// 设置工序号
processRoute.setProcessNo(processRouteDTO != null ? processRouteDTO.getProcessNo() : null);
// 设置工序名称
processRoute.setProcessName(processRouteDTO != null ? processRouteDTO.getProcessName() : null);
if (materialAndRoute != null && StringUtils.isNotEmpty(materialAndRoute.getMaterialCode())) {
ImMaterial materialByCode = materialService.getMaterialByCode(materialAndRoute.getMaterialCode());
if (materialByCode != null && materialByCode.getSingleWeight() != null) {
processRoute.setDiscWeight(Double.valueOf(String.valueOf(materialByCode.getSingleWeight())));
} else {
processRoute.setDiscWeight(null);
}
} else {
processRoute.setDiscWeight(null);
}
processRoute.setMaterial(materialAndRoute != null ? materialAndRoute.getCaizhi() : null);
// 设置物料代码
processRoute.setMaterialCode(materialAndRoute != null ? materialAndRoute.getMaterialCode() : null);
processRoute.setMaterialName(materialAndRoute != null ? materialAndRoute.getMaterialName() : null);
processRoute.setWorkCenter(processRouteDTO != null ? processRouteDTO.getWorkCenter() : null);
// 基本时长
processRoute.setActivityDuration(processRouteDTO != null ? processRouteDTO.getActivityDuration() : null);
processRoute.setProcessDescription(processRouteDTO != null ? processRouteDTO.getProcessDescription() : null);
processRoute.setProcessControl(processRouteDTO != null ? processRouteDTO.getProcessControl() : null);
processRoute.setXuStartTime(null);
processRoute.setXuEndTime(null);
processRoute.setActivityUnit("");
// 本批数量对应
processRoute.setBatchQuantity(materialAndRoute != null ? materialAndRoute.getBenpi() : null);
if (materialAndRoute != null && materialAndRoute.getDantai() != null) {
processRoute.setFirstBatchQuantity(Double.valueOf(materialAndRoute.getDantai()));
} else {
processRoute.setFirstBatchQuantity(null);
}
List<MaterialUseDTO> materialUsageDTOList = materialAndRoute != null ? materialAndRoute.getMaterialUseDTOS() : null;
if (materialUsageDTOList != null) {
for (MaterialUseDTO materialUsageDTO : materialUsageDTOList) {
if (materialUsageDTO != null) {
processRoute.setUnitQuantity(materialUsageDTO.getFenzi());
processRoute.setBomMaterial(materialUsageDTO.getCaizhi());
processRoute.setRawMaterialCode(materialUsageDTO.getMaterialCode());
processRoute.setRawMaterialName(materialUsageDTO.getMaterialName());
processRoute.setBomUnit(materialUsageDTO.getChildUnit());
if ("".equals(materialUsageDTO.getChildUnit())) {
if (materialUsageDTO.getFenmu() != null) {
processRoute.setDiscUsage(String.valueOf(Double.valueOf(materialUsageDTO.getFenmu())));
} else {
processRoute.setDiscUsage(null);
}
} else {
if (materialUsageDTO.getFenzi() != null && materialUsageDTO.getFenmu() != null && materialUsageDTO.getFenmu() != 0) {
processRoute.setDiscUsage(String.valueOf(materialUsageDTO.getFenzi() / materialUsageDTO.getFenmu()));
} else {
processRoute.setDiscUsage(null);
}
}
processRoute.setMaterial(materialUsageDTO.getCaizhi());
} else {
processRoute.setUnitQuantity(null);
processRoute.setBomMaterial(null);
processRoute.setRawMaterialCode(null);
processRoute.setRawMaterialName(null);
processRoute.setBomUnit(null);
processRoute.setDiscUsage(null);
processRoute.setMaterial(null);
}
}
}
return processRoute;
}
@Log(title = "生成金蝶标准工艺")
@SaCheckPermission("system:route:getKindeeExcel")
@GetMapping("/getKindeeExcel")
public ResponseEntity<String> getKindeeExcel(String rooteProdet) throws IOException {
List<CombinedDTO> planRouteList = iProcessRouteService.getSelecPlanRouteList(rooteProdet);
List<BomDetails> bomDetailsList = new ArrayList<>();
List<ProcessRoute> routeList = new ArrayList<>();
List<MaterialBom> materialBoms = new ArrayList<>();
// 将数据写入excel 中
for (CombinedDTO combinedDTO : planRouteList) {
processCombinedDTO(combinedDTO, bomDetailsList, routeList, materialBoms, rooteProdet);
}
// 批量插入数据库
try {
bomDetailsMapper.insertBatch(bomDetailsList);
baseMapper.insertBatch(routeList);
materialBomMapper.insertBatch(materialBoms);
return ResponseEntity.ok("保存成功");
} catch (Exception e) {
// 处理异常并返回失败信息
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("保存失败: " + e.getMessage());
}
}
private ProcessRoute createProcessRoute(PlannedProcessVo process, CombinedDTO combinedDTO, String productionOrderNo) {
ProcessRoute processRoute = new ProcessRoute();
// 设置路线描述为生产订单号
processRoute.setRouteDescription(productionOrderNo);
// 设置工序号
processRoute.setProcessNo(process.getFOperNumber());
// 设置工序名称
processRoute.setProcessName(process.getFProcessName());
String materialCode = combinedDTO.getMaterialCode();
try {
List<ProcessRoute> singleWeightList = iProcessRouteService.getSingleWeght(materialCode);
if (singleWeightList != null && !singleWeightList.isEmpty()) {
processRoute.setDiscWeight(singleWeightList.get(0).getDiscWeight());
}
} catch (Exception e) {
// 记录日志或采取其他措施
log.error("Error fetching single weight for material code: " + materialCode, e);
}
// 设置物料代码
processRoute.setMaterialCode(combinedDTO.getMaterialCode());
processRoute.setMaterialName(combinedDTO.getMaterialName());
Double fOperQty = process.getFOperQty();
long l = fOperQty.longValue();
processRoute.setWorkCenter(process.getFWorkCenterName());
// 基本时长
processRoute.setActivityDuration(process.getFActivity1BaseQty());
processRoute.setProcessDescription(process.getFOperDescription());
processRoute.setProcessControl(process.getFOptCtrlCodeIFName());
processRoute.setXuStartTime(process.getFSeqPlanStartTime());
processRoute.setXuEndTime(process.getFSeqPlanFinishTime());
processRoute.setActivityUnit("");
// 本批数量对应
processRoute.setBatchQuantity(process.getFMOQty());
List<MaterialUsageDTO> materialUsageDTOList = combinedDTO.getMaterialUsageDTOList();
for (MaterialUsageDTO materialUsageDTO : materialUsageDTOList) {
processRoute.setUnitQuantity(materialUsageDTO.getFNumerator());
processRoute.setBomMaterial(materialUsageDTO.getChildMaterial());
processRoute.setRawMaterialCode(materialUsageDTO.getMaterialCode());
processRoute.setRawMaterialName(materialUsageDTO.getMaterialName());
processRoute.setBomUnit(materialUsageDTO.getUnit());
if (materialUsageDTO.getUnit().equals("")) {
processRoute.setDiscUsage(String.valueOf(materialUsageDTO.getFDenominator()));
} else {
processRoute.setDiscUsage(String.valueOf(materialUsageDTO.getFNumerator() / materialUsageDTO.getFDenominator()));
}
processRoute.setMaterial(materialUsageDTO.getChildMaterial());
}
return processRoute;
}
private BomDetails createBomDetails(MaterialUsageDTO materialUsageDTO, CombinedDTO combinedDTO, String productionOrderNo) {
BomDetails bomDetails = new BomDetails();
bomDetails.setTotalWeight(productionOrderNo);
bomDetails.setFNumber(combinedDTO.getMaterialCode());
bomDetails.setFName(combinedDTO.getMaterialName());
bomDetails.setPartNumber(materialUsageDTO.getMaterialCode());
bomDetails.setUnitWeight("");
bomDetails.setWareHouse(materialUsageDTO.getUnit());
//子项分子
bomDetails.setQuantity(String.valueOf(materialUsageDTO.getFNumerator()));
//子项分母
bomDetails.setDenominator(materialUsageDTO.getFDenominator());
bomDetails.setName(materialUsageDTO.getMaterialName());
if (materialUsageDTO.getItemType().equals("1")) {
bomDetails.setStats("外购");
} else {
bomDetails.setStats("自制");
}
bomDetails.setMaterial(materialUsageDTO.getChildMaterial());
return bomDetails;
}
private MaterialBom creatBomMaterial(MaterialUsageDTO materialUsageDTO, CombinedDTO combinedDTO, String productionOrderNo) {
MaterialBom materialBom = new MaterialBom();
materialBom.setProjectNumber(productionOrderNo);
materialBom.setParentMaterialCode(combinedDTO.getMaterialCode());
materialBom.setParentMaterialName(combinedDTO.getMaterialName());
materialBom.setMaterialCode(materialUsageDTO.getMaterialCode());
materialBom.setMaterialName(materialUsageDTO.getMaterialName());
materialBom.setUnit(materialUsageDTO.getUnit());
materialBom.setMaterialType(materialUsageDTO.getItemType());
materialBom.setQuantity(String.valueOf(BigDecimal.valueOf(materialUsageDTO.getFNumerator())));
return materialBom;
}
/**
* 导出工艺路线列表
*/
@SaCheckPermission("system:route:getAllRouteAndUse")
@Log(title = "获取全部工艺路线和物料清单", businessType = BusinessType.OTHER)
@PostMapping("/getAllRouteAndUse")
public void getAllRouteAndUse(@RequestParam("rooteProdet") String rooteProdet) {
log.info("获取项目生产数据表:{}", rooteProdet);
// 下载Excel模板 (切换为FTP方式)
// SmbUtil.downloadExcelFiles(rooteProdet);
String ftpHost = "192.168.5.18";
String ftpUser = "admin";
String ftpPass = "hbyt2025";
int ftpPort = 21;
String localDir = "D:\\file";
// 假设远程目录结构与SMB一致为 /2026/{rooteProdet}
String remoteDir = "/2026/" + rooteProdet;
R<String> ftpResult = FtpUtil.downloadFtpDirectoryFiles(ftpHost, ftpUser, ftpPass, ftpPort, remoteDir, localDir);
if (R.isError(ftpResult)) {
log.error("FTP下载失败: {}", ftpResult.getMsg());
} else {
log.info("FTP下载结果: {}", ftpResult.getMsg());
}
// 构建Excel文件路径
String ExcelName = "D:\\file\\" + rooteProdet + "汇总表.xlsx";
File file = new File(ExcelName);
if (!file.exists()) {
throw new ServiceException("文件不存在,请确认路径是否正确");
}
//读取file的所有的物料编码
try {
if (file.exists()) {
// 读取Excel的sheet6 从第三行开始 读取到第4列 无数据的跳过
DefaultExcelListener<ProcessRouteGetDTO> listener = new DefaultExcelListener<>(true);
EasyExcel.read(ExcelName, ProcessRouteGetDTO.class, listener).sheet(6).headRowNumber(3).doRead();
List<ProcessRouteGetDTO> list = listener.getExcelResult().getList();
List<JDMaterialAndRoute> list1 = iProcessRouteService.getProcessRouteGD(list, rooteProdet);
List<BomDetails> bomDetailsList = new ArrayList<>();
List<ProcessRoute> routeList = new ArrayList<>();
List<MaterialBom> materialBoms = new ArrayList<>();
for (JDMaterialAndRoute materialAndRoute : list1) {
processMaterAndRoute(materialAndRoute, bomDetailsList, routeList, materialBoms, rooteProdet);
}
bomDetailsMapper.insertBatch(bomDetailsList);
baseMapper.insertBatch(routeList);
materialBomMapper.insertBatch(materialBoms);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 更新生产订单仓库字段
*/
@SaCheckPermission("system:route:updateProductionOrders")
@Log(title = "更新生产订单仓库", businessType = BusinessType.OTHER)
@PostMapping("/updateProductionOrders")
public R updateProductionOrders(@RequestParam("rooteProdet") String rooteProdet, @RequestParam("cangKuNum") String cangKuNum) throws Exception {
//判断此项目是否有
List<String> list = iProcessRouteService.updateProductionOrders(rooteProdet, cangKuNum);
return R.ok(list);
}
/**
* 更新采购申请入库仓库仓库
*/
@SaCheckPermission("system:route:updateProductionOrders")
@Log(title = "更新采购申请单仓库", businessType = BusinessType.OTHER)
@PostMapping("/updateCgOrders")
public R updateCgOrders(@RequestParam("rooteProdet") String rooteProdet, @RequestParam("cangKuNum") String cangKuNum) throws Exception {
//判断此项目是否有
List<String> list = iProcessRouteService.updateCgOrders(rooteProdet, cangKuNum);
return R.ok(list);
}
}