/* * Copyright (c) 2018-2025, ztt All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: ztt */ package com.chinaztt.mes.basic.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.text.csv.CsvData; import cn.hutool.core.text.csv.CsvReader; import cn.hutool.core.text.csv.CsvRow; import cn.hutool.core.text.csv.CsvUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.chinaztt.ifs.api.feign.IfsFeignClient; import com.chinaztt.mes.basic.entity.Part; import com.chinaztt.mes.basic.excel.PartData; import com.chinaztt.mes.basic.mapper.PartMapper; import com.chinaztt.mes.basic.service.PartService; import com.chinaztt.mes.basic.util.DictUtils; import com.chinaztt.mes.basic.util.PartUtils; import com.chinaztt.mes.basic.util.TransactionUtils; import com.chinaztt.mes.basic.vo.PartVo; import com.chinaztt.mes.common.util.JsonUtil; import com.chinaztt.mes.common.util.MultipartFileToFile; import com.chinaztt.ztt.common.core.util.R; import com.chinaztt.ztt.common.security.util.SecurityUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import com.google.gson.Gson; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.util.EntityUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.core.env.Environment; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.*; import java.util.concurrent.CompletableFuture; /** * 零件 * * @author fenglang * @date 2020-08-17 14:37:35 */ @AllArgsConstructor @Service @Slf4j public class PartServiceImpl extends ServiceImpl implements PartService { private DictUtils dictUtils; private PartUtils partUtils; private IfsFeignClient ifsFeignClient; private DiscoveryClient discoveryClient; private Environment environment; private RedisTemplate redisTemplate; private TransactionUtils transactionUtils; @Autowired private ThreadPoolTaskExecutor threadPoolTaskExecutor; ; @Override public void importPartExcel(List list) { if (CollectionUtil.isEmpty(list)) { return; } List partCodes = getBaseMapper().getPartConcatEcl(); Map dicmattype = dictUtils.getDicKey("material_type"); Map dicplanMethod = dictUtils.getDicKey("planning_method_type"); for (PartData data : list) { if (StringUtils.isEmpty(data.getEngChgLevel())) { data.setEngChgLevel("1"); } if (partCodes.contains(data.getPartNo() + "_" + data.getEngChgLevel())) { throw new RuntimeException("重复零件号:" + data.getPartNo() + "版本号:" + data.getEngChgLevel()); } Part part = new Part(); part.setPartName(data.getPartName()); part.setPartNo(data.getPartNo()); part.setSpecs(data.getSpec()); part.setCharacteristic1(data.getCharacteristic1()); part.setCharacteristic2(data.getCharacteristic2()); part.setCharacteristic3(data.getCharacteristic3()); part.setPartModel(data.getPartModel()); part.setVoltageLevel(data.getVoltageLevel()); part.setUnit(data.getUnit()); // 默认是4 part.setMaterialType(StringUtils.isEmpty(data.getMaterialType()) ? "4" : (StringUtils.isEmpty(dicmattype.get(data.getMaterialType())) ? "4" : dicmattype.get(data.getMaterialType()))); part.setAssortment(data.getAssortment()); part.setCategory(data.getCategory()); part.setThreeLevelClassification(data.getThreeLevelClassification()); // 默认是 A part.setPlanningMethod(StringUtils.isEmpty(data.getPlanningMethod()) ? "A" : (StringUtils.isEmpty(dicplanMethod.get(data.getPlanningMethod())) ? "A" : dicplanMethod.get(data.getPlanningMethod()))); part.setEngChgLevel(data.getEngChgLevel()); // 默认是 不启用批次管理 part.setLotTrackingIfs(data.getLotTrackingIfs() == null ? false : data.getLotTrackingIfs()); part.setDescription(data.getDescription()); partCodes.add(data.getPartNo() + "_" + part.getEngChgLevel()); baseMapper.insert(part); } } @Override public IPage getPartPage(Page page, QueryWrapper ew, Long bomId) { return baseMapper.getPartPage(page, ew, bomId); } @Override public List query(String keyword) { if (StringUtils.isEmpty(keyword)) { return null; } return baseMapper.query(keyword); } @Override public IPage> getQualityPartPage(Page page, QueryWrapper ew) { return baseMapper.getQualityPartPage(page, ew); } @Override public IPage> getNotInQualityPartPage(Page page, QueryWrapper ew) { return baseMapper.getNotInQualityPartPage(page, ew); } @Override public IPage> getReportPartsPage(Page page, QueryWrapper ew) { return baseMapper.getReportPartsPage(page, ew); } @Override public R getPart(Part part) { return R.ok(partUtils.getErpPart(part)); } @Override public R ifsSync(List ids) { return ifsSyncById(ids); } private R ifsSyncById(List ids) { JSONArray batchInfo = new JSONArray(); for (Long id : ids) { Part part = baseMapper.selectById(id); if (null == part) { return R.failed("id为" + id + "的零件不存在"); } else { batchInfo.add(ifsDataMake(part)); } } //这句话是判断ztt-ifs服务是否在线的日后有用 // List instances = discoveryClient.getInstances("ztt-ifs"); return ifsFeignClient.importInventPartStd(new JSONObject().fluentPut("BATCH_INFO", batchInfo), true); } /** * ifs 数据拼接 * * @param part * @return */ private JSONObject ifsDataMake(Part part) { JSONObject p = new JSONObject(); //零件编号 p.put("PART_NO", part.getPartNo()); //零件描述 p.put("PART_DESC", part.getPartName()); //单位 p.put("UNIT_MEAS", part.getUnit()); //多层跟踪 p.put("MULTILEVEL_TRACKING_DB", "TRACKING_OFF"); //批次管理 p.put("LOT_TRACK_CODE", (part.getLotTrackingIfs() == null || !part.getLotTrackingIfs()) ? "NOT LOT TRACKING" : "LOT TRACKING"); //批次数量规则 NOT LOT TRACKING 对应 ONE_LOT ,LOT TRACKING 对应 MULTI_LOTS p.put("LOT_QTY_RULE", (part.getLotTrackingIfs() == null || !part.getLotTrackingIfs()) ? "ONE_LOT" : "MULTI_LOTS"); //版本号 p.put("ENG_CHG_LEVEL", StringUtils.isEmpty(part.getEngChgLevel()) ? "1" : part.getEngChgLevel()); //零件类型 p.put("TYPE_CODE", part.getMaterialType()); //计划方法 p.put("PLANNING_METHOD", StringUtils.isEmpty(part.getPlanningMethod()) ? "A" : part.getPlanningMethod()); p.put("EFF_PHASE_IN_DATE", "2000-01-01"); return p; } /** * 从主数据平台同步零件数据 * * @param jsonObject * @return */ @Override public R parySync(JSONObject jsonObject) { try { String version = jsonObject.get("version") == null ? "1" : jsonObject.getString("version"); String partNo = jsonObject.getString("material_number"); //判断是否存在 Part part = getBaseMapper().selectOne(Wrappers.lambdaQuery().eq(Part::getPartNo, partNo).eq(Part::getEngChgLevel, version)); if (part == null) { part = new Part(); } //零件版本 part.setEngChgLevel(version); //零件号 part.setPartNo(partNo); String spec = jsonObject.get("material_spec") == null ? "" : jsonObject.getString("material_spec"); String name = jsonObject.get("material_name") == null ? "" : jsonObject.getString("material_name"); //规格型号 part.setSpecs(jsonObject.getString("material_spec")); //主数据平台零件名称 + 空格 + 主数据平台规格 = 零件名称 part.setPartName((name + " " + spec).trim()); //物料描述 part.setDescription(spec); //单位 part.setUnit(jsonObject.getString("unit")); //一级分类 part.setAssortment(jsonObject.getString("firstCategoryName")); //二级分类 part.setCategory(jsonObject.getString("secondCategoryName")); //三级分类 part.setThreeLevelClassification(jsonObject.getString("thirdCategoryName")); //自定义字段数据的插入 JSONArray jsonObjectProperty = jsonObject.getJSONArray("propertiesInfo"); if (CollectionUtil.isNotEmpty(jsonObjectProperty)) { List jsonObjectList = jsonObjectProperty.toJavaList(JSONObject.class); Map map = new HashMap<>(); jsonObjectList.forEach(e -> { if (null != e.get("attribute") && null != e.get("attribute_value")) { map.put(e.getString("attribute"), e.getString("attribute_value")); } }); part.setPartModel(map.get("型号")); part.setCharacteristic1(map.get("特性1")); part.setCharacteristic2(map.get("特性2")); part.setCharacteristic3(map.get("特性3")); part.setVoltageLevel(map.get("电压等级")); } if (part.getId() == null) { //插入的时候默认插入批次管理为 false 计划方法为A 零件类型为 “3” part.setLotTrackingIfs(false); part.setPlanningMethod("A"); part.setMaterialType("3"); baseMapper.insert(part); } else { baseMapper.updateById(part); } //这边需要说明提下 因为 主数据平台的成功编码和本系统的成功编码是反的 所以 成功调用的是 R.falid 失败是 R.ok return R.failed("推送成功"); } catch (Exception e) { //这边需要说明提下 因为 主数据平台的成功编码和本系统的成功编码是反的 所以 成功调用的是 R.falid 失败是 R.ok return R.ok().setMsg(e.getMessage()); } } @Override public boolean doSave(Part part) { Part partByFind = baseMapper.selectOne(Wrappers.lambdaQuery() .eq(Part::getPartNo, part.getPartNo()) .eq(Part::getEngChgLevel, part.getEngChgLevel())); if (partByFind != null) { throw new RuntimeException("零件号版本号重复:" + partByFind.getPartName() + "-" + partByFind.getPartNo()); } baseMapper.insert(part); return true; } @Override @Transactional(rollbackFor = Exception.class) public boolean doUpdate(Part part) { Part partByFind = baseMapper.selectOne(Wrappers.lambdaQuery() .eq(Part::getPartNo, part.getPartNo()) .eq(Part::getEngChgLevel, part.getEngChgLevel()) .ne(Part::getId, part.getId())); if (partByFind != null) { throw new RuntimeException("零件号版本号重复:" + partByFind.getPartName() + "-" + partByFind.getPartNo()); } //对接IFS // R result = ifsFeignClient.importInventPartStd(new JSONObject().fluentPut("BATCH_INFO", new JSONArray().fluentAdd(ifsDataMake(part))), true); // if (result.getCode() == 1) { // throw new RuntimeException("IFS错误——" + result.getMsg()); // } baseMapper.updateById(part); return true; } @Override public IPage getRoutingPartPage(Page page, QueryWrapper ew, Long bomId) { Integer componentNum = this.baseMapper.countComponentNum(bomId); if (componentNum > 1) { return this.baseMapper.getPartPage(page, ew, bomId); } else { return this.baseMapper.getPartPageIncludeOwn(page, ew, bomId); } } @Override @Async public void syncPart() { String key = "syncPart_lock"; if (redisTemplate.hasKey(key)) { throw new RuntimeException("有同步任务正在处理"); } redisTemplate.opsForValue().set(key, 1, 1000 * 3600); CloseableHttpClient httpClient = HttpClientBuilder.create().build(); String syncErpUrl = environment.getProperty("erpPartUrl"); HttpPost httpPost = new HttpPost(syncErpUrl); httpPost.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000); httpPost.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 1000 * 3600); // 将参数转换为JSON字符串 Map params = new HashMap<>(); // params.put("startTime", customOrderSyncDTO.getStartTime()); // params.put("endTime", customOrderSyncDTO.getEndTime()); String jsonParams = new Gson().toJson(params); // 设置请求体为JSON格式 StringEntity requestEntity = new StringEntity(jsonParams, ContentType.APPLICATION_JSON); httpPost.setEntity(requestEntity); String responseString = null; try { CloseableHttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); responseString = EntityUtils.toString(entity, "UTF-8"); // log.info(responseString); response.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } finally { redisTemplate.delete(key); try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override @Transactional(rollbackFor = Exception.class) public Long syncNewIfs(String date) { Map dicmattype = dictUtils.getDicKey("material_type"); Map dicunit = dictUtils.getDicKey("unit"); String key = "syncPart_lock" + SecurityUtils.getUser().getId(); if (redisTemplate.hasKey(key)) { throw new RuntimeException("有同步任务正在处理"); } redisTemplate.opsForValue().set(key, 1, 1000 * 3600); ListpartList=new ArrayList(); Connection conn =null; PreparedStatement pstmt =null; try { String url =""; //判断日期有否 if (Objects.isNull(date)){ url = "http://192.168.20.47:8008/PurchService.ashx?contract=KJZS&contractKey=4ttDeLKNsZuhstjtROMcRE1USNFXKdFYE7lQ2p1m5Bo=&procedureName=QUERY_INVENTORY_PART_INFO_STD&userId=7632&inAttr={}"; }else { Mapmap=new HashMap<>(); map.put("MODIFY_DATE", date); url = "http://192.168.20.47:8008/PurchService.ashx?contract=KJZS&contractKey=4ttDeLKNsZuhstjtROMcRE1USNFXKdFYE7lQ2p1m5Bo=&procedureName=QUERY_INVENTORY_PART_INFO_STD&userId=7632&inAttr="+new ObjectMapper().writeValueAsString(map); } log.info("开始执行同步==========》"); String body = HttpRequest.get(url).execute().body(); log.info("执行同步结束===========》"); Map mapResult = JsonUtil.jsonToPojo(body, Map.class); List> data = JsonUtil.jsonToPojo(JsonUtil.jsonToString(mapResult.get("INVENTORY_PART_INFO")), List.class); System.out.println(data.size()); //data.forEach(System.out::println); Listno=new ArrayList(); data.forEach(l->{ Part part = new Part(); part.setPartNo(String.valueOf(l.get("PART_NO"))); no.add(part.getPartNo()); part.setPartName(String.valueOf(l.get("PART_DESC"))); part.setMaterialType(dicmattype.get(l.get("TYPE_CODE"))); part.setUnit(dicunit.get(l.get("UNIT_MEAS"))); part.setAssortment(String.valueOf(l.get("FIRST_CLASS"))); part.setCategory(String.valueOf(l.get("SECOND_CLASS"))); part.setThreeLevelClassification(String.valueOf(l.get("THIRD_CLASS"))); // part1.setMaterialAttribute(dicmatatype.get(part.get("ACCOUNTING_GROUP_DESC"))); Object netWeight = Optional.ofNullable(l.get("NET_WEIGHT")).orElse("1"); if(!Objects.equals(netWeight,"1")){ part.setWeight(BigDecimal.valueOf(Double.parseDouble(String.valueOf(l.get("NET_WEIGHT"))))); } part.setEngChgLevel("1"); part.setPlanningMethod(String.valueOf(l.get("PART_STATUS"))); //part.setPlanningMethodIfs(l.get("PART_STATUS")); part.setLotTrackingIfs(!(l.get("LOT_TRACK_DB").equals("NOT LOT TRACKING"))); part.setSunit(dicunit.get(l.get("UNIT_MEAS_FOR_WEIGHT"))); partList.add(part); }); if(partList.size()>0) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().select(Part::getPartNo).in(Part::getPartNo, no); List selectList = baseMapper.selectList(queryWrapper); //System.out.println(baseMapper.selectList(queryWrapper)); partList.removeIf(mainObj -> selectList.stream().anyMatch(subObj -> subObj.getPartNo().equals(mainObj.getPartNo()))); System.out.println("过滤长度=============================》"+partList.size()); partList.forEach(l->{ baseMapper.insert(l); }); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } finally { //JDBCUtil.close(pstmt,conn); redisTemplate.delete(key); } return (long) partList.size(); } @Override public void asyncUploadExcel(MultipartFile file) { String key = "syncPart_lock" + SecurityUtils.getUser().getId(); if (redisTemplate.hasKey(key)) { throw new RuntimeException("有导入任务正在处理"); } redisTemplate.opsForValue().set(key, 1, 1000 * 3600); RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(),true); Map dicmattype = dictUtils.getDicKey("material_type"); Map dicunit = dictUtils.getDicKey("unit"); CompletableFuture.runAsync(()->{ asyncExcel(file,dicmattype,dicunit); redisTemplate.delete(key); },threadPoolTaskExecutor); } //触发零件 @Override public String triggerAdd(PartVo partVo) { Part part = new Part(); BeanUtils.copyProperties(partVo,part); //创建者 part.setCreateUser(partVo.getCreate_name()); //更新者 part.setUpdateUser(partVo.getUpdate_name()); //零件号 part.setPartNo(partVo.getMaterial_number()); //名称 part.setPartName(partVo.getMaterial_name()); //零件描述 part.setDescription(partVo.getMaterial_description()); //单位 part.setUnit(partVo.getUnit()); //一级分类 part.setAssortment(partVo.getFirstCategoryName()); //二级分类 part.setCategory(partVo.getSecondCategoryName()); //三级分类 part.setThreeLevelClassification(partVo.getThirdCategoryName()); //规格 part.setSpecs(partVo.getMaterial_spec()); //版本号 part.setEngChgLevel(partVo.getTemplate_version().substring(1)); //计划方法 part.setPlanningMethod("A"); //型号 part.setPartModel(partVo.getMaterial_spec()); if (partVo.getType().equals("add")){ baseMapper.insert(part); return "新增"+part.getPartNo()+"零件号成功" ; }else { baseMapper.update(part,Wrappers.lambdaUpdate().eq(Part::getPartNo,part.getPartNo())); return "修改"+part.getPartNo()+"零件号成功" ; } } public void asyncExcel(MultipartFile file,Map dicmattype,Map dicunit){ File file1 = MultipartFileToFile.multipartFileToFile(file); CsvReader reader = CsvUtil.getReader(); reader.setFieldSeparator(','); //从文件中读取CSV数据 CsvData data = reader.read(file1, CharsetUtil.CHARSET_GBK); List rows = data.getRows(); //遍历行 Listlist = new ArrayList<>(); Listno=new ArrayList(); for (CsvRow csvRow : rows) { //getRawList返回一个List列表,列表的每一项为CSV中的一个单元格(既逗号分隔部分) List rawList = filter(csvRow.getRawList()); //System.out.println(rawList); if(rawList.get(0).equals("是否设备备件")){ continue; } if(rawList.get(1).equals("88.118.1/A0172320")){ Console.log(rawList); for (int i = 0; i < rawList.size(); i++) { System.out.println(i+"====="+rawList.get(i)); } Console.log(rawList.get(6)); } Part part = new Part(); part.setIsEquipment(rawList.get(0)); part.setPartNo(rawList.get(1)); no.add(rawList.get(1)); part.setPartName(rawList.get(2)); part.setDescription(rawList.get(3)); part.setMaterialType(rawList.get(6)); part.setUnit(rawList.get(8)); part.setAssets(rawList.get(16)); part.setAssetsType(rawList.get(17)); part.setPlanningMethod(rawList.get(18)); part.setSuppliesType(rawList.get(19)); part.setAbcType(rawList.get(20)); part.setHz(rawList.get(21)); part.setCycle(rawList.get(22)); part.setSunit(rawList.get(33)); part.setVolume(rawList.get(35)); part.setTotalNum(rawList.get(36)); part.setGetNum(rawList.get(37)); part.setDefaultMr(rawList.get(60)); part.setDopR(rawList.get(61)); part.setNetto(rawList.get(62)); part.setNumCount(rawList.get(64)); part.setIvm(rawList.get(66)); part.setIcl(rawList.get(67)); part.setSii(rawList.get(68)); part.setZc(rawList.get(69)); part.setEsca(rawList.get(72)); list.add(part); } list.forEach(r->{ r.setEngChgLevel("1"); no.add(r.getPartNo()); r.setMaterialType(dicmattype.get(r.getMaterialType())); r.setUnit(dicunit.get(r.getUnit())); r.setSunit(dicunit.get(r.getSunit())); }); list.stream().filter(r-> Objects.isNull(r.getMaterialType())).forEach(System.out::println); if(list.size()>0) { List> partition = Lists.partition(no, 10000); partition.forEach(l->{ QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().select(Part::getPartNo).in(Part::getPartNo, l); List selectList = baseMapper.selectList(queryWrapper); list.removeIf(mainObj -> selectList.stream().anyMatch(subObj -> subObj.getPartNo().equals(mainObj.getPartNo()))); }); log.info("过滤后长度=============================》"+list.size()); list.forEach(l->{ try { baseMapper.insert(l); }catch (Exception e) { e.printStackTrace(); } }); } MultipartFileToFile.delteTempFile(file1); } /** * 过滤修改不正确数据格式 * @param rawList * @return */ public static List filter( List rawList){ Listfilters = new ArrayList<>(); for (int i = 0; i < rawList.size(); i++) { if (rawList.get(i).contains("|")&&rawList.get(i).contains(",")&&rawList.get(i).split(",").length>1) { String[] split = rawList.get(i).split(","); if (!Objects.equals(split[1], "") &&split[0].charAt(0)==split[1].charAt(0)){ Arrays.stream(split).forEach(filters::add); }else { filters.add(rawList.get(i)); } }else { filters.add(rawList.get(i)); } } return filters; } }