feat(system): 新增物料BOM相关功能
- 新增物料BOM校验逻辑 - 添加货主信息更新功能 - 实现安全库存更新 - 优化物料导入导出功能 - 新增双单位支持
This commit is contained in:
parent
c57f04959c
commit
918935b13a
@ -94,19 +94,27 @@ public class WxRobotUtil {
|
||||
*/
|
||||
|
||||
public void sendMarkdownMsgToWeChatGroup(String markdownMsg, String robotId) {
|
||||
String messageContent = markdownMsg.toString();
|
||||
if (messageContent.length() > 4096) {
|
||||
messageContent = messageContent.substring(0, 4096); // 截断到最大长度
|
||||
}
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
HashMap<String, Object> markdownMap = new HashMap<>();
|
||||
markdownMap.put("content", markdownMsg);
|
||||
markdownMap.put("content", messageContent);
|
||||
paramMap.put("msgtype", "markdown");
|
||||
paramMap.put("markdown", markdownMap);
|
||||
String sendUrl = SEND_MESSAGE_URL + "?key=" + robotId;
|
||||
log.info("发送URL: {}", sendUrl);
|
||||
log.info("发送参数: {}", paramMap);
|
||||
|
||||
|
||||
ResponseEntity<Object> result = httpRequestUtil.doPost(sendUrl, paramMap);
|
||||
JSONObject dataObject = JSONObject.parseObject(JSONObject.toJSONString(result.getBody()));
|
||||
Integer errcode = Integer.valueOf(dataObject.get("errcode").toString());
|
||||
if (errcode.equals(0)) {
|
||||
log.info("企业微信推送Markdown消息成功,时间:" + new Date());
|
||||
} else {
|
||||
log.error("企业微信推送Markdown消息失败,时间:" + new Date());
|
||||
log.error("企业微信推送Markdown消息失败,时间:" + new Date() + ",错误信息:" + dataObject.toJSONString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -378,6 +378,7 @@ public class BomDetailsController extends BaseController {
|
||||
public R updateFBMaterial(@RequestBody List<Map<String, String>> bomDetailParams) {
|
||||
List<BomDetails> bomDetailsList = new ArrayList<>();
|
||||
Set<String> processedMaterials = new HashSet<>(); // 用于跟踪已处理的物料编码
|
||||
List<String> failedMaterials = new ArrayList<>(); // 用于跟踪处理失败的物料
|
||||
|
||||
// 遍历前端传来的数据
|
||||
for (Map<String, String> param : bomDetailParams) {
|
||||
@ -393,18 +394,21 @@ public class BomDetailsController extends BaseController {
|
||||
for (BomDetails material : bomDetails) {
|
||||
// 只在第一次遇到该物料时新增父级物料
|
||||
if (!processedMaterials.contains(material.getFNumber())) {
|
||||
try { log.info("开始新增不存在的物料 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
try {
|
||||
log.info("开始新增不存在的物料 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
Double fbWorkTime = iProcessRouteService.getFaWorkTime(material);
|
||||
JdUtil.loadChengPinMaterialPreservation(material, fbWorkTime);
|
||||
processedMaterials.add(material.getFNumber()); // 标记为已处理
|
||||
} catch (Exception e) {
|
||||
log.error("新增父级物料失败: {}", e.getMessage());
|
||||
failedMaterials.add(material.getPartNumber());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取工艺表中的非委外工时
|
||||
Double fbWorkTime = iProcessRouteService.getFbWorkTime(material);
|
||||
if (material.getPartNumber() != null && material.getName() != null&& material.getUnitWeight().equals("否")) {
|
||||
if (material.getPartNumber() != null && material.getName() != null
|
||||
&& material.getUnitWeight().equals("否")) {
|
||||
String state = determineState(material);
|
||||
log.info("开始新增不存在的物料 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
|
||||
@ -414,29 +418,82 @@ public class BomDetailsController extends BaseController {
|
||||
log.info("新增物料成功 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
material.setUnitWeight("新增成功");
|
||||
} else {
|
||||
log.error("新增物料失败 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(),
|
||||
material.getName());
|
||||
log.error("新增物料失败 ==> 物料图号: {}, 物料名称: {}", material.getPartNumber(), material.getName());
|
||||
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());
|
||||
}
|
||||
}
|
||||
//保存物料之前进行BOM校验
|
||||
List<JDBom> selectBomList = JdUtil.getSelectBomList(fnumber);
|
||||
|
||||
// 保存物料清单之前进行BOM校验
|
||||
if (!validateBOM(fnumber, bomDetails)) {
|
||||
log.error("BOM校验失败,物料编码: {}", fnumber);
|
||||
failedMaterials.add(fnumber);
|
||||
continue; // 跳过保存
|
||||
}
|
||||
|
||||
// 物料清单保存方法
|
||||
FBloadBillOfMaterialsPreservation(bomDetails);
|
||||
bomDetailsList.addAll(bomDetails);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回处理结果
|
||||
return R.ok("成功", bomDetailsList);
|
||||
}
|
||||
|
||||
// BOM 校验方法
|
||||
private boolean validateBOM(String fnumber, List<BomDetails> bomDetails) {
|
||||
List<BomDetails> JDBomList = JdUtil.getSelectBomList(fnumber);
|
||||
|
||||
// 1. 判断BOM是否为空
|
||||
if (JDBomList == null || JDBomList.isEmpty()) {
|
||||
log.error("BOM为空,物料编码: {}", fnumber);
|
||||
return false; // BOM校验失败
|
||||
}
|
||||
|
||||
// 2. 检查子项数量是否一致
|
||||
if (JDBomList.size() != bomDetails.size()) {
|
||||
log.error("BOM子项数量不一致,物料编码: {},金蝶子项数量: {},传入子项数量: {}",
|
||||
fnumber, JDBomList.size(), bomDetails.size());
|
||||
return false; // BOM校验失败
|
||||
}
|
||||
|
||||
// 3. 比较每个子项的内容
|
||||
for (int i = 0; i < JDBomList.size(); i++) {
|
||||
BomDetails jdBomDetail = JDBomList.get(i);
|
||||
BomDetails inputBomDetail = bomDetails.get(i);
|
||||
|
||||
// 比较物料编码和名称
|
||||
if (!jdBomDetail.getFNumber().equals(inputBomDetail.getFNumber()) ||
|
||||
!jdBomDetail.getName().equals(inputBomDetail.getName())) {
|
||||
log.error("BOM子项内容不一致,物料编码: {},金蝶物料: {},传入物料: {}",
|
||||
fnumber, jdBomDetail.getFNumber(), inputBomDetail.getFNumber());
|
||||
return false; // BOM校验失败
|
||||
}
|
||||
|
||||
// 比较分子和分母(假设有分子和分母字段)
|
||||
if (!jdBomDetail.getDenominator().equals(inputBomDetail.getDenominator()) ||
|
||||
!jdBomDetail.getQuantity().equals(inputBomDetail.getQuantity())) {
|
||||
log.error("BOM子项分子分母不一致,物料编码: {},金蝶分子: {}, 分母: {},传入分子: {}, 分母: {}",
|
||||
fnumber, jdBomDetail.getDenominator(), jdBomDetail.getDenominator(),
|
||||
inputBomDetail.getDenominator(), inputBomDetail.getDenominator());
|
||||
return false; // BOM校验失败
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有校验通过
|
||||
log.info("BOM校验通过,物料编码: {}", fnumber);
|
||||
return true; // BOM校验成功
|
||||
}
|
||||
|
||||
/*
|
||||
* 物料清单保存方法
|
||||
@ -1366,8 +1423,23 @@ public class BomDetailsController extends BaseController {
|
||||
|
||||
// 创建FBaseUnitId对象,并加入SubHeadEntity
|
||||
JsonObject fBaseUnitId = new JsonObject();
|
||||
fBaseUnitId.addProperty("FNumber", "jian");
|
||||
subHeadEntity.add("FBaseUnitId", fBaseUnitId);
|
||||
if (bomDetails1.getPartNumber().startsWith("015") || bomDetails1.getName().contains("磨光棒")) {
|
||||
if (bomDetails1.getWareHouse() != null) {
|
||||
if (bomDetails1.getWareHouse().equals("KG")) {
|
||||
fBaseUnitId.addProperty("FNumber", "004");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("根")) {
|
||||
fBaseUnitId.addProperty("FNumber", "003");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("mm")) {
|
||||
fBaseUnitId.addProperty("FNumber", "005");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fBaseUnitId.addProperty("FNumber", "jian");
|
||||
}
|
||||
|
||||
if (states.equals("1")) {
|
||||
subHeadEntity.addProperty("FIsPurchase", true);
|
||||
subHeadEntity.addProperty("FIsSale", true);
|
||||
@ -1385,8 +1457,24 @@ public class BomDetailsController extends BaseController {
|
||||
JsonObject subHeadEntity1 = new JsonObject();
|
||||
model.add("SubHeadEntity1", subHeadEntity1);
|
||||
JsonObject fStoreUnitId = new JsonObject();
|
||||
fStoreUnitId.addProperty("FNumber", "jian");
|
||||
subHeadEntity1.add("FStoreUnitID", fStoreUnitId);
|
||||
// 如果是原材料的话且
|
||||
if (bomDetails1.getPartNumber().startsWith("015") || bomDetails1.getName().contains("磨光棒")) {
|
||||
if (bomDetails1.getWareHouse() != null) {
|
||||
if (bomDetails1.getWareHouse().equals("KG")) {
|
||||
fStoreUnitId.addProperty("FNumber", "004");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("根")) {
|
||||
fStoreUnitId.addProperty("FNumber", "003");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("mm")) {
|
||||
fStoreUnitId.addProperty("FNumber", "005");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fStoreUnitId.addProperty("FNumber", "jian");
|
||||
}
|
||||
|
||||
subHeadEntity1.addProperty("FUnitConvertDir", "1");
|
||||
|
||||
// 创建FStockId对象,并加入SubHeadEntity1
|
||||
@ -1407,6 +1495,21 @@ public class BomDetailsController extends BaseController {
|
||||
// 创建FPurchaseUnitId对象,并加入SubHeadEntity1
|
||||
JsonObject fPurchaseUnitId = new JsonObject();
|
||||
fPurchaseUnitId.addProperty("FNumber", "jian");
|
||||
if (bomDetails1.getPartNumber().startsWith("015") || bomDetails1.getName().contains("磨光棒")) {
|
||||
if (bomDetails1.getWareHouse() != null) {
|
||||
if (bomDetails1.getWareHouse().equals("KG")) {
|
||||
fPurchaseUnitId.addProperty("FNumber", "004");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("根")) {
|
||||
fPurchaseUnitId.addProperty("FNumber", "003");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("mm")) {
|
||||
fPurchaseUnitId.addProperty("FNumber", "005");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fPurchaseUnitId.addProperty("FNumber", "jian");
|
||||
}
|
||||
subHeadEntity1.add("FPurchaseUnitId", fPurchaseUnitId);
|
||||
|
||||
// 创建SubHeadEntity3对象,并加入Model
|
||||
@ -1416,6 +1519,22 @@ public class BomDetailsController extends BaseController {
|
||||
// 创建FPurchasePriceUnitId对象,并加入SubHeadEntity3
|
||||
JsonObject fPurchasePriceUnitId = new JsonObject();
|
||||
fPurchasePriceUnitId.addProperty("FNumber", "jian");
|
||||
if (bomDetails1.getPartNumber().startsWith("015") || bomDetails1.getName().contains("磨光棒")) {
|
||||
if (bomDetails1.getWareHouse() != null) {
|
||||
if (bomDetails1.getWareHouse().equals("KG")) {
|
||||
fPurchasePriceUnitId.addProperty("FNumber", "004");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("根")) {
|
||||
fPurchasePriceUnitId.addProperty("FNumber", "003");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("mm")) {
|
||||
fPurchasePriceUnitId.addProperty("FNumber", "005");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fPurchasePriceUnitId.addProperty("FNumber", "jian");
|
||||
}
|
||||
|
||||
subHeadEntity3.add("FPurchasePriceUnitId", fPurchasePriceUnitId);
|
||||
|
||||
subHeadEntity3.addProperty("FIsQuota", false);
|
||||
@ -1450,6 +1569,21 @@ public class BomDetailsController extends BaseController {
|
||||
// 创建FProduceUnitId对象,并加入SubHeadEntity5
|
||||
JsonObject fProduceUnitId = new JsonObject();
|
||||
fProduceUnitId.addProperty("FNumber", "jian");
|
||||
if (bomDetails1.getPartNumber().startsWith("015") || bomDetails1.getName().contains("磨光棒")) {
|
||||
if (bomDetails1.getWareHouse() != null) {
|
||||
if (bomDetails1.getWareHouse().equals("KG")) {
|
||||
fProduceUnitId.addProperty("FNumber", "004");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("根")) {
|
||||
fProduceUnitId.addProperty("FNumber", "003");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("mm")) {
|
||||
fProduceUnitId.addProperty("FNumber", "005");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fProduceUnitId.addProperty("FNumber", "jian");
|
||||
}
|
||||
subHeadEntity5.add("FProduceUnitId", fProduceUnitId);
|
||||
// 实际作工时,并加入SubHeadEntity5
|
||||
|
||||
@ -1461,7 +1595,24 @@ public class BomDetailsController extends BaseController {
|
||||
// 创建FBOMUnitId对象,并加入SubHeadEntity5
|
||||
JsonObject fBOMUnitId = new JsonObject();
|
||||
fBOMUnitId.addProperty("FNumber", "jian");
|
||||
if (bomDetails1.getPartNumber().startsWith("015") || bomDetails1.getName().contains("磨光棒")) {
|
||||
if (bomDetails1.getWareHouse() != null) {
|
||||
if (bomDetails1.getWareHouse().equals("KG")) {
|
||||
fBOMUnitId.addProperty("FNumber", "004");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("根")) {
|
||||
fBOMUnitId.addProperty("FNumber", "003");
|
||||
}
|
||||
if (bomDetails1.getWareHouse().equals("mm")) {
|
||||
fBOMUnitId.addProperty("FNumber", "005");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
fBOMUnitId.addProperty("FNumber", "jian");
|
||||
}
|
||||
subHeadEntity5.add("FBOMUnitId", fBOMUnitId);
|
||||
|
||||
if (states.equals("1")) {
|
||||
subHeadEntity5.addProperty("FIsMainPrd", false);
|
||||
} else {
|
||||
@ -1880,11 +2031,7 @@ public class BomDetailsController extends BaseController {
|
||||
break;
|
||||
}
|
||||
subHeadEntity5.add("FBOMUnitId", fBOMUnitId);
|
||||
if (states.equals("1")) {
|
||||
subHeadEntity5.addProperty("FIsMainPrd", false);
|
||||
} else {
|
||||
subHeadEntity5.addProperty("FIsMainPrd", true);
|
||||
}
|
||||
subHeadEntity5.addProperty("FIsMainPrd", !states.equals("1"));
|
||||
subHeadEntity5.addProperty("FIssueType", "1");
|
||||
|
||||
// 创建FPickStockId对象,并加入SubHeadEntity5
|
||||
|
||||
@ -21,10 +21,17 @@ import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.kingdee.bos.webapi.sdk.K3CloudApi;
|
||||
import com.ruoyi.common.utils.HttpRequestUtil;
|
||||
import com.ruoyi.common.utils.WxRobotUtil;
|
||||
import com.ruoyi.system.domain.SafetyStock;
|
||||
import com.ruoyi.system.domain.WlStockData;
|
||||
import com.ruoyi.system.domain.vo.SafetyStockVo;
|
||||
import com.ruoyi.system.domain.vo.WlStockDataVo;
|
||||
import com.ruoyi.system.mapper.SafetyStockMapper;
|
||||
import com.ruoyi.system.mapper.WlStockDataMapper;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@ -70,7 +77,7 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
private final IKingdeeWorkCenterDataService iKingdeeWorkCenterDataService;
|
||||
private final HttpRequestUtil httpRequestUtil;
|
||||
private static final Logger log = LoggerFactory.getLogger(KingdeeWorkCenterDataController.class);
|
||||
|
||||
private final WlStockDataMapper baseMapper;;
|
||||
/**
|
||||
* 查询金蝶工段数据列表
|
||||
*/
|
||||
@ -263,7 +270,12 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
"> 数量信息:计划<font color=\"comment\">1.00</font>,已转入<font color=\"comment\">1.00</font>,已转出<font color=\"comment\">0.00</font>\n\n"
|
||||
+
|
||||
"请相关部门负责人关注并及时处理!";
|
||||
wxRobotUtil.sendMarkdownMsgToWeChatGroup(markdownMsg, robotId);
|
||||
String messageContent = markdownMsg;
|
||||
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();
|
||||
}
|
||||
@ -336,7 +348,12 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
// 添加结束语
|
||||
markdownMsg.append("请相关部门负责人关注并及时处理!");
|
||||
// 发送消息
|
||||
wxRobotUtil.sendMarkdownMsgToWeChatGroup(markdownMsg.toString(), robotId);
|
||||
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();
|
||||
|
||||
@ -556,5 +573,80 @@ public class KingdeeWorkCenterDataController extends BaseController {
|
||||
return R.fail("发送工段数据失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
@SaCheckPermission("system:workCenterData:getKuCun")
|
||||
@Log(title = "金蝶工段数据延期数据", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/getKuCun")
|
||||
public R<Void> getKuCun() {
|
||||
|
||||
String robotId = "0d2390e0-3e74-49fc-bd02-900b86bf0f55";
|
||||
StringBuilder markdownMsg = new StringBuilder();
|
||||
|
||||
// 获取今天的日期
|
||||
Date today = new Date();
|
||||
Date sixAM = DateUtil.parse(DateUtil.format(today, "yyyy-MM-dd") + " 06:00:00");
|
||||
|
||||
// 创建查询条件
|
||||
LambdaQueryWrapper<WlStockData> safetyStockLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
// 获取时间在今天6点以后的数据
|
||||
safetyStockLambdaQueryWrapper.ge(WlStockData::getCreateTime, sixAM);
|
||||
|
||||
List<WlStockData> safetyStocks = baseMapper.selectList(safetyStockLambdaQueryWrapper);
|
||||
try {
|
||||
if (CollUtil.isEmpty(safetyStocks)) {
|
||||
markdownMsg.append("## 🚀 安全库存提醒\n\n")
|
||||
.append("今日暂无安全库存预警数据。");
|
||||
} else {
|
||||
markdownMsg.append("## 🚀 安全库存提醒\n\n")
|
||||
.append("以下是今日的安全库存预警数据:\n\n");
|
||||
|
||||
// 只显示前三个安全库存数据
|
||||
int count = Math.min(3, safetyStocks.size());
|
||||
for (int i = 0; i < count; i++) {
|
||||
WlStockData safetyStock = safetyStocks.get(i);
|
||||
markdownMsg.append("### 物料信息\n")
|
||||
.append("#### 物料编号: **").append(safetyStock.getMaterialCode()).append("**\n")
|
||||
.append("> **物料名称:** ").append(safetyStock.getMaterialName()).append("\n")
|
||||
.append("> **可用库存:** ").append(String.format("%.2f", safetyStock.getAvailableStock())).append("\n")
|
||||
.append("> **当前库存:** ").append(String.format("%.2f", safetyStock.getCurrentStock())).append("\n")
|
||||
.append("> **最大库存:** ").append(String.format("%.2f", safetyStock.getMaxsafetyStock())).append("\n")
|
||||
.append("> **创建时间:** ").append(DateUtil.formatDateTime(safetyStock.getCreateTime())).append("\n")
|
||||
.append("---\n"); // 添加分隔线
|
||||
}
|
||||
|
||||
// 添加总数汇总
|
||||
markdownMsg.append("### 总数汇总\n")
|
||||
.append("> 今日安全库存预警数据总数: **").append(safetyStocks.size()).append("**\n");
|
||||
}
|
||||
|
||||
// 生成Excel文件
|
||||
String fileName = String.format("%s安全预警数据_%s.xlsx","企标", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
|
||||
String filePath = FileUtils.getTempDirectoryPath() + File.separator + fileName;
|
||||
|
||||
// 使用EasyExcel写入数据
|
||||
EasyExcel.write(filePath, WlStockDataVo.class)
|
||||
.sheet("工段数据")
|
||||
.doWrite(BeanUtil.copyToList(safetyStocks, WlStockDataVo.class));
|
||||
|
||||
// 发送Excel文件
|
||||
File excelFile = new File(filePath);
|
||||
wxRobotUtil.sendFileToWeChatGroup(excelFile, robotId);
|
||||
|
||||
// 删除临时文件
|
||||
FileUtils.deleteQuietly(excelFile);
|
||||
markdownMsg.append("\n详细数据请查看发送的Excel文件!");
|
||||
String messageContent = markdownMsg.toString();
|
||||
int maxLength = 1000;
|
||||
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) {
|
||||
markdownMsg.append("- ").append("安全库存").append(" (获取失败: ").append(e.getMessage()).append(")\n");
|
||||
return R.fail("发送安全库存数据失败:" + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -101,7 +101,6 @@ public class WlStockDataController extends BaseController {
|
||||
|
||||
/**
|
||||
* 删除安全库存单据
|
||||
*
|
||||
* @param ids 主键串
|
||||
*/
|
||||
@SaCheckPermission("system:stockData:remove")
|
||||
@ -114,8 +113,6 @@ public class WlStockDataController extends BaseController {
|
||||
|
||||
/**
|
||||
* 生成安全库存单据
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@SaCheckPermission("system:stockData:generateDoc")
|
||||
@Log(title = "安全库存单据", businessType = BusinessType.OTHER)
|
||||
|
||||
@ -45,7 +45,7 @@ import java.util.Map;
|
||||
/**
|
||||
* 工序任务
|
||||
*
|
||||
* @author ruoyi
|
||||
* @author tzy
|
||||
* @date 2024-06-27
|
||||
*/
|
||||
@Validated
|
||||
@ -54,7 +54,7 @@ import java.util.Map;
|
||||
@RequestMapping("/system/procedure")
|
||||
public class WorkProcedureController extends BaseController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(KingdeeWorkCenterDataController.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(WorkProcedureController.class);
|
||||
private final IWorkProcedureService iWorkProcedureService;
|
||||
private final IKingdeeWorkCenterDataService iKingdeeWorkCenterDataService;
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ public class ProductctionPlanGatteDto {
|
||||
private String text;
|
||||
private String start_date;
|
||||
private String end_date;
|
||||
//天数
|
||||
private Long duration;
|
||||
private Integer type;
|
||||
private Boolean open;
|
||||
|
||||
@ -50,4 +50,6 @@ public interface IWorkProcedureService {
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
List<ProductctionPlanGatteDto> getGongXuTasks(String text);
|
||||
|
||||
List<ProductctionPlanGatteDto> getAllTasks1();
|
||||
}
|
||||
|
||||
@ -145,7 +145,6 @@ public class EleMaterialsServiceImpl implements IEleMaterialsService {
|
||||
@Override
|
||||
public Boolean updateByBo(EleMaterialsBo bo) {
|
||||
EleMaterials update = BeanUtil.toBean(bo, EleMaterials.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import com.ruoyi.system.mapper.SafetyStockMapper;
|
||||
import com.ruoyi.system.mapper.WlStockDataMapper;
|
||||
import com.ruoyi.system.runner.JdUtil;
|
||||
import com.ruoyi.system.service.IWlStockDataService;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -229,7 +230,69 @@ public class WlStockDataServiceImpl implements IWlStockDataService {
|
||||
}
|
||||
}
|
||||
}
|
||||
@XxlJob("generateDoc2")
|
||||
public List<WlStockData> generateDoc2() {
|
||||
List<SafetyStock> safetyStocks = safetyStockMapper.selectList();
|
||||
if (CollectionUtils.isEmpty(safetyStocks)) {
|
||||
logger.warn("没有找到安全库存数据");
|
||||
logMessages("没有找到安全库存数据");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 使用固定大小的线程池而不是CachedThreadPool,避免创建过多线程
|
||||
ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
|
||||
List<WlStockData> wlStockDataList = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
try {
|
||||
// 创建所有任务的Future列表
|
||||
List<CompletableFuture<Void>> futures = safetyStocks.stream()
|
||||
.map(safetyStock -> CompletableFuture
|
||||
.supplyAsync(() -> processWithRetry(safetyStock), executor)
|
||||
.thenAccept(wlStockData -> {
|
||||
if (wlStockData != null) {
|
||||
wlStockDataList.add(wlStockData);
|
||||
}
|
||||
})
|
||||
.exceptionally(e -> {
|
||||
logger.error("处理安全库存数据失败: {}", safetyStock.getMaterialCode(), e);
|
||||
logMessages("处理安全库存数据失败: " + safetyStock.getMaterialCode());
|
||||
return null;
|
||||
}))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 等待所有任务完成
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.get(5, TimeUnit.MINUTES); // 设置整体超时时间
|
||||
|
||||
// 批量保存数据
|
||||
if (!wlStockDataList.isEmpty()) {
|
||||
boolean success = baseMapper.insertBatch(wlStockDataList);
|
||||
logger.info("批量插入{}条数据: {}", wlStockDataList.size(), success);
|
||||
logMessages("批量插入" + wlStockDataList.size() + "条数据成功");
|
||||
}
|
||||
|
||||
return wlStockDataList;
|
||||
|
||||
} catch (TimeoutException e) {
|
||||
logger.error("生成文档操作超时", e);
|
||||
logMessages("生成单据操作超时");
|
||||
throw new ServiceException("操作超时,请稍后重试");
|
||||
} catch (Exception e) {
|
||||
logger.error("生成文档时发生错误", e);
|
||||
logMessages("生成单据发生错误: " + e.getMessage());
|
||||
throw new ServiceException("生成文档失败:" + e.getMessage());
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
private WlStockData processWithRetry(SafetyStock safetyStock) {
|
||||
int retryCount = 0;
|
||||
while (retryCount < MAX_RETRIES) {
|
||||
@ -356,11 +419,11 @@ public class WlStockDataServiceImpl implements IWlStockDataService {
|
||||
wlStockData.setMaxsafetyStock(BigDecimal.valueOf(maxSafetyStock));
|
||||
wlStockData.setSecAvbqty(BigDecimal.valueOf(fSecAVBQty));
|
||||
|
||||
wlStockData.setDocumentType(String.format("物料编码:%s||可用库存:%.2f||库存量:%.2f||生产订单:%.2f||" +
|
||||
/* wlStockData.setDocumentType(String.format("物料编码:%s||可用库存:%.2f||库存量:%.2f||生产订单:%.2f||" +
|
||||
"采购订单:%.2f||预留量:%.2f||最大库存:%.2f||最低库存:%.2f",
|
||||
safetyStock.getMaterialCode(), availableStock, fSecAVBQty, productionQty,
|
||||
purchaseQty, fSecQty, maxSafetyStock, minSafetyStock));
|
||||
|
||||
*/
|
||||
return wlStockData;
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
package com.ruoyi.system.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.kingdee.bos.webapi.sdk.K3CloudApi;
|
||||
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.utils.StringUtils;
|
||||
import com.ruoyi.system.domain.ProductionPlan;
|
||||
@ -22,6 +28,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
@ -130,6 +137,99 @@ public class WorkProcedureServiceImpl implements IWorkProcedureService {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public List<ProductctionPlanGatteDto> getAllTasks1() {
|
||||
try {
|
||||
K3CloudApi client = new K3CloudApi();
|
||||
JsonObject parameter = new JsonObject();
|
||||
parameter.addProperty("FWorkCenterName", "机一工段");
|
||||
Object[] parameters = new Object[] { parameter.toString() };
|
||||
String execute = client.execute(
|
||||
"Ljint.Kingdee.YiTe.KanBan.WebApi.ProduceWebApi.ExecuteService,Ljint.Kingdee.YiTe.KanBan.WebApi",
|
||||
parameters);
|
||||
|
||||
// 解析响应
|
||||
JSONObject response = JSONObject.parseObject(execute);
|
||||
if (!"true".equals(response.getString("IsSuccess"))) {
|
||||
String errorMsg = response.getString("Message");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取明天的日期字符串 (格式: yyyy-MM-dd)
|
||||
String tomorrow = DateUtil.format(DateUtil.tomorrow().toLocalDateTime().plusDays(1), "yyyy-MM-dd");
|
||||
|
||||
// 获取数据数组
|
||||
JSONArray dataArray = response.getJSONArray("data");
|
||||
if (dataArray == null || dataArray.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ProductctionPlanGatteDto> tasks = new ArrayList<>();
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
for (int i = 0; i < dataArray.size(); i++) {
|
||||
JSONArray queryList = dataArray.getJSONObject(i).getJSONArray("QueryList");
|
||||
for (int j = 0; j < queryList.size(); j++) {
|
||||
JSONObject item = queryList.getJSONObject(j);
|
||||
|
||||
// 获取计划结束时间并转换为日期格式进行比较
|
||||
String planFinishTime = item.getString("FOperPlanFinishTime2");
|
||||
if (org.springframework.util.StringUtils.hasText(planFinishTime)) {
|
||||
// 提取日期部分进行比较 (去掉时间部分)
|
||||
String finishDate = planFinishTime.split(" ")[0];
|
||||
// 只处理明天结束的工单
|
||||
if (tomorrow.equals(finishDate)) {
|
||||
// 转换为 ProductctionPlanGatteDto 对象
|
||||
ProductctionPlanGatteDto task = new ProductctionPlanGatteDto();
|
||||
task.setId(item.getLong("Id")); // 假设有 Id 字段
|
||||
task.setText(item.getString("MoOrderNo"));
|
||||
task.setToolTipsTxt(item.getString("FProcessName"));
|
||||
task.setType(1);
|
||||
LocalDate startDate = item.getDate("FOperPlanStartTime2").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
LocalDate endDate = item.getDate("FOperPlanFinishTime2").toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
task.setStart_date(startDate.toString());
|
||||
task.setEnd_date(endDate.toString());
|
||||
|
||||
long duration = ChronoUnit.DAYS.between(startDate, endDate);
|
||||
task.setDuration(duration);
|
||||
|
||||
task.setOpen(true);
|
||||
task.setProgress(1L);
|
||||
task.setStatus("yellow");
|
||||
task.setParent(null); // 父任务没有parent
|
||||
|
||||
tasks.add(task);
|
||||
|
||||
// 处理子任务
|
||||
JSONArray subTasksArray = item.getJSONArray("SubTasks");
|
||||
if (subTasksArray != null) {
|
||||
for (int k = 0; k < subTasksArray.size(); k++) {
|
||||
JSONObject subTaskItem = subTasksArray.getJSONObject(k);
|
||||
ProductctionPlanGatteDto subTask = new ProductctionPlanGatteDto();
|
||||
subTask.setId(subTaskItem.getLong("SubTaskId"));
|
||||
subTask.setText(subTaskItem.getString("FProcessName"));
|
||||
subTask.setToolTipsTxt(subTaskItem.getString("SubTaskProcessName"));
|
||||
subTask.setStart_date(subTaskItem.getString("FOperPlanStartTime2"));
|
||||
subTask.setEnd_date(subTaskItem.getString("FOperPlanFinishTime2"));
|
||||
subTask.setDuration(subTaskItem.getLong("1"));
|
||||
subTask.setOpen(true);
|
||||
subTask.setProgress(1L);
|
||||
subTask.setStatus("yellow");
|
||||
subTask.setParent(task.getId()); // 设置父任务ID
|
||||
|
||||
tasks.add(subTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tasks;
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询工序任务
|
||||
|
||||
Loading…
Reference in New Issue
Block a user