package com.ruoyi.system.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.kingdee.bos.webapi.entity.RepoRet; import com.kingdee.bos.webapi.sdk.K3CloudApi; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; 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.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.utils.JdUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.BomDetails; import com.ruoyi.system.domain.BomVariable; import com.ruoyi.system.domain.MaterialProperties; import com.ruoyi.system.domain.bo.BomVariableBo; import com.ruoyi.system.domain.vo.BomVariableVo; import com.ruoyi.system.mapper.BomDetailsMapper; import com.ruoyi.system.service.IBomVariableService; import com.ruoyi.system.service.IMaterialPropertiesService; import lombok.RequiredArgsConstructor; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; 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.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.*; import static org.aspectj.bridge.MessageUtil.fail; /** * bom变量 * * @author tzy * @date 2024-04-08 */ @Validated @RequiredArgsConstructor @RestController @RequestMapping("/system/variable") public class BomVariableController extends BaseController { private final IMaterialPropertiesService iMaterialPropertiesService; private final IBomVariableService iBomVariableService; @Resource private BomDetailsMapper iBomDetailsmapper; // 错误消息定义为常量 private static final String ERROR_INVALID_PARAMETERS = "参数错误"; private static final String ERROR_MATERIAL_NOT_FOUND = "物料不存在"; private static final String MESSAGE_MATERIAL_FOUND = "物料存在"; private static final Logger log = LoggerFactory.getLogger(BomVariableController.class); /** * 查询bom变量列表 */ @SaCheckPermission("system:variable:list") @GetMapping("/list") public TableDataInfo list(BomVariableBo bo, PageQuery pageQuery) { return iBomVariableService.queryPageList(bo, pageQuery); } /** * 导出bom变量列表 */ @SaCheckPermission("system:variable:export") @Log(title = "bom变量", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(BomVariableBo bo, HttpServletResponse response) { List list = iBomVariableService.queryList(bo); ExcelUtil.exportExcel(list, "bom变量", BomVariableVo.class, response); } /** * 获取bom变量详细信息 * * @param id 主键 */ @SaCheckPermission("system:variable:query") @GetMapping("/{id}") public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { return R.ok(iBomVariableService.queryById(id)); } /** * 新增bom变量 */ @SaCheckPermission("system:variable:add") @Log(title = "bom变量", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody BomVariableBo bo) { return toAjax(iBomVariableService.insertByBo(bo)); } /** * 修改bom变量 */ @SaCheckPermission("system:variable:edit") @Log(title = "bom变量", businessType = BusinessType.UPDATE) @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody BomVariableBo bo) { return toAjax(iBomVariableService.updateByBo(bo)); } /** * 删除bom变量 * * @param ids 主键串 */ @SaCheckPermission("system:variable:remove") @Log(title = "bom变量", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { return toAjax(iBomVariableService.deleteWithValidByIds(Arrays.asList(ids), true)); } /** * 导入数据 * * @param file 导入文件 */ @Log(title = "明细导入", businessType = BusinessType.IMPORT) @SaCheckPermission("system:variable:import") @PostMapping(value = "/importData/{ids}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R importData(@RequestPart("file") MultipartFile file, @PathVariable String ids) throws Exception { String outputFilePath = null; // 生成不重复的FNumber集合 Set uniqueFNumbers = new HashSet<>(); String[] split = ids.split(","); for (String id : split) { BomVariable bo = iBomVariableService.selectById(Long.parseLong(id)); // 使用try-with-resources确保Workbook资源被正确关闭 log.info("开始处理Excel文件"); try (Workbook detailsSheet = WorkbookFactory.create(file.getInputStream())) { Sheet sheet = detailsSheet.getSheetAt(0); List> data = new ArrayList<>(); // 遍历每一行 for (Row row : sheet) { List rowData = new ArrayList<>(); // 遍历当前行的每一列 for (Cell cell : row) { switch (cell.getCellType()) { case STRING: String cellValue = cell.getStringCellValue() .replace("{V1}", bo.getV1()) .replace("{V2}", bo.getV2()) //.replace("{V22}", bo.getV22()) .replace("{V3}", bo.getV3()) // .replace("{V23}", bo.getV23()) .replace("{V5}", bo.getV5()) .replace("{V6}", bo.getV6()) .replace("{V8}", bo.getV8()) .replace("{G1}", bo.getG1()) .replace("{V9}", bo.getV9()) .replace("{G2}", bo.getG2()) //.replace("{G1}", bo.getG1()) .replace("{V10}", bo.getV10()) .replace("{G5}", bo.getG5()) /* .replace("{G8}", bo.getG8())*/ .replace("{V12}", bo.getV12()) .replace("{G6}", bo.getG6()) .replace("{G7}", bo.getG7()) .replace("{V14}", bo.getV14()) // .replace("{V15}", bo.getV15()) /* .replace("{G9}", bo.getG9())*/ .replace("{V41}", bo.getV41()) .replace("{V42}", bo.getV42()) .replace("{V43}", bo.getV43()) .replace("{V44}", bo.getV44()) .replace("{V45}", bo.getV45()) .replace("{V46}", bo.getV46()) .replace("{V47}", bo.getV47()) .replace("{V48}", bo.getV48()) .replace("{V49}", bo.getV49()) .replace("{V50}", bo.getV50()); //.replace("{V11}", bo.getV11()); //.replace("{V13}", bo.getV13()) //.replace("{V51}", bo.getV51()); rowData.add(cellValue); break; case NUMERIC: rowData.add(String.valueOf(cell.getNumericCellValue())); break; default: break; } } data.add(rowData); } // 创建新的Workbook和Sheet //使用导入文件名和这个拼接 设置生成的文件名称 String originalFilename = file.getOriginalFilename(); if (originalFilename.contains("{V1}")) { //将v1替换成 bo.getV1() SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String currentTime = dateFormat.format(new Date()); String replace = originalFilename.replace("{V1}", bo.getV1()).replace(".xlsx", ""); outputFilePath = "D:\\30Dbom\\" + replace + currentTime + ".xlsx"; } else { String newName = originalFilename.replace(".xlsx", ""); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String currentTime = dateFormat.format(new Date()); outputFilePath = "D:\\30Dbom\\" + bo.getV1() + "_" + newName + currentTime + ".xlsx"; } try (Workbook newWorkbook = new XSSFWorkbook(); FileOutputStream outputStream = new FileOutputStream(outputFilePath)) { Sheet newSheet = newWorkbook.createSheet("New Sheet"); // 将数据写入新的Sheet int rowNum = 0; for (List rowData : data) { Row newRow = newSheet.createRow(rowNum++); int cellNum = 0; for (String cellData : rowData) { Cell newCell = newRow.createCell(cellNum++); newCell.setCellValue(cellData); } } // 导出数据到新的Excel文件 newWorkbook.write(outputStream); log.info("数据写入完成,新的Excel文件已保存为 {}"); // 获取第一行数据 List firstRow = data.get(2); if (!firstRow.isEmpty()) { // 获取父级图号和父级物料名称 标题在第一行 String parentFNumber = firstRow.get(1); String parentFName =firstRow.get(2); System.out.println("第一行第一列的值(父级图号): " + parentFNumber); //跳过第一行 int rowsToSkip = 3; for (int i = rowsToSkip; i < data.size(); i++) { List rowData = data.get(i); BomDetails bomDetails = new BomDetails(); System.out.println("Row Data: " + rowData); // 添加日志输出 // 设置父级图号属性 bomDetails.setFNumber(parentFNumber); bomDetails.setStats(String.valueOf(rowData.get(rowData.size() - 1))); uniqueFNumbers.add(parentFNumber); //设置父级物料名称 bomDetails.setFName(parentFName); // 检查并转换数量 bomDetails.setPartNumber(rowData.get(1)); bomDetails.setName(rowData.get(2)); String quantityStr = rowData.get(3); if (!quantityStr.isEmpty()) { int decimalIndex = quantityStr.indexOf("."); if (decimalIndex != -1) { quantityStr = quantityStr.substring(0, decimalIndex); } bomDetails.setQuantity(quantityStr); } // 检查并转换单重 if (!rowData.get(5).isEmpty()) { bomDetails.setUnitWeight(rowData.get(5)); } // 检查并转换总重 /* if (!rowData.get(6).isEmpty()) { bomDetails.setTotalWeight(rowData.get(6)); }*/ bomDetails.setMaterial(rowData.get(4)); //查询物料是否存在 String materialVerification = isMaterialVerification(rowData.get(1), rowData.get(2)); if (materialVerification.equals("物料存在")) { bomDetails.setRemarks("物料存在"); } else { // 获取rowData列表的最后一个元素 String lastElement = rowData.get(rowData.size() - 1); //调用金蝶保存接口 if (lastElement == null || lastElement.isEmpty() || lastElement.equals("外购")) { String states = "1"; //调用金蝶物料保存接口 log.info("开始新增不存在的物料==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); int result = loadMaterialPreservation(rowData.get(1), rowData.get(2), states,rowData.get(4)); if (result == 1) { log.info("新增物料成功==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); } else { log.error("新增物料失败==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); } } else if(lastElement.equals("自制") || lastElement.startsWith("009")){ String states = "2"; //调用金蝶物料保存接口 log.info("开始新增不存在的物料==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); int result = loadMaterialPreservation(rowData.get(1), rowData.get(2), states,rowData.get(4)); if (result == 1) { log.info("新增物料成功==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); } else { log.error("新增物料失败==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); } }else if(lastElement == null || lastElement.isEmpty() || lastElement.equals("委外")){ String states = "3"; //调用金蝶物料保存接口 log.info("开始新增不存在的物料==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); int result = loadMaterialPreservation(rowData.get(1), rowData.get(2), states,rowData.get(4)); if (result == 1) { log.info("新增物料成功==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); } else { log.error("新增物料失败==>" + " 物料图号:" + rowData.get(1) + " 物料名称:" + rowData.get(2)); } } bomDetails.setRemarks("物料已添加"); } int insert = iBomDetailsmapper.insert(bomDetails); if (insert == 0) { log.error("插入明细数据失败"); } else { log.info("插入明细数据成功"); } } } else { log.error("数据集合为空或第一行数据为空"); } } } catch (Exception e) { log.error("写入新的Excel文件时发生错误: {}", e); return R.fail("处理Excel文件时发生错误"); } } // 将不重复的FNumber集合转换为JSON数组并打印出来 ObjectMapper objectMapper = new ObjectMapper(); String jsonOutput = objectMapper.writeValueAsString(uniqueFNumbers); log.info("不重复的FNumbers:=====================================》 " + jsonOutput); return R.ok("文件输出路径为:" + outputFilePath); } /** * 物料验证 * 验证物料在金蝶中是否存在 */ public String isMaterialVerification(String drawingNumber, String name) { if (Objects.isNull(drawingNumber) || drawingNumber.isEmpty() || Objects.isNull(name) || name.isEmpty()) { return ERROR_INVALID_PARAMETERS; } JsonArray jsonArray; try { jsonArray = JdUtils.loadMaterialQuery(drawingNumber, name); } catch (Exception e) { log.error("查询物料信息时发生异常", e); return "查询物料信息时发生异常"; // 捕获异常并返回通用错误消息,具体实现中可进一步细化异常处理 } if (Objects.isNull(jsonArray)) { return ERROR_MATERIAL_NOT_FOUND; } else { for (JsonElement jsonElement : jsonArray) { if (jsonElement.isJsonObject()) { JsonObject jsonObject = jsonElement.getAsJsonObject(); String FNumber = getSafeString(jsonObject, "FNumber"); String FName = getSafeString(jsonObject, "FName"); if (FNumber != null && FName != null) { log.info("图号为: " + FNumber); log.info("物料为: " + FName); } } } return MESSAGE_MATERIAL_FOUND; } } // 安全获取JSON字符串字段值 private String getSafeString(JsonObject jsonObject, String key) { if (jsonObject.has(key) && !jsonObject.get(key).isJsonNull()) { return jsonObject.get(key).getAsString(); } return null; } /* 获取生成的明细中的bom 明细在前端勾选上对应的父级物料图号 * 得到对应的集合 * */ public int loadMaterialPreservation(String partNumber, String name, String states,String cailiao) { K3CloudApi client = new K3CloudApi(); // 创建一个空的JsonObject JsonObject json = new JsonObject(); // 添加IsAutoSubmitAndAudit字段 json.addProperty("IsAutoSubmitAndAudit", "true"); // 创建Model对象,并加入JsonObject JsonObject model = new JsonObject(); json.add("Model", model); // 添加Model字段 model.addProperty("FMATERIALID", 0); model.addProperty("FNumber", partNumber); model.addProperty("FName", name); // 创建FMaterialGroup对象,并加入Model JsonObject fMaterialGroup = new JsonObject(); fMaterialGroup.addProperty("FNumber", "A000106"); model.add("FMaterialGroup", fMaterialGroup); model.addProperty("FIsHandleReserve", true); // 创建SubHeadEntity对象,并加入Model JsonObject subHeadEntity = new JsonObject(); model.add("SubHeadEntity", subHeadEntity); subHeadEntity.addProperty("FErpClsID", states); subHeadEntity.addProperty("FFeatureItem", "1"); MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(cailiao); if (materialProperties!=null){ JsonObject FSVRIAssistant = new JsonObject(); FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId()); model.add("F_SVRI_Assistant",FSVRIAssistant); } // 创建FCategoryID对象,并加入SubHeadEntity JsonObject fCategoryID = new JsonObject(); fCategoryID.addProperty("FNumber", "007"); subHeadEntity.add("FCategoryID", fCategoryID); // 创建FTaxRateId对象,并加入SubHeadEntity JsonObject fTaxRateId = new JsonObject(); fTaxRateId.addProperty("FNUMBER", "SL02_SYS"); subHeadEntity.add("FTaxRateId", fTaxRateId); // 创建FBaseUnitId对象,并加入SubHeadEntity JsonObject fBaseUnitId = new JsonObject(); fBaseUnitId.addProperty("FNumber", "jian"); subHeadEntity.add("FBaseUnitId", fBaseUnitId); subHeadEntity.addProperty("FIsPurchase", true); subHeadEntity.addProperty("FIsInventory", true); subHeadEntity.addProperty("FIsSubContract", true); subHeadEntity.addProperty("FIsSale", true); subHeadEntity.addProperty("FIsProduce", true); // 创建SubHeadEntity1对象,并加入Model JsonObject subHeadEntity1 = new JsonObject(); model.add("SubHeadEntity1", subHeadEntity1); JsonObject fStoreUnitId = new JsonObject(); fStoreUnitId.addProperty("FNumber", "jian"); subHeadEntity1.add("FStoreUnitID", fStoreUnitId); subHeadEntity1.addProperty("FUnitConvertDir", "1"); // 创建FStockId对象,并加入SubHeadEntity1 //仓库代码为 半成品库007 JsonObject fStockId = new JsonObject(); fStockId.addProperty("FNumber", "007"); subHeadEntity1.add("FStockId", fStockId); // 创建FCurrencyId对象,并加入SubHeadEntity1 JsonObject fCurrencyId = new JsonObject(); fCurrencyId.addProperty("FNumber", "PRE001"); subHeadEntity1.add("FCurrencyId", fCurrencyId); subHeadEntity1.addProperty("FIsSNPRDTracy", false); subHeadEntity1.addProperty("FSNManageType", "1"); subHeadEntity1.addProperty("FSNGenerateTime", "1"); subHeadEntity1.addProperty("FBoxStandardQty", 0.0); // 创建FPurchaseUnitId对象,并加入SubHeadEntity1 JsonObject fPurchaseUnitId = new JsonObject(); fPurchaseUnitId.addProperty("FNumber", "jian"); subHeadEntity1.add("FPurchaseUnitId", fPurchaseUnitId); // 创建SubHeadEntity3对象,并加入Model JsonObject subHeadEntity3 = new JsonObject(); model.add("SubHeadEntity3", subHeadEntity3); // 创建FPurchasePriceUnitId对象,并加入SubHeadEntity3 JsonObject fPurchasePriceUnitId = new JsonObject(); fPurchasePriceUnitId.addProperty("FNumber", "jian"); subHeadEntity3.add("FPurchasePriceUnitId", fPurchasePriceUnitId); subHeadEntity3.addProperty("FIsQuota", false); subHeadEntity3.addProperty("FQuotaType", "1"); JsonObject subHeadEntity6 = new JsonObject(); model.add("SubHeadEntity6", subHeadEntity6); subHeadEntity6.addProperty("FCheckProduct", true); subHeadEntity6.addProperty("FCheckReturn", true); // 创建SubHeadEntity5对象,并加入Model JsonObject subHeadEntity5 = new JsonObject(); model.add("SubHeadEntity5", subHeadEntity5); // 创建FProduceUnitId对象,并加入SubHeadEntity5 JsonObject fProduceUnitId = new JsonObject(); fProduceUnitId.addProperty("FNumber", "jian"); subHeadEntity5.add("FProduceUnitId", fProduceUnitId); // 创建FProduceBillType对象,并加入SubHeadEntity5 JsonObject fProduceBillType = new JsonObject(); fProduceBillType.addProperty("FNUMBER", "SCDD01_SYS"); subHeadEntity5.add("FProduceBillType", fProduceBillType); // 创建FBOMUnitId对象,并加入SubHeadEntity5 JsonObject fBOMUnitId = new JsonObject(); fBOMUnitId.addProperty("FNumber", "jian"); subHeadEntity5.add("FBOMUnitId", fBOMUnitId); subHeadEntity5.addProperty("FIsMainPrd", true); subHeadEntity5.addProperty("FIssueType", "1"); // 创建FPickStockId对象,并加入SubHeadEntity5 JsonObject fPickStockId = new JsonObject(); fPickStockId.addProperty("FNumber", "CK010"); subHeadEntity1.add("FPickStockId", fPickStockId); subHeadEntity5.addProperty("FOverControlMode", "1"); subHeadEntity5.addProperty("FStandHourUnitId", "3600"); subHeadEntity5.addProperty("FBackFlushType", "1"); String jsonData = json.toString(); System.out.println(jsonData); try { //业务对象标识 String formId = "BD_MATERIAL"; //调用接口 String resultJson = client.save(formId, jsonData); //用于记录结果 Gson gson = new Gson(); //对返回结果进行解析和校验 RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class); if (repoRet.getResult().getResponseStatus().isIsSuccess()) { System.out.printf("接口返回结果: %s%n", gson.toJson(repoRet.getResult())); log.info("接口返回结果: %s%n" + gson.toJson(repoRet.getResult())); return 1; } else { fail("接口返回结果: " + gson.toJson(repoRet.getResult().getResponseStatus())); log.error("接口返回结果: 失败 " + gson.toJson(repoRet.getResult().getResponseStatus())); return 0; } } catch (Exception e) { fail(e.getMessage()); } return 1; } }