*企业微信推送
*bom Jiaoyan日志
This commit is contained in:
parent
6abb92c321
commit
5a3739b2bc
@ -167,6 +167,12 @@
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15to18</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hierynomus</groupId>
|
||||
<artifactId>smbj</artifactId>
|
||||
<version>0.14.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PDF -->
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
|
||||
@ -34,6 +34,8 @@ public class SecurityConfig {
|
||||
.antMatchers("/system/proPlan/**").anonymous()
|
||||
.antMatchers("/system/mrp/**").anonymous()
|
||||
.antMatchers("/system/orderPro/**").anonymous()
|
||||
.antMatchers("/system/cost/**").anonymous()
|
||||
.antMatchers("/dev-api/system/cost/**").anonymous()
|
||||
// .antMatchers("/dev-api/system/proPlan/overdue").anonymous()
|
||||
// .antMatchers("/dev-api/system/proPlan/expiryProjects").anonymous()
|
||||
.antMatchers("/dev-api/system/material/list/").anonymous()
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<artifactId>ruoyi-vue-plus</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.7.0</version>
|
||||
</parent>
|
||||
</parent><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin></plugins></build>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
|
||||
@ -21,21 +21,20 @@ 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.common.result.BOMUploadResult;
|
||||
import com.ruoyi.system.domain.dto.BOMItem;
|
||||
import com.ruoyi.system.domain.dto.BOMUploadResult;
|
||||
import com.ruoyi.common.utils.JdUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.domain.BomDetails;
|
||||
import com.ruoyi.system.domain.FigureSave;
|
||||
import com.ruoyi.system.domain.MaterialProperties;
|
||||
import com.ruoyi.system.domain.ProcessOrderPro;
|
||||
import com.ruoyi.system.domain.bo.BomDetailsBo;
|
||||
import com.ruoyi.system.domain.bo.ProcessOrderProBo;
|
||||
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.FigureSaveMapper;
|
||||
import com.ruoyi.system.mapper.BomDetailsMapper;
|
||||
import com.ruoyi.system.mapper.ProcessOrderProMapper;
|
||||
import com.ruoyi.system.runner.JdUtil;
|
||||
import com.ruoyi.system.service.*;
|
||||
@ -45,8 +44,6 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -84,8 +81,10 @@ public class BomDetailsController extends BaseController {
|
||||
|
||||
private final IProcessOrderProService iProcessOrderProService;
|
||||
|
||||
private final IFigureSaveService iFigureSaveService;
|
||||
private final ProcessOrderProMapper processOrderProMapper;
|
||||
|
||||
private final BomDetailsMapper bomDetailsMapper;
|
||||
|
||||
/**
|
||||
* 查询bom明细列表
|
||||
*/
|
||||
@ -382,27 +381,38 @@ public class BomDetailsController extends BaseController {
|
||||
for (BomDetails material : bomDetails) {
|
||||
// 获取工艺表中的非委外工时
|
||||
Double fbWorkTime = iProcessRouteService.getFbWorkTime(material);
|
||||
|
||||
if (material.getPartNumber() != null && material.getName() != null && material.getUnitWeight().equals("否")) {
|
||||
String state = determineState(material);
|
||||
log.info("开始新增不存在的物料 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
try {
|
||||
int result = loadMaterialPreservation(material, state, fbWorkTime);
|
||||
if (result == 1) {
|
||||
log.info("新增物料成功 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
material.setUnitWeight("新增成功");
|
||||
} else {
|
||||
log.error("新增物料失败 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
//判断bom类型是生产还是电气
|
||||
if (material.getBomType().equals("0")) {
|
||||
try {
|
||||
int result = loadMaterialPreservation(material, state, fbWorkTime);
|
||||
if (result == 1) {
|
||||
material.setUnitWeight("新增成功");
|
||||
} else {
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
// 更新物料状态
|
||||
iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class));
|
||||
} catch (Exception e) {
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
int result = loadMaterialToDQ(material, state);
|
||||
if (result == 1) {
|
||||
material.setUnitWeight("新增成功");
|
||||
} else {
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
// 更新物料状态
|
||||
iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class));
|
||||
} catch (Exception e) {
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
// 更新物料状态
|
||||
iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class));
|
||||
} catch (Exception e) {
|
||||
log.error("处理物料时发生异常: {}", e.getMessage());
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
|
||||
} else {
|
||||
log.error("物料信息不完整,无法新增物料");
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
}
|
||||
@ -411,22 +421,20 @@ public class BomDetailsController extends BaseController {
|
||||
boolean needUpload = !validateBOM(fnumber, bomDetails);
|
||||
if (needUpload) {
|
||||
try {
|
||||
// 物料清单保存方法
|
||||
// 物料清单保存方法,判断是电气还是生产
|
||||
BOMUploadResult bomUploadResult = FBloadBillOfMaterialsPreservation(bomDetails, bo);
|
||||
if (bomUploadResult.isSuccess()) {
|
||||
KindegeeLogDTO logDTO = new KindegeeLogDTO();
|
||||
logDTO.setProjectCode(bo.getProductionOrderNo());
|
||||
logDTO.setMaterialCode(fnumber); // 使用物料编码而不是单个物料的编码
|
||||
logDTO.setMaterialName(fname);
|
||||
logDTO.setCode(bomUploadResult.getNumber());
|
||||
logDTO.setReason(bomUploadResult.getNumber()+"OK");
|
||||
logDTO.setCode("200");
|
||||
logDTO.setReason("成功上传"+"版本号:"+bomUploadResult.getNumber());
|
||||
logDTOS.add(logDTO);
|
||||
} else {
|
||||
KindegeeLogDTO logDTO = new KindegeeLogDTO();
|
||||
logDTO.setProjectCode(bo.getProductionOrderNo());
|
||||
logDTO.setMaterialCode(fnumber);
|
||||
logDTO.setMaterialName(fname);
|
||||
logDTO.setCode(bomUploadResult.getNumber());
|
||||
logDTO.setCode("300");
|
||||
logDTO.setReason(bomUploadResult.getErrorMessage());
|
||||
logDTOS.add(logDTO);
|
||||
}
|
||||
@ -439,8 +447,7 @@ public class BomDetailsController extends BaseController {
|
||||
KindegeeLogDTO logDTO = new KindegeeLogDTO();
|
||||
logDTO.setProjectCode(bo.getProductionOrderNo());
|
||||
logDTO.setMaterialCode(fnumber);
|
||||
logDTO.setMaterialName(fname);
|
||||
logDTO.setCode("200");
|
||||
logDTO.setCode("100");
|
||||
logDTO.setReason("BOM已存在且一致");
|
||||
logDTOS.add(logDTO);
|
||||
log.info("BOM已存在且一致,物料编码: {},跳过保存", fnumber);
|
||||
@ -450,13 +457,14 @@ public class BomDetailsController extends BaseController {
|
||||
//更新项目进度
|
||||
ProcessOrderPro processOrderProBo = iProcessOrderProService.selectByProjectNumber(totalWeight);
|
||||
|
||||
processOrderProBo.setDrawingType( JSONUtil.toJsonStr(logDTOS));
|
||||
processOrderProBo.setDrawingType(JSONUtil.toJsonStr(logDTOS));
|
||||
processOrderProBo.setBomStatus(2L);
|
||||
processOrderProMapper.updateById(processOrderProBo);
|
||||
// 返回处理结果
|
||||
return R.ok("成功", bomDetailsList);
|
||||
|
||||
}
|
||||
|
||||
private boolean validateBOM(String fnumber, List<BomDetails> bomDetails) {
|
||||
List<JdValidateBomDTO> JDBomList = JdUtil.getSelectBomList(fnumber);
|
||||
|
||||
@ -701,7 +709,7 @@ public class BomDetailsController extends BaseController {
|
||||
}
|
||||
|
||||
// FBOM物料清单保存
|
||||
public BOMUploadResult FBloadBillOfMaterialsPreservation(List<BomDetails> bomlist, ProcessOrderPro bo) {
|
||||
public BOMUploadResult FBloadBillOfMaterialsPreservation(List<BomDetails> bomlist, ProcessOrderPro bo) {
|
||||
|
||||
BomDetails bomDetails1 = bomlist.get(0);
|
||||
int verification = isMaterialVerification(bomDetails1.getFNumber(), bomDetails1.getFName());
|
||||
@ -805,9 +813,7 @@ public class BomDetailsController extends BaseController {
|
||||
fTreeEntityItem.addProperty("F_HBYT_BJBM", details.getPartdiagramCode());
|
||||
fTreeEntityItem.addProperty("F_HBYT_BJMC", details.getPartdiagramName());
|
||||
fTreeEntityItem.addProperty("FDOSAGETYPE", "2");
|
||||
//判断这个在原材料表中单位如果是根,的话 那分子就是1 分母就是分子
|
||||
|
||||
fTreeEntityItem.addProperty("FNUMERATOR", details.getQuantity());
|
||||
fTreeEntityItem.addProperty("FNUMERATOR", details.getQuantity()); // 分子
|
||||
fTreeEntityItem.addProperty("FDENOMINATOR", details.getDenominator());
|
||||
|
||||
// 添加货主信息 查看这个bom中是否符合货主信息
|
||||
@ -1724,7 +1730,10 @@ public class BomDetailsController extends BaseController {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 创建电气物料
|
||||
/**
|
||||
* / 创建电气物料
|
||||
*/
|
||||
|
||||
public int loadMaterialToDQ(BomDetails bomDetails1, String states) {
|
||||
K3CloudApi client = new K3CloudApi();
|
||||
// 创建一个空的JsonObject
|
||||
@ -1738,7 +1747,8 @@ public class BomDetailsController extends BaseController {
|
||||
|
||||
// 添加Model字段
|
||||
model.addProperty("FMATERIALID", 0);
|
||||
model.addProperty("FSpecification", bomDetails1.getRemarks());// 备注仓库
|
||||
model.addProperty("FSpecification", bomDetails1.getMaterial());// 规格 为存入的材质字段
|
||||
model.addProperty("F_HBYT_PP", bomDetails1.getWareHouse());// 品牌 为存入的仓库字段
|
||||
model.addProperty("FNumber", bomDetails1.getPartNumber());
|
||||
model.addProperty("FName", bomDetails1.getName());
|
||||
MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails1.getMaterial());
|
||||
@ -2108,10 +2118,9 @@ public class BomDetailsController extends BaseController {
|
||||
subHeadEntity1.add("FPickStockId", fPickStockId);
|
||||
|
||||
subHeadEntity5.addProperty("FOverControlMode", "1");
|
||||
subHeadEntity5.addProperty("FStandHourUnitId", "3600");
|
||||
subHeadEntity5.addProperty("FStandHourUnitId", "60");
|
||||
subHeadEntity5.addProperty("FBackFlushType", "1");
|
||||
String jsonData = json.toString();
|
||||
System.out.println(jsonData);
|
||||
try {
|
||||
// 业务对象标识
|
||||
String formId = "BD_MATERIAL";
|
||||
@ -2135,6 +2144,7 @@ public class BomDetailsController extends BaseController {
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public BOMUploadResult parseK3Response(String jsonResponse) {
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
@ -2166,20 +2176,61 @@ public class BomDetailsController extends BaseController {
|
||||
* @param file 导入文件
|
||||
*/
|
||||
|
||||
@Log(title = "明细导入", businessType = BusinessType.IMPORT)
|
||||
@SaCheckPermission("system:details:import")
|
||||
@PostMapping(value = "/importData21", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public R<Void> importData21(@RequestPart("file") MultipartFile file) throws Exception {
|
||||
@Log(title = "导入电气bom", businessType = BusinessType.IMPORT)
|
||||
@SaCheckPermission("system:details:importElectricalBom")
|
||||
@PostMapping(value = "/importElectricalBom", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public void importElectricalBom(@RequestPart("file") MultipartFile file) throws Exception {
|
||||
List<ElectricalMaterialBomVO> electricalMaterialBomVOS = ExcelUtil.importExcel(file.getInputStream(), ElectricalMaterialBomVO.class);
|
||||
List<BomDetails> list = new ArrayList<>();
|
||||
for (ElectricalMaterialBomVO bomVO : electricalMaterialBomVOS) {
|
||||
BomDetails bomDetails = new BomDetails();
|
||||
bomDetails.setTotalWeight(bomVO.getProductionOrderNo());
|
||||
bomDetails.setFNumber(bomVO.getDrawingNo());
|
||||
bomDetails.setFName(bomVO.getDrawingName());
|
||||
bomDetails.setPartdiagramCode(bomVO.getParentDrawingNo());
|
||||
bomDetails.setPartdiagramName(bomVO.getParentPart());
|
||||
bomDetails.setFNumber(bomVO.getParentDrawingNo());
|
||||
bomDetails.setFName(bomVO.getParentPart());
|
||||
bomDetails.setPartNumber(bomVO.getDrawingNo());
|
||||
bomDetails.setName(bomVO.getDrawingName());
|
||||
bomDetails.setMaterial(bomVO.getModel());//
|
||||
bomDetails.setWareHouse(bomVO.getBrand());
|
||||
bomDetails.setStats("外购");
|
||||
String quantity = bomVO.getQuantity().toString();
|
||||
bomDetails.setQuantity(quantity);
|
||||
bomDetails.setRemarks(bomVO.getUnit());
|
||||
bomDetails.setUpdateTime(new Date());
|
||||
bomDetails.setBomType("1");//0 是生产bom 1 是电气bom
|
||||
list.add(bomDetails);
|
||||
}
|
||||
return null;
|
||||
List<BomDetailsVo> bomDetailsVos1 = BeanUtil.copyToList(list, BomDetailsVo.class);
|
||||
List<BomDetails> bomDetails = saveBomDetails(bomDetailsVos1);
|
||||
bomDetailsMapper.insertBatch(bomDetails);
|
||||
|
||||
}
|
||||
|
||||
// 保存到 BomDetails 表中
|
||||
//TODO: 使用本地库加速
|
||||
private List<BomDetails> saveBomDetails(List<BomDetailsVo> bomDetailsVos) {
|
||||
List<BomDetails> materialsToAdd = new ArrayList<>();
|
||||
for (BomDetailsVo bomDetailsVo : bomDetailsVos) {
|
||||
BomDetails bomDetails = BeanUtil.toBean(bomDetailsVo, BomDetails.class);
|
||||
// 验证物料是否存在
|
||||
int materialVerification = isMaterialVerification(bomDetails.getPartNumber(), bomDetails.getName());
|
||||
if (materialVerification == 1) {
|
||||
bomDetails.setUnitWeight("是");
|
||||
materialsToAdd.add(bomDetails);
|
||||
} else if (materialVerification == 2) {
|
||||
bomDetails.setUnitWeight("否");
|
||||
materialsToAdd.add(bomDetails);
|
||||
} else if (materialVerification == 3) {
|
||||
bomDetails.setUnitWeight("编码名称不符");
|
||||
materialsToAdd.add(bomDetails);
|
||||
}
|
||||
}
|
||||
return materialsToAdd;
|
||||
}
|
||||
@Log(title = "推送工艺工序")
|
||||
@SaCheckPermission("system:route:viewGetBomUploadStatus")
|
||||
@PostMapping("/viewGetBomUploadStatus")
|
||||
public R<BOMItem> viewGetBomUploadStatus(@RequestParam String rooteProdet) {
|
||||
return iProcessRouteService.viewGetBomUploadStatus(rooteProdet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ public class BomVariableController extends BaseController {
|
||||
if (decimalIndex != -1) {
|
||||
quantityStr = quantityStr.substring(0, decimalIndex);
|
||||
}
|
||||
bomDetails.setQuantity(Double.valueOf(quantityStr));
|
||||
bomDetails.setQuantity(quantityStr);
|
||||
}
|
||||
// 检查并转换单重
|
||||
if (!rowData.get(5).isEmpty()) {
|
||||
|
||||
@ -271,7 +271,7 @@ public class ImMaterialController extends BaseController {
|
||||
@XxlJob("updateMaterials")
|
||||
public Boolean updateMaterials() throws Exception {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
List<ImMaterial> imMaterials = updateJdMaterial(sdf.format(date));
|
||||
Boolean result = iImMaterialService.updateByFMid(imMaterials);
|
||||
return result;
|
||||
|
||||
@ -2,8 +2,10 @@ package com.ruoyi.system.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
@ -19,12 +21,14 @@ import com.ruoyi.common.utils.HttpRequestUtil;
|
||||
import com.ruoyi.common.utils.WxRobotUtil;
|
||||
import com.ruoyi.common.poi.ExcelTemplateProc;
|
||||
import com.ruoyi.common.poi.DynamicDataMapping;
|
||||
import com.ruoyi.system.domain.ProcessRoute;
|
||||
import com.ruoyi.system.domain.SafetyStock;
|
||||
import com.ruoyi.system.domain.WlStockData;
|
||||
import com.ruoyi.system.domain.dto.*;
|
||||
import com.ruoyi.system.domain.vo.WlStockDataVo;
|
||||
import com.ruoyi.system.mapper.WlStockDataMapper;
|
||||
import com.ruoyi.system.runner.JdUtil;
|
||||
import com.ruoyi.system.service.IProcessRouteService;
|
||||
import com.ruoyi.system.service.ISafetyStockService;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -39,6 +43,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||
@ -74,7 +79,8 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
private static final Logger log = LoggerFactory.getLogger(KingdeeWorkCenterDataController.class);
|
||||
private final WlStockDataMapper baseMapper;
|
||||
private final ISafetyStockService iSafetyStockService;
|
||||
|
||||
@Autowired
|
||||
IProcessRouteService iProcessRouteService;
|
||||
/**
|
||||
* 查询金蝶工段数据列表
|
||||
*/
|
||||
@ -381,8 +387,9 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
msg.append("- ").append(workCenter).append(" (无数据)\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
List<KingdeeWorkCenterDataBo> dataList = result.getData();
|
||||
//加入暂停项目的过滤
|
||||
List<KingdeeWorkCenterDataBo> dataList = result.getData().stream().filter(item -> item.getMoOrderNo() != null && !item.getMoOrderNo().contains("暂停"))
|
||||
.collect(Collectors.toList());
|
||||
msg.append("- ").append(workCenter).append(" (共").append(dataList.size()).append("条数据)\n");
|
||||
|
||||
// 生成Excel文件
|
||||
@ -433,10 +440,8 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
List<KingdeeWorkCenterDataBo> kingdeeWorkCenterDataVos = new ArrayList<>();
|
||||
parameter.addProperty("FWorkCenterName", workCenter);
|
||||
Object[] parameters = new Object[]{parameter.toString()};
|
||||
String execute = client.execute(
|
||||
"Ljint.Kingdee.YiTe.KanBan.WebApi.ProduceWebApi.ExecuteService,Ljint.Kingdee.YiTe.KanBan.WebApi",
|
||||
parameters);
|
||||
log.info("金蝶接口返回数据: {}", execute);
|
||||
String execute = client.execute("Ljint.Kingdee.YiTe.KanBan.WebApi.ProduceWebApi.ExecuteService,Ljint.Kingdee.YiTe.KanBan.WebApi121303", parameters);
|
||||
log.info("金蝶接口:" + workCenter + "===> 返回数据: {}", execute);
|
||||
|
||||
// 解析响应
|
||||
JSONObject response = JSONObject.parseObject(execute);
|
||||
@ -444,7 +449,6 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
String errorMsg = response.getString("Message");
|
||||
return R.fail("获取工段数据失败:" + errorMsg);
|
||||
}
|
||||
|
||||
// 获取明天的日期字符串 (格式: yyyy-MM-dd)
|
||||
String yesterday = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd");
|
||||
|
||||
@ -518,26 +522,30 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
public R<Void> getMassageDelayDate() {
|
||||
try {
|
||||
// String robotId = "4d2f037d-0cee-493a-a4ff-1758f67b8069";
|
||||
String robotId = "483489b2-b219-468c-851f-f56a34a62d91";
|
||||
String robotId = "483489b2-b219-468c-851f-f56a34a62d91";
|
||||
// String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e";
|
||||
List<String> workCenters = Arrays.asList("机一工段", "机二工段", "机三工段", "装一工段", "装二工段", "委外中心", "电钳工段", "铆焊工段");
|
||||
|
||||
String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss");
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("🏭 延期数据更新提醒\n\n")
|
||||
.append("更新时间:").append(currentTime).append("\n\n")
|
||||
.append("🔧 工作中心数据统计:\n");
|
||||
// 构建Markdown消息
|
||||
StringBuilder markdownMsg = new StringBuilder();
|
||||
markdownMsg.append("# 生产延期数据更新提醒\n\n")
|
||||
.append("> **统计时间:** <font color=\"info\">").append(currentTime).append("</font>\n\n")
|
||||
.append("## 🔧 工作中心数据统计:\n");
|
||||
|
||||
// 获取并统计每个工段的数据
|
||||
for (String workCenter : workCenters) {
|
||||
try {
|
||||
R<List<KingdeeWorkCenterDataBo>> result = getKingdeeDelayData(workCenter);
|
||||
List<KingdeeWorkCenterDataBo> data = result.getData();
|
||||
if (R.isError(result) || CollUtil.isEmpty(result.getData())) {
|
||||
msg.append("- ").append(workCenter).append(" (无数据)\n");
|
||||
markdownMsg.append("- ").append(workCenter).append(":<font color=\"comment\">无数据</font>\n");
|
||||
continue;
|
||||
}
|
||||
List<KingdeeWorkCenterDataBo> dataList = result.getData().stream().filter(item -> item.getMoOrderNo() != null && !item.getMoOrderNo().contains("暂停"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<KingdeeWorkCenterDataBo> dataList = result.getData();
|
||||
msg.append("- ").append(workCenter).append(" (共").append(dataList.size()).append("条数据)\n");
|
||||
markdownMsg.append("- ").append(workCenter).append(":共 <font color=\"warning\">").append(dataList.size()).append("</font> 条\n");
|
||||
|
||||
// 生成Excel文件
|
||||
String fileName = String.format("%s生产延期数据_%s.xlsx", workCenter,
|
||||
@ -558,12 +566,18 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取工段{}数据失败", workCenter, e);
|
||||
msg.append("- ").append(workCenter).append(" (获取失败: ").append(e.getMessage()).append(")\n");
|
||||
markdownMsg.append("- ").append(workCenter).append(":<font color=\"warning\">获取失败: ").append(e.getMessage()).append("</font>\n");
|
||||
}
|
||||
}
|
||||
|
||||
msg.append("\n详细数据请查看发送的Excel文件!");
|
||||
wxRobotUtil.sendMsgToWeChatGroup(msg.toString(), robotId, true); // @所有人
|
||||
// 结尾提示与分段发送
|
||||
markdownMsg.append("\n> **📊 详细数据请查看发送的Excel文件!**");
|
||||
String messageContent = markdownMsg.toString();
|
||||
int maxLength = 4096;
|
||||
for (int i = 0; i < messageContent.length(); i += maxLength) {
|
||||
String part = messageContent.substring(i, Math.min(i + maxLength, messageContent.length()));
|
||||
wxRobotUtil.sendMarkdownMsgToWeChatGroup(part, robotId);
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
|
||||
@ -916,6 +930,7 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
map.put("FDate", item.getFDate());
|
||||
map.put("FDeliveryDate", item.getFDeliveryDate());
|
||||
map.put("FUCHNText2", item.getFUCHNText2());
|
||||
map.put("FCreateDate", item.getFCreateDate());
|
||||
mapList.add(map);
|
||||
index++;
|
||||
}
|
||||
@ -944,6 +959,7 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
map.put("FApplicationDate", item.getFApplicationDate());
|
||||
map.put("FUCHNText", item.getFUCHNText());
|
||||
map.put("FCreatorIdFName", item.getFCreatorIdFName());
|
||||
map.put("FCreateDate", item.getFCreateDate());
|
||||
mapList.add(map);
|
||||
index++;
|
||||
}
|
||||
@ -956,7 +972,6 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
*/
|
||||
private List<PurchaseOrderExcelDTO> filterPurchaseOrders(List<PurchaseOrderExcelDTO> allOrders) {
|
||||
LocalDate today = LocalDate.now();
|
||||
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
|
||||
|
||||
log.info("开始过滤采购订单,总数: {}, 当前日期: {}", allOrders.size(), today.format(outputFormatter));
|
||||
@ -966,30 +981,45 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
String productionOrderNo = allOrder.getFUCHNText2();
|
||||
String deliveryDate = allOrder.getFDeliveryDate();
|
||||
|
||||
// 条件3: 交货日期不能为空,并且必须早于今天
|
||||
// ✅ 条件1: 暂停项目过滤
|
||||
if (productionOrderNo != null && productionOrderNo.contains("暂停")) {
|
||||
log.debug("过滤掉: 暂停项目: {}", productionOrderNo);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ✅ 条件2: 交货日期不能为空
|
||||
if (deliveryDate == null || deliveryDate.trim().isEmpty()) {
|
||||
log.debug("过滤掉: 交货日期为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
String dateStr = deliveryDate.split("T")[0]; // 取 yyyy-MM-dd 部分
|
||||
LocalDate delivery = LocalDate.parse(dateStr, inputFormatter);
|
||||
// ✅ 格式化交货日期
|
||||
LocalDate delivery = parseDate(deliveryDate);
|
||||
if (delivery == null) {
|
||||
log.warn("解析交货日期失败: {}", deliveryDate);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 转换格式
|
||||
String formatted = delivery.format(outputFormatter);
|
||||
allOrder.setFDeliveryDate(formatted);
|
||||
|
||||
// ✅ 条件3: 只保留交货日期早于今天的
|
||||
if (!delivery.isBefore(today)) {
|
||||
log.debug("过滤掉: 交货日期未过期: {}", formatted);
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析交货日期失败: {}", deliveryDate, e);
|
||||
continue;
|
||||
}
|
||||
allOrder.setFQty(formatQty(allOrder.getFQty()));
|
||||
// ✅ 顺便格式化其他日期字段
|
||||
allOrder.setFDate(formatDate(allOrder.getFDate()));
|
||||
allOrder.setFDeliveryDate(formatDate(allOrder.getFDeliveryDate()));
|
||||
allOrder.setFCreateDate(formatDate(allOrder.getFCreateDate()));
|
||||
|
||||
filteredOrders.add(allOrder);
|
||||
filteredOrders.add(allOrder);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("处理订单异常: {}", productionOrderNo, e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("过滤完成,剩余数量: {}", filteredOrders.size());
|
||||
@ -1002,7 +1032,6 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
*/
|
||||
private List<PurchaseRequestExcelDTO> filterReqPurchaseOrders(List<PurchaseRequestExcelDTO> allOrders) {
|
||||
LocalDate today = LocalDate.now();
|
||||
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
|
||||
|
||||
log.info("开始过滤采购申请订单,总数: {}, 当前日期: {}", allOrders.size(), today.format(outputFormatter));
|
||||
@ -1010,39 +1039,54 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
|
||||
for (PurchaseRequestExcelDTO allOrder : allOrders) {
|
||||
String productionOrderNo = allOrder.getFUCHNText();
|
||||
String deliveryDate = allOrder.getFArrivalDate();
|
||||
if (allOrder.getFCloseStatus().equals("A")) {
|
||||
String arrivalDate = allOrder.getFArrivalDate();
|
||||
|
||||
// 状态转换
|
||||
if ("A".equals(allOrder.getFCloseStatus())) {
|
||||
allOrder.setFCloseStatus("未关闭");
|
||||
}
|
||||
if (allOrder.getFDocumentStatus().equals("C")) {
|
||||
if ("C".equals(allOrder.getFDocumentStatus())) {
|
||||
allOrder.setFDocumentStatus("已审核");
|
||||
}
|
||||
|
||||
// 暂停项目过滤
|
||||
if (productionOrderNo != null && productionOrderNo.contains("暂停")) {
|
||||
log.debug("过滤掉: 暂停项目: {}", productionOrderNo);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 条件3: 交货日期不能为空,并且必须早于今天
|
||||
if (deliveryDate == null || deliveryDate.trim().isEmpty()) {
|
||||
log.debug("过滤掉: 交货日期为空");
|
||||
// 到货日期不能为空
|
||||
if (arrivalDate == null || arrivalDate.trim().isEmpty()) {
|
||||
log.debug("过滤掉: 到货日期为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
String dateStr = deliveryDate.split("T")[0]; // 取 yyyy-MM-dd 部分
|
||||
LocalDate delivery = LocalDate.parse(dateStr, inputFormatter);
|
||||
LocalDate delivery = parseDate(arrivalDate);
|
||||
if (delivery == null) {
|
||||
log.warn("解析到货日期失败: {}", arrivalDate);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 转换格式
|
||||
// 转换为中文日期格式
|
||||
String formatted = delivery.format(outputFormatter);
|
||||
allOrder.setFArrivalDate(formatted);
|
||||
|
||||
// 只保留已过期的日期
|
||||
if (!delivery.isBefore(today)) {
|
||||
log.debug("过滤掉: 交货日期未过期: {}", formatted);
|
||||
log.debug("过滤掉: 到货日期未过期: {}", formatted);
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析交货日期失败: {}", deliveryDate, e);
|
||||
continue;
|
||||
}
|
||||
allOrder.setFReqQty(formatQty(allOrder.getFReqQty()));
|
||||
allOrder.setFCreateDate(formatDate(allOrder.getFCreateDate()));
|
||||
allOrder.setFApplicationDate(formatDate(allOrder.getFApplicationDate()));
|
||||
allOrder.setFArrivalDate(formatDate(allOrder.getFArrivalDate()));
|
||||
|
||||
filteredOrders.add(allOrder);
|
||||
filteredOrders.add(allOrder);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("处理订单异常: {}", productionOrderNo, e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("过滤完成,剩余数量: {}", filteredOrders.size());
|
||||
@ -1123,4 +1167,499 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将日期字符串(如 "2025-09-22T10:52:03.6" 或 "2025-09-22")格式化为 "yyyy年MM月dd日"
|
||||
*/
|
||||
private String formatDate(String dateStr) {
|
||||
if (dateStr == null || dateStr.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
LocalDate date = parseDate(dateStr);
|
||||
if (date != null) {
|
||||
return date.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return dateStr; // 解析失败则返回原值
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期字符串,支持带 T 的 ISO 格式或普通 yyyy-MM-dd 格式
|
||||
*/
|
||||
private LocalDate parseDate(String dateStr) {
|
||||
if (dateStr == null || dateStr.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 先取出 T 之前的部分
|
||||
String clean = dateStr.split("T")[0];
|
||||
return LocalDate.parse(clean, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} catch (Exception e) {
|
||||
log.debug("日期解析失败: {}", dateStr, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单据状态编码到中文的映射
|
||||
* A -> 创建,B -> 审核中,C -> 已审核,其它原样返回
|
||||
*/
|
||||
private String mapDocumentStatus(String status) {
|
||||
if (status == null || status.trim().isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
switch (status) {
|
||||
case "A":
|
||||
return "创建";
|
||||
case "B":
|
||||
return "审核中";
|
||||
case "C":
|
||||
return "已审核";
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数量为两位小数
|
||||
*/
|
||||
private String formatQty(String qtyStr) {
|
||||
if (qtyStr == null || qtyStr.trim().isEmpty()) {
|
||||
return "0.00";
|
||||
}
|
||||
try {
|
||||
double value = Double.parseDouble(qtyStr);
|
||||
return String.format("%.2f", value);
|
||||
} catch (NumberFormatException e) {
|
||||
log.debug("数量格式化失败: {}", qtyStr, e);
|
||||
return qtyStr;
|
||||
}
|
||||
}
|
||||
|
||||
@Log(title = "获取开工延时的生产订单")
|
||||
@XxlJob("getConstructionDelay")
|
||||
@PostMapping("/getConstructionDelay")
|
||||
public R<Void> getConstructionDelay() {
|
||||
try {
|
||||
|
||||
// String robotId = "4d2f037d-0cee-493a-a4ff-1758f67b8069";
|
||||
String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e";
|
||||
String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss");
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("🏭 生产订单未开工的延期通知\n\n").append("更新时间:").append(currentTime).append("\n\n").append("🔧 订单数据统计:\n");
|
||||
// 获取生产订单数据
|
||||
List<ConstructionDelayDTO> purchaseOrderList1 = JdUtil.getConstructionDelay();
|
||||
|
||||
List<ConstructionDelayDTO> purchaseOrderList = filterConstructionDel(purchaseOrderList1);
|
||||
msg.append("- 到期未开工:").append(purchaseOrderList.size()).append("条\n");
|
||||
// 生成Excel文件使用采购模板
|
||||
String fileName = String.format("生产订单未开工的延期数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
|
||||
String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName;
|
||||
// 准备模板数据
|
||||
Map<String, Object> staticDataMap = new HashMap<>();
|
||||
staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"));
|
||||
staticDataMap.put("purchaseOrderCount", purchaseOrderList.size());
|
||||
List<DynamicDataMapping> dynamicDataMappingList = new ArrayList<>();
|
||||
// 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化)
|
||||
if (!purchaseOrderList.isEmpty()) {
|
||||
List<Map<String, Object>> orderDataList = new ArrayList<>();
|
||||
// 为避免循环中重复远程查询,增加简单的单号级缓存
|
||||
Map<String, OperationPlannDTO> plannCache = new HashMap<>();
|
||||
int index = 1;
|
||||
for (ConstructionDelayDTO item : purchaseOrderList) {
|
||||
String billNo = item.getFBillNo();
|
||||
OperationPlannDTO plann = plannCache.get(billNo);
|
||||
if (plann == null) {
|
||||
try {
|
||||
plann = JdUtil.getOperationPlann(billNo);
|
||||
} catch (Exception ex) {
|
||||
log.warn("获取工序汇报单失败,单号:{},原因:{}", billNo, ex.getMessage());
|
||||
}
|
||||
plannCache.put(billNo, plann); // 即便为 null 也缓存,避免重复失败调用
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("index", index++);
|
||||
map.put("F_HBYT_SCLH", item.getF_HBYT_SCLH());
|
||||
map.put("FBillNo", item.getFBillNo());
|
||||
map.put("FPickMtrlStatus", item.getFPickMtrlStatus());
|
||||
map.put("FWorkShopIDFName", item.getFWorkShopIDFName());
|
||||
map.put("FMaterialIdFNumber", item.getFMaterialIdFNumber());
|
||||
map.put("FMaterialName", item.getFMaterialName());
|
||||
// 工序号/数量/工序名称做空值保护,避免因远程返回空导致 NPE
|
||||
String operNumber = (plann != null && StringUtils.hasText(plann.getFOperNumber())) ? plann.getFOperNumber() : "-";
|
||||
String operQty = (plann != null && StringUtils.hasText(plann.getFOperQty())) ? formatQty(plann.getFOperQty()) : "-";
|
||||
String processName = (plann != null && StringUtils.hasText(plann.getFProcessIdFName())) ? plann.getFProcessIdFName() : "-";
|
||||
map.put("FOperNumber", operNumber);
|
||||
map.put("FOperQty", operQty);
|
||||
map.put("FProcessIdFName", processName);
|
||||
map.put("FPlanStartDate", item.getFPlanStartDate());
|
||||
map.put("FPlanFinishDate", item.getFPlanFinishDate());
|
||||
map.put("Deydays", item.getDeydays());
|
||||
map.put("createTime", new Date());
|
||||
orderDataList.add(map);
|
||||
}
|
||||
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ConstructionDelayDTO", orderDataList));
|
||||
}
|
||||
// 使用采购模板生成Excel
|
||||
String templatePath = "EXCEL模板/生产开工未领料模板.xlsx";
|
||||
ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList);
|
||||
// 发送Excel文件
|
||||
File excelFile = new File(filePath);
|
||||
if (excelFile.exists()) {
|
||||
wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId);
|
||||
FileUtils.deleteQuietly(excelFile);
|
||||
}
|
||||
msg.append("\n详细数据请查看发送的Excel文件!");
|
||||
wxRobotUtil.sendMsgToWeChatGroup(msg.toString(), robotId, true); // @所有人
|
||||
|
||||
return R.ok();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送工段数据失败", e);
|
||||
return R.fail("发送工段数据失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Log(title = "工序汇报单订单-未入库")
|
||||
@XxlJob("getProductionOrder")
|
||||
@PostMapping("/getProductionOrder")
|
||||
public R<Void> getProductionOrder() {
|
||||
//TO DO:
|
||||
|
||||
try {
|
||||
String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e";
|
||||
String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss");
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("🏭 工序汇报未入库\n\n").append("更新时间:").append(currentTime).append("\n\n").append("🔧 订单数据统计:\n");
|
||||
|
||||
//工序汇报单,未入库列表
|
||||
List<ProcessReportDTO> processReportDTOList = JdUtil.getProcessReport();
|
||||
msg.append("- 到期未开工:").append(processReportDTOList.size()).append("条\n");
|
||||
// 生成Excel文件使用采购模板
|
||||
String fileName = String.format("工序汇报未入库的延期数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
|
||||
String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName;
|
||||
// 准备模板数据
|
||||
Map<String, Object> staticDataMap = new HashMap<>();
|
||||
staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"));
|
||||
staticDataMap.put("purchaseOrderCount", processReportDTOList.size());
|
||||
List<DynamicDataMapping> dynamicDataMappingList = new ArrayList<>();
|
||||
// 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化)
|
||||
if (!processReportDTOList.isEmpty()) {
|
||||
List<Map<String, Object>> reportList = new ArrayList<>();
|
||||
int index = 1;
|
||||
for (ProcessReportDTO item : processReportDTOList) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("index", index++);
|
||||
map.put("FSCLH", item.getFSCLH());
|
||||
map.put("FBillNo", item.getFBillNo());
|
||||
map.put("FWorkShopID", item.getFWorkShopID());
|
||||
map.put("FMoNumber", item.getFMoNumber());
|
||||
map.put("FOperNumber", item.getFOperNumber());
|
||||
map.put("FOperDescription", item.getFOperDescription());
|
||||
map.put("FQuaQty", formatQty(item.getFQuaQty()));
|
||||
map.put("FFinishQty", formatQty(item.getFFinishQty()));
|
||||
map.put("FStockInQuaAuxQty", formatQty(item.getFStockInQuaAuxQty()));
|
||||
map.put("FStockInFailAuxQty", formatQty(item.getFStockInFailAuxQty()));
|
||||
map.put("FRKD", item.getFRKD());
|
||||
map.put("FDate", parseDate(item.getFDate()));
|
||||
map.put("createTime", new Date());
|
||||
reportList.add(map);
|
||||
}
|
||||
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessReportDTO", reportList));
|
||||
}
|
||||
// 使用采购模板生成Excel
|
||||
String templatePath = "EXCEL模板/工序汇报未入库.xlsx";
|
||||
ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList);
|
||||
// 发送Excel文件
|
||||
File excelFile = new File(filePath);
|
||||
if (excelFile.exists()) {
|
||||
wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId);
|
||||
FileUtils.deleteQuietly(excelFile);
|
||||
}
|
||||
msg.append("\n详细数据请查看发送的Excel文件!");
|
||||
wxRobotUtil.sendMsgToWeChatGroup(msg.toString(), robotId, true); // @所有人
|
||||
|
||||
return R.ok();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送工段数据失败", e);
|
||||
return R.fail("发送工段数据失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Log(title = "工序转移未及时转移")
|
||||
@XxlJob("getProcessTransferForm")
|
||||
@PostMapping("/getProcessTransferForm")
|
||||
public R<Void> getProcessTransferForm() {
|
||||
//TO D0:需要查询工序计划的时间是否在今日
|
||||
try {
|
||||
String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e";
|
||||
String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss");
|
||||
// 构建 Markdown 消息
|
||||
StringBuilder markdownMsg = new StringBuilder();
|
||||
markdownMsg.append("🏭 **工序转移**\n\n");
|
||||
markdownMsg.append("- 📊 统计时间:").append(currentTime).append("\n");
|
||||
markdownMsg.append("- 📋 订单数据统计:\n");
|
||||
//工序汇报单,未入库列表
|
||||
List<ProcessTransferFormDTO> processReportDTOList = JdUtil.getProcessTransferForm();
|
||||
markdownMsg.append(" - 工序转移数据:").append(processReportDTOList.size()).append("条\n");
|
||||
// 追加Excel文件提示
|
||||
if (processReportDTOList.size() > 0) {
|
||||
markdownMsg.append("\n📄 详细数据请查看发送的 Excel 文件\n");
|
||||
}
|
||||
// 生成Excel文件使用采购模板
|
||||
String fileName = String.format("工序转移数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
|
||||
String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName;
|
||||
// 准备模板数据
|
||||
Map<String, Object> staticDataMap = new HashMap<>();
|
||||
staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"));
|
||||
staticDataMap.put("purchaseOrderCount", processReportDTOList.size());
|
||||
List<DynamicDataMapping> dynamicDataMappingList = new ArrayList<>();
|
||||
// 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化)
|
||||
if (!processReportDTOList.isEmpty()) {
|
||||
|
||||
List<Map<String, Object>> reportList = new ArrayList<>();
|
||||
int index = 1;
|
||||
for (ProcessTransferFormDTO item : processReportDTOList) {
|
||||
//ProcessRoute routes = iProcessRouteService.getProcessRoutesXuTime(item.getFSCLH(), item.getFProductIdNumber(), item.getFInOperNumber());
|
||||
/* Date inStart = (routes == null ? null : routes.getXuStartTime());
|
||||
Date createDate = null;
|
||||
if (StringUtils.hasText(item.getFCreateDate())) {
|
||||
try {
|
||||
createDate = DateUtil.parse(item.getFCreateDate());
|
||||
} catch (Exception ignored) { }
|
||||
}
|
||||
// 当两者时间均可用时:仅过滤“未晚于转入序开始”的记录(即不延迟)
|
||||
if (inStart != null && createDate != null && createDate.before(inStart)) {
|
||||
continue;
|
||||
}*/
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("index", index++);
|
||||
map.put("FSCLH", item.getFSCLH());
|
||||
map.put("FProductIdNumber", item.getFProductIdNumber());
|
||||
map.put("FDocumentStatus", mapDocumentStatus(item.getFDocumentStatus()));
|
||||
map.put("FMOBillNo", item.getFMOBillNo());
|
||||
map.put("FBillNo", item.getFBillNo());
|
||||
map.put("FProductName", item.getFProductName());
|
||||
map.put("FOutDeptIdFName", item.getFOutDeptIdFName());
|
||||
map.put("FOutOperNumber", item.getFOutOperNumber());
|
||||
map.put("FOutProcessIdName", item.getFOutProcessIdName());
|
||||
map.put("FInDeptIdFName", item.getFInDeptIdFName());
|
||||
map.put("FInOperNumber", item.getFInOperNumber());
|
||||
map.put("FInProcessIdFName", item.getFInProcessIdFName());
|
||||
map.put("FOperUnit", item.getFOperUnit());
|
||||
map.put("FOperTransferQty", formatQty(item.getFOperTransferQty()));
|
||||
map.put("FOperQualifiedQty", formatQty(item.getFOperQualifiedQty()));
|
||||
map.put("FOperProFailQty", formatQty(item.getFOperProFailQty()));
|
||||
map.put("FCreateDate", parseDate(item.getFCreateDate()));
|
||||
map.put("createTime", new Date());
|
||||
reportList.add(map);
|
||||
}
|
||||
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessTransferFormDTO", reportList));
|
||||
}
|
||||
// 使用采购模板生成Excel
|
||||
String templatePath = "EXCEL模板/工序转移数据.xlsx";
|
||||
ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList);
|
||||
// 发送消息
|
||||
wxRobotUtil.sendMarkdownMsgToWeChatGroup(markdownMsg.toString(), robotId);
|
||||
|
||||
// 发送Excel文件
|
||||
File excelFile = new File(filePath);
|
||||
if (excelFile.exists()) {
|
||||
wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId);
|
||||
FileUtils.deleteQuietly(excelFile);
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送工段数据失败", e);
|
||||
return R.fail("发送工段数据失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> convertConstructionDelayToMapList(List<ConstructionDelayDTO> purchaseOrderList) {
|
||||
List<Map<String, Object>> mapList = new ArrayList<>();
|
||||
int index = 1;
|
||||
for (ConstructionDelayDTO item : purchaseOrderList) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("index", index);
|
||||
|
||||
// —— 按照 ConstructionDelayDTO 字段 ——
|
||||
map.put("F_HBYT_SCLH", item.getF_HBYT_SCLH()); // 生产令号
|
||||
map.put("FBillNo", item.getFBillNo()); // 单据编码(若有)
|
||||
map.put("FWorkShopIDFName", item.getFWorkShopIDFName()); // 车间名称
|
||||
map.put("FMaterialIdFNumber", item.getFMaterialIdFNumber()); // 物料编码
|
||||
map.put("FMaterialName", item.getFMaterialName()); // 物料名称
|
||||
map.put("FPlanStartDate", formatDate(item.getFPlanStartDate())); // 计划开工时间(格式化)
|
||||
map.put("FPlanFinishDate", formatDate(item.getFPlanFinishDate())); // 计划完工时间(格式化)
|
||||
map.put("Deydays", item.getDeydays()); // 超期天数
|
||||
mapList.add(map);
|
||||
index++;
|
||||
}
|
||||
return mapList;
|
||||
}
|
||||
|
||||
private List<ConstructionDelayDTO> filterConstructionDel(List<ConstructionDelayDTO> allPurchaseOrderList) {
|
||||
LocalDate today = LocalDate.now();
|
||||
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
|
||||
|
||||
log.info("开始过滤生产订单,总数: {}, 当前日期: {}", allPurchaseOrderList.size(), today.format(outputFormatter));
|
||||
List<ConstructionDelayDTO> filteredOrders = new ArrayList<>();
|
||||
|
||||
for (ConstructionDelayDTO allOrder : allPurchaseOrderList) {
|
||||
String productionOrderNo = allOrder.getF_HBYT_SCLH();
|
||||
String deliveryDate = allOrder.getFPlanFinishDate();
|
||||
|
||||
// ✅ 条件1: 暂停项目过滤
|
||||
if (productionOrderNo != null && productionOrderNo.contains("暂停")) {
|
||||
log.debug("过滤掉: 暂停项目: {}", productionOrderNo);
|
||||
continue;
|
||||
} // ✅ 条件1: 暂停项目过滤
|
||||
if (productionOrderNo == null || productionOrderNo.isEmpty()) {
|
||||
log.debug("过滤掉: 无令号项目: {}", productionOrderNo);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
// ✅ 格式化交货日期
|
||||
LocalDate delivery = parseDate(deliveryDate);
|
||||
if (delivery == null) {
|
||||
log.warn("解析交货日期失败: {}", deliveryDate);
|
||||
continue;
|
||||
}
|
||||
String formatted = delivery.format(outputFormatter);
|
||||
allOrder.setFPlanFinishDate(formatted);
|
||||
// ✅ 顺便格式化其他日期字段
|
||||
LocalDate planStart = parseDate(allOrder.getFPlanStartDate());
|
||||
if (planStart == null) {
|
||||
log.warn("解析开工日期失败: {}", allOrder.getFPlanStartDate());
|
||||
continue;
|
||||
}
|
||||
// 计算过期天数:今天减去开工时间
|
||||
long delayDays = ChronoUnit.DAYS.between(planStart, today);
|
||||
if (delayDays > 2) {
|
||||
allOrder.setDeydays((int) delayDays);
|
||||
allOrder.setFPlanStartDate(planStart.format(outputFormatter));
|
||||
allOrder.setFPlanFinishDate(formatted);
|
||||
filteredOrders.add(allOrder);
|
||||
} else {
|
||||
log.debug("订单{} 延期{}天,不满足>2天条件,过滤", productionOrderNo, delayDays);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("处理订单异常: {}", productionOrderNo, e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("过滤完成,剩余数量: {}", filteredOrders.size());
|
||||
return filteredOrders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 质检不及时数据
|
||||
*/
|
||||
@XxlJob("getUninspectedData")
|
||||
@Log(title = "质检不及时数据", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/getUninspectedData")
|
||||
public R<List<ProcessInspectionDTO>> getUninspectedData() {
|
||||
try {
|
||||
String robotId = "8af8abea-3f21-4ca7-ad0a-5b7a2cf4d78e";
|
||||
String currentTime = DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss");
|
||||
//工序汇报单,未入库列表
|
||||
List<ProcessInspectionDTO> processReportDTOList = JdUtil.getUninspectedData();
|
||||
|
||||
// 构建Markdown消息
|
||||
StringBuilder markdownMsg = new StringBuilder();
|
||||
markdownMsg.append("# 工序质检不及时告警通知\n\n")
|
||||
.append("> **统计时间:** <font color=\"info\">").append(currentTime).append("</font>\n")
|
||||
.append("> **未质检工序数量:** <font color=\"warning\">").append(processReportDTOList.size()).append("</font> 条\n\n");
|
||||
|
||||
// 如果有未质检数据,显示前N条详细信息(默认3条)
|
||||
if (!processReportDTOList.isEmpty()) {
|
||||
markdownMsg.append("## 🔍 未质检工序详情(前2条)\n\n");
|
||||
int displayCount = Math.min(2, processReportDTOList.size());
|
||||
for (int i = 0; i < displayCount; i++) {
|
||||
ProcessInspectionDTO item = processReportDTOList.get(i);
|
||||
markdownMsg.append("### ").append(i + 1).append(". ").append(item.getFMaterialName()).append("\n")
|
||||
.append("> **生产订单号:** <font color=\"comment\">").append(item.getMoOrderNo()).append("</font>\n")
|
||||
.append("> **工序名称:** <font color=\"info\">").append(item.getFProcessName()).append("</font>\n")
|
||||
.append("> **工作中心:** <font color=\"comment\">").append(item.getFWorkCenterName()).append("</font>\n")
|
||||
.append("> **检验状态:** <font color=\"warning\">").append(item.getFInspectStatus()).append("</font>\n")
|
||||
.append("> **待检数量:** <font color=\"warning\">").append(item.getFWaitInspectQty()).append("</font>\n")
|
||||
.append("> **已检数量:** <font color=\"info\">").append(item.getFFinishInspectQty()).append("</font>\n")
|
||||
.append("> **合格数量:** <font color=\"info\">").append(item.getFQuaQty()).append("</font>\n")
|
||||
.append("> **提交检验时间:** ").append(item.getFSubmitInspectTime()).append("\n\n");
|
||||
}
|
||||
if (processReportDTOList.size() > displayCount) {
|
||||
markdownMsg.append("> **注意:** 还有 ").append(processReportDTOList.size() - displayCount).append(" 条未质检记录,详细信息请查看Excel文件\n\n");
|
||||
}
|
||||
} else {
|
||||
markdownMsg.append("## ✅ 暂无未质检工序\n\n");
|
||||
}
|
||||
|
||||
markdownMsg.append("> **创建时间:** ").append(DateUtil.formatDateTime(new Date())).append("\n");
|
||||
|
||||
// 追加Excel提示到Markdown消息
|
||||
markdownMsg.append("\n> **📊 详细数据请查看发送的Excel文件!**");
|
||||
// 生成Excel文件使用采购模板
|
||||
String fileName = String.format("工序未质检数据_%s.xlsx", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
|
||||
String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName;
|
||||
// 准备模板数据
|
||||
Map<String, Object> staticDataMap = new HashMap<>();
|
||||
staticDataMap.put("currentTime", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"));
|
||||
staticDataMap.put("purchaseOrderCount", processReportDTOList.size());
|
||||
List<DynamicDataMapping> dynamicDataMappingList = new ArrayList<>();
|
||||
// 添加数据(仅在此方法内映射,避免对已格式化日期再次格式化)
|
||||
if (!processReportDTOList.isEmpty()) {
|
||||
List<Map<String, Object>> reportList = new ArrayList<>();
|
||||
int index = 1;
|
||||
for (ProcessInspectionDTO item : processReportDTOList) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("index", index++);
|
||||
map.put("moBillNo", item.getMoBillNo());
|
||||
map.put("moOrderNo", item.getMoOrderNo());
|
||||
map.put("fMaterialName", item.getFMaterialName());
|
||||
map.put("fProcessName", item.getFProcessName());
|
||||
map.put("fWorkCenterName", item.getFWorkCenterName());
|
||||
map.put("fInspectStatus", item.getFInspectStatus());
|
||||
map.put("fWaitInspectQty", item.getFWaitInspectQty());
|
||||
map.put("fFinishInspectQty", item.getFFinishInspectQty());
|
||||
map.put("fQuaQty", item.getFQuaQty());
|
||||
map.put("fReworkQty", item.getFReworkQty());
|
||||
map.put("fFailQty", item.getFFailQty());
|
||||
map.put("fSubmitInspectTime", item.getFSubmitInspectTime());
|
||||
map.put("fFinishInspectTime", item.getFFinishInspectTime());
|
||||
map.put("fDescription", parseDate(item.getFDescription()));
|
||||
reportList.add(map);
|
||||
}
|
||||
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList("ProcessInspectionDTO", reportList));
|
||||
}
|
||||
// 使用采购模板生成Excel
|
||||
String templatePath = "EXCEL模板/质检模板.xlsx";
|
||||
ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, filePath, staticDataMap, dynamicDataMappingList);
|
||||
// 发送Excel文件
|
||||
File excelFile = new File(filePath);
|
||||
if (excelFile.exists()) {
|
||||
wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId);
|
||||
FileUtils.deleteQuietly(excelFile);
|
||||
}
|
||||
// 发送Markdown消息(企业微信要求使用 msgtype=markdown),并按长度分段
|
||||
String messageContent = markdownMsg.toString();
|
||||
int maxLength = 4096;
|
||||
for (int i = 0; i < messageContent.length(); i += maxLength) {
|
||||
String part = messageContent.substring(i, Math.min(i + maxLength, messageContent.length()));
|
||||
wxRobotUtil.sendMarkdownMsgToWeChatGroup(part, robotId);
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送工段数据失败", e);
|
||||
return R.fail("发送工段数据失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
package com.ruoyi.system.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
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.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.domain.vo.PartCostVo;
|
||||
import com.ruoyi.system.domain.bo.PartCostBo;
|
||||
import com.ruoyi.system.service.IPartCostService;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 零件成本
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/system/cost")
|
||||
public class PartCostController extends BaseController {
|
||||
|
||||
private final IPartCostService iPartCostService;
|
||||
|
||||
/**
|
||||
* 查询零件成本列表
|
||||
*/
|
||||
@SaCheckPermission("system:cost:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<PartCostVo> list(PartCostBo bo, PageQuery pageQuery) {
|
||||
return iPartCostService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出零件成本列表
|
||||
*/
|
||||
@SaCheckPermission("system:cost:export")
|
||||
@Log(title = "零件成本", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(PartCostBo bo, HttpServletResponse response) {
|
||||
List<PartCostVo> list = iPartCostService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "零件成本", PartCostVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取零件成本详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@SaCheckPermission("system:cost:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<PartCostVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(iPartCostService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增零件成本
|
||||
*/
|
||||
@SaCheckPermission("system:cost:add")
|
||||
@Log(title = "零件成本", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody PartCostBo bo) {
|
||||
return toAjax(iPartCostService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改零件成本
|
||||
*/
|
||||
@SaCheckPermission("system:cost:edit")
|
||||
@Log(title = "零件成本", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody PartCostBo bo) {
|
||||
return toAjax(iPartCostService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除零件成本
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("system:cost:remove")
|
||||
@Log(title = "零件成本", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(iPartCostService.deleteWithValidByIds(Arrays.asList(ids), true));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 在金蝶获取成本价
|
||||
*/
|
||||
@SaCheckPermission("system:cost:getObtainPartData")
|
||||
@Log(title = "在金蝶获取成本价", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/getObtainPartData")
|
||||
public R<Void> getObtainPartData() {
|
||||
return toAjax(iPartCostService.getObtainPartData());
|
||||
}
|
||||
}
|
||||
@ -170,9 +170,8 @@ public class PcRigidChainController extends BaseController {
|
||||
|
||||
DefaultExcelListener<PcRigidChainVo> excelListener = new DefaultExcelListener<>(true);
|
||||
EasyExcel.read(new ByteArrayInputStream(fileBytes), PcRigidChainVo.class, excelListener)
|
||||
.excelType(ExcelTypeEnum.XLS)
|
||||
.sheet(readSheet.getSheetNo())
|
||||
.headRowNumber(4)
|
||||
.headRowNumber(3)
|
||||
.doRead();
|
||||
|
||||
List<PcRigidChainVo> list = excelListener.getExcelResult().getList();
|
||||
@ -214,38 +213,6 @@ public class PcRigidChainController extends BaseController {
|
||||
PcRigidChain dbChain = chainMap.get(searchKey);
|
||||
if (dbChain != null) {
|
||||
matchedCount++;
|
||||
log.info("找到匹配记录: {}", typeName);
|
||||
|
||||
// 记录修改前的关键字段值
|
||||
log.info("修改前字段值:");
|
||||
log.info(" - ID: {}", dbChain.getId());
|
||||
log.info(" - Journey: {} -> {}", dbChain.getJourney(), vOne);
|
||||
log.info(" - TypeName: {} -> {}", dbChain.getTypeName(), typeName);
|
||||
log.info(" - Type: {} -> {}", dbChain.getType(), type);
|
||||
log.info(" - Box: {} -> {}", dbChain.getBox(), box);
|
||||
log.info(" - AxialDirection: {} -> {}", dbChain.getAxialDirection(), s);
|
||||
|
||||
// 记录Excel中的关键字段值
|
||||
log.info("Excel数据关键字段:");
|
||||
log.info(" - VOne: {}", pcRigidChainVO.getVOne());
|
||||
log.info(" - VTwo: {}", pcRigidChainVO.getVTwo());
|
||||
log.info(" - VThree: {}", pcRigidChainVO.getVThree());
|
||||
log.info(" - LOne: {}", pcRigidChainVO.getLOne());
|
||||
log.info(" - LTwo: {}", pcRigidChainVO.getLTwo());
|
||||
log.info(" - LThree: {}", pcRigidChainVO.getLThree());
|
||||
log.info(" - SumWeight: {}", pcRigidChainVO.getSumWeight());
|
||||
log.info(" - ChainWeight: {}", pcRigidChainVO.getChainWeight());
|
||||
log.info(" - DynamicLoad: {}", pcRigidChainVO.getDynamicLoad());
|
||||
log.info(" - DeadLoad: {}", pcRigidChainVO.getDeadLoad());
|
||||
log.info(" - Speed: {}", pcRigidChainVO.getSpeed());
|
||||
log.info(" - Efficiency: {}", pcRigidChainVO.getEfficiency());
|
||||
log.info(" - ChainPitch: {}", pcRigidChainVO.getChainPitch());
|
||||
log.info(" - PitchRadius: {}", pcRigidChainVO.getPitchRadius());
|
||||
log.info(" - MinimumAltitude: {}", pcRigidChainVO.getMinimumAltitude());
|
||||
log.info(" - SingleMeterChainWeight: {}", pcRigidChainVO.getSingleMeterChainWeight());
|
||||
log.info(" - DrivingBoxWeight: {}", pcRigidChainVO.getDrivingBoxWeight());
|
||||
log.info(" - ChainBoxWeight: {}", pcRigidChainVO.getChainBoxWeight());
|
||||
log.info(" - Univalence: {}", pcRigidChainVO.getUnivalence());
|
||||
|
||||
// 执行字段复制和更新
|
||||
BeanUtil.copyProperties(pcRigidChainVO, dbChain, "id");
|
||||
@ -254,34 +221,8 @@ public class PcRigidChainController extends BaseController {
|
||||
dbChain.setType(type);
|
||||
dbChain.setBox(box);
|
||||
dbChain.setAxialDirection(s);
|
||||
dbChain.setCreateTime(new Date());
|
||||
dbChain.setUpdateTime(new Date());
|
||||
|
||||
// 记录修改后的关键字段值
|
||||
log.info("修改后字段值:");
|
||||
log.info(" - Journey: {}", dbChain.getJourney());
|
||||
log.info(" - TypeName: {}", dbChain.getTypeName());
|
||||
log.info(" - Type: {}", dbChain.getType());
|
||||
log.info(" - Box: {}", dbChain.getBox());
|
||||
log.info(" - AxialDirection: {}", dbChain.getAxialDirection());
|
||||
log.info(" - LOne: {}", dbChain.getLOne());
|
||||
log.info(" - LTwo: {}", dbChain.getLTwo());
|
||||
log.info(" - LThree: {}", dbChain.getLThree());
|
||||
log.info(" - SumWeight: {}", dbChain.getSumWeight());
|
||||
log.info(" - ChainWeight: {}", dbChain.getChainWeight());
|
||||
log.info(" - DynamicLoad: {}", dbChain.getDynamicLoad());
|
||||
log.info(" - DeadLoad: {}", dbChain.getDeadLoad());
|
||||
log.info(" - Speed: {}", dbChain.getSpeed());
|
||||
log.info(" - Efficiency: {}", dbChain.getEfficiency());
|
||||
log.info(" - ChainPitch: {}", dbChain.getChainPitch());
|
||||
log.info(" - PitchRadius: {}", dbChain.getPitchRadius());
|
||||
log.info(" - MinimumAltitude: {}", dbChain.getMinimumAltitude());
|
||||
log.info(" - SingleMeterChainWeight: {}", dbChain.getSingleMeterChainWeight());
|
||||
log.info(" - DrivingBoxWeight: {}", dbChain.getDrivingBoxWeight());
|
||||
log.info(" - ChainBoxWeight: {}", dbChain.getChainBoxWeight());
|
||||
log.info(" - Univalence: {}", dbChain.getUnivalence());
|
||||
log.info(" - CreateTime: {}", dbChain.getCreateTime());
|
||||
log.info(" - UpdateTime: {}", dbChain.getUpdateTime());
|
||||
|
||||
pcRigidChainsToUpdate.add(dbChain);
|
||||
log.info("物料: {} 已添加到更新列表", typeName);
|
||||
@ -301,27 +242,7 @@ public class PcRigidChainController extends BaseController {
|
||||
int failCount = 0;
|
||||
|
||||
for (PcRigidChain pcRigidChain : pcRigidChainsToUpdate) {
|
||||
log.info("正在更新物料: {}, ID: {}", pcRigidChain.getTypeName(), pcRigidChain.getId());
|
||||
// 记录更新前的关键字段值
|
||||
log.info("更新前数据库字段值:");
|
||||
log.info(" - Journey: {}", pcRigidChain.getJourney());
|
||||
log.info(" - LOne: {}", pcRigidChain.getLOne());
|
||||
log.info(" - LTwo: {}", pcRigidChain.getLTwo());
|
||||
log.info(" - LThree: {}", pcRigidChain.getLThree());
|
||||
log.info(" - SumWeight: {}", pcRigidChain.getSumWeight());
|
||||
log.info(" - ChainWeight: {}", pcRigidChain.getChainWeight());
|
||||
log.info(" - DynamicLoad: {}", pcRigidChain.getDynamicLoad());
|
||||
log.info(" - DeadLoad: {}", pcRigidChain.getDeadLoad());
|
||||
log.info(" - Speed: {}", pcRigidChain.getSpeed());
|
||||
log.info(" - Efficiency: {}", pcRigidChain.getEfficiency());
|
||||
log.info(" - ChainPitch: {}", pcRigidChain.getChainPitch());
|
||||
log.info(" - PitchRadius: {}", pcRigidChain.getPitchRadius());
|
||||
log.info(" - MinimumAltitude: {}", pcRigidChain.getMinimumAltitude());
|
||||
log.info(" - SingleMeterChainWeight: {}", pcRigidChain.getSingleMeterChainWeight());
|
||||
log.info(" - DrivingBoxWeight: {}", pcRigidChain.getDrivingBoxWeight());
|
||||
log.info(" - ChainBoxWeight: {}", pcRigidChain.getChainBoxWeight());
|
||||
log.info(" - Univalence: {}", pcRigidChain.getUnivalence());
|
||||
|
||||
pcRigidChain.setUpdateTime(new Date());
|
||||
int i = pcRigidChainMapper.updateById(pcRigidChain);
|
||||
if (i > 0) {
|
||||
successCount++;
|
||||
|
||||
@ -236,10 +236,14 @@ public class ProcessOrderProController extends BaseController {
|
||||
*/
|
||||
|
||||
@SaCheckPermission("system:processOrderPro:uploadPDF")
|
||||
@Log(title = "上传PDF", businessType = BusinessType.UPDATE)
|
||||
@Log(title = "下载PDF", businessType = BusinessType.UPDATE)
|
||||
@CrossOrigin(origins = "*", allowedHeaders = "*", exposedHeaders = {"Content-Disposition", "Content-Length"})
|
||||
@GetMapping("/uploadPDF")
|
||||
public void uploadPDF(@RequestParam Long id, HttpServletResponse response) {
|
||||
try {
|
||||
// CORS headers for all responses (success and error)
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition, Content-Length");
|
||||
// 调用service方法获取文件路径
|
||||
R<String> result = iProcessOrderProService.uploadPDF(id);
|
||||
if (result.getCode() != 200) {
|
||||
@ -264,6 +268,7 @@ public class ProcessOrderProController extends BaseController {
|
||||
response.setContentType("application/zip");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(file.getName(), "UTF-8") + "\"");
|
||||
response.setHeader("Content-Length", String.valueOf(file.length()));
|
||||
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition, Content-Length");
|
||||
|
||||
// 写入文件流
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
@ -343,6 +348,7 @@ public class ProcessOrderProController extends BaseController {
|
||||
public List<OverdueProjectVo> getOverdueProjects() {
|
||||
return iProcessOrderProService.getOverdueProjects();
|
||||
}
|
||||
|
||||
@SaCheckPermission("system:orderPro:geMRPResults")
|
||||
@Log(title = "获取MRP复核结果", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/getMRPResults/{id}")
|
||||
@ -423,7 +429,6 @@ public class ProcessOrderProController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 电气外包分类条件:物料编码开头空格/特定前缀 或 备注包含"外购"
|
||||
if (materialCode.startsWith(" ")
|
||||
|| materialCode.startsWith("009301") || materialCode.startsWith("009999")
|
||||
@ -541,11 +546,11 @@ public class ProcessOrderProController extends BaseController {
|
||||
// 总装部件优先
|
||||
boolean isTotal1 = "总装部件".equals(m1);
|
||||
boolean isTotal2 = "总装部件".equals(m2);
|
||||
|
||||
|
||||
if (isTotal1 && !isTotal2) return -1;
|
||||
if (!isTotal1 && isTotal2) return 1;
|
||||
if (isTotal1 && isTotal2) return 0;
|
||||
|
||||
|
||||
// 其他材质按字母顺序排序
|
||||
if (m1 == null && m2 == null) return 0;
|
||||
if (m1 == null) return 1;
|
||||
@ -652,7 +657,6 @@ public class ProcessOrderProController extends BaseController {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ProcessRoute vo = new ProcessRoute();
|
||||
|
||||
// 根据列索引读取数据,保留原始空格
|
||||
@ -747,9 +751,7 @@ public class ProcessOrderProController extends BaseController {
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ProductionOrderVo vo = new ProductionOrderVo();
|
||||
|
||||
// 根据列索引读取数据,保留原始空格
|
||||
vo.setId(getCellValueAsLong(row.getCell(0)));
|
||||
vo.setDrawingNo(getCellValueAsString(row.getCell(1))); // 图号
|
||||
|
||||
@ -443,7 +443,7 @@ public class ProcessRouteController extends BaseController {
|
||||
@Log(title = "推送工艺工序")
|
||||
@SaCheckPermission("system:route:pushRouteBom")
|
||||
@PostMapping("/pushRouteBom")
|
||||
public ProcessRoutePushResultDTO pushRouteBom(@RequestParam String rooteProdet) {
|
||||
public R<ProcessRoutePushResultDTO> pushRouteBom(@RequestParam String rooteProdet) {
|
||||
return iProcessRouteService.pushRouteBom(rooteProdet);
|
||||
}
|
||||
|
||||
@ -644,7 +644,7 @@ public class ProcessRouteController extends BaseController {
|
||||
materialBom.setUnit(materialUsageDTO.getChildUnit());
|
||||
materialBom.setMaterialType(materialUsageDTO.getCaizhi());
|
||||
//保留四位小数
|
||||
materialBom.setQuantity(String.valueOf(new BigDecimal(materialUsageDTO.getFenzi()).divide(new BigDecimal(materialUsageDTO.getFenmu()),4, RoundingMode.HALF_UP)));
|
||||
materialBom.setQuantity(String.valueOf(BigDecimal.valueOf(materialUsageDTO.getFenzi()).divide(new BigDecimal(materialUsageDTO.getFenmu()),4, RoundingMode.HALF_UP)));
|
||||
|
||||
return materialBom;
|
||||
}
|
||||
@ -658,7 +658,7 @@ public class ProcessRouteController extends BaseController {
|
||||
bomDetails.setUnitWeight("是");
|
||||
bomDetails.setWareHouse(materialUsageDTO.getChildUnit());
|
||||
//子项分子
|
||||
bomDetails.setQuantity(materialUsageDTO.getFenzi());
|
||||
bomDetails.setQuantity(String.valueOf(materialUsageDTO.getFenzi()));
|
||||
//子项分母
|
||||
bomDetails.setDenominator(Double.valueOf(materialUsageDTO.getFenmu()));
|
||||
bomDetails.setName(materialUsageDTO.getMaterialName());
|
||||
@ -801,7 +801,7 @@ public class ProcessRouteController extends BaseController {
|
||||
bomDetails.setUnitWeight("是");
|
||||
bomDetails.setWareHouse(materialUsageDTO.getUnit());
|
||||
//子项分子
|
||||
bomDetails.setQuantity(materialUsageDTO.getFNumerator());
|
||||
bomDetails.setQuantity(String.valueOf(materialUsageDTO.getFNumerator()));
|
||||
//子项分母
|
||||
bomDetails.setDenominator(materialUsageDTO.getFDenominator());
|
||||
bomDetails.setName(materialUsageDTO.getMaterialName());
|
||||
|
||||
@ -76,7 +76,7 @@ public class BomDetails extends BaseEntity {
|
||||
* 子项分子
|
||||
*/
|
||||
@JsonProperty("FNUMERATOR")
|
||||
private Double quantity;
|
||||
private String quantity;
|
||||
/**
|
||||
* 子项分母
|
||||
*/
|
||||
@ -106,4 +106,8 @@ public class BomDetails extends BaseEntity {
|
||||
* 子项单重
|
||||
*/
|
||||
private Double singleWeghit;
|
||||
/**
|
||||
*bom类型
|
||||
*/
|
||||
private String bomType;
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
package com.ruoyi.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 零件成本对象 part_cost
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("part_cost")
|
||||
public class PartCost extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@JsonProperty("FMaterialId.FNumber")
|
||||
private String materialCode;
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@JsonProperty("FMaterialName")
|
||||
private String materialName;
|
||||
/**
|
||||
* 成本价
|
||||
*/
|
||||
@JsonProperty("FPrice")
|
||||
private BigDecimal costPrice;
|
||||
/**
|
||||
* 创建日期
|
||||
*/
|
||||
@JsonProperty("FCreateDate")
|
||||
private Date createDate;
|
||||
/**
|
||||
* 车间
|
||||
*/
|
||||
@JsonProperty("FEntryWorkShopId.FName")
|
||||
private String workshop;
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
@JsonProperty("FUnitID.FName")
|
||||
private String unit;
|
||||
/**
|
||||
* 仓库
|
||||
*/
|
||||
@JsonProperty("FStockId.FName")
|
||||
private String warehouse;
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
@JsonProperty("FSpecification")
|
||||
private String specificationModel;
|
||||
|
||||
}
|
||||
@ -79,4 +79,8 @@ public class BomDetailsBo extends BaseEntity {
|
||||
* 单重
|
||||
*/
|
||||
private Double danzhong;
|
||||
/**
|
||||
*bom类型
|
||||
*/
|
||||
private String bomType;
|
||||
}
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
package com.ruoyi.system.domain.bo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 零件成本业务对象 part_cost
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PartCostBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@NotNull(message = "ID不能为空", groups = { EditGroup.class })
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@NotBlank(message = "物料编码不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FMaterialId.FNumber")
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@NotBlank(message = "物料名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FMaterialName")
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 成本价
|
||||
*/
|
||||
@NotNull(message = "成本价不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FPrice")
|
||||
private BigDecimal costPrice;
|
||||
|
||||
/**
|
||||
* 创建日期
|
||||
*/
|
||||
@NotNull(message = "创建日期不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FCreateDate")
|
||||
private Date createDate;
|
||||
|
||||
/**
|
||||
* 车间
|
||||
*/
|
||||
@NotBlank(message = "车间不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FEntryWorkShopId.FName")
|
||||
private String workshop;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
@NotBlank(message = "单位不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FUnitID.FName")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 仓库
|
||||
*/
|
||||
@NotBlank(message = "仓库不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FStockId.FName")
|
||||
private String warehouse;
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
@NotBlank(message = "规格型号", groups = { AddGroup.class, EditGroup.class })
|
||||
@JsonProperty("FSpecification")
|
||||
private String specificationModel;
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@Data
|
||||
public class BOMItem {
|
||||
int id;
|
||||
private List<KindegeeLogDTO> items;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.ruoyi.common.result;
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ConstructionDelayDTO {
|
||||
//生产令号
|
||||
@JsonProperty("F_HBYT_SCLH")
|
||||
private String F_HBYT_SCLH;
|
||||
//单据编码
|
||||
@JsonProperty("FBillNo")
|
||||
private String FBillNo;
|
||||
//车间名称
|
||||
@JsonProperty("FWorkShopID.FName")
|
||||
private String FWorkShopIDFName;
|
||||
//物料编码
|
||||
@JsonProperty("FMaterialId.FNumber")
|
||||
private String FMaterialIdFNumber;
|
||||
//物料名称
|
||||
@JsonProperty("FMaterialName")
|
||||
private String FMaterialName;
|
||||
//计划开工时间
|
||||
@JsonProperty("FPlanStartDate")
|
||||
private String FPlanStartDate;
|
||||
//计划完工时间
|
||||
@JsonProperty("FPlanFinishDate")
|
||||
private String FPlanFinishDate;
|
||||
//计划完工时间
|
||||
@JsonProperty("FPickMtrlStatus")
|
||||
private String FPickMtrlStatus;
|
||||
//超期天数
|
||||
private int Deydays;
|
||||
|
||||
@JsonProperty("FOperNumber")
|
||||
private String FOperNumber;
|
||||
|
||||
@JsonProperty("FOperQty")
|
||||
private String FOperQty;
|
||||
|
||||
@JsonProperty("FOutProcessId.FName")
|
||||
private String FProcessIdFName;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 质检检验单数据
|
||||
* @author tzy
|
||||
* @date 2025-10-26
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class InspectionSheetDTO {
|
||||
//生产令号
|
||||
@JsonProperty("F_UCHN_Text")
|
||||
private String productionOrderNumber;
|
||||
|
||||
//单据编码
|
||||
@JsonProperty("FBillNo")
|
||||
private String FBillNo;
|
||||
|
||||
//单据状态
|
||||
@JsonProperty("FDocumentStatus")
|
||||
private String DocumentStatus;
|
||||
|
||||
//物料编码
|
||||
@JsonProperty("FMaterialId.FNumber")
|
||||
private String FMaterialIdFNumber;
|
||||
|
||||
//物料名称
|
||||
@JsonProperty("FMaterialName")
|
||||
private String FMaterialName;
|
||||
|
||||
//规格型号
|
||||
@JsonProperty("FMaterialModel")
|
||||
private String FMaterialModel;
|
||||
|
||||
//质检状态
|
||||
@JsonProperty("FQCStatus")
|
||||
private String FQCStatus;
|
||||
|
||||
// 检验结果
|
||||
@JsonProperty("FInspectResult")
|
||||
private String FInspectResult;
|
||||
|
||||
// 单位
|
||||
@JsonProperty("FUnitID.FName")
|
||||
private String FUnitIDFName;
|
||||
|
||||
// 检验数量
|
||||
@JsonProperty("FInspectQty")
|
||||
private String FInspectQty;
|
||||
|
||||
// 合格数
|
||||
@JsonProperty("FQualifiedQty")
|
||||
private String FQualifiedQty;
|
||||
|
||||
// 不合格数
|
||||
@JsonProperty("FUnqualifiedQty")
|
||||
private String FUnqualifiedQty;
|
||||
|
||||
//超期天数
|
||||
private int Deydays;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class OperationPlannDTO {
|
||||
|
||||
@JsonProperty("FOperNumber")
|
||||
private String FOperNumber;
|
||||
|
||||
@JsonProperty("FOperQty")
|
||||
private String FOperQty;
|
||||
|
||||
@JsonProperty("FOutProcessId.FName")
|
||||
private String FProcessIdFName;
|
||||
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ProcessInspectionDTO {
|
||||
/** 单编号 */
|
||||
private String moBillNo;
|
||||
|
||||
/** 生产订单号 */
|
||||
private String moOrderNo;
|
||||
|
||||
/** 子订单号 */
|
||||
private String subOrderNo;
|
||||
|
||||
/** 物料名称 */
|
||||
private String fMaterialName;
|
||||
|
||||
/** 工序名称 */
|
||||
private String fProcessName;
|
||||
|
||||
/** 工作中心(工段)名称 */
|
||||
private String fWorkCenterName;
|
||||
|
||||
/** 检验状态(如:未完成、已完成) */
|
||||
private String fInspectStatus;
|
||||
|
||||
/** 待检数量 */
|
||||
private Integer fWaitInspectQty;
|
||||
|
||||
/** 已检验数量 */
|
||||
private Integer fFinishInspectQty;
|
||||
|
||||
/** 合格数量 */
|
||||
private Integer fQuaQty;
|
||||
|
||||
/** 返工数量 */
|
||||
private Integer fReworkQty;
|
||||
|
||||
/** 报废数量 */
|
||||
private Integer fFailQty;
|
||||
|
||||
/** 提交检验时间(字符串格式,如 "12-24") */
|
||||
private String fSubmitInspectTime;
|
||||
|
||||
/** 完成检验时间(字符串格式) */
|
||||
private String fFinishInspectTime;
|
||||
|
||||
/** 备注或描述 */
|
||||
private String fDescription;
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 工序汇报单实体
|
||||
* @author tzy
|
||||
* @date 2025-10-28
|
||||
*/
|
||||
@Data
|
||||
public class ProcessReportDTO {
|
||||
//生产令号
|
||||
@JsonProperty("F_HBYT_SCLH")
|
||||
private String FSCLH;
|
||||
|
||||
//单据编号
|
||||
@JsonProperty("FBillNo")
|
||||
private String FBillNo;
|
||||
|
||||
//加工车间
|
||||
@JsonProperty("FWorkShopID.FName")
|
||||
private String FWorkShopID;
|
||||
|
||||
//工序号
|
||||
@JsonProperty("FOperNumber")
|
||||
private String FOperNumber;
|
||||
//工序说明
|
||||
@JsonProperty("FOperDescription")
|
||||
private String FOperDescription;
|
||||
|
||||
|
||||
//合格数量
|
||||
@JsonProperty("FQuaQty")
|
||||
private String FQuaQty;
|
||||
//合格数量
|
||||
@JsonProperty("FMoNumber")
|
||||
private String FMoNumber;
|
||||
|
||||
// 完工数量
|
||||
@JsonProperty("FFinishQty")
|
||||
private String FFinishQty;
|
||||
|
||||
// 合格品入库数量
|
||||
@JsonProperty("FStockInQuaAuxQty")
|
||||
private String FStockInQuaAuxQty;
|
||||
|
||||
//不合格品入库数量
|
||||
@JsonProperty("FStockInFailAuxQty")
|
||||
private String FStockInFailAuxQty;
|
||||
|
||||
//入库点
|
||||
@JsonProperty("F_HBYT_RKD")
|
||||
private String FRKD;
|
||||
|
||||
//单据日期
|
||||
@JsonProperty("FDate")
|
||||
private String FDate;
|
||||
|
||||
}
|
||||
@ -19,6 +19,11 @@ public class ProcessRouteXuDTO {
|
||||
* 工序路线描述
|
||||
*/
|
||||
private String processDescription;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String errorMessage;
|
||||
|
||||
/**
|
||||
* 工艺路线
|
||||
*/
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 工序转移单
|
||||
* @author tzy
|
||||
* @date 2025-10-28
|
||||
*/
|
||||
@Data
|
||||
public class ProcessTransferFormDTO {
|
||||
|
||||
//生产令号
|
||||
@JsonProperty("F_HBYT_SCLH")
|
||||
private String FSCLH;
|
||||
//单据编码
|
||||
@JsonProperty("FBillNo")
|
||||
private String FBillNo;
|
||||
//单据编码
|
||||
@JsonProperty("FDocumentStatus")
|
||||
private String FDocumentStatus;
|
||||
//单据编码
|
||||
@JsonProperty("FMOBillNo")
|
||||
private String FMOBillNo;
|
||||
//产品编码
|
||||
@JsonProperty("FProductId.FNumber")
|
||||
private String FProductIdNumber;
|
||||
|
||||
//产品名称
|
||||
@JsonProperty("FProductName")
|
||||
private String FProductName;
|
||||
|
||||
//转出加工车间
|
||||
@JsonProperty("FOutDeptId.FName")
|
||||
private String FOutDeptIdFName;
|
||||
|
||||
//转出工序计划号
|
||||
@JsonProperty("FOutOperNumber")
|
||||
private String FOutOperNumber;
|
||||
|
||||
//转出作业
|
||||
@JsonProperty("FOutProcessId.FName")
|
||||
private String FOutProcessIdName;
|
||||
|
||||
//转入加工车间
|
||||
@JsonProperty("FInDeptId.FName")
|
||||
private String FInDeptIdFName;
|
||||
|
||||
//转入工序计划号
|
||||
@JsonProperty("FInOperNumber")
|
||||
private String FInOperNumber;
|
||||
|
||||
//转入作业
|
||||
@JsonProperty("FInProcessId.FName")
|
||||
private String FInProcessIdFName;
|
||||
|
||||
//工序单位
|
||||
@JsonProperty("FOperUnitId.FName")
|
||||
private String FOperUnit;
|
||||
|
||||
//转移数量
|
||||
@JsonProperty("FOperTransferQty")
|
||||
private String FOperTransferQty;
|
||||
|
||||
//合格数量
|
||||
@JsonProperty("FOperQualifiedQty")
|
||||
private String FOperQualifiedQty;
|
||||
|
||||
//工废数量
|
||||
@JsonProperty("FOperProFailQty")
|
||||
private String FOperProFailQty;
|
||||
|
||||
//创建日期
|
||||
@JsonProperty("FCreateDate")
|
||||
private String FCreateDate;
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package com.ruoyi.system.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* 生产订单开工未领料数据
|
||||
* @author tzy
|
||||
* @date 2025-10-26
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class ProductionOrderDTO {
|
||||
|
||||
//生产令号
|
||||
@JsonProperty("F_HBYT_SCLH")
|
||||
private String productionOrderNumber;
|
||||
|
||||
//单据编码
|
||||
@JsonProperty("FBillNo")
|
||||
private String FBillNo;
|
||||
|
||||
//单据状态
|
||||
@JsonProperty("FDocumentStatus")
|
||||
private String DocumentStatus;
|
||||
|
||||
//物料编码
|
||||
@JsonProperty("FMaterialId.FNumber")
|
||||
private String FMaterialIdFNumber;
|
||||
|
||||
//物料名称
|
||||
@JsonProperty("FMaterialName")
|
||||
private String FMaterialName;
|
||||
|
||||
//材质
|
||||
@JsonProperty("F_UCHN_BaseProperty_qtr")
|
||||
private String material;
|
||||
|
||||
//单位
|
||||
@JsonProperty("FUnitId.FName")
|
||||
private String unit;
|
||||
|
||||
//生产车间
|
||||
@JsonProperty("FWorkShopID.FName")
|
||||
private String productionWorkshop;
|
||||
|
||||
//数量
|
||||
@JsonProperty("FQty")
|
||||
private String quantity;
|
||||
|
||||
//业务状态
|
||||
@JsonProperty("FStatus")
|
||||
private String businessStatus;
|
||||
|
||||
//领料状态
|
||||
@JsonProperty("FPickMtrlStatus")
|
||||
private String materialRequisitionStatus;
|
||||
|
||||
//计划开工时间
|
||||
@JsonProperty("FPlanStartDate")
|
||||
private String FPlanStartDate;
|
||||
|
||||
//计划完工时间
|
||||
@JsonProperty("FPlanFinishDate")
|
||||
private String FPlanFinishDate;
|
||||
|
||||
//超期天数
|
||||
private int Deydays;
|
||||
}
|
||||
@ -52,5 +52,10 @@ public class PurchaseOrderExcelDTO {
|
||||
*/
|
||||
@JsonProperty("F_UCHN_Text2")
|
||||
private String FUCHNText2;
|
||||
/**
|
||||
* 创建日期
|
||||
*/
|
||||
@JsonProperty("FCreateDate")
|
||||
private String FCreateDate;
|
||||
|
||||
}
|
||||
|
||||
@ -79,11 +79,17 @@ public class PurchaseRequestExcelDTO {
|
||||
* 生产令号
|
||||
*/
|
||||
@JsonProperty("F_UCHN_Text")
|
||||
private String FUCHNText;/**
|
||||
private String FUCHNText;
|
||||
/**
|
||||
* 生产令号
|
||||
*/
|
||||
@JsonProperty("FCreatorId.FName")
|
||||
private String FCreatorIdFName;
|
||||
/**
|
||||
* 创建日期
|
||||
*/
|
||||
@JsonProperty("FCreateDate")
|
||||
private String FCreateDate;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -103,5 +103,8 @@ public class BomDetailsVo {
|
||||
private Double danZhong;
|
||||
|
||||
private Double singleWeghit;
|
||||
|
||||
/**
|
||||
*bom类型
|
||||
*/
|
||||
private String bomType;
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ public class ElectricalMaterialBomVO {
|
||||
* 品牌
|
||||
*/
|
||||
@ExcelProperty(value = "品牌")
|
||||
private Double Brand;
|
||||
private String Brand;
|
||||
|
||||
/**
|
||||
* 单台数量
|
||||
@ -58,7 +58,7 @@ public class ElectricalMaterialBomVO {
|
||||
* 单位
|
||||
*/
|
||||
@ExcelProperty(value = "单位")
|
||||
private Double unit;
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* 零件成本视图对象 part_cost
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class PartCostVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@ExcelProperty(value = "ID")
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@ExcelProperty(value = "物料编码")
|
||||
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@ExcelProperty(value = "物料名称")
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 成本价
|
||||
*/
|
||||
@ExcelProperty(value = "成本价")
|
||||
private BigDecimal costPrice;
|
||||
|
||||
/**
|
||||
* 创建日期
|
||||
*/
|
||||
@ExcelProperty(value = "创建日期")
|
||||
private Date createDate;
|
||||
|
||||
/**
|
||||
* 车间
|
||||
*/
|
||||
@ExcelProperty(value = "车间")
|
||||
private String workshop;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
@ExcelProperty(value = "单位")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 仓库
|
||||
*/
|
||||
@ExcelProperty(value = "仓库")
|
||||
private String warehouse;
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
@ExcelProperty(value = "规格型号")
|
||||
private String specificationModel;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.ruoyi.system.mapper;
|
||||
|
||||
import com.ruoyi.system.domain.PartCost;
|
||||
import com.ruoyi.system.domain.vo.PartCostVo;
|
||||
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 零件成本Mapper接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
public interface PartCostMapper extends BaseMapperPlus<PartCostMapper, PartCost, PartCostVo> {
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -18,10 +18,9 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@ -104,14 +103,24 @@ public class PDFGenerator {
|
||||
throw new RuntimeException("无法创建目录: " + directoryPath);
|
||||
}
|
||||
} else {
|
||||
// 如果目录存在,删除其中的所有文件
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (!file.delete()) {
|
||||
System.err.println("无法删除文件: " + file.getAbsolutePath());
|
||||
// 目录存在:使用NIO递归清理目录内容(不删除根目录本身)
|
||||
try {
|
||||
Path root = Paths.get(directoryPath);
|
||||
if (java.nio.file.Files.exists(root)) {
|
||||
try (java.util.stream.Stream<java.nio.file.Path> walk = java.nio.file.Files.walk(root)) {
|
||||
walk.filter(p -> !p.equals(root))
|
||||
.sorted(java.util.Comparator.reverseOrder()) // 先删子路径再删父路径
|
||||
.forEach(p -> {
|
||||
try {
|
||||
java.nio.file.Files.deleteIfExists(p);
|
||||
} catch (IOException e) {
|
||||
System.err.println("删除失败: " + p.toString() + ": " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("清理目录失败: " + directoryPath + ", " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
for (CombinedDTO combinedVo : combinedVoList) {
|
||||
@ -125,10 +134,12 @@ public class PDFGenerator {
|
||||
String materialCode;
|
||||
Long fmoQty;
|
||||
String fDepartmentName;
|
||||
// 获取第一序的工序名称
|
||||
String OrderNumber = "";
|
||||
// 获取第一序的工序名称
|
||||
List<PlannedProcessVo> processes = combinedVo.getProcesses();
|
||||
if (!processes.isEmpty()) {
|
||||
fProcessName = processes.get(0).getFProcessName();
|
||||
OrderNumber = combinedVo.getOrderNumber();
|
||||
productionOrderNumber = String.valueOf(combinedVo.getProcesses().get(0).getFBillNo());
|
||||
starttime = combinedVo.getProcesses().get(0).getFPlanStartTime();
|
||||
endtime = combinedVo.getProcesses().get(0).getFPlanFinishTime();
|
||||
@ -166,11 +177,11 @@ public class PDFGenerator {
|
||||
|
||||
// 获取当前时间的毫秒时间戳
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String pdfPath = departmentFolder.getAbsolutePath() + "\\" + fDepartmentName + "_"
|
||||
+ materialCode1.replace("/", "_") + "_" + productionOrderNumber + ".pdf";
|
||||
String pdfPath = departmentFolder.getAbsolutePath() + "\\" + fDepartmentName + "_" + materialCode1.replace("/", "_") + "_" + productionOrderNumber + ".pdf";
|
||||
PDDocument document = null;
|
||||
try {
|
||||
// 创建 PDF 文件并写入内容
|
||||
PDDocument document = new PDDocument();
|
||||
document = new PDDocument();
|
||||
PDPage page = new PDPage();
|
||||
document.addPage(page);
|
||||
PDType0Font font = PDType0Font.load(document, new File(fontPath));
|
||||
@ -223,14 +234,15 @@ public class PDFGenerator {
|
||||
float[] processColWidths = { 35, 78, 35, 55, 45, 170, 55, 60, 60 };
|
||||
yStart = processTableStartY;
|
||||
|
||||
drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] {
|
||||
// 使用支持换行的方法绘制表头
|
||||
yStart = drawTableRowWithWrap(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] {
|
||||
"工序号", "工序名称", "数量", "工作中心", "工时(分)", "工序说明", "控制码", "开始时间", "结束时间" }, document, page,
|
||||
rowHeight, pageHeight);
|
||||
|
||||
for (PlannedProcessVo process : combinedVo.getProcesses()) {
|
||||
SimpleDateFormat formatte1r = new SimpleDateFormat("yyyy-MM-dd");
|
||||
yStart -= rowHeight;
|
||||
drawTableRow(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] {
|
||||
// 使用支持换行的方法绘制数据行,特别是工序说明字段
|
||||
yStart = drawTableRowWithWrap(contentStream, font, margin, yStart, tableWidth, processColWidths, new String[] {
|
||||
String.valueOf(process.getFOperNumber()), process.getFProcessName(),
|
||||
String.valueOf(process.getFOperQty()),
|
||||
process.getFWorkCenterName(), String.format("%.2f", process.getFActivity1BaseQty()),
|
||||
@ -309,6 +321,14 @@ public class PDFGenerator {
|
||||
pdfPaths.add(pdfPath);
|
||||
} catch (IOException | WriterException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (document != null) {
|
||||
try {
|
||||
document.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -478,4 +498,122 @@ public class PDFGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
// ... 其他代码 ...
|
||||
|
||||
// Java 8兼容的文本换行处理方法
|
||||
private static List<String> wrapText(String text, PDType0Font font, float fontSize, float maxWidth) throws IOException {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
lines.add("");
|
||||
return lines;
|
||||
}
|
||||
|
||||
// 去除换行符,用空格替换
|
||||
text = text.replace("\n", " ").replace("\r", " ").trim();
|
||||
|
||||
// 增加边距,确保文本不会超出边界
|
||||
float effectiveWidth = maxWidth - 20; // 增加边距到20个单位
|
||||
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
|
||||
// 逐字符处理,更好地支持中文
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char currentChar = text.charAt(i);
|
||||
String testLine = currentLine.toString() + currentChar;
|
||||
|
||||
float textWidth = font.getStringWidth(testLine) / 1000 * fontSize;
|
||||
|
||||
if (textWidth <= effectiveWidth) {
|
||||
currentLine.append(currentChar);
|
||||
} else {
|
||||
// 当前行已满,开始新行
|
||||
if (currentLine.length() > 0) {
|
||||
lines.add(currentLine.toString().trim());
|
||||
currentLine = new StringBuilder();
|
||||
currentLine.append(currentChar);
|
||||
} else {
|
||||
// 单个字符就超宽(极少见情况),强制添加
|
||||
lines.add(String.valueOf(currentChar));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一行
|
||||
if (currentLine.length() > 0) {
|
||||
lines.add(currentLine.toString().trim());
|
||||
}
|
||||
|
||||
// 如果没有任何内容,至少返回一个空行
|
||||
if (lines.isEmpty()) {
|
||||
lines.add("");
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
// Java 8兼容的改进表格绘制方法,支持自动换行
|
||||
private static float drawTableRowWithWrap(PDPageContentStream contentStream, PDType0Font font, float margin,
|
||||
float yStart, float tableWidth, float[] colWidths, String[] cells, PDDocument document,
|
||||
PDPage page, float baseRowHeight, float pageHeight) throws IOException {
|
||||
|
||||
float nextX = margin;
|
||||
float nextY = yStart;
|
||||
float fontSize = 10;
|
||||
int maxColumns = Math.min(cells.length, colWidths.length);
|
||||
|
||||
// 计算每列的文本行数,确定实际行高
|
||||
List<List<String>> allCellLines = new ArrayList<List<String>>();
|
||||
int maxLines = 1;
|
||||
|
||||
for (int i = 0; i < maxColumns; i++) {
|
||||
String cellText = cells[i] != null ? cells[i] : "";
|
||||
List<String> lines = wrapText(cellText, font, fontSize, colWidths[i]);
|
||||
allCellLines.add(lines);
|
||||
maxLines = Math.max(maxLines, lines.size());
|
||||
}
|
||||
|
||||
float actualRowHeight = baseRowHeight * maxLines;
|
||||
|
||||
// 检查是否需要分页
|
||||
if (nextY - actualRowHeight < margin) {
|
||||
contentStream.close();
|
||||
// 创建新页面
|
||||
page = new PDPage();
|
||||
document.addPage(page);
|
||||
contentStream = new PDPageContentStream(document, page);
|
||||
// 重置Y坐标为新页面顶部
|
||||
nextY = pageHeight - margin;
|
||||
}
|
||||
|
||||
// 绘制表格边框和内容
|
||||
nextX = margin;
|
||||
for (int i = 0; i < maxColumns; i++) {
|
||||
List<String> lines = allCellLines.get(i);
|
||||
|
||||
// 绘制单元格边框
|
||||
contentStream.moveTo(nextX, nextY);
|
||||
contentStream.lineTo(nextX, nextY - actualRowHeight);
|
||||
contentStream.lineTo(nextX + colWidths[i], nextY - actualRowHeight);
|
||||
contentStream.lineTo(nextX + colWidths[i], nextY);
|
||||
contentStream.closeAndStroke();
|
||||
|
||||
// 绘制文本内容
|
||||
for (int lineIndex = 0; lineIndex < lines.size(); lineIndex++) {
|
||||
String line = lines.get(lineIndex);
|
||||
if (!line.isEmpty()) {
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(font, fontSize);
|
||||
float textY = nextY - 15 - (lineIndex * (fontSize + 2));
|
||||
contentStream.newLineAtOffset(nextX + 8, textY); // 增加左边距到8个单位
|
||||
contentStream.showText(line);
|
||||
contentStream.endText();
|
||||
}
|
||||
}
|
||||
|
||||
nextX += colWidths[i];
|
||||
}
|
||||
|
||||
return nextY - actualRowHeight; // 返回下一行的Y坐标
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -70,7 +70,6 @@ public class updatePcessPlanConver {
|
||||
String formId = "SFC_OperationPlanning";
|
||||
//调用接口
|
||||
String resultJson = client.save(formId, jsonOutput);
|
||||
System.out.println("调用接口:+++++" + jsonOutput);
|
||||
//用于记录结果
|
||||
Gson gson = new Gson();
|
||||
//对返回结果进行解析和校验
|
||||
@ -108,7 +107,6 @@ public class updatePcessPlanConver {
|
||||
//业务对象标识工序计划表
|
||||
String formId = "SFC_OperationPlanning";
|
||||
//调用接口
|
||||
System.out.println("调用接口:"+model.getFProcessId_number()+"+++++" + jsonOutput);
|
||||
String resultJson = client.save(formId, jsonOutput);
|
||||
//用于记录结果
|
||||
Gson gson = new Gson();
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
package com.ruoyi.system.service;
|
||||
|
||||
import com.ruoyi.system.domain.vo.PartCostVo;
|
||||
import com.ruoyi.system.domain.bo.PartCostBo;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 零件成本Service接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
public interface IPartCostService {
|
||||
|
||||
/**
|
||||
* 查询零件成本
|
||||
*/
|
||||
PartCostVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询零件成本列表
|
||||
*/
|
||||
TableDataInfo<PartCostVo> queryPageList(PartCostBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询零件成本列表
|
||||
*/
|
||||
List<PartCostVo> queryList(PartCostBo bo);
|
||||
|
||||
/**
|
||||
* 新增零件成本
|
||||
*/
|
||||
Boolean insertByBo(PartCostBo bo);
|
||||
|
||||
/**
|
||||
* 修改零件成本
|
||||
*/
|
||||
Boolean updateByBo(PartCostBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除零件成本信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
boolean getObtainPartData();
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.ruoyi.system.service;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.dto.BOMItem;
|
||||
import com.ruoyi.system.domain.BomDetails;
|
||||
import com.ruoyi.system.domain.MaterialBom;
|
||||
import com.ruoyi.system.domain.ProcessRoute;
|
||||
@ -84,7 +85,7 @@ public interface IProcessRouteService {
|
||||
* 推送工艺路线
|
||||
*/
|
||||
|
||||
ProcessRoutePushResultDTO pushRouteBom(String rooteProdet);
|
||||
R<ProcessRoutePushResultDTO> pushRouteBom(String rooteProdet);
|
||||
/**
|
||||
* 获取所有的项目令号
|
||||
*/
|
||||
@ -143,4 +144,9 @@ public interface IProcessRouteService {
|
||||
String getRouteCode(String materialCode,String code);
|
||||
|
||||
List<ProcessRoute> selectByProjectNumber(String productionOrderNo);
|
||||
|
||||
R<BOMItem> viewGetBomUploadStatus(String rooteProdet);
|
||||
|
||||
//根据令号和物料编码 查询工艺路线
|
||||
ProcessRoute getProcessRoutesXuTime(String productionOrderNo, String materialCode,String xu);
|
||||
}
|
||||
|
||||
@ -107,6 +107,7 @@ public class BomDetailsServiceImpl implements IBomDetailsService {
|
||||
lqw.like(StringUtils.isNotBlank(bo.getFName()), BomDetails::getFName, bo.getFName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStats()), BomDetails::getStats, bo.getStats());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getWareHouse()), BomDetails::getWareHouse, bo.getWareHouse());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getBomType()), BomDetails::getBomType, bo.getBomType());
|
||||
lqw.orderByAsc(BomDetails::getTotalWeight);
|
||||
return lqw;
|
||||
}
|
||||
@ -222,11 +223,10 @@ public class BomDetailsServiceImpl implements IBomDetailsService {
|
||||
MaterialBom matchedMaterialBom = materialBomMap.get(key);
|
||||
if (matchedMaterialBom != null) {
|
||||
if (matchedMaterialBom.getUnit().equals("根")) {
|
||||
bomDetail.setQuantity(Double.valueOf(String.valueOf(matchedMaterialBom.getQuantity()).split("/")[0]));
|
||||
bomDetail.setQuantity(String.valueOf(matchedMaterialBom.getQuantity()).split("/")[0]);
|
||||
bomDetail.setDenominator(Double.valueOf(String.valueOf(matchedMaterialBom.getQuantity()).split("/")[1]));
|
||||
|
||||
} else {
|
||||
bomDetail.setQuantity(Double.valueOf(String.valueOf(matchedMaterialBom.getQuantity())));
|
||||
bomDetail.setQuantity(String.valueOf(matchedMaterialBom.getQuantity()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,21 +179,6 @@ public class ImMaterialServiceImpl implements IImMaterialService {
|
||||
try {
|
||||
|
||||
LambdaQueryWrapper<ImMaterial> lqw = buildQueryWrapper(bo);
|
||||
lqw.like(StringUtils.isNotBlank(bo.getMaterialCode()), ImMaterial::getMaterialCode, bo.getMaterialCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), ImMaterial::getMaterialName, bo.getMaterialName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getClassificationName()), ImMaterial::getClassificationName, bo.getClassificationName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getImCategory()), ImMaterial::getImCategory, bo.getImCategory());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getMaterialQuality()), ImMaterial::getMaterialQuality, bo.getMaterialQuality());
|
||||
lqw.eq(bo.getSingleWeight() != null, ImMaterial::getSingleWeight, bo.getSingleWeight());
|
||||
lqw.eq( ImMaterial::getForbidStatus, "A");
|
||||
lqw.like(StringUtils.isNotBlank(bo.getUnit()), ImMaterial::getUnit, bo.getUnit());
|
||||
lqw.like(bo.getFlag() != null, ImMaterial::getFlag, bo.getFlag());
|
||||
lqw.orderBy(true, false, ImMaterial::getModifyDate);
|
||||
|
||||
|
||||
System.out.println("+++++++++++++++++++++++++++++++++++++++"+lqw.getSqlSegment());
|
||||
|
||||
// 执行查询
|
||||
Page<ImMaterialVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
if (CollectionUtils.isEmpty(result.getRecords())) {
|
||||
return TableDataInfo.build(result); // 如果结果为空,直接返回
|
||||
@ -414,11 +399,10 @@ public class ImMaterialServiceImpl implements IImMaterialService {
|
||||
lqw.like(StringUtils.isNotBlank(bo.getImCategory()), ImMaterial::getImCategory, bo.getImCategory());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getMaterialQuality()), ImMaterial::getMaterialQuality, bo.getMaterialQuality());
|
||||
lqw.eq(bo.getSingleWeight() != null, ImMaterial::getSingleWeight, bo.getSingleWeight());
|
||||
lqw.eq(bo.getForbidStatus() != null, ImMaterial::getForbidStatus, "否");
|
||||
lqw.like(bo.getUnitPrice() != null, ImMaterial::getUnitPrice, bo.getUnitPrice());
|
||||
lqw.eq( ImMaterial::getForbidStatus, "A");
|
||||
lqw.like(StringUtils.isNotBlank(bo.getUnit()), ImMaterial::getUnit, bo.getUnit());
|
||||
lqw.like(bo.getFlag() != null, ImMaterial::getFlag, bo.getFlag());
|
||||
lqw.orderBy(true, false, ImMaterial::getUnit);
|
||||
lqw.orderBy(true, false, ImMaterial::getModifyDate);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@ -745,9 +729,11 @@ public class ImMaterialServiceImpl implements IImMaterialService {
|
||||
// 根据 materialId 查询是否存在
|
||||
ImMaterial existing = baseMapper.selectByMid(imMaterial.getMaterialId());
|
||||
if (imMaterial.getForbidStatus().equals("A")){
|
||||
imMaterial.setForbidStatus("否");
|
||||
imMaterial.setForbidStatus("A");
|
||||
imMaterial.setUpdateTime(new Date());
|
||||
}else {
|
||||
imMaterial.setForbidStatus("是");
|
||||
imMaterial.setForbidStatus("B");
|
||||
imMaterial.setUpdateTime(new Date());
|
||||
}
|
||||
|
||||
if (existing != null) {
|
||||
|
||||
@ -145,7 +145,7 @@ public class MaterialBomServiceImpl implements IMaterialBomService {
|
||||
bomDetails.setName(bo.getMaterialName());
|
||||
bomDetails.setName(bo.getMaterialName());
|
||||
bomDetails.setDenominator(1.0);
|
||||
bomDetails.setQuantity(Double.valueOf(bo.getQuantity()));
|
||||
bomDetails.setQuantity(bo.getQuantity());
|
||||
bomDetails.setStats("外购");
|
||||
bomDetails.setMaterial(bo.getMaterialType());
|
||||
int flag = bomDetailsMapper.insert(bomDetails);
|
||||
|
||||
@ -0,0 +1,166 @@
|
||||
package com.ruoyi.system.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.runner.JdUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.system.domain.bo.PartCostBo;
|
||||
import com.ruoyi.system.domain.vo.PartCostVo;
|
||||
import com.ruoyi.system.domain.PartCost;
|
||||
import com.ruoyi.system.mapper.PartCostMapper;
|
||||
import com.ruoyi.system.service.IPartCostService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 零件成本Service业务层处理
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-24
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class PartCostServiceImpl implements IPartCostService {
|
||||
|
||||
private final PartCostMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询零件成本
|
||||
*/
|
||||
@Override
|
||||
public PartCostVo queryById(Long id){
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询零件成本列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<PartCostVo> queryPageList(PartCostBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<PartCost> lqw = buildQueryWrapper(bo);
|
||||
Page<PartCostVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询零件成本列表
|
||||
*/
|
||||
@Override
|
||||
public List<PartCostVo> queryList(PartCostBo bo) {
|
||||
LambdaQueryWrapper<PartCost> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<PartCost> buildQueryWrapper(PartCostBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<PartCost> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getMaterialCode()), PartCost::getMaterialCode, bo.getMaterialCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), PartCost::getMaterialName, bo.getMaterialName());
|
||||
lqw.eq(bo.getCostPrice() != null, PartCost::getCostPrice, bo.getCostPrice());
|
||||
lqw.eq(bo.getCreateDate() != null, PartCost::getCreateDate, bo.getCreateDate());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getWorkshop()), PartCost::getWorkshop, bo.getWorkshop());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), PartCost::getUnit, bo.getUnit());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getWarehouse()), PartCost::getWarehouse, bo.getWarehouse());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getSpecificationModel()), PartCost::getSpecificationModel, bo.getSpecificationModel());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增零件成本
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(PartCostBo bo) {
|
||||
PartCost add = BeanUtil.toBean(bo, PartCost.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改零件成本
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(PartCostBo bo) {
|
||||
PartCost update = BeanUtil.toBean(bo, PartCost.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(PartCost entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除零件成本
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getObtainPartData() {
|
||||
List<PartCost> list = JdUtil.getObtainPartData();
|
||||
if (list == null || list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, PartCost> uniq = new LinkedHashMap<>();
|
||||
for (PartCost pc : list) {
|
||||
if (pc == null) continue;
|
||||
|
||||
String code = pc.getMaterialCode();
|
||||
String name = pc.getMaterialName();
|
||||
BigDecimal cost = pc.getCostPrice();
|
||||
|
||||
// 过滤无效数据
|
||||
if (StringUtils.isBlank(code) || StringUtils.isBlank(name) || cost == null || cost.compareTo(BigDecimal.ZERO) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 以 物料编码 + 名称 为唯一键
|
||||
String key = code + "|" + name;
|
||||
|
||||
PartCost existing = uniq.get(key);
|
||||
// 保留 createDate 最新的
|
||||
if (existing == null ||
|
||||
(pc.getCreateDate() != null &&
|
||||
(existing.getCreateDate() == null || pc.getCreateDate().after(existing.getCreateDate())))) {
|
||||
uniq.put(key, pc);
|
||||
}
|
||||
}
|
||||
|
||||
List<PartCost> deduped = new ArrayList<>(uniq.values());
|
||||
if (deduped.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除旧记录
|
||||
for (PartCost pc : deduped) {
|
||||
LambdaQueryWrapper<PartCost> delWrapper = Wrappers.lambdaQuery();
|
||||
delWrapper.eq(PartCost::getMaterialCode, pc.getMaterialCode())
|
||||
.eq(PartCost::getMaterialName, pc.getMaterialName());
|
||||
baseMapper.delete(delWrapper);
|
||||
}
|
||||
|
||||
// 批量插入最新记录
|
||||
return baseMapper.insertBatch(deduped);
|
||||
}
|
||||
|
||||
}
|
||||
@ -538,7 +538,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService {
|
||||
log.info("出图接口响应=====>{}", response);
|
||||
// 2. 开始轮询状态接口,直到完成
|
||||
boolean finished = false;
|
||||
int maxRetry = 60; // 最多轮询 60 次(根据需求调整,比如 60*5s=5分钟)
|
||||
int maxRetry = 360; // 最多轮询 60 次(根据需求调整,比如 60*5s=5分钟)
|
||||
int count = 0;
|
||||
|
||||
while (!finished && count < maxRetry) {
|
||||
@ -968,9 +968,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService {
|
||||
FigureSave figureSave = figureSaveMapper.selectById(id);
|
||||
ProcessOrderPro processOrderPro = baseMapper.selectById(figureSave);
|
||||
if (figureSave == null) return "图纸信息不存在";
|
||||
|
||||
String code = figureSave.getProductionCode();
|
||||
|
||||
// 2. 拼接本地路径和FTP路径
|
||||
String localPath = Constants.BASIC_URL;
|
||||
String ftpPath = "";
|
||||
@ -1252,7 +1250,7 @@ public class ProcessOrderProServiceImpl implements IProcessOrderProService {
|
||||
dto.setRawMaterialName(bom.getMaterialName());
|
||||
dto.setBomMaterial(bom.getMaterialType());
|
||||
dto.setBomUnit(bom.getUnit());
|
||||
|
||||
|
||||
// 单位转换:如果单位为mm,则数值乘以1000
|
||||
String quantity = bom.getQuantity();
|
||||
if ("mm".equals(bom.getUnit()) && quantity != null) {
|
||||
|
||||
@ -19,11 +19,12 @@ import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.system.domain.dto.BOMItem;
|
||||
import com.ruoyi.system.domain.dto.BOMUploadResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.controller.ProcessRouteController;
|
||||
import com.ruoyi.system.domain.*;
|
||||
import com.ruoyi.system.domain.bo.MaterialBomBo;
|
||||
import com.ruoyi.system.domain.bo.ProcessOrderProBo;
|
||||
import com.ruoyi.system.domain.bo.ProcessRouteBo;
|
||||
import com.ruoyi.system.domain.dto.*;
|
||||
import com.ruoyi.system.domain.vo.*;
|
||||
@ -265,7 +266,6 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param materialCode
|
||||
* @return
|
||||
@ -291,8 +291,40 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
@Override
|
||||
public List<ProcessRoute> selectByProjectNumber(String productionOrderNo) {
|
||||
LambdaQueryWrapper<ProcessRoute> war = new LambdaQueryWrapper<>();
|
||||
war.eq(ProcessRoute::getRouteDescription,productionOrderNo);
|
||||
return baseMapper.selectList(war);
|
||||
war.eq(ProcessRoute::getRouteDescription, productionOrderNo);
|
||||
return baseMapper.selectList(war);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取bom的上传状态
|
||||
*/
|
||||
@Override
|
||||
public R<BOMItem> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param productionOrderNo
|
||||
* @param materialCode
|
||||
* @param xu
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ProcessRoute getProcessRoutesXuTime(String productionOrderNo, String materialCode, String xu) {
|
||||
LambdaQueryWrapper<ProcessRoute> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ProcessRoute::getRouteDescription, productionOrderNo)
|
||||
.eq(ProcessRoute::getMaterialCode, materialCode)
|
||||
.eq(ProcessRoute::getProcessNo,xu);
|
||||
if (baseMapper.selectOne(wrapper) != null) {
|
||||
return baseMapper.selectOne(wrapper);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -569,8 +601,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
saveBomDetails(bomDetailsVos);
|
||||
List<ProcessRoute> routeArrayList = new ArrayList<>();
|
||||
Map<String, Double> inventoryCache = new HashMap<>();
|
||||
|
||||
|
||||
// 批量查询所有需要的库存信息
|
||||
boolean allEmpty = processRoutes.stream().allMatch(route -> route.getProcessNo() == null && route.getProcessName() == null);
|
||||
//获取工艺中所有的时间 挑选出最早的时间和最晚的时间
|
||||
// 获取最早的开始时间
|
||||
@ -585,13 +616,13 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
.max(Comparator.comparing(ProcessRoute::getXuEndTime))
|
||||
.map(ProcessRoute::getXuEndTime)
|
||||
.orElse(null);
|
||||
//更新至计划模块中
|
||||
//更新至计划模块中
|
||||
if (earliestStartTime != null && latestEndTime != null) {
|
||||
ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(processRoutes.get(0).getRouteDescription());
|
||||
ProcessOrderPro processOrderPro = processOrderProMapper.selectByProjectNumber(processRoutes.get(0).getRouteDescription());
|
||||
processOrderPro.setPlanStartTime(earliestStartTime);
|
||||
processOrderPro.setPlanEndTime(latestEndTime);
|
||||
processOrderPro.setUpdateTime(new Date());
|
||||
log.info("更新计划生成令号为:{},计划开始时间:{},计划结束时间:{}",processRoutes.get(0).getRouteDescription(), earliestStartTime, latestEndTime);
|
||||
log.info("更新计划生成令号为:{},计划开始时间:{},计划结束时间:{}", processRoutes.get(0).getRouteDescription(), earliestStartTime, latestEndTime);
|
||||
processOrderProMapper.updateById(processOrderPro);
|
||||
}
|
||||
|
||||
@ -681,23 +712,42 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ProcessRoute processRoute : processRoutes) {
|
||||
if (processRoute.getProcessNo() != null
|
||||
||processRoute.getWorkCenter()!= null
|
||||
||processRoute.getProcessName() != null
|
||||
||processRoute.getMaterial().equals("总装部件")) {
|
||||
processRoute.setActivityUnit("分");
|
||||
processRoute.setCreateTime(new Date());
|
||||
processRoute.setUpdateTime(new Date());
|
||||
processRoute.setBatchQuantity(processRoute.getBatchQuantity());
|
||||
processRoute.setUnitQuantity(processRoute.getUnitQuantity());
|
||||
routeArrayList.add(processRoute);
|
||||
}
|
||||
Date now = new Date();
|
||||
|
||||
// 先组装 routeArrayList
|
||||
routeArrayList = processRoutes.stream()
|
||||
.filter(pr -> pr.getProcessNo() != null
|
||||
|| pr.getWorkCenter() != null
|
||||
|| pr.getProcessName() != null)
|
||||
.map(pr -> {
|
||||
// 如果描述为空,则用工序控制码
|
||||
if (pr.getProcessDescription() == null || pr.getProcessDescription().isEmpty()) {
|
||||
pr.setProcessDescription(pr.getProcessName());
|
||||
}
|
||||
// 公共逻辑
|
||||
pr.setActivityUnit("分");
|
||||
pr.setCreateTime(now);
|
||||
pr.setUpdateTime(now);
|
||||
return pr;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// ✅ 校验是否存在相同物料编码 + 相同工序号
|
||||
Set<String> duplicateKeys = routeArrayList.stream()
|
||||
.map(pr -> pr.getMaterialCode() + "-" + pr.getProcessNo())
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.groupingBy(key -> key, Collectors.counting()))
|
||||
.entrySet().stream()
|
||||
.filter(e -> e.getValue() > 1)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!duplicateKeys.isEmpty()) {
|
||||
log.error("发现重复的物料编码+工序号组合: {}", duplicateKeys);
|
||||
throw new RuntimeException("存在重复的物料编码和工序号组合: " + duplicateKeys);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
return baseMapper.insertBatch(routeArrayList);
|
||||
} catch (Exception e) {
|
||||
log.error("批量插入工艺路线失败", e);
|
||||
@ -733,10 +783,10 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
if ("mm".equals(unit)) {
|
||||
// 将毫米转换为米并保留4位小数
|
||||
materialBom.setQuantity(String.valueOf(new BigDecimal(quantity).divide(BigDecimal.valueOf(1000), 4, RoundingMode.HALF_UP)));
|
||||
} else if("根".equals(unit) && quantity.contains("/")){
|
||||
} else if ("根".equals(unit) && quantity.contains("/")) {
|
||||
//写入工艺表时分数的体现 直接取分母 以"/"为分割符,取第二个字符串
|
||||
materialBom.setQuantity(quantity);
|
||||
}else {
|
||||
} else {
|
||||
// 其他单位直接使用原值,保留2位小数
|
||||
materialBom.setQuantity(String.valueOf(new BigDecimal(quantity).setScale(2, RoundingMode.HALF_UP)));
|
||||
}
|
||||
@ -777,6 +827,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
bomDetails.setPartdiagramName(productionOrderVo.getParentPart());
|
||||
bomDetails.setPartNumber(productionOrderVo.getDrawingNo());
|
||||
bomDetails.setName(productionOrderVo.getDrawingName());
|
||||
bomDetails.setBomType("0");
|
||||
Double quantity = productionOrderVo.getQuantity();
|
||||
|
||||
bomDetails.setQuantity(quantity != null ? quantity : 0.0);
|
||||
@ -830,6 +881,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
bomDetails.setFName(processRoute.getMaterialName());
|
||||
bomDetails.setPartNumber(processRoute.getRawMaterialCode());
|
||||
bomDetails.setName(processRoute.getRawMaterialName());
|
||||
bomDetails.setBomType("0");
|
||||
// 添加单重验证和日志
|
||||
Double discWeight = processRoute.getDiscWeight();
|
||||
bomDetails.setDanZhong(discWeight);
|
||||
@ -838,7 +890,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
|
||||
// 处理单位换算
|
||||
if ("mm".equals(processRoute.getBomUnit())) {
|
||||
bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage())/ 1000.0); // 转换为米
|
||||
bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage()) / 1000.0); // 转换为米
|
||||
bomDetails.setDenominator(1.0); // 转换为米
|
||||
} else if ("根".equals(processRoute.getBomUnit())) {
|
||||
// 写入工艺表时分数的体现 直接取分母 以"/"为分割符,取第二个字符串
|
||||
@ -846,7 +898,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
String quanity2 = processRoute.getDiscUsage().split("/")[1];
|
||||
bomDetails.setQuantity(Double.parseDouble(quanity));
|
||||
bomDetails.setDenominator(Double.parseDouble(quanity2));
|
||||
bomDetails.setDenominator( Double.parseDouble(processRoute.getDiscUsage().split("/")[1]));
|
||||
bomDetails.setDenominator(Double.parseDouble(processRoute.getDiscUsage().split("/")[1]));
|
||||
bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage().split("/")[0]));
|
||||
} else {
|
||||
bomDetails.setQuantity(Double.parseDouble(processRoute.getDiscUsage()));
|
||||
@ -1072,12 +1124,12 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
|
||||
// 验证物料是否存在
|
||||
int materialVerification = isMaterialVerification(bomDetails.getPartNumber(), bomDetails.getName());
|
||||
if (materialVerification ==1) {
|
||||
if (materialVerification == 1) {
|
||||
bomDetails.setUnitWeight("是");
|
||||
} else if(materialVerification ==2){
|
||||
} else if (materialVerification == 2) {
|
||||
bomDetails.setUnitWeight("否");
|
||||
materialsToAdd.add(bomDetails);
|
||||
}else if(materialVerification ==3){
|
||||
} else if (materialVerification == 3) {
|
||||
bomDetails.setUnitWeight("编码名称不符");
|
||||
}
|
||||
|
||||
@ -1206,7 +1258,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessRoutePushResultDTO pushRouteBom(String rooteProdet) {
|
||||
public R<ProcessRoutePushResultDTO> pushRouteBom(String rooteProdet) {
|
||||
List<ProcessRouteXuDTO> rawBomList = getProcessRoute(rooteProdet);
|
||||
List<ProcessRouteXuDTO> successfulRoutes = new ArrayList<>();
|
||||
List<ProcessRouteXuDTO> failedRoutes = new ArrayList<>();
|
||||
@ -1217,6 +1269,14 @@ 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) {
|
||||
@ -1229,6 +1289,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
successfulRoutes.add(processRouteXuDTO);
|
||||
} else {
|
||||
log.info("工艺路线保存失败: " + processRouteXuDTO.getMaterialCode() + result.getMessage());
|
||||
processRouteXuDTO.setErrorMessage( result.getMessage());
|
||||
failedRoutes.add(processRouteXuDTO);
|
||||
}
|
||||
} else {
|
||||
@ -1246,7 +1307,7 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
//更新项目状态 推送工艺
|
||||
processOrderPro.setBomStatus(3L);
|
||||
processOrderProMapper.updateById(processOrderPro);
|
||||
return resultDTO;
|
||||
return R.ok(resultDTO);
|
||||
}
|
||||
|
||||
public ProcessRoutePushResultDTO pushRouteQBBom(String rooteProdet) {
|
||||
@ -1566,6 +1627,8 @@ public class ProcessRouteServiceImpl implements IProcessRouteService {
|
||||
K3CloudApi client = new K3CloudApi();
|
||||
ProcessModel processModel = createProcessModel(rawBomList);
|
||||
String jsonStr = JSONUtil.toJsonStr(processModel);
|
||||
|
||||
log.debug("推送工艺报文=====》{}",JSONUtil.toJsonStr(jsonStr));
|
||||
try {
|
||||
// 业务对象标识
|
||||
String formId = "ENG_Route";
|
||||
|
||||
BIN
ruoyi-system/src/main/resources/EXCEL模板/工序汇报未入库.xlsx
Normal file
BIN
ruoyi-system/src/main/resources/EXCEL模板/工序汇报未入库.xlsx
Normal file
Binary file not shown.
BIN
ruoyi-system/src/main/resources/EXCEL模板/工序转移数据.xlsx
Normal file
BIN
ruoyi-system/src/main/resources/EXCEL模板/工序转移数据.xlsx
Normal file
Binary file not shown.
BIN
ruoyi-system/src/main/resources/EXCEL模板/生产开工未领料模板.xlsx
Normal file
BIN
ruoyi-system/src/main/resources/EXCEL模板/生产开工未领料模板.xlsx
Normal file
Binary file not shown.
Binary file not shown.
@ -26,6 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="wareHouse" column="ware_house"/>
|
||||
<result property="danZhong" column="dan_zhong"/>
|
||||
<result property="singleWeghit" column="single_weghit"/>
|
||||
<result property="bomType" column="bom_type"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.system.mapper.PartCostMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.system.domain.PartCost" id="PartCostResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="materialCode" column="material_code"/>
|
||||
<result property="materialName" column="material_name"/>
|
||||
<result property="costPrice" column="cost_price"/>
|
||||
<result property="createDate" column="create_date"/>
|
||||
<result property="workshop" column="workshop"/>
|
||||
<result property="unit" column="unit"/>
|
||||
<result property="warehouse" column="warehouse"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="specificationModel" column="specification_model"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
</mapper>
|
||||
@ -27,7 +27,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
<!-- 根据项目编号查询 -->
|
||||
<select id="selectByProjectNumber" resultType="com.ruoyi.system.domain.ProcessOrderPro">
|
||||
SELECT id, production_order_no, production_name, drawing_no, drawing_name,
|
||||
SELECT id, production_order_no, production_name, drawing_no, drawing_name,drawing_type,
|
||||
plan_end_time, plan_start_time, create_by, create_time, update_by, update_time
|
||||
FROM process_order_pro
|
||||
WHERE production_order_no = #{routeDescription}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user