This commit is contained in:
tzy 2025-11-09 19:16:38 +08:00
commit 595ebfb395
18 changed files with 131 additions and 42 deletions

View File

@ -21,17 +21,13 @@ 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.enums.BusinessType;
import com.ruoyi.system.domain.dto.BOMItem;
import com.ruoyi.system.domain.dto.BOMUploadResult;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.common.utils.JdUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.BomDetails;
import com.ruoyi.system.domain.MaterialProperties;
import com.ruoyi.system.domain.ProcessOrderPro;
import com.ruoyi.system.domain.bo.BomDetailsBo;
import com.ruoyi.system.domain.dto.JdValidateBomDTO;
import com.ruoyi.system.domain.dto.JdChildDTO;
import com.ruoyi.system.domain.dto.KindegeeLogDTO;
import com.ruoyi.system.domain.vo.BomDetailsVo;
import com.ruoyi.system.domain.vo.ElectricalMaterialBomVO;
import com.ruoyi.system.mapper.BomDetailsMapper;
@ -418,7 +414,8 @@ public class BomDetailsController extends BaseController {
}
// 第二步BOM校验和上传在循环外部
boolean needUpload = !validateBOM(fnumber, bomDetails);
ValidateBomResult validateResult = validateBOM(fnumber, bomDetails);
boolean needUpload = !validateResult.isMatch();
if (needUpload) {
try {
// 物料清单保存方法,判断是电气还是生产
@ -448,7 +445,7 @@ public class BomDetailsController extends BaseController {
logDTO.setProjectCode(bo.getProductionOrderNo());
logDTO.setMaterialCode(fnumber);
logDTO.setCode("100");
logDTO.setReason("BOM已存在且一致");
logDTO.setReason("BOM已存在且一致,版本号:" + validateResult.getVersion());
logDTOS.add(logDTO);
log.info("BOM已存在且一致物料编码: {},跳过保存", fnumber);
}
@ -465,12 +462,13 @@ public class BomDetailsController extends BaseController {
}
private boolean validateBOM(String fnumber, List<BomDetails> bomDetails) {
private ValidateBomResult validateBOM(String fnumber, List<BomDetails> bomDetails) {
List<JdValidateBomDTO> JDBomList = JdUtil.getSelectBomList(fnumber);
if (JDBomList == null || JDBomList.isEmpty()) {
log.error("未在金蝶中找到相同的BOM需要上传物料编码: {}", fnumber);
return false;
return ValidateBomResult.notMatched();
}
// 子项排序 PartNumber -> Name -> PartdiagramCode -> PartdiagramName 保证顺序唯一
@ -575,12 +573,13 @@ public class BomDetailsController extends BaseController {
if (isMatch) {
log.info("BOM完全相同物料编码: {},无需上传", fnumber);
return true; // 找到匹配BOM
// 记录BOM版本号
return ValidateBomResult.matched(jdBom.getFNumberVersion());
}
}
log.info("BOM不存在或不一致物料编码: {},需要上传", fnumber);
return false; // 所有BOM都不匹配
return ValidateBomResult.notMatched(); // 所有BOM都不匹配
}
// null/空格统一处理方法
@ -2229,7 +2228,7 @@ public class BomDetailsController extends BaseController {
@Log(title = "推送工艺工序")
@SaCheckPermission("system:route:viewGetBomUploadStatus")
@PostMapping("/viewGetBomUploadStatus")
public R<BOMItem> viewGetBomUploadStatus(@RequestParam String rooteProdet) {
public R<String> viewGetBomUploadStatus(@RequestParam String rooteProdet) {
return iProcessRouteService.viewGetBomUploadStatus(rooteProdet);
}

View File

@ -7,6 +7,7 @@ import java.text.SimpleDateFormat;
import java.util.*;
import com.alibaba.excel.EasyExcel;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ruoyi.common.excel.DefaultExcelListener;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
@ -17,6 +18,7 @@ import com.ruoyi.common.poi.DynamicDataMapping;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.FigureSaveBo;
import com.ruoyi.system.domain.dto.ProcessRouteExcelDTO;
import com.ruoyi.system.domain.dto.ProcessRoutePushResultDTO;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.domain.vo.BomDataVO;
import com.ruoyi.system.mapper.ProcessOrderProMapper;
@ -356,6 +358,15 @@ public class ProcessOrderProController extends BaseController {
return iMrpResultCheckService.getMRPResults(id);
}
@SaCheckPermission("system:orderPro:geMRPResults")
@Log(title = "获取工艺上传结果", businessType = BusinessType.OTHER)
@PostMapping("/getRouteLog/{id}")
public R<String> getRouteLog(@PathVariable Long id) throws JsonProcessingException {
return iProcessOrderProService.getRouteLog(id);
}
@SaCheckPermission("system:route:exportRoute")
@Log(title = "下载工艺生产表", businessType = BusinessType.EXPORT)
@PostMapping("/exportRoute")

View File

@ -76,6 +76,13 @@ public class ProcessRouteController extends BaseController {
return originalId + 1000;
}
@Log(title = "查看BOM上传状态")
@SaCheckPermission("system:route:viewGetBomUploadStatus")
@PostMapping("/viewGetBomUploadStatus")
public R<String> viewGetBomUploadStatus(@RequestParam String rooteProdet) {
return iProcessRouteService.viewGetBomUploadStatus(rooteProdet);
}
/**
* 主动更新可用库存
*/

View File

@ -87,4 +87,9 @@ public class ProcessOrderPro extends BaseEntity {
* 工艺状态(0,未完成 1,完成 2已上传)
*/
private Long routeStatus;
/**
* 工艺上传日志
*/
private String routeLog;
}

View File

@ -106,5 +106,9 @@ public class ProcessOrderProBo extends BaseEntity {
* 工艺状态(0,未完成 1,完成 2已上传)
*/
private Long routeStatus;
/**
* 工艺上传日志
*/
private String routeLog;
}

View File

@ -4,16 +4,20 @@ import lombok.Data;
@Data
public class BOMUploadResult {
private boolean success; // 是否成功
private boolean success; // 是否成功兼容旧逻辑
private String id; // 金蝶内部ID
private String number; // 单据编号
private String errorMessage; // 错误信息失败时才有
private String number; // 单据编号用于记录版本号
private String errorMessage; // 错误信息失败时才有兼容旧逻辑
private String code; // 结果编码200=成功上传100=已存在且一致300=上传失败
private String msg; // 结果说明或错误消息
public static BOMUploadResult success(String id, String number) {
BOMUploadResult result = new BOMUploadResult();
result.setSuccess(true);
result.setId(id);
result.setNumber(number);
result.setCode("200");
result.setMsg("成功");
return result;
}
@ -21,6 +25,8 @@ public class BOMUploadResult {
BOMUploadResult result = new BOMUploadResult();
result.setSuccess(false);
result.setErrorMessage(errorMessage);
result.setCode("300");
result.setMsg(errorMessage);
return result;
}
}

View File

@ -17,6 +17,11 @@ public class JdValidateBomDTO {
*/
@JsonProperty("FMATERIALID.FNumber")
private String fNumber;
/**
* bom版本
*/
@JsonProperty("FNumber")
private String fNumberVersion;
/**
* 父级物料名称
*/

View File

@ -12,7 +12,7 @@ public class OperationPlannDTO {
@JsonProperty("FOperQty")
private String FOperQty;
@JsonProperty("FOutProcessId.FName")
@JsonProperty("FProcessId.FName")
private String FProcessIdFName;
}

View File

@ -1,12 +1,17 @@
package com.ruoyi.system.domain.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ProcessRoutePushResultDTO {
private List<ProcessRouteXuDTO> successfulRoutes;
private List<ProcessRouteXuDTO> failedRoutes;
private List<String> duplicateRoutes;
private Date time;
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.system.domain.dto;
import lombok.Data;
@Data
public class ValidateBomResult {
// 是否存在且一致
private boolean match;
// 一致的BOM版本号来自金蝶的FNumber不存在或不一致时可为空
private String version;
public static ValidateBomResult matched(String version) {
ValidateBomResult r = new ValidateBomResult();
r.setMatch(true);
r.setVersion(version);
return r;
}
public static ValidateBomResult notMatched() {
ValidateBomResult r = new ValidateBomResult();
r.setMatch(false);
r.setVersion(null);
return r;
}
}

View File

@ -2,11 +2,9 @@ package com.ruoyi.system.domain.vo;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;

View File

@ -116,5 +116,9 @@ public class ProcessOrderProVo {
private String drawingPathUrl;
private Date createTime;
/**
* 工艺上传日志
*/
@ExcelProperty(value = "工艺上传日志")
private String routeLog;
}

View File

@ -2211,7 +2211,7 @@ public class JdUtil {
json.addProperty("FormId", "ENG_BOM");
json.addProperty("FieldKeys",
"FID,FMATERIALID.FNumber,FITEMNAME,FUNITID.FName,FCHILDITEMNAME,FCHILDITEMPROPERTY,FMATERIALIDCHILD.FNumber,FNUMERATOR,FDENOMINATOR,F_HBYT_BJBM,F_HBYT_BJMC");
"FID,FMATERIALID.FNumber,FNumber,FITEMNAME,FUNITID.FName,FCHILDITEMNAME,FCHILDITEMPROPERTY,FMATERIALIDCHILD.FNumber,FNUMERATOR,FDENOMINATOR,F_HBYT_BJBM,F_HBYT_BJMC");
JsonArray filterString = new JsonArray();
JsonObject filterObject = new JsonObject();
filterObject.addProperty("FieldName", "FMATERIALID.FNumber");
@ -2295,11 +2295,14 @@ public class JdUtil {
String key = obj.get("FID").getAsString() + "_" +
obj.get("FMATERIALID.FNumber").getAsString() + "_" +
obj.get("FNumber").getAsString() + "_" +
obj.get("FITEMNAME").getAsString();
JdValidateBomDTO parentDTO = bomMap.computeIfAbsent(key, k -> {
JdValidateBomDTO dto = new JdValidateBomDTO();
dto.setFID(obj.get("FID").getAsString());
dto.setFNumber(obj.get("FMATERIALID.FNumber").getAsString());
// 记录BOM版本号金蝶返回的 FNumber 字段
dto.setFNumberVersion(obj.get("FNumber").getAsString());
dto.setFName(obj.get("FITEMNAME").getAsString());
dto.setChilds(new ArrayList<>());
return dto;

View File

@ -1,10 +1,14 @@
package com.ruoyi.system.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.MrpResultCheck;
import com.ruoyi.system.domain.ProcessOrderPro;
import com.ruoyi.system.domain.ProcessRoute;
import com.ruoyi.system.domain.bo.FigureSaveBo;
import com.ruoyi.system.domain.dto.ProcessRouteExcelDTO;
import com.ruoyi.system.domain.dto.ProcessRoutePushResultDTO;
import com.ruoyi.system.domain.dto.ProcessRouteXuDTO;
import com.ruoyi.system.domain.vo.OverdueProjectVo;
import com.ruoyi.system.domain.vo.ProcessOrderProVo;
import com.ruoyi.system.domain.bo.ProcessOrderProBo;
@ -79,4 +83,6 @@ public interface IProcessOrderProService {
List<OverdueProjectVo> getOverdueProjects();
List<ProcessRouteExcelDTO> getRouteAndBomDetail(List<ProcessRoute> routlist,List<ProductionOrderVo> processDataList,ProcessOrderPro orderPro);
R<String> getRouteLog(Long id) throws JsonProcessingException;
}

View File

@ -145,7 +145,7 @@ public interface IProcessRouteService {
List<ProcessRoute> selectByProjectNumber(String productionOrderNo);
R<BOMItem> viewGetBomUploadStatus(String rooteProdet);
R<String> viewGetBomUploadStatus(String rooteProdet);
//根据令号和物料编码 查询工艺路线
ProcessRoute getProcessRoutesXuTime(String productionOrderNo, String materialCode,String xu);

View File

@ -1,9 +1,13 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfReader;
import com.ruoyi.common.constant.Constants;
@ -21,6 +25,7 @@ import com.ruoyi.common.utils.file.PDFDocHelper;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.FigureSaveBo;
import com.ruoyi.system.domain.dto.ProcessRouteExcelDTO;
import com.ruoyi.system.domain.dto.ProcessRoutePushResultDTO;
import com.ruoyi.system.domain.dto.excuteDrawing.DataInfo;
import com.ruoyi.system.domain.dto.excuteDrawing.ProductInfo;
import com.ruoyi.system.domain.dto.excuteDrawing.PwProductionBill;
@ -45,7 +50,7 @@ import com.ruoyi.system.mapper.ProcessOrderProMapper;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.core.type.TypeReference;
import java.io.*;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
@ -1273,6 +1278,17 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService {
return resultList;
}
/**
* @param id
* @return
*/
@Override
public R<String> getRouteLog(Long id) throws JsonProcessingException {
ProcessOrderPro processOrderPro = baseMapper.selectById(id);
String jsonStr = processOrderPro.getRouteLog();
return R.ok(jsonStr == null ? "" : jsonStr);
}
public static String[] getNullPropertyNames(Object source) {
BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

View File

@ -296,17 +296,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
}
/**
* 获取bom的上传状态
* 获取bom的上传状态直接返回原始 JSON 字符串前端自行解析
*/
@Override
public R<BOMItem> viewGetBomUploadStatus(String rooteProdet) {
public R<String> viewGetBomUploadStatus(String rooteProdet) {
ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(rooteProdet);
String drawingType = processOrderPro.getDrawingType(); // 这里就是 JSON
// 转换 JSON 数组 -> List<BOMItem>
List<KindegeeLogDTO> bomItems = JSONUtil.toList(drawingType, KindegeeLogDTO.class);
BOMItem result = new BOMItem();
result.setItems(bomItems);
return R.ok(result);
String drawingType = processOrderPro == null ? null : processOrderPro.getDrawingType();
return R.ok(drawingType == null ? "" : drawingType);
}
/**
@ -786,12 +782,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
} else if ("".equals(unit) && quantity.contains("/")) {
//写入工艺表时分数的体现 直接取分母 "/"为分割符,取第二个字符串
materialBom.setQuantity(quantity);
} else {
} else if(!"".equals(unit)&&quantity.contains("/") ){
//
throw new RuntimeException("单位不为根的时候不能为分数");
}else {
// 其他单位直接使用原值保留2位小数
materialBom.setQuantity(String.valueOf(new BigDecimal(quantity).setScale(2, RoundingMode.HALF_UP)));
}
// 这里插入 materialBom 数据
materialBomMapper.insert(materialBom);
}
@ -1269,14 +1266,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
Map<String, List<ProcessRouteSelectDTO>> groupedByFNumber = jdProcessRoute.stream().collect(Collectors.groupingBy(ProcessRouteSelectDTO::getFNumber));
// 当前物料的工艺路线
List<ProcessRouteDTO> processRouteDT = processRouteXuDTO.getProcessRouteDT();
/*boolean hasDuplicate = processRouteDT.stream()
.map(ProcessRouteDTO::getProcessNo) // 取出所有 processNo
.filter(Objects::nonNull) // 避免空指针
.collect(Collectors.toSet()) // 放进 Set
.size() < processRouteDT.size();
if (hasDuplicate){
return R.fail("工序号重复请检查!");
}*/
// 比较工艺路线
boolean isDifferent = compareProcessRoutes(processRouteDT, groupedByFNumber);
if (isDifferent) {
@ -1300,12 +1290,16 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
}
// 封装结果
ProcessRoutePushResultDTO resultDTO = new ProcessRoutePushResultDTO();
resultDTO.setTime(new Date());
resultDTO.setSuccessfulRoutes(successfulRoutes);
resultDTO.setFailedRoutes(failedRoutes);
resultDTO.setDuplicateRoutes(duplicateRoutes);
String jsonStr = JSONUtil.toJsonStr(resultDTO);
ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(rooteProdet);
//更新项目状态 推送工艺
processOrderPro.setBomStatus(3L);
processOrderPro.setRouteLog(jsonStr);
log.info("<UNK>: " + jsonStr);
processOrderProMapper.updateById(processOrderPro);
return R.ok(resultDTO);
}

View File

@ -24,6 +24,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="drawingPath" column="drawing_path"/>
<result property="bomStatus" column="bom_status"/>
<result property="routeStatus" column="route_status"/>
<result property="routeLog" column="route_log"/>
</resultMap>
<!-- 根据项目编号查询 -->
<select id="selectByProjectNumber" resultType="com.ruoyi.system.domain.ProcessOrderPro">