package com.vci.ubcs.code.service.impl; import com.alibaba.fastjson.JSONObject; import com.vci.ubcs.code.constant.MdmBtmTypeConstant; import com.vci.ubcs.code.constant.MdmEngineConstant; import com.vci.ubcs.code.enumpack.CodeLevelTypeEnum; import com.vci.ubcs.code.enumpack.CodeSecTypeEnum; import com.vci.ubcs.code.enumpack.CodeUseButtonPositionTypeEnum; import com.vci.ubcs.code.lifecycle.CodeDefaultLC; import com.vci.ubcs.code.entity.CodeClassifyTemplateAttrDO; import com.vci.ubcs.code.entity.CodeClassifyTemplateDO; import com.vci.ubcs.code.utils.DateUtils; import com.vci.corba.common.VCIError; import com.vci.frameworkcore.compatibility.SmUserQueryServiceI; import com.vci.frameworkcore.constant.FrameWorkDefaultValueConstant; import com.vci.frameworkcore.lcstatuspck.FrameworkDataLCStatus; import com.vci.frameworkcore.pagemodel.SmUserVO; import com.vci.starter.revision.bo.TreeWrapperOptions; import com.vci.starter.revision.service.RevisionModelUtil; import com.vci.starter.web.constant.QueryOptionConstant; import com.vci.starter.web.constant.RegExpConstant; import com.vci.starter.web.enumpck.BooleanEnum; import com.vci.starter.web.enumpck.UserSecretEnum; import com.vci.starter.web.enumpck.VciFieldTypeEnum; import com.vci.starter.web.exception.VciBaseException; import com.vci.starter.web.pagemodel.*; import com.vci.starter.web.toolmodel.DateConverter; import com.vci.starter.web.util.VciBaseUtil; import com.vci.starter.web.util.VciDateUtil; import com.vci.starter.web.wrapper.VciQueryWrapperForDO; import com.vci.ubcs.code.service.*; import com.vci.ubcs.code.vo.pagemodel.*; import com.vci.web.dto.BaseModelDTO; import com.vci.web.pageModel.KeyValue; import com.vci.web.pageModel.*; import com.vci.web.service.*; import com.vci.web.service.impl.FormulaServiceImpl; import com.vci.web.service.impl.OsEnumServiceImpl; import com.vci.web.util.WebUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO; import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO; import com.vci.ubcs.code.dto.CodeDeleteBatchDTO; import com.vci.ubcs.code.dto.CodeOrderDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import plm.bs.bom.clientobject.ClientBusinessObject; import plm.bs.bom.clientobject.ClientBusinessObjectOperation; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; import static com.vci.frameworkcore.constant.FrameWorkBusLangCodeConstant.DATA_OID_NOT_EXIST; import static com.vci.web.constant.EnumIdConstant.LC_STATUS_SUBFIX; /** * 主数据引擎服务 * * @author weidy * @date 2022-2-22 */ @Service public class MdmEngineServiceImpl implements MdmEngineServiceI { /** * 必输 */ public static final String REQUIRED_CHAR = "*"; /** * 替换字符 */ public static final String SPECIAL_CHAR = "VCI"; /** * 模板的服务 */ @Autowired private CodeClassifyTemplateServiceI templateService; /** * 模板按钮服务 */ @Autowired private CodeClassifyTemplateButtonServiceI templateButtonService; /** * 分类的服务 */ @Autowired private CodeClassifyServiceI classifyService; /** * 业务数据的服务 */ @Autowired @Lazy private WebBoServiceI boService; /** * 公式的服务 */ @Autowired private FormulaServiceImpl formulaService; /** * 枚举的服务 */ @Autowired private OsEnumServiceI enumService; /** * 生命周期的服务 */ @Autowired private OsLifeCycleServiceI lifeCycleService; /** * 编码规则的服务 */ @Autowired private CodeRuleServiceI ruleService; /** * 分类码值的服务 */ @Autowired private CodeClassifyValueServiceI classifyValueService; /** * 关键属性的配置 */ @Autowired private CodeKeyAttrRepeatRuleServiceI keyRuleService; /** * 功能按钮的服务 */ @Autowired private SmOperationServiceI operationService; /** * 生成编码的服务 */ @Autowired private MdmProductCodeServiceI productCodeService; /** * 阶段的服务 */ @Autowired private CodePhaseAttrServiceI phaseAttrService; /** * 日志 */ private Logger logger = LoggerFactory.getLogger(getClass()); /** * 密级的服务 */ @Autowired private WebSecretServiceI secretService; /** * 可输可选 */ @Autowired private BdSelectInputCharServiceI charService; /** * 对象的操作 */ @Autowired private RevisionModelUtil revisionModelUtil; /** * 相似项查询规则 */ @Autowired private CodeResembleRuleServiceI resembleRuleService; /** * 属性的服务 */ @Autowired private OsAttributeServiceI attributeService; /** * 用户查询的服务 */ @Autowired(required = false) private SmUserQueryServiceI userQueryService; /** * 模板属性的服务 */ @Autowired private CodeClassifyTemplateAttrServiceI templateAttrService; /** * 拷贝的版本 */ public static final String COPY_FROM_VERSION = "copyfromversion"; /** * 使用分类主键获取页面的内容,包含按钮 * * @param codeClassifyOid 主题库分类主键 * @param functionId 功能的编号 * @return UI相关的内容 */ @Override public MdmUIInfoVO getUIInfoByClassifyOid(String codeClassifyOid, String functionId) { VciBaseUtil.alertNotNull(codeClassifyOid, "主题库分类主键"); MdmUIInfoVO uiInfoVO = getTableDefineByTemplateVO(getUsedTemplateByClassifyOid(codeClassifyOid)); uiInfoVO.setLeaf(classifyService.countChildrenByClassifyOid(codeClassifyOid) == 0); if (StringUtils.isNotBlank(functionId) && !"~".equalsIgnoreCase(functionId)) { List operationVOS = operationService.listButtonByFunctionId(functionId); if (operationVOS == null) { operationVOS = new ArrayList<>(); } //查询扩展按钮 List buttonVOS = listButtonInToolbarByClassifyOid(codeClassifyOid); if (!CollectionUtils.isEmpty(buttonVOS)) { for (int i = 0; i < buttonVOS.size(); i++) { CodeButtonVO buttonVO = buttonVOS.get(i); SmOperationVO operationVO = new SmOperationVO(); operationVO.setModuleNo(functionId); operationVO.setUniqueFlag(buttonVO.getId()); operationVO.setName(buttonVO.getName()); operationVO.setAlias(operationVO.getName()); operationVO.setExecuteJs(buttonVO.getExecutejs()); operationVO.setIconCls(buttonVO.getIconcls()); operationVOS.add(operationVO); } } uiInfoVO.setButtons(operationVOS); } return uiInfoVO; } /** * 使用主题库分类获取ui相关的内容(不包含按钮) * * @param codeClassifyOid 主题库的分类的主键 * @return UI相关的内容 */ @Override public MdmUIInfoVO getTableDefineByClassifyOid(String codeClassifyOid) { VciBaseUtil.alertNotNull(codeClassifyOid, "主题库分类主键"); return getTableDefineByTemplateVO(getUsedTemplateByClassifyOid(codeClassifyOid)); } /** * 使用模板显示对象转换为表格的信息(包含扩展的按钮) * * @param templateVO 模板的信息 * @return UI相关的内容(仅包含表格信息) */ private MdmUIInfoVO getTableDefineByTemplateVO(CodeClassifyTemplateVO templateVO) { //先看这个分类本身是否有模板 MdmUIInfoVO uiInfoVO = new MdmUIInfoVO(); uiInfoVO.setTemplateVO(templateVO); //我们需要将模板转换为表格相关的显示信息 uiInfoVO.setTableDefineVO(wrapperTableDefineByTemplate(uiInfoVO.getTemplateVO(),false)); //需要去看扩展的按钮,只有列表里面本身才添加进去,工具栏上的单独获取 List buttonVOS = templateButtonService.listButtonByTemplateOid(templateVO.getOid(), true); if (!CollectionUtils.isEmpty(buttonVOS)) { //我们要分开为按钮,还是在操作列里面 List tableButtonVOs = buttonVOS.stream().filter(s -> CodeUseButtonPositionTypeEnum.TABLE.getValue().equalsIgnoreCase(s.getButtonuse())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(tableButtonVOs)) { UITableFieldVO optionFieldVO = new UITableFieldVO(); optionFieldVO.setField("options"); optionFieldVO.setTitle("操作"); optionFieldVO.setFieldType("text"); optionFieldVO.setOptionField(true); List buttons = new ArrayList<>(); Map optionJsMap = new HashMap<>(); tableButtonVOs.stream().forEach(buttonVO -> { KeyValue kv = new KeyValue(); kv.setKey(buttonVO.getId()); kv.setValue(buttonVO.getClassifybuttonoidName()); kv.setAttributes(VciBaseUtil.objectToMap(buttonVO)); buttons.add(kv); optionJsMap.put(buttonVO.getId(), buttonVO.getButtonVO().getExecutejs()); }); optionFieldVO.setOptionJsMap(optionJsMap); uiInfoVO.getTableDefineVO().getCols().get(0).add(optionFieldVO); } } return uiInfoVO; } /** * 使用分类的主键获取可以使用的模板对象 * * @param codeClassifyOid 分类的主键 * @return 模板的显示对象 */ @Override public CodeClassifyTemplateVO getUsedTemplateByClassifyOid(String codeClassifyOid) { return getUsedTemplateByClassifyOid(codeClassifyOid, true); } /** * 使用分类的主键获取可以使用的模板对象 * * @param codeClassifyOid 分类的主键 * @param hasAttr 包含属性 * @return 模板的显示对象 */ @Override public CodeClassifyTemplateVO getUsedTemplateByClassifyOid(String codeClassifyOid, boolean hasAttr) { List templateVOs = templateService.listReleaseTemplateByClassifyOid(codeClassifyOid, hasAttr); return templateVOs.get(templateVOs.size() - 1); } /** * 使用模板的主键获取表单的信息 * * @param codeClassifyTemplateOid 模板的主键 * @return ui相关的内容 */ @Override public MdmUIInfoVO getFormDefineByTemplateOid(String codeClassifyTemplateOid) { return getFormDefineByTemplateOid(codeClassifyTemplateOid, null); } /** * 使用模板的主键获取表单的信息 * * @param codeClassifyTemplateOid 模板的主键 * @param codeClassifyOid 使用模板的分类主键 * @return ui相关的内容 */ @Override public MdmUIInfoVO getFormDefineByTemplateOid(String codeClassifyTemplateOid, String codeClassifyOid) { CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(codeClassifyTemplateOid); MdmUIInfoVO uiInfoVO = new MdmUIInfoVO(); uiInfoVO.setTemplateVO(templateVO); uiInfoVO.setFormDefineVO(wrapperFormDefineByTemplate(templateVO, codeClassifyOid)); wrapperResemble(templateVO, uiInfoVO); return uiInfoVO; } /** * 封装相似项查询的列表 * * @param templateVO 模板的显示对象 * @param uiInfoVO 页面的信息 */ private void wrapperResemble(CodeClassifyTemplateVO templateVO, MdmUIInfoVO uiInfoVO) { List resembleAttrList = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getSamerepeatattrflag()) || VciQueryWrapperForDO.ID_FIELD.equalsIgnoreCase(s.getId())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(resembleAttrList) && resembleAttrList.size() > 1) { UITableDefineVO resembleTable = new UITableDefineVO(); resembleTable.setOid(templateVO.getOid()); resembleTable.setBtmType(templateVO.getBtmTypeId()); resembleTable.setDisplayQueryArea(false); resembleTable.setPageVO(new UITablePageVO()); //处理所有的列,这个模板没有合并的表头的情况 List fieldVOList = new ArrayList<>(); resembleAttrList.forEach(attrVO -> { UITableFieldVO tableFieldVO = templateAttr2TableField(attrVO,false); tableFieldVO.setHidden(false); fieldVOList.add(tableFieldVO); }); List> cols = new ArrayList<>(); cols.add(fieldVOList); resembleTable.setCols(cols); uiInfoVO.setResembleTableVO(resembleTable); } } /** * 使用模板的主键获取表单的信息 * * @param templateOid 模板的主键 * @param executionId 流程执行id * @param processUse 流程模板的用途 * @return ui相关的内容 */ @Override public List getFieldByProcessTemplate(String templateOid, String executionId, String processUse) { VciBaseUtil.alertNotNull(templateOid, "模板主键", executionId, "流程的执行Id", processUse, "流程模板用途"); while (StringUtils.countMatches(executionId, ".") > 1) { executionId = executionId.substring(0, executionId.lastIndexOf(".")); } String sql = "select distinct (t.codetempattrOidArr)\n" + "from " + VciBaseUtil.getTableName(MdmBtmTypeConstant.CODE_CLASSIFY_PROCESS_TEMPLATE) + " t\n" + "join PLFLOWINSTANCE plfi on t.ID = plfi.PLTEMPLATEPUID\n" + "where plfi.PLEXECUTIONID = '" + executionId + "' and t.CLASSIFYTEMPLATEOID = '" + templateOid + "' and t.CODEPROCESSUSE = '" + processUse + "'"; List tempAttrOidArr = boService.queryByOnlySql(sql); if (CollectionUtils.isEmpty(tempAttrOidArr) || StringUtils.isBlank(tempAttrOidArr.get(0).getAttributeValue("codetempattroidarr"))) { return new ArrayList<>(); } return VciBaseUtil.str2List(tempAttrOidArr.get(0).getAttributeValue("codetempattroidarr")); } /** * 使用主题库分类的主键获取表单的信息 * * @param codeClassifyOid 分类的主键 * @return ui相关的内容 */ @Override public MdmUIInfoVO getFormDefineByClassifyOid(String codeClassifyOid) { MdmUIInfoVO uiInfoVO = new MdmUIInfoVO(); CodeClassifyTemplateVO templateVO = getUsedTemplateByClassifyOid(codeClassifyOid); uiInfoVO.setTemplateVO(templateVO); uiInfoVO.setFormDefineVO(wrapperFormDefineByTemplate(templateVO, codeClassifyOid)); wrapperResemble(templateVO, uiInfoVO); return uiInfoVO; } /** * 使用分类的主键获取表格的定义 * * @param codeClassifyOid 分类主键 * @param phase 阶段的名称 * @return UI相关的信息(仅包含表单) */ @Override public MdmUIInfoVO getTableDefineByClassifyOid_v2(String codeClassifyOid, String phase) { MdmUIInfoVO uiInfoVO = new MdmUIInfoVO(); CodeClassifyTemplateVO templateVO = getUsedTemplateByClassifyOid(codeClassifyOid); uiInfoVO.setTemplateVO(templateVO); UITableDefineVO uiTableDefineVO = wrapperTableDefineByTemplate(templateVO,true); List phaseAttrIdList = listPhaseAttrByClassifyOid(codeClassifyOid, phase); uiTableDefineVO.getCols().stream().forEach(list -> { List visiableTableField=new ArrayList<>(); if(StringUtils.isNotBlank(phase)) { visiableTableField = list.stream().filter(col -> phaseAttrIdList.stream().anyMatch(s -> StringUtils.equalsIgnoreCase(col.getField(), s) || (StringUtils.equalsIgnoreCase(col.getFieldType(), "combox") && StringUtils.equalsIgnoreCase(col.getSortField(), s)) || (StringUtils.equalsIgnoreCase(col.getFieldType(), "refer") && StringUtils.equalsIgnoreCase(col.getQueryField(), s)) )).collect(Collectors.toList()); }else{ visiableTableField= list.stream().filter(col -> templateVO.getAttributes().stream().anyMatch(s -> (!s.getReadonlyflag().equalsIgnoreCase("true")&& StringUtils.equalsIgnoreCase(col.getField(), s.getId())) || (StringUtils.equalsIgnoreCase(col.getFieldType(), "combox") && StringUtils.equalsIgnoreCase(col.getSortField(), s.getId())) || (StringUtils.equalsIgnoreCase(col.getFieldType(), "refer") && StringUtils.equalsIgnoreCase(col.getQueryField(), s.getId())) )).collect(Collectors.toList()); } visiableTableField.stream().forEach(vo -> { uiTableDefineVO.setHasEditor(true); if ("refer".equalsIgnoreCase(vo.getFieldType())) { setReferConfig2EditConfig(vo); } else if ("combox".equalsIgnoreCase(vo.getFieldType())) { setComboxConfig2EditConfig(vo); } else if (StringUtils.isNotBlank(vo.getDateFormate())){ vo.setEdit("date"); }else { vo.setEdit(vo.getFieldType()); } }); }); uiInfoVO.setTableDefineVO(uiTableDefineVO); wrapperResemble(templateVO, uiInfoVO); return uiInfoVO; } /** * 加载成参照的修改配置 * @param vo 表格字段显示对象 */ private void setReferConfig2EditConfig(UITableFieldVO vo) { if (!CollectionUtils.isEmpty(vo.getReferConfig().getWhere())){ vo.getReferConfig().getWhere().keySet().forEach(key -> { vo.getReferConfig().getWhere().put(key, "'" + vo.getReferConfig().getWhere().get(key) + "'"); }); } if (StringUtils.isNotBlank(vo.getReferConfig().getParentValue())){ String parentValue = vo.getReferConfig().getParentValue(); parentValue ="\\" + parentValue.replaceAll("'","{vci-quote}").replaceAll("=","{vci-equals}"); vo.getReferConfig().setParentValue(parentValue); } String referConfig = vo.getReferConfig().toString() .replaceAll("=",":") .replaceAll("UITableCustomDefineVO","") .replaceAll("UIFieldSortVO","") .replaceAll("UITablePageVO","") .replaceAll("UITableFieldVO","") .replaceAll("UIFormReferVO","") .replaceAll("\\{vci-equals}","=") .replaceAll("\\{vci-quote}","\\\\'") .replaceAll("'null'","null"); referConfig = referConfig + ",fieldMap:{" + vo.getQueryField() + ":'" + vo.getReferConfig().getValueField() + "'}"; vo.setEditConfig("{referConfig:" + referConfig + "}"); vo.setEdit(vo.getFieldType()); } /** * 加载成下拉框的修改配置 * @param vo 表格字段显示对象 */ private void setComboxConfig2EditConfig(UITableFieldVO vo) { vo.setEditConfig("{editable:true,comboxKey:'" + vo.getComboxKey() + "'"); if (!CollectionUtils.isEmpty(vo.getData())){ vo.setEditConfig(vo.getEditConfig()+", comboxConfig:"); for (int i = 0; i < vo.getData().size(); i++) { KeyValue data = vo.getData().get(i); if (i == vo.getData().size() -1){ vo.setEditConfig(vo.getEditConfig() + "{attributes:"+data.getAttributes()+",key:'"+data.getKey()+"',value:'"+data.getValue()+"'}]}"); }else if (i == 0){ vo.setEditConfig(vo.getEditConfig() + "{data:[{attributes:"+data.getAttributes()+",key:'"+data.getKey()+"',value:'"+data.getValue()+"'},"); }else{ vo.setEditConfig(vo.getEditConfig() + "{attributes:"+data.getAttributes()+",key:'"+data.getKey()+"',value:'"+data.getValue()+"'},"); } } vo.setEditConfig(vo.getEditConfig() + ",valueField:'" + vo.getQueryField() + "'"); } vo.setEditConfig(vo.getEditConfig() + "}"); vo.setEdit(vo.getFieldType()); } /** * 使用模板主键获取ui相关的内容 * * @param templateOid 模板的主键 * @return ui相关的内容 */ @Override public MdmUIInfoVO getTableDefineByTemplateOid(String templateOid) { return getTableDefineByTemplateVO(templateService.getObjectHasAttrByOid(templateOid)); } /** * 使用分类主键获取工具栏中的按钮信息 * * @param codeClassifyOid 分类的主键 * @return 按钮的信息,会按照排序号进行排序 */ @Override public List listButtonInToolbarByClassifyOid(String codeClassifyOid) { CodeClassifyTemplateVO templateVO = getUsedTemplateByClassifyOid(codeClassifyOid); return listButtonInToolbarByTemplateOid(templateVO.getOid()); } /** * 使用模板主键获取工具栏中的按钮信息 * * @param templateOid 模板的主键 * @return 按钮的信息,会按照排序号进行排序 */ @Override public List listButtonInToolbarByTemplateOid(String templateOid) { List buttonVOS = templateButtonService.listButtonByTemplateOid(templateOid, true); if (CollectionUtils.isEmpty(buttonVOS)) { return new ArrayList<>(); } List toolbarButtons = buttonVOS.stream().filter(s -> CodeUseButtonPositionTypeEnum.TOOLBAR.getValue().equalsIgnoreCase(s.getButtonuse())).collect(Collectors.toList()); if (CollectionUtils.isEmpty(toolbarButtons)) { return new ArrayList<>(); } List buttonVOList = new ArrayList<>(); for (int i = 0; i < toolbarButtons.size(); i++) { buttonVOList.add(toolbarButtons.get(i).getButtonVO()); } return buttonVOList; } /** * 使用分类获取对应的数据 * * @param codeClassifyOid 分类的主键 * @param templateOid 模板的主键 * @param conditionMap 查询条件 * @param pageHelper 分页的对象 * @return 数据(包含下级分类) */ @Override public DataGrid> gridTableDataByClassifyOid(String codeClassifyOid, String templateOid, Map conditionMap, PageHelper pageHelper) { //1. 使用分类获取所有的下级分类,然后根据分类查询对应的数据 //2. 全部使用当前分类的当前模板来展示内容 //3. 如果模板上有枚举注入,组合规则,和参照的,需要执行转换 //4. 查询的时候,直接使用codeclsfpath来查询 CodeClassifyVO topClassifyVO = classifyService.getTopClassifyVO(codeClassifyOid); CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(templateOid); if (topClassifyVO == null || StringUtils.isBlank(topClassifyVO.getBtmtypeid())) { throw new VciBaseException("当前主题库分类没有顶层分类,或者顶层分类没有设置业务类型"); } String btmTypeId = topClassifyVO.getBtmtypeid(); if (StringUtils.isBlank(btmTypeId)) { return new DataGrid<>("这个分类所属顶层分类没有添加业务类型"); } if (conditionMap == null) { conditionMap = new HashMap<>(); } //pageHelper.addDefaultDesc("createTime"); pageHelper.addDefaultDesc("id"); if (!classifyService.checkHasChild(codeClassifyOid)) { conditionMap.put(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD, codeClassifyOid); } else { conditionMap.put(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD, QueryOptionConstant.IN + "(select oid from " + VciBaseUtil.getTableName(MdmBtmTypeConstant.CODE_CLASSIFY) + " where lcstatus='" + FrameWorkDefaultValueConstant.FRAMEWORK_DATA_ENABLED + "' start with parentCodeClassifyOid = '" + codeClassifyOid + "' CONNECT BY PRIOR OID = parentCodeClassifyOid )"); } conditionMap.put("islastr", "1"); conditionMap.put("islastv", "1"); return queryGrid(btmTypeId, templateVO, conditionMap, pageHelper); // List selectFieldList = templateVO.getAttributes().stream().map(CodeClassifyTemplateAttrVO::getId).collect(Collectors.toList()); // //参照让平台直接查询就行 // List finalSelectFieldList = selectFieldList; // List referAttrVOs = templateVO.getAttributes().stream().filter( // s -> StringUtils.isNotBlank(s.getReferbtmid()) // && // (finalSelectFieldList.size() ==0 || finalSelectFieldList.contains(s.getId().toLowerCase(Locale.ROOT))) // ).collect(Collectors.toList()); // if(!CollectionUtils.isEmpty(referAttrVOs)){ // for (int i = 0; i < referAttrVOs.size(); i++) { // selectFieldList.add(referAttrVOs.get(i).getId() + ".name"); // } // } // //我们使用和业务类型的来查询 // DataGrid> dataGrid = boService.queryGridByBo(btmTypeId, conditionMap, pageHelper, selectFieldList); // //我们需要使用模板来转换 // if(!CollectionUtils.isEmpty(dataGrid.getData())){ // wrapperData(dataGrid.getData(),templateVO,finalSelectFieldList,false); // } // return dataGrid; } /** * 查询编码数据的列表 * * @param btmType 业务类型 * @param templateVO 模板的对象,需要包含模板的属性 * @param conditionMap 查询条件 * @param pageHelper 分页对象 * @return 数据列表 */ @Override public DataGrid> queryGrid(String btmType, CodeClassifyTemplateVO templateVO, Map conditionMap, PageHelper pageHelper) { CodeTemplateAttrSqlBO sqlBO = getSqlByTemplateVO(btmType, templateVO, conditionMap, pageHelper); List maps = boService.queryByOnlySqlForMap(sqlBO.getSqlHasPage()); DataGrid> dataGrid = new DataGrid<>(); List> dataList = new ArrayList<>(); if (!CollectionUtils.isEmpty(maps)) { maps.stream().forEach(map -> { Map data = new HashMap<>(); map.forEach((key, value) -> { data.put(((String) key).toLowerCase(Locale.ROOT), (String) value); }); dataList.add(data); }); } dataGrid.setData(dataList); if (!CollectionUtils.isEmpty(dataList)) { wrapperData(dataGrid.getData(), templateVO, sqlBO.getSelectFieldList(), false); dataGrid.setTotal(boService.queryCountBySql(sqlBO.getSqlCount(), new HashMap<>())); } return dataGrid; } /** * 根据模板属性生成相应的sql信息 * * @param btmType 业务类型 * @param templateVO 模板显示对象,必须包含属性 * @param conditionMap 查询条件 * @param pageHelper 分页和排序对象 * @return sql的相关信息 */ @Override public CodeTemplateAttrSqlBO getSqlByTemplateVO(String btmType, CodeClassifyTemplateVO templateVO, Map conditionMap, PageHelper pageHelper) { //因为参照不一定是在平台的属性池里面设置,所以我们得需要自行处理 //参考VciQueryWrapper来处理 //1. 找到所有的字段, Map attrVOMap = templateVO.getAttributes().stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); List selectFieldList = attrVOMap.keySet().stream().collect(Collectors.toList()); //所有的参照的字段 Map joinTableList = new ConcurrentHashMap<>(); List referAttrVOs = templateVO.getAttributes().stream().filter( s -> StringUtils.isNotBlank(s.getReferbtmid()) || StringUtils.isNotBlank(s.getReferConfig()) ).collect(Collectors.toList()); Map referFieldMap = new HashMap<>(); if (!CollectionUtils.isEmpty(referAttrVOs)) { referAttrVOs.parallelStream().forEach(attrVO -> { UIFormReferVO referVO = null; if (StringUtils.isNotBlank(attrVO.getReferConfig())) { referVO = JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class); } else { referVO = new UIFormReferVO(); referVO.setReferType(attrVO.getReferbtmid()); referVO.setValueField(VciQueryWrapperForDO.OID_FIELD); referVO.setTextField("name"); } String referTable = VciBaseUtil.getTableName(referVO.getReferType()); String referTableNick = attrVO.getId() + "0"; String left = " left join " + referTable + " " + referTableNick + " on " + referTableNick + "." + referVO.getValueField() + " = t." + attrVO.getId(); joinTableList.put(attrVO.getId(), left); String referShowField = attrVO.getId() + "Name"; List textFields = VciBaseUtil.str2List(referVO.getTextField()); String showFieldInSource = ""; if (textFields.contains("name")) { showFieldInSource = "name"; } else { showFieldInSource = textFields.get(0); } referFieldMap.put(attrVO.getId(), referTableNick + "." + showFieldInSource); selectFieldList.add(referTableNick + "." + showFieldInSource + " as " + referShowField); }); } Optional.ofNullable(attributeService.getDefaultAttributeVOMap()).orElseGet(() -> new HashMap<>()).keySet().stream().forEach(attrId -> { if (!selectFieldList.contains(attrId) && !"secretgrade".equalsIgnoreCase(attrId)) { selectFieldList.add(attrId); } }); if (!selectFieldList.contains(MdmEngineConstant.CODE_FIELD)) { selectFieldList.add(MdmEngineConstant.CODE_FIELD); } if (!selectFieldList.contains(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD)) { selectFieldList.add(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD); } if (!selectFieldList.contains(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD)) { selectFieldList.add(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD); } if (!selectFieldList.contains(MdmEngineConstant.CODE_FULL_PATH_FILED)) { selectFieldList.add(MdmEngineConstant.CODE_FULL_PATH_FILED); } //处理查询条件 //TODO 验证sql注入 List andSql = new ArrayList<>(); List orSql = new ArrayList<>(); if (!CollectionUtils.isEmpty(conditionMap)) { Map orConditionMap = new HashMap<>(); Map andCondtionMap = new HashMap<>(); //先分离or的查询条件,另外当查询条件是空的时候也不查询 conditionMap.forEach((k, v) -> { if (StringUtils.isNotBlank(v)) { if (v.startsWith(QueryOptionConstant.OR)) { orConditionMap.put(k, v.substring(QueryOptionConstant.OR.length())); } else { andCondtionMap.put(k, v); } } }); andCondtionMap.forEach((k, v) -> { andSql.add(getConditionSql(k.toLowerCase(), v, referFieldMap, attrVOMap)); }); orConditionMap.forEach((k, v) -> { orSql.add(getConditionSql(k.toLowerCase(), v, referFieldMap, attrVOMap)); }); } //组合起来 StringBuilder andSb = new StringBuilder(); andSql.stream().forEach(s -> { andSb.append(s).append(SPACE).append(QueryOptionConstant.AND).append(SPACE); }); String andString = andSb.toString().trim(); String endWithSql = QueryOptionConstant.AND; if (andString.endsWith(endWithSql)) { andString = andString.substring(0, andString.length() - endWithSql.length()); } String orString = orSql.stream().collect(Collectors.joining(" or ")); String whereSql = ""; if (StringUtils.isNotBlank(orString)) { if (StringUtils.isBlank(andString)) { andString = " 1 = 1 "; } whereSql = SPACE + "(" + SPACE + andString + SPACE + ") and (" + SPACE + orString + SPACE + ")" + SPACE; } else { whereSql = andString + SPACE; } if (attrVOMap.keySet().contains("secretgrade")) { Integer userSecret = VciBaseUtil.getCurrentUserSecret(); if (userSecret == null || userSecret == 0) { userSecret = secretService.getMinUserSecret(); } whereSql += " and ( t.secretGrade <= " + userSecret + ") "; } String tableName = VciBaseUtil.getTableName(btmType); String sql = "select " + selectFieldList.stream().map(s -> (s.contains(".") ? s : ("t." + s))).collect(Collectors.joining(",")) + " from " + tableName + SPACE + "t" + SPACE + joinTableList.values().stream().collect(Collectors.joining(SPACE)) + (StringUtils.isBlank(whereSql) ? "" : " where ") + whereSql; if (pageHelper == null) { pageHelper = new PageHelper(-1); } //看看排序 String orderSql = pageHelper.getOrderSql("t"); sql += (orderSql == null ? "" : orderSql); String whereSubfixForPage = " ) A where rownum < " + (pageHelper.getLimit() * pageHelper.getPage() + 1) + ") where RN >= " + (pageHelper.getLimit() * (pageHelper.getPage() - 1) + 1); String sqlHasPage = pageHelper.getLimit() > 0 ? ("select * from (select A.*,rownum RN from (" + sql + whereSubfixForPage) : sql; String sqlCount = "select count(1) from " + tableName + SPACE + "t" + SPACE + joinTableList.values().stream().collect(Collectors.joining(SPACE)) + (StringUtils.isBlank(whereSql) ? "" : " where ") + whereSql; CodeTemplateAttrSqlBO sqlBO = new CodeTemplateAttrSqlBO(); sqlBO.setTableName(tableName); sqlBO.setJoinTable(joinTableList); sqlBO.setNickName("t"); sqlBO.setPageHelper(pageHelper); sqlBO.setSqlHasPage(sqlHasPage); sqlBO.setSqlCount(sqlCount); sqlBO.setSqlUnPage(sql); return sqlBO; } /** * 空格 */ public static final String SPACE = " "; /** * 组合查询条件的sql * * @param key 字段 * @param value 名字 * @param referFieldMap 参照的字段 * @param attrVOMap 属性的映射 * @return Sql语句 */ private String getConditionSql(String key, String value, Map referFieldMap, Map attrVOMap) { if (key.endsWith("_begin")) { //说明是>=的。我们需要先获取一下 String field = (key.substring(0, key.length() - 6).toLowerCase().trim()); if (referFieldMap.containsKey(field)) { //说明还是参照里面的,我们默认这种情况下都是字符串吧,因为参照的属性不一定用的平台的属性池里的,所以大部分情况下,显示的属性都是字符串吧 return referFieldMap.get(field) + SPACE + " >= '" + value + "'" + SPACE; } else { return (field.contains(".") ? "" : "t.") + field + SPACE + " >= " + getStringValueInWhere(value, field, attrVOMap); } } else if (key.endsWith("_end")) { //说明是<=的。我们需要先获取一下 String field = (key.substring(0, key.length() - 6).toLowerCase().trim()); if (referFieldMap.containsKey(field)) { //说明还是参照里面的,我们默认这种情况下都是字符串吧,因为参照的属性不一定用的平台的属性池里的,所以大部分情况下,显示的属性都是字符串吧 return referFieldMap.get(field) + SPACE + " <= '" + value + "'" + SPACE; } else { return (field.contains(".") ? "" : "t.") + field + SPACE + " <= " + getStringValueInWhere(field, value, attrVOMap); } } else { if (referFieldMap.containsKey(key)) { //说明是参照的,我们参照的查询都认为是字符串,如果是时间格式的查询肯定有问题, String selectKey = referFieldMap.get(key); return getSqlByValue(selectKey, value, null); } else { return getSqlByValue(key, value, attrVOMap); } } } /** * 封装最终的sql语句中的值部分 * * @param selectKey 查询的字段 * @param value 值 * @param attrVOMap 属性的显示对象映射 * @return sql里的值 */ private String getSqlByValue(String selectKey, String value, Map attrVOMap) { StringBuilder sql = new StringBuilder(); if (!selectKey.contains(".") && (attrVOMap.containsKey(selectKey.toLowerCase(Locale.ROOT)) || attributeService.isDefaultAttr(selectKey) || selectKey.matches(RegExpConstant.LETTER))) { sql.append("t."); } if (value.startsWith(QueryOptionConstant.IN)) { sql.append(selectKey) .append(SPACE) .append("in") .append(SPACE) .append("(") .append(value.replace(QueryOptionConstant.IN, "")) .append(")"); } else if (value.startsWith(QueryOptionConstant.NOTIN)) { sql.append(selectKey) .append(SPACE) .append("not in") .append(SPACE) .append("(") .append(value.replace(QueryOptionConstant.NOTIN, "")) .append(")"); } else if (value.startsWith(QueryOptionConstant.NOTEQUAL)) { value = value.replace(QueryOptionConstant.NOTEQUAL, ""); value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append(QueryOptionConstant.NOTEQUAL) .append(SPACE) .append(value); } else if (value.startsWith(QueryOptionConstant.MORETHAN)) { value = value.replace(QueryOptionConstant.MORETHAN, ""); value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append(QueryOptionConstant.MORETHAN) .append(SPACE) .append(value); } else if (value.startsWith(QueryOptionConstant.MORE)) { value = value.replace(QueryOptionConstant.MORE, ""); value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append(QueryOptionConstant.MORE) .append(SPACE) .append(value); } else if (value.startsWith(QueryOptionConstant.LESSTHAN)) { value = value.replace(QueryOptionConstant.LESSTHAN, ""); value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append(QueryOptionConstant.LESSTHAN) .append(SPACE) .append(value); } else if (value.startsWith(QueryOptionConstant.LESS)) { value = value.replace(QueryOptionConstant.LESS, ""); value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append(QueryOptionConstant.LESS) .append(SPACE) .append(value); } else if (value.startsWith(QueryOptionConstant.ISNOTNULL)) { sql.append(selectKey) .append(SPACE) .append(" is not null"); } else if (value.startsWith(QueryOptionConstant.ISNULL)) { sql.append(selectKey) .append(SPACE) .append(" is null"); } else if (value.contains("*")) { //说明是like,或者lefe like ,right like value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append("like") .append(SPACE) // .append("'") .append(value.replace("*", "%")) // .append("'") .append(SPACE); } else { value= value.replace(SPECIAL_CHAR,REQUIRED_CHAR); value = getStringValueInWhere(selectKey, value, attrVOMap); sql.append(selectKey) .append(SPACE) .append(QueryOptionConstant.EQUAL) .append(SPACE) .append(value); } sql.append(SPACE); return sql.toString(); } /** * 默认的时间格式 */ private static final String DATETIME_FORMAT = "yyyy-mm-dd hh24:mi:ss"; /** * 日期格式 */ private static final String DATE_FORMAT = "yyyy-mm-dd"; /** * 只是sql */ public static final String ONLY = "${vcionly}"; /** * 获取查询条件中的值的,处理不同的类型 * * @param value 值 * @param field 字段名称 * @return 日期或者时间格式会包括to_date,字符串会加' */ private String getStringValueInWhere(String field, String value, Map attrVOMap) { if ((field.contains(".") && !field.toLowerCase(Locale.ROOT).startsWith("t.")) || attrVOMap == null || !field.replace("t.", "").matches(RegExpConstant.LETTER) || value.startsWith(ONLY)) { //说明可能是指定的某个条件,直接返回 if (value.startsWith(ONLY)) { value = value.replace(ONLY, ""); } if ((value.startsWith("(") && value.endsWith(")")) || (value.startsWith("'") && value.endsWith("'"))) { return value; } if (field.contains(".") && attrVOMap != null && attrVOMap.containsKey(field.split("\\.")[0].toLowerCase(Locale.ROOT))) { //是参照 return "'" + value + "'"; } else { return value; } } else { //看看是不是这个对象里的属性 if (attrVOMap.containsKey(field)) { VciFieldTypeEnum fieldTypeEnum = VciFieldTypeEnum.valueOf(attrVOMap.get(field).getAttributedatatype()); if ("ts".equalsIgnoreCase(field)) { return "to_timestamp('" + value + "', '" + DATETIME_FORMAT + ".ff')"; } DateConverter dateConverter = new DateConverter(); if (VciFieldTypeEnum.VTDateTime.equals(fieldTypeEnum)) { //实际上,数据库都是timestamp的类型. dateConverter.setAsText(value); return "to_date('" + dateConverter.getAsText(VciDateUtil.DateTimeFormat) + "','" + DATETIME_FORMAT + "')"; } else if (VciFieldTypeEnum.VTDate.equals(fieldTypeEnum)) { dateConverter.setAsText(value); return "to_date('" + dateConverter.getAsText(VciDateUtil.DateFormat) + "','" + DATE_FORMAT + "')"; } else if (VciFieldTypeEnum.VTDouble.equals(fieldTypeEnum) || VciFieldTypeEnum.VTLong.equals(fieldTypeEnum) || VciFieldTypeEnum.VTInteger.equals(fieldTypeEnum)) { return value; } else { return "'" + value + "'"; } } else { if ((value.startsWith("(") && value.endsWith(")")) || (value.startsWith("'") && value.endsWith("'"))) { return value; } return "'" + value + "'"; } } } /** * 封装开关的内容,常用于导出 * @param dataMap 数据的内容 * @param templateVO 模板的显示 */ @Override public void wrapperBoolean(List> dataMap, CodeClassifyTemplateVO templateVO){ List booleanAttributes = templateVO.getAttributes().stream().filter(s -> VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(s.getAttributedatatype())).map(s -> s.getId().toLowerCase(Locale.ROOT)).collect(Collectors.toList()); if(!CollectionUtils.isEmpty(booleanAttributes)){ dataMap.stream().forEach(data -> { booleanAttributes.stream().forEach(attrId->{ if(data.containsKey(attrId)){ String value = data.get(attrId); data.put(attrId, BooleanEnum.TRUE.getValue().equalsIgnoreCase(value)?"是":"否"); } }); }); } } /** * 封装查询出来的数据 * * @param dataMap 数据的映射 * @param templateVO 模板的属性 * @param onlySelectAttrIdList 仅仅查询的属性字段 * @param form 表单里使用 */ @Override public void wrapperData(List> dataMap, CodeClassifyTemplateVO templateVO, Collection onlySelectAttrIdList, boolean form) { if (onlySelectAttrIdList == null) { onlySelectAttrIdList = new ArrayList<>(); } //先转换一下时间格式 List finalOnlySelectAttrIdList = onlySelectAttrIdList.stream().collect(Collectors.toList()); List dateFormatAttrVOs = templateVO.getAttributes().stream().filter( s -> StringUtils.isNotBlank(s.getCodedateformat()) && (finalOnlySelectAttrIdList.size() == 0 || finalOnlySelectAttrIdList.contains(s.getId().toLowerCase(Locale.ROOT))) ).collect(Collectors.toList()); //枚举的内容 List enumAttrVOs = templateVO.getAttributes().stream().filter( s -> (StringUtils.isNotBlank(s.getEnumid()) || StringUtils.isNotBlank(s.getEnumString())) && (finalOnlySelectAttrIdList.size() == 0 || finalOnlySelectAttrIdList.contains(s.getId().toLowerCase(Locale.ROOT))) ).collect(Collectors.toList()); List userIds = new ArrayList<>(); dataMap.stream().forEach(data -> { //处理时间 if (!form) { //表单的时候只能用统一的时间格式 wrapperDateFormat(dateFormatAttrVOs, data); } //处理枚举 wrapperEnum(enumAttrVOs, data); String lcstatus = data.get(VciQueryWrapperForDO.LC_STATUS_FIELD); String copyFromVersion = data.getOrDefault(COPY_FROM_VERSION,""); if ((CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(lcstatus) || CodeDefaultLC.AUDITING.getValue().equalsIgnoreCase(lcstatus)) && StringUtils.isBlank(copyFromVersion) ) { data.put(VciQueryWrapperForDO.ID_FIELD, "******"); } data.put(VciQueryWrapperForDO.LC_STATUS_FIELD_TEXT.toLowerCase(Locale.ROOT), CodeDefaultLC.getTextByValue(lcstatus)); if(CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(lcstatus) && StringUtils.isNotBlank(copyFromVersion)){ data.put(VciQueryWrapperForDO.LC_STATUS_FIELD_TEXT.toLowerCase(Locale.ROOT), "修改中"); } if (data.containsKey("creator")) { userIds.add(data.get("creator")); } if (data.containsKey("lastmodifier")) { userIds.add(data.get("lastmodifier")); } }); if (!CollectionUtils.isEmpty(userIds)) { Map userVOMap = Optional.ofNullable(userQueryService.listUserByUserIds(userIds)).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); dataMap.stream().forEach(data -> { String creator = data.getOrDefault("creator", null); if (StringUtils.isNotBlank(creator) && userVOMap.containsKey(creator.toLowerCase(Locale.ROOT))) { data.put("creator", creator + "(" + userVOMap.get(creator.toLowerCase(Locale.ROOT)).getName() + ")"); } String lastmodifier = data.getOrDefault("lastmodifier", null); if (StringUtils.isNotBlank(lastmodifier) && userVOMap.containsKey(lastmodifier.toLowerCase(Locale.ROOT))) { data.put("lastmodifier", lastmodifier + "(" + userVOMap.get(lastmodifier.toLowerCase(Locale.ROOT)).getName() + ")"); } }); } } /** * 处理时间格式 * * @param dateFormatAttrVOs 时间格式的属性 * @param data 当前行数据 */ private void wrapperDateFormat(Collection dateFormatAttrVOs, Map data) { if (!CollectionUtils.isEmpty(dateFormatAttrVOs)) { dateFormatAttrVOs.stream().forEach(dateFormatAttrVO -> { String attrId = dateFormatAttrVO.getId().toLowerCase(Locale.ROOT); String oldValue = data.getOrDefault(attrId, null); if (StringUtils.isNotBlank(oldValue)) { DateConverter dateConverter = new DateConverter(); try { dateConverter.setAsText(oldValue); Date value = dateConverter.getValue(); if (value != null) { data.put(attrId, VciDateUtil.date2Str(value, dateFormatAttrVO.getCodedateformat())); } } catch (Throwable e) { //转换可能有问题,这就使用原本存储的值 } } }); } } /** * 处理枚举的内容,如果不在枚举中,会返回原本的值 * * @param enumAttrVOs 枚举属性 * @param data 当前行数据 */ private void wrapperEnum(Collection enumAttrVOs, Map data) { //处理枚举的内容,为了兼容以前的数据,如果数据不能使用枚举转换的话,那还是显示以前的值 if (!CollectionUtils.isEmpty(enumAttrVOs)) { enumAttrVOs.stream().forEach(enumAttrVO -> { String attrId = enumAttrVO.getId().toLowerCase(Locale.ROOT); String oldValue = data.getOrDefault(attrId, null); if (StringUtils.isNotBlank(oldValue)) { List comboxKVs = listComboboxItems(enumAttrVO); String newValue = oldValue; KeyValue keyValue = Optional.ofNullable(comboxKVs).orElseGet(() -> new ArrayList<>()).stream().filter(s -> s.getKey().equalsIgnoreCase(oldValue)).findFirst().orElseGet(() -> null); if (keyValue != null) { newValue = keyValue.getValue(); } data.put(attrId + "Text", newValue); } }); } } /** * 获取枚举的下拉选项 * * @param attrVO 模板属性的对象 * @return 下拉选项 */ @Override public List listComboboxItems(CodeClassifyTemplateAttrVO attrVO) { List comboboxKVs; if (StringUtils.isNotBlank(attrVO.getEnumString())) { comboboxKVs = JSONObject.parseArray(attrVO.getEnumString(), KeyValue.class); } else { comboboxKVs = enumService.getEnum(attrVO.getEnumid()); } return comboboxKVs; } /** * 处理组合规则的内容,如果不在枚举中,会返回原本的值 * * @param compAttrVOs 组合规则属性 * @param data 当前行数据 */ private void wrapperComponentRule(Collection compAttrVOs, Map data) { if (!CollectionUtils.isEmpty(compAttrVOs)) { compAttrVOs.stream().forEach(attrVO -> { String attrId = attrVO.getId().toLowerCase(Locale.ROOT); //用公式去计算 //先用当前数据替换一下 String calculatedValue = formulaService.getValueByFormula(data, attrVO.getComponentrule()); data.put(attrId, calculatedValue); }); } } /** * 使用数据主键获取数据的全部信息 * * @param oid 主键 * @param templateOid 模板的主键 * @return 数据的内容 */ @Override public BaseResult> getDataByOid(String oid, String templateOid) { CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(templateOid); //为了防止模板上的业务类型与分类上不对应 CodeClassifyVO topClassifyVO = classifyService.getTopClassifyVO(templateVO.getCodeclassifyoid()); String btmId = topClassifyVO.getBtmtypeid(); //查询数据 Map conditionMap = WebUtil.getOidQuery(oid); CodeTemplateAttrSqlBO sqlBO = getSqlByTemplateVO(btmId, templateVO, conditionMap, new PageHelper(-1)); //我们使用和业务类型的来查询 List cbos = boService.queryByOnlySql(sqlBO.getSqlUnPage()); if (CollectionUtils.isEmpty(cbos)) { throw new VciBaseException("数据在系统中不存在,是否因为修改过业务类型?"); } Map data = new HashMap<>(); ClientBusinessObject cbo = cbos.get(0); WebUtil.copyValueToMapFromCbos(cbo, data); List> dataList = new ArrayList<>(); dataList.add(data); wrapperData(dataList, templateVO, sqlBO.getSelectFieldList(), true); BaseResult> result = BaseResult.success(data); //我们要看是否不是升版的,升版的话,需要对比不相等的属性 String copy = cbo.getCopyFromVersion(); if (StringUtils.isBlank(copy)) { copy = cbo.getAttributeValue("copyfromversion"); } if (StringUtils.isNotBlank(copy)) { //说明有变更的内容 CodeTemplateAttrSqlBO oldSqlBO = getSqlByTemplateVO(btmId, templateVO, WebUtil.getOidQuery(copy), new PageHelper(-1)); //我们使用和业务类型的来查询 List oldCbos = boService.queryByOnlySql(oldSqlBO.getSqlUnPage()); if (!CollectionUtils.isEmpty(oldCbos)) { Map newData = new HashMap<>(); WebUtil.copyValueToMapFromCbos(cbo, newData); Map oldData = new HashMap<>(); WebUtil.copyValueToMapFromCbos(oldCbos.get(0), oldData); Map difFieldMap = new HashMap<>(); newData.forEach((key, value) -> { String oldValue = oldData.getOrDefault(key, ""); if (value == null) { value = ""; } if (oldValue == null) { oldValue = ""; } if (!value.equalsIgnoreCase(oldValue)) { difFieldMap.put(key, oldValue); } }); List> difFieldList = new ArrayList<>(); difFieldList.add(difFieldMap); result.setData(difFieldList); } } return result; } /** * 使用主题库分类获取编码规则 * * @param codeClassifyOid 分类的主键 * @return 编码规则的内容 */ @Override public CodeRuleVO getCodeRuleByClassifyOid(String codeClassifyOid) { VciBaseUtil.alertNotNull(codeClassifyOid, "分类的主键"); CodeClassifyVO classifyVO = classifyService.getObjectByOid(codeClassifyOid); String codeRuleOid = classifyVO.getCoderuleoid(); if (StringUtils.isBlank(codeRuleOid)) { //往上找 CodeClassifyFullInfoBO fullInfo = classifyService.getClassifyFullInfo(codeClassifyOid); return getCodeRuleByClassifyFullInfo(fullInfo); } //我们查询编码规则 return ruleService.getObjectHasSecByOid(codeRuleOid); } /** * 使用分类的全部信息获取编码规则 * * @param fullInfoBO 分类的全部信息 * @return 规则的内容 */ @Override public CodeRuleVO getCodeRuleByClassifyFullInfo(CodeClassifyFullInfoBO fullInfoBO) { //往上找 String codeRuleOid = ""; if (StringUtils.isNotBlank(fullInfoBO.getCurrentClassifyVO().getCoderuleoid())) { codeRuleOid = fullInfoBO.getCurrentClassifyVO().getCoderuleoid(); } else { if (CollectionUtils.isEmpty(fullInfoBO.getParentClassifyVOs())) { //说明已经是最高层级, throw new VciBaseException("当前主题库分类,以及它的所有的上级分类都没有设置编码规则"); } List parentClassifyVOList = fullInfoBO.getParentClassifyVOs().stream().sorted((o1, o2) -> o1.getDataLevel().compareTo(o2.getDataLevel())).collect(Collectors.toList()); //从最高的level开始获取 for (int i = 0; i < parentClassifyVOList.size(); i++) { CodeClassifyVO record = parentClassifyVOList.get(i); if (StringUtils.isNotBlank(record.getCoderuleoid())) { codeRuleOid = record.getCoderuleoid(); break; } } if (StringUtils.isBlank(codeRuleOid)) { throw new VciBaseException("当前主题库分类,以及它的所有的上级分类都没有设置编码规则"); } } return ruleService.getObjectHasSecByOid(codeRuleOid); } /** * 使用码段的主键获取分类的码值内容 * * @param classifySecOid 码段的主键 * @param parentClassifyValueOid 上级分类的主键 * @return 分类码值的内容 */ @Override public List listCodeClassifyValueBySecOid(String classifySecOid, String parentClassifyValueOid) { return classifyValueService.listCodeClassifyValueBySecOid(classifySecOid, parentClassifyValueOid); } /** * 申请单一编码 * * @param orderDTO 申请的信息,需要包含属性的内容和码段相关的内容 * @return 返回编码的内容 */ @Override public String addSaveCode(CodeOrderDTO orderDTO) { VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键", orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键"); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(orderDTO.getCodeRuleOid()); //1.判断规则中除了流水码段,是否有其他码段 checkSecValueOnOrder(ruleVO, orderDTO); //2.判断必输项 checkRequiredAttrOnOrder(templateVO, orderDTO); //3.先注入,再组合,最后校验 switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO); //4.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的 switchComponentAttrOnOrder(templateVO, orderDTO); //5.校验规则 checkVerifyOnOrder(templateVO, orderDTO); //6.关键属性 checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO); //7.枚举转换 checkEnumOnOrder(templateVO, orderDTO); //8.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储 switchDateAttrOnOrder(templateVO, orderDTO); //9.生成编码的信息 ClientBusinessObject cbo = boService.createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()); //默认的属性都不用从前端拷贝 //设置编码需要的默认属性的内容 copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, false); //TODO:因为默认的属性都不拷贝,目前集团码叫name,并没有从DTO拷贝到cbo里。增加一个单独处理,以后再看要不要调整 cbo.setName(orderDTO.getName() == null ? "" : orderDTO.getName()); //end -- modify by lihang @20220407 List cboList = new ArrayList<>(); //备注 cbo.setDescription(orderDTO.getDescription()==null?"":orderDTO.getDescription()); cboList.add(cbo); List codeList = productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), cboList); batchSaveSelectChar(templateVO, cboList); return codeList.size() > 0 ? codeList.get(0) : ""; } /** * 修改主题库数据 * * @param orderDTO 数据的内容,不用包含码段的内容了 */ @Override public void editSaveCode(CodeOrderDTO orderDTO) { VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性的内容都为空", orderDTO.getOid(), "数据主键", orderDTO.getCodeClassifyOid(), "主题库分类的主键"); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); //找业务类型,然后使用主键去获取数据库里的数据 List cbos = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), WebUtil.getOidQuery(orderDTO.getOid())); if (CollectionUtils.isEmpty(cbos)) { throw new VciBaseException(DATA_OID_NOT_EXIST); } ClientBusinessObject cbo = cbos.get(0); if (!cbo.getTs().contains(VciDateUtil.date2Str(orderDTO.getTs(), VciDateUtil.DateTimeFormat))) { throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试"); } if (!CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(cbo.getLcStatus()) && !orderDTO.isEditInProcess()) { throw new VciBaseException("数据不是{0}的状态,不允许修改", new String[]{CodeDefaultLC.EDITING.getText()}); } //注意模板不能使用数据存储的时候的模板,因为可能会变化 //1. 判断必输项 CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); checkRequiredAttrOnOrder(templateVO, orderDTO); //2.先注入,再组合,最后校验 switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO); //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的 switchComponentAttrOnOrder(templateVO, orderDTO); //4.校验规则 checkVerifyOnOrder(templateVO, orderDTO); //5.判断关键属性 checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO); //6.校验枚举的内容是否正确 checkEnumOnOrder(templateVO, orderDTO); //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储 switchDateAttrOnOrder(templateVO, orderDTO); //默认的内容不能变,所以只需要拷贝自定义的相关属性即可 copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true); //企业码和集团码的不修改 cbo.setDescription(orderDTO.getDescription()==null?"":orderDTO.getDescription()); cbo.setName(orderDTO.getName()==null?"":orderDTO.getName()); try { cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription()); cbo.setAttributeValue("name", orderDTO.getName()); } catch (VCIError e) { e.printStackTrace(); } //修改的时候,编码是不变的 BatchCBO batchCBO = new BatchCBO(); batchCBO.getUpdateCbos().add(cbo); List cboList = new ArrayList<>(); cboList.add(cbo); boService.persistenceBatch(batchCBO); batchSaveSelectChar(templateVO, cboList); } /** * 升版的主题库数据 * * @param orderDTO 数据的内容,不需要包含码段的内容 */ @Override public void upSaveCode(CodeOrderDTO orderDTO) { VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性的内容为空", orderDTO.getCopyFromVersion(), "原始数据的主键", orderDTO.getCodeClassifyOid(), "主题库分类的主键"); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); //找业务类型,然后使用主键去获取数据库里的数据 List cbos = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), WebUtil.getOidQuery(orderDTO.getCopyFromVersion())); if (CollectionUtils.isEmpty(cbos)) { throw new VciBaseException(DATA_OID_NOT_EXIST); } ClientBusinessObject oldCbo = cbos.get(0); if (!CodeDefaultLC.RELEASED.getValue().equalsIgnoreCase(oldCbo.getLcStatus())) { throw new VciBaseException("数据不是{0}的状态,不允许数据更改", new String[]{CodeDefaultLC.RELEASED.getText()}); } //需要升版 ClientBusinessObjectOperation cboOperation = new ClientBusinessObjectOperation(); ClientBusinessObject cbo = null; try { //cbo = cboOperation.createBusinessObjectVersion(oldCbo,VciBaseUtil.getCurrentUserId()); cbo = cboOperation.reviseBusinessObject(oldCbo, ""); } catch (VCIError e) { throw new VciBaseException("初始化相关的内容出现了错误", new String[0], e); } //1. 判断必输项 CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); checkRequiredAttrOnOrder(templateVO, orderDTO); //2.先注入,再组合,最后校验 switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO); //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的 switchComponentAttrOnOrder(templateVO, orderDTO); //4.校验规则 checkVerifyOnOrder(templateVO, orderDTO); //5.判断关键属性 checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO); //6.校验枚举的内容是否正确 checkEnumOnOrder(templateVO, orderDTO); //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储 switchDateAttrOnOrder(templateVO, orderDTO); //默认的内容不能变,所以只需要拷贝自定义的相关属性即可 copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true); //企业码和集团码的不修改 // cbo.setDescription(orderDTO.getDescription()); // cbo.setName(orderDTO.getName()); cbo.setDescription(orderDTO.getDescription()==null?"":orderDTO.getDescription()); cbo.setName(orderDTO.getName()==null?"":orderDTO.getName()); try { cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription()); cbo.setAttributeValue("name", orderDTO.getName()); } catch (VCIError e) { e.printStackTrace(); } //数据的时候,编码是不变的 cbo.setCreateTime(DateUtils.convert2String(new Date(Long.parseLong(cbo.getCreateTime())), "yyyy-MM-dd HH:mm:ss")); cbo.setLastModifyTime(DateUtils.convert2String(new Date(Long.parseLong(cbo.getLastModifyTime())), "yyyy-MM-dd HH:mm:ss")); List cboList = new ArrayList<>(); cboList.add(cbo); try { cboOperation.saveRevisionBuinessObject(cbo); } catch (VCIError vciError) { throw new VciBaseException("数据更改保存出错了", new String[0], vciError); } batchSaveSelectChar(templateVO, cboList); } /** * 保存可输可选的信息 * * @param templateVO 模板的对象 * @param cboList 数据的内容 */ @Override public void batchSaveSelectChar(CodeClassifyTemplateVO templateVO, List cboList) { if (templateVO != null && !CollectionUtils.isEmpty(cboList)) { //是异步的,所以直接循环 List selectAttrVOs = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getLibraryIdentification())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(selectAttrVOs)) { SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo(); selectAttrVOs.parallelStream().forEach(attrVO -> { List valuesList = new CopyOnWriteArrayList<>(); cboList.parallelStream().forEach(cbo -> { String value = cbo.getAttributeValue(attrVO.getId()); if (StringUtils.isNotBlank(value)) { valuesList.add(value); } }); if (!CollectionUtils.isEmpty(valuesList)) { charService.saveBySameNamespaceAndFlag(templateVO.getBtmTypeId(), attrVO.getLibraryIdentification(), valuesList, sessionInfo); } }); } } } /** * 删除主题库数据 * * @param deleteBatchDTO 数据的内容,必须要有主键和分类主键 */ @Override public void deleteCode(CodeDeleteBatchDTO deleteBatchDTO) { VciBaseUtil.alertNotNull(deleteBatchDTO, "编码申请相关的属性和码段的内容都为空", deleteBatchDTO.getOidList(), "数据主键", deleteBatchDTO.getCodeClassifyOid(), "主题库分类的主键"); CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(deleteBatchDTO.getCodeClassifyOid()); //找业务类型,然后使用主键去获取数据库里的数据 Collection> oidCollection = VciBaseUtil.switchCollectionForOracleIn(deleteBatchDTO.getOidList()); List cboList = new ArrayList<>(); oidCollection.stream().forEach(oids -> { Map conditionMap = new HashMap<>(); conditionMap.put("oid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")"); List cbos = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), conditionMap); cboList.addAll(cbos); }); if (CollectionUtils.isEmpty(cboList)) { throw new VciBaseException("数据全部在系统中不存在"); } List editCBOs = cboList.stream().filter(s -> !CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(s.getLcStatus())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(editCBOs)) { ClientBusinessObject cbo = editCBOs.get(0); throw new VciBaseException("编码为{0}等共{1}条数据的状态不是[{2}],不允许删除", new String[]{cbo.getId(), String.valueOf(editCBOs.size()), CodeDefaultLC.EDITING.getText()}); } //只能删除自己创建的数据 String userId = WebUtil.getCurrentUserId(); for (ClientBusinessObject clientBusinessObject:cboList){ String creator = clientBusinessObject.getCreator(); if(!userId.equalsIgnoreCase(creator)){ throw new VciBaseException("编码为"+clientBusinessObject.getId()+"的数据不是当前用户创建,不能删除!"); } } BatchCBO batchCBO = new BatchCBO(); batchCBO.getDeleteCbos().addAll(cboList); WebUtil.setPersistence(false); batchCBO.copyFromOther(productCodeService.recycleCode(classifyFullInfo.getCurrentClassifyVO().getBtmtypeid(), deleteBatchDTO.getOidList())); WebUtil.setPersistence(true); boService.persistenceBatch(batchCBO); } /** * 拷贝数据到cbo对象上 * * @param classifyFullInfo 分类的全部信息 * @param cbo 业务数据 * @param orderDTO 编码申请的信息 * @param templateVO 模板的显示对象 * @param edit 是否为修改 */ private void copyValueToCBO(CodeClassifyFullInfoBO classifyFullInfo, ClientBusinessObject cbo, CodeOrderDTO orderDTO, CodeClassifyTemplateVO templateVO, boolean edit) { String fullPath = ""; if (!CollectionUtils.isEmpty(classifyFullInfo.getParentClassifyVOs())) { fullPath = classifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))) .map(CodeClassifyVO::getOid).collect(Collectors.joining("##")); } else { fullPath = classifyFullInfo.getCurrentClassifyVO().getOid(); } orderDTO.getData().forEach((key, value) -> { if (!edit || (!boService.checkUnAttrUnEdit(key) && !VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(key))) { try { cbo.setAttributeValue(key, value); } catch (VCIError e) { logger.error("设置属性的值错误", e); } } }); try { cbo.setAttributeValue(MdmEngineConstant.CODE_CLASSIFY_OID_FIELD, classifyFullInfo.getCurrentClassifyVO().getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_TEMPLATE_OID_FIELD, templateVO.getOid()); cbo.setAttributeValue(MdmEngineConstant.CODE_FULL_PATH_FILED, fullPath); if (!edit && StringUtils.isBlank(orderDTO.getLcStatus())) { //找生命周期的起始状态, if (StringUtils.isNotBlank(cbo.getLctId())) { OsLifeCycleVO lifeCycleVO = lifeCycleService.getLifeCycleById(cbo.getLctId()); if (lifeCycleVO != null) { cbo.setLcStatus(lifeCycleVO.getStartStatus()); } else { cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); } } else { cbo.setLcStatus(CodeDefaultLC.EDITING.getValue()); } } int secret = VciBaseUtil.getInt(cbo.getAttributeValue(MdmEngineConstant.SECRET_FIELD)); if (secret == 0 || !secretService.checkDataSecret(secret)) { Integer userSecret = VciBaseUtil.getCurrentUserSecret(); cbo.setAttributeValue(MdmEngineConstant.SECRET_FIELD, String.valueOf((userSecret == null || userSecret == 0) ? UserSecretEnum.NONE.getValue() : userSecret)); } } catch (Throwable e) { logger.error("设置默认的属性的值错误", e); } } /** * 转换组合规则的值 * * @param templateVO 模板的显示对象,需要包含模板属性 * @param orderDTO 编码申请的信息 */ private void switchComponentAttrOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { Map compAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getComponentrule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(compAttrVOMap)) { Map dataMap = WebUtil.objectToMapString(orderDTO); Map dataLowMap = new HashMap<>(); if (!CollectionUtils.isEmpty(dataMap)) { dataMap.forEach((key, value) -> { dataLowMap.put(key.toLowerCase(Locale.ROOT), value); }); } dataLowMap.putAll(orderDTO.getData()); compAttrVOMap.forEach((attrId, attrVO) -> { dataLowMap.put(attrId, formulaService.getValueByFormula(dataLowMap, attrVO.getComponentrule())); }); dataLowMap.forEach((key, value) -> { setValueToOrderDTO(orderDTO, key, value); }); } } /** * 处理分类注入的信息 * * @param templateVO 模板的显示对象,必须要后模板的属性 * @param classifyFullInfoBO 分类的全路径 * @param orderDTO 编码申请的信息 */ private void switchClassifyLevelOnOrder(CodeClassifyTemplateVO templateVO, CodeClassifyFullInfoBO classifyFullInfoBO, CodeOrderDTO orderDTO) { Map classifyAttrVOMap = templateVO.getAttributes().stream().filter( s -> StringUtils.isNotBlank(s.getClassifyinvokeattr()) && StringUtils.isNotBlank(s.getClassifyinvokelevel()) ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (classifyFullInfoBO.getTopClassifyVO() == null) { //需要重新查询一下,因为这个是指定的分类进来的 } if (!CollectionUtils.isEmpty(classifyAttrVOMap)) { classifyAttrVOMap.forEach((attrId, attrVO) -> { //分类注入的编号或者名称, //层级包含指定层和最小层 CodeClassifyVO classifyVO = null; if (!CodeLevelTypeEnum.MIN.getValue().equalsIgnoreCase(attrVO.getClassifyinvokelevel()) && !"min".equalsIgnoreCase(attrVO.getClassifyinvokelevel())) { //指定了层级的 //注意,因为查询上级分类出来的层级是倒序的,即顶层节点是最大的值 List classifyVOS = classifyFullInfoBO.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))).collect(Collectors.toList()); int level = VciBaseUtil.getInt(attrVO.getClassifyinvokelevel()); if (classifyVOS.size() >= level && level > 0) { classifyVO = classifyVOS.get(level - 1); } } else { //当前的分类 classifyVO = classifyFullInfoBO.getCurrentClassifyVO(); } if (classifyVO == null) { //说明层级有误 orderDTO.getData().put(attrId, "分类树上没有层级[" + attrVO.getClassifyinvokelevel() + "]"); // classifyVO = classifyFullInfoBO.getCurrentClassifyVO(); } else { Map classifyDataMap = VciBaseUtil.objectToMapString(classifyVO); String value = classifyDataMap.getOrDefault(attrVO.getClassifyinvokeattr(), ""); orderDTO.getData().put(attrId, value); } }); } } /** * 转换时间的格式 * * @param templateVO 模板的显示对象,需要包含属性 * @param orderDTO 编码申请的信息 */ private void switchDateAttrOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { Map dateAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getCodedateformat())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(dateAttrVOMap)) { dateAttrVOMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (StringUtils.isNotBlank(value)) { DateConverter dateConverter = new DateConverter(); dateConverter.setAsText(value); value = VciDateUtil.date2Str(dateConverter.getValue(), VciDateUtil.DateTimeMillFormat); setValueToOrderDTO(orderDTO, attrId, value); } }); } } /** * 校验枚举的内容 * * @param templateVO 模板的显示对象,需要包含属性 * @param orderDTO 编码申请的信息 */ private void checkEnumOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { //如果枚举可以修改,则不需要校验是否符合枚举的选项 Map enumAttrVOMap = templateVO.getAttributes().stream().filter(s -> (StringUtils.isNotBlank(s.getEnumString()) || StringUtils.isNotBlank(s.getEnumid())) && !VciBaseUtil.getBoolean(s.getEnumeditflag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(enumAttrVOMap)) { enumAttrVOMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (StringUtils.isNotBlank(value)) { //有值才能校验 List comboboxKVs = listComboboxItems(attrVO); if (!comboboxKVs.stream().anyMatch(s -> value.equalsIgnoreCase(s.getKey()))) { throw new VciBaseException("属性【{0}】的值不符合枚举的要求", new String[]{attrVO.getName()}); } } }); } } /** * 校验正则表达式是否正确 * * @param templateVO 模板的信息,必须包含属性的内容 * @param orderDTO 编码申请的相关的信息 */ private void checkVerifyOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { Map verifyAttrVOMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getVerifyrule())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(verifyAttrVOMap)) { verifyAttrVOMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (StringUtils.isNotBlank(value) && !value.matches(attrVO.getVerifyrule())) { //校验正则表达式 throw new VciBaseException("属性[{0}]的值不符合校验规则的要求", new String[]{attrVO.getName()}); } }); } } /** * 校验关键属性 * * @param classifyFullInfo 分类的全部信息 * @param templateVO 模板的内容,必须包含模板属性 * @param orderDTO 编码申请的相关的信息 */ private void checkKeyAttrOnOrder(CodeClassifyFullInfoBO classifyFullInfo, CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { //先获取关键属性的规则,也利用继承的方式 CodeKeyAttrRepeatRuleVO keyRuleVO = keyRuleService.getRuleByClassifyFullInfo(classifyFullInfo); //注意的是keyRuleVO可能为空,表示不使用规则控制 //获取所有的关键属性 Map ketAttrMap = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getKeyattrflag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); Map conditionMap = new HashMap<>(); boolean trimAll = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnoreallspaceflag()); //全部去空的优先级大于去空 boolean trim = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorespaceflag()); boolean ignoreCase = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorecaseflag()); boolean ignoreWidth = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorewidthflag()); ketAttrMap.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (value == null) { value = ""; } wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap); }); //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可 if (!CollectionUtils.isEmpty(conditionMap)) { final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()) + " t where 1 = 1 "}; conditionMap.forEach((key, value) -> { sql[0] += " and " + key + " = " + value; }); if (StringUtils.isNotBlank(orderDTO.getOid())) { //修改的时候,需要排除自己 sql[0] += " and oid != '" + orderDTO.getOid() + "'"; } else if (StringUtils.isNotBlank(orderDTO.getCopyFromVersion())) { sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'"; } sql[0] += " and islastR = '1' and islastV = '1' "; if (boService.queryCountBySql(sql[0], new HashMap<>()) > 0) { String ruleInfoMsg = keyRuleVO == null ? "" : "查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}"; String[] objs = new String[]{trim ? "是" : "否", ignoreCase ? "是" : "否", ignoreWidth ? "是" : "否", trimAll ? "是" : "否"}; throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs); } } } /** * 封装关键属性的查询语句 * * @param value 当前的值 * @param keyRuleVO 关键属性的控制规则,可以为空 * @param attrId 属性的编号 * @param trim 是否去除空格 * @param ignoreCase 是否不区分大小写 * @param ignoreWidth 是否忽略全半角 * @param trimAll 是否忽略全部空格 * @param conditionMap 查询条件 */ @Override public void wrapperKeyAttrConditionMap(String value, CodeKeyAttrRepeatRuleVO keyRuleVO, String attrId, boolean trim, boolean ignoreCase, boolean ignoreWidth, boolean trimAll, Map conditionMap) { boolean ignoreSpace = trim || trimAll; if (StringUtils.isBlank(value)) { //为空的时候,不能用QueryOperation.ISNULL,平台不知道啥时候不处理这种了 conditionMap.put("t."+attrId, "null"); } else { if (keyRuleVO != null) { String queryKey = ""; String queryValue = ""; String temp = ""; if (ignoreCase && ignoreSpace && ignoreWidth) { //忽略大小写,且去空,忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(UPPER(to_single_byte(%s)) " + (trimAll ? ",' ','')" : ")"); } else if (ignoreCase && ignoreSpace && !ignoreWidth) { //忽略大小写、去空、不忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(UPPER(%s) " + (trimAll ? ",' ','')" : ")"); } else if (ignoreCase && !ignoreSpace && ignoreWidth) { //忽略大小写、不去空、忽略全半角 temp = "UPPER(to_single_byte(%s))"; } else if (!ignoreCase && ignoreSpace && ignoreWidth) { //不忽略大小写、去空、忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(to_single_byte(%s) " + (trimAll ? ",' ','')" : ")"); } else if (ignoreCase && !ignoreSpace && !ignoreWidth) { //忽略大小写、不去空、不忽略全半角 temp = "UPPER(%s)"; } else if (!ignoreCase && !ignoreCase && ignoreWidth) { //不忽略大小写、不去空、忽略全半角 temp = "to_single_byte(%s)"; } else if (!ignoreCase && ignoreSpace && !ignoreWidth) { //不忽略大小写、去空、不忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(%s " + (trimAll ? ",' ','')" : ")"); } else if (!ignoreCase && !ignoreSpace && !ignoreWidth) { //不忽略大小写、不去空、不忽略全半角 temp = "%s"; } queryKey = String.format(temp, "t."+attrId); queryValue = String.format(temp, "'" + (trim ? value.trim() : value) + "'"); conditionMap.put(queryKey, queryValue); } else { //为空的时候不代表不校验,只是不去除相关的信息 conditionMap.put("t."+attrId, value); } } } /** * 从编码申请信息对象上获取某个属性的值 * * @param orderDTO 编码申请对象 * @param attrId 属性的编号 * @return 值 */ private String getValueFromOrderDTO(CodeOrderDTO orderDTO, String attrId) { attrId = attrId.toLowerCase(Locale.ROOT); String value = null; if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId) || VciQueryWrapperForDO.SECRET_MANAGE_FIELD_MAP.containsKey(attrId) || VciQueryWrapperForDO.REVISION_MANAGE_FIELD_MAP.containsKey(attrId) || VciQueryWrapperForDO.LIFECYCLE_MANAGE_FIELD_MAP.containsKey(attrId) || VciQueryWrapperForDO.BASE_MODEL_COMPATIBILITY_MAP.containsValue(attrId) ) { value = WebUtil.getStringValueFromObject(WebUtil.getValueFromField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO)); } else { //说明是自行配置的 //前端必须要传递小写的属性 value = orderDTO.getData().getOrDefault(attrId, ""); } return value; } /** * 设置新的值到申请对象上 * * @param orderDTO 编码申请对象 * @param attrId 属性的编号 * @param value 值 */ private void setValueToOrderDTO(CodeOrderDTO orderDTO, String attrId, String value) { attrId = attrId.toLowerCase(Locale.ROOT); if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) { WebUtil.setValueToField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO, value); } else { orderDTO.getData().put(attrId, value); } } /** * 校验属性是否为必输 * * @param templateVO 模板的显示对象,需要包含模板属性 * @param orderDTO 编码申请的信息 */ private void checkRequiredAttrOnOrder(CodeClassifyTemplateVO templateVO, CodeOrderDTO orderDTO) { Map requiredAttrMap = templateVO.getAttributes().stream().filter( s -> VciBaseUtil.getBoolean(s.getRequireflag()) && StringUtils.isBlank(s.getComponentrule()) && StringUtils.isBlank(s.getClassifyinvokeattr())) .collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t)); if (!CollectionUtils.isEmpty(requiredAttrMap)) { requiredAttrMap.forEach((attrId, attrVO) -> { //只有企业编码,状态,备注,模板主键,分类主键这几个是固定的,其余都是自行配置的 if (StringUtils.isBlank(getValueFromOrderDTO(orderDTO, attrId))) { throw new VciBaseException("属性【{0}】必须要输入(选择)内容", new String[]{attrVO.getName()}); } }); } } /** * 判断编码的码段是否输入或者选择了码值 * * @param ruleVO 规则的显示对象 * @param orderDTO 编码申请的内容 */ @Override public void checkSecValueOnOrder(CodeRuleVO ruleVO, CodeOrderDTO orderDTO) { List unSerialSecOidList = ruleVO.getSecVOList().stream().filter( s -> !(CodeSecTypeEnum.CODE_SERIAL_SEC.getValue().equalsIgnoreCase(s.getSectype()) || CodeSecTypeEnum.CODE_ATTR_SEC.getValue().equalsIgnoreCase(s.getSectype()) || CodeSecTypeEnum.CODE_DATE_SEC.getValue().equalsIgnoreCase(s.getSectype()) || CodeSecTypeEnum.CODE_LEVEL_SEC.getValue().equalsIgnoreCase(s.getSectype()) || VciBaseUtil.getBoolean(s.getNullableFlag())) ).map(CodeBasicSecVO::getOid).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(unSerialSecOidList)) { if (CollectionUtils.isEmpty(orderDTO.getSecDTOList())) { throw new VciBaseException("非流水码段(或者必输码段)必须要输入(或选择)码值"); } if (orderDTO.getSecDTOList().stream().anyMatch(s -> !unSerialSecOidList.contains(s.getSecOid()) && StringUtils.isBlank(s.getSecValue()))) { throw new VciBaseException("非流水码段(或者必输码段)必须要输入(或选择)码值"); } } } /** * 使用分类和阶段的编号,获取包含的属性 * * @param codeClassifyOid 分类的主键 * @param phase 阶段的名称 * @return 属性的英文名称 */ @Override public List listPhaseAttrByClassifyOid(String codeClassifyOid, String phase) { CodeClassifyTemplateVO templateVO = getUsedTemplateByClassifyOid(codeClassifyOid, false); //找阶段 return phaseAttrService.listAttrByTemplateOidAndPhaseId(templateVO.getOid(), phase); } /** * 路径上包含当前分类的所有分类信息 * * @param codeClassifyOid 分类的主键 * @return 分类树 */ @Override public List hasSelfClassifyTree(String codeClassifyOid) { if (StringUtils.isBlank(codeClassifyOid)) { return new ArrayList<>(); } CodeClassifyFullInfoBO fullInfo = classifyService.getClassifyFullInfo(codeClassifyOid); //查询子 List childrenClassifys = classifyService.listChildrenClassify(codeClassifyOid, true, "id", true); Map classifyVOMap = new HashMap<>(); classifyVOMap.putAll(Optional.ofNullable(fullInfo.getParentClassifyVOs()).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t))); classifyVOMap.putAll(Optional.ofNullable(childrenClassifys).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t))); TreeWrapperOptions treeWrapperOptions = new TreeWrapperOptions(CodeClassifyServiceImpl.PARENT_FIELD_NAME.toLowerCase(Locale.ROOT)); return revisionModelUtil.doList2Trees(classifyVOMap.values().stream().collect(Collectors.toList()), treeWrapperOptions, (CodeClassifyVO s) -> { return s.getId() + " " + s.getName() + (FrameworkDataLCStatus.DISABLED.getValue().equalsIgnoreCase(s .getLcStatus()) ? (" 【停用】 ") : ""); }); } /** * 分类注入的内容预览 * * @param codeClassifyOid 分类的主键 * @param codeTemplateOid 模板的主键 * @return key是分类注入的属性,value是注入后的值 */ @Override public Map previewClassify(String codeClassifyOid, String codeTemplateOid) { if (StringUtils.isBlank(codeClassifyOid) || StringUtils.isBlank(codeTemplateOid)) { return new HashMap<>(); } //查询分类的信息,查询模板的信息 CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyOid); CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(codeTemplateOid); // CodeOrderDTO orderDTO = new CodeOrderDTO(); orderDTO.setData(new HashMap<>()); switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO); return orderDTO.getData(); } /** * 预览组合规则 * * @param orderDTO 预览的信息,包含模板的主键 * @return key是组合规则的属性。value是组合后的值,。如果缺少某个属性的值,会作为value返回 */ @Override public Map previewCompRule(CodeOrderDTO orderDTO) { VciBaseUtil.alertNotNull(orderDTO, "编码申请相关信息", orderDTO.getTemplateOid(), "模板的主键"); //查询分类的信息,查询模板的信息 CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); switchComponentAttrOnOrder(templateVO, orderDTO); return orderDTO.getData(); } /** * 修改状态 * * @param baseModelDTO 数据传输对象 */ @Override public void changeStatus(BaseModelDTO baseModelDTO) { VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态"); List oids = VciBaseUtil.str2List(baseModelDTO.getOid()); List cboList = boService.selectCBOByOidCollection(oids, baseModelDTO.getBtmname()); //还需要修改allCode的生命周期 Map conditionMap = new HashMap<>(); conditionMap.put("createcodeoid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")"); conditionMap.put("createcodebtm", baseModelDTO.getBtmname()); List codeCbos = boService.queryCBO(MdmBtmTypeConstant.CODE_ALL_CODE, conditionMap); // 回收需要业务数据删除 if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) { BatchCBO batchCBO = new BatchCBO(); batchCBO.getDeleteCbos().addAll(cboList); boService.persistenceBatch(batchCBO); } else { lifeCycleService.transCboStatus(cboList, baseModelDTO.getLcStatus()); } lifeCycleService.transCboStatus(codeCbos, baseModelDTO.getLcStatus()); } /** * 相似项查询 * * @param orderDTO 编码的相关信息 * @return 数据列表 */ @Override public DataGrid> resembleQuery(CodeOrderDTO orderDTO) { VciBaseUtil.alertNotNull(orderDTO, "申请的信息", orderDTO.getCodeClassifyOid(), "分类主键", orderDTO.getTemplateOid(), "模板主键"); CodeClassifyFullInfoBO fullInfoBO = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid()); CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); switchClassifyLevelOnOrder(templateVO, fullInfoBO, orderDTO); switchDateAttrOnOrder(templateVO, orderDTO); switchComponentAttrOnOrder(templateVO, orderDTO); //需要获取是否有相似查询属性 Map attrVOs = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getSamerepeatattrflag())).collect(Collectors.toMap(s -> s.getId(), t -> t)); if (CollectionUtils.isEmpty(attrVOs)) { //都没有属性,肯定不能查询了 return new DataGrid<>(); } Map conditionMap = new HashMap<>(); //我们首先获取有没有查询规则 CodeResembleRuleVO resembleRuleVO = Optional.ofNullable(getUseResembleRule(fullInfoBO, fullInfoBO.getCurrentClassifyVO())).orElseGet(() -> new CodeResembleRuleVO()); attrVOs.forEach((attrId, attrVO) -> { String value = getValueFromOrderDTO(orderDTO, attrId); if (value == null) { value = ""; } wrapperResembleConditionMap(value, resembleRuleVO, attrId, conditionMap); }); //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可 if (!CollectionUtils.isEmpty(conditionMap)) { Map andConditionMap = new HashMap<>(); andConditionMap.put("islastr", "1"); andConditionMap.put("islastv", "1"); if (StringUtils.isNotBlank(orderDTO.getOid())) { andConditionMap.put("oid", QueryOptionConstant.NOTEQUAL + orderDTO.getOid()); } conditionMap.putAll(andConditionMap); PageHelper pageHelper = new PageHelper(-1); pageHelper.addDefaultDesc("id"); return queryGrid(fullInfoBO.getTopClassifyVO().getBtmtypeid(), templateVO, conditionMap, pageHelper); } return new DataGrid<>(); } /** * 封装相似项查询的查询条件的映射 * * @param value 值 * @param resembleRuleVO 相似项规则 * @param attrId 属性的编号 * @param conditionMap 查询条件 */ @Override public void wrapperResembleConditionMap(String value, CodeResembleRuleVO resembleRuleVO, String attrId, Map conditionMap) { boolean ignoreSpace = VciBaseUtil.getBoolean(resembleRuleVO.getIgnorespaceflag()) || VciBaseUtil.getBoolean(resembleRuleVO.getIgnoreallspaceflag()); if (StringUtils.isBlank(value)) { //为空的时候就不查询它就是 } else { String queryKey = ""; String queryValue = ""; boolean ignoreCase = VciBaseUtil.getBoolean(resembleRuleVO.getIgnorecaseflag()); boolean ignoreWidth = VciBaseUtil.getBoolean(resembleRuleVO.getIgnorewidthflag()); boolean trimAll = VciBaseUtil.getBoolean(resembleRuleVO.getIgnoreallspaceflag()); boolean trim = VciBaseUtil.getBoolean(resembleRuleVO.getIgnoreallspaceflag()); String temp = ""; if (ignoreCase && ignoreSpace && ignoreWidth) { //忽略大小写,且去空,忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(UPPER(to_single_byte('%s')) " + (trimAll ? ",' ','')" : ")"); } else if (ignoreCase && ignoreSpace && !ignoreWidth) { //忽略大小写、去空、不忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(UPPER(%s) " + (trimAll ? ",' ','')" : ")"); } else if (ignoreCase && !ignoreSpace && ignoreWidth) { //忽略大小写、不去空、忽略全半角 temp = "UPPER(to_single_byte('%s'))"; } else if (!ignoreCase && ignoreSpace && ignoreWidth) { //不忽略大小写、去空、忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(to_single_byte('%s') " + (trimAll ? ",' ','')" : ")"); } else if (ignoreCase && !ignoreSpace && !ignoreWidth) { //忽略大小写、不去空、不忽略全半角 temp = "UPPER(%s)"; } else if (!ignoreCase && !ignoreCase && ignoreWidth) { //不忽略大小写、不去空、忽略全半角 temp = "to_single_byte('%s')"; } else if (!ignoreCase && ignoreSpace && !ignoreWidth) { //不忽略大小写、去空、不忽略全半角 temp = (trimAll ? "REPLACE" : "TRIM") + "(%s " + (trimAll ? ",' ','')" : ")"); } else if (!ignoreCase && !ignoreSpace && !ignoreWidth) { //不忽略大小写、不去空、不忽略全半角 temp = "%s"; } if (StringUtils.isNotBlank(resembleRuleVO.getLinkCharacter())) { List chars = VciBaseUtil.str2List(resembleRuleVO.getLinkCharacter()); for (int i = 0; i < chars.size(); i++) { String s = chars.get(i); temp = "replace(" + temp + ",'" + s + "','')"; } } queryValue = String.format(temp, (trim ? value.trim() : value)); temp = temp.replace("to_single_byte('%s')","to_single_byte(%s)"); queryKey = String.format(temp, "t."+attrId); conditionMap.put(queryKey, QueryOptionConstant.OR + queryValue); } } /** * 使用分类主键获取相似查询规则 * * @param codeClassifyOid 分类主键 * @return 规则,如果不存在会返回null */ @Override public CodeResembleRuleVO getUseResembleRuleByClassifyOid(String codeClassifyOid) { CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyOid); return getUseResembleRule(classifyFullInfo, classifyFullInfo.getCurrentClassifyVO()); } /** * 获取使用的相似查询规则 * * @param fullInfoBO 类全部信息 * @param currentClassifyVO 当前的分类 * @return 规则,如果不存在会返回Null */ @Override public CodeResembleRuleVO getUseResembleRule(CodeClassifyFullInfoBO fullInfoBO, CodeClassifyVO currentClassifyVO) { if (currentClassifyVO == null) { return null; } if (currentClassifyVO != null && StringUtils.isNotBlank(currentClassifyVO.getCodeResembleRuleOid())) { //说明已经存在 return resembleRuleService.getObjectByOid(currentClassifyVO.getCodeResembleRuleOid()); } if (StringUtils.isBlank(currentClassifyVO.getParentcodeclassifyoid())) { return null; } Map classifyVOMap = fullInfoBO.getParentClassifyVOs().stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); return getUseResembleRule(fullInfoBO, classifyVOMap.getOrDefault(currentClassifyVO.getParentcodeclassifyoid(), null)); } /** * 模板属性转换为表单定义的信息 * * @param templateVO 模板的显示对象 * @param codeClassifyOid 分类的主键,为空的时候,获取模板所属的分类主键.用于产生分类注入 * @return 表格的信息 */ private UIFormDefineVO wrapperFormDefineByTemplate(CodeClassifyTemplateVO templateVO, String codeClassifyOid) { UIFormDefineVO formDefineVO = new UIFormDefineVO(); formDefineVO.setOid(templateVO.getOid()); formDefineVO.setBtmType(templateVO.getBtmTypeId()); if (StringUtils.isBlank(codeClassifyOid)) { codeClassifyOid = templateVO.getCodeclassifyoid(); } CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyOid); List itemVOS = new ArrayList<>(); Map> attrGroupMap = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getAttributegroup())).collect(Collectors.groupingBy(s -> s.getAttributegroup())); templateVO.getAttributes().forEach(attrVO -> { UIFormItemVO formItemVO = templateAttr2FormField(attrVO, templateVO.getBtmTypeId()); itemVOS.add(formItemVO); }); //处理属性分组 if (!CollectionUtils.isEmpty(attrGroupMap)) { //按照分组的属性排列,找到每一个分组的第一个属性 for (String key : attrGroupMap.keySet()) { List value = attrGroupMap.get(key); //找到这个分组的属性的第一个 CodeClassifyTemplateAttrVO attrVO = value.stream().sorted(((o1, o2) -> o1.getOrdernum().compareTo(o2.getOrdernum()))).findFirst().get(); //我们找到这个属性在最终的itemVOs里的位置 UIFormItemVO lineVO = new UIFormItemVO(); lineVO.setField(attrVO.getId() + "_line"); lineVO.setType("line"); lineVO.setText(key); //找位置 for (int i = 0; i < itemVOS.size(); i++) { UIFormItemVO record = itemVOS.get(i); if (record.getField().equalsIgnoreCase(attrVO.getId())) { itemVOS.add(i, lineVO); break; } } } } CodeOrderDTO orderDTO = new CodeOrderDTO(); switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO); if (!CollectionUtils.isEmpty(orderDTO.getData())) { orderDTO.getData().forEach((key, value) -> { for (int i = 0; i < itemVOS.size(); i++) { UIFormItemVO itemVO = itemVOS.get(i); if (itemVO.getField().equalsIgnoreCase(key)) { itemVO.setDefaultValue(value); break; } } }); } formDefineVO.setItems(itemVOS); //查询是否有分类注入的 return formDefineVO; } /** * 模板属性转换为表格定义的信息 * * @param templateVO 模板的显示对象 * @param forEdit 是否是编辑所需 * @return 表格的信息 */ private UITableDefineVO wrapperTableDefineByTemplate(CodeClassifyTemplateVO templateVO,boolean forEdit) { //封装信息 UITableDefineVO tableDefineVO = new UITableDefineVO(); tableDefineVO.setOid(templateVO.getOid()); tableDefineVO.setBtmType(templateVO.getBtmTypeId()); tableDefineVO.setDisplayQueryArea(true); //前端会默认分页的信息 //处理所有的列,这个模板没有合并的表头的情况 List fieldVOList = new ArrayList<>(); Map comboxOrReferFieldMap = new HashMap<>(); templateVO.getAttributes().forEach(attrVO -> { UITableFieldVO tableFieldVO = templateAttr2TableField(attrVO,forEdit); if ("combox".equalsIgnoreCase(tableFieldVO.getFieldType())) { comboxOrReferFieldMap.put(tableFieldVO.getSortField(), tableFieldVO.getField()); } if ("refer".equalsIgnoreCase(tableFieldVO.getFieldType())) { comboxOrReferFieldMap.put(tableFieldVO.getSortField(), tableFieldVO.getField()); } if(StringUtils.isNotBlank(tableFieldVO.getEdit())){ tableDefineVO.setHasEditor(true); } fieldVOList.add(tableFieldVO); }); List> cols = new ArrayList<>(); cols.add(fieldVOList); tableDefineVO.setCols(cols); Map fieldVOMap = fieldVOList.stream().collect(Collectors.toMap(s -> s.getField().toLowerCase(Locale.ROOT), t -> t)); //查询属性 List queryAttrVOs = templateVO.getAttributes().stream().filter(s -> BooleanEnum.TRUE.getValue().equalsIgnoreCase(s.getQueryattrflag())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(queryAttrVOs)) { List queryFieldVOs = new ArrayList<>(); queryAttrVOs.stream().forEach(attrVO -> { String attrId = attrVO.getId().toLowerCase(Locale.ROOT); attrId = comboxOrReferFieldMap.getOrDefault(attrId, attrVO.getId()).toLowerCase(Locale.ROOT); if (fieldVOMap.containsKey(attrId)) { queryFieldVOs.add(fieldVOMap.get(attrId)); } }); tableDefineVO.setQueryColumns(queryFieldVOs); } //高级属性 List seniorQueryAttrVOs = templateVO.getAttributes().stream().filter(s -> BooleanEnum.TRUE.getValue().equalsIgnoreCase(s.getSeniorqueryattrflag())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(seniorQueryAttrVOs)) { List queryFieldVOs = new ArrayList<>(); seniorQueryAttrVOs.stream().forEach(attrVO -> { String attrId = attrVO.getId().toLowerCase(Locale.ROOT); attrId = comboxOrReferFieldMap.getOrDefault(attrId, attrId).toLowerCase(Locale.ROOT); if (fieldVOMap.containsKey(attrId)) { queryFieldVOs.add(fieldVOMap.get(attrId)); } }); tableDefineVO.setSeniorQueryColumns(queryFieldVOs); } return tableDefineVO; } /** * 模板属性转换为表格显示的配置 * * @param attrVO 模板属性 * @param forEdit 是否是编辑所需 * @return 表格的字段 */ @Override public UITableFieldVO templateAttr2TableField(CodeClassifyTemplateAttrVO attrVO,boolean forEdit) { UITableFieldVO fieldVO = new UITableFieldVO(); if (SECRET_FILED.equalsIgnoreCase(attrVO.getId())) { attrVO.setEnumid(OsEnumServiceImpl.MY_DATA_SECRET); } fieldVO.setField(attrVO.getId()); fieldVO.setTitle(attrVO.getName()); fieldVO.setFieldType(vciFieldTypeMap.getOrDefault(attrVO.getAttributedatatype(), "text")); fieldVO.setSort(true); fieldVO.setSortField(fieldVO.getField()); fieldVO.setQueryField(fieldVO.getField()); if (forEdit){ fieldVO.setHidden(!VciBaseUtil.getBoolean(attrVO.getFormdisplayflag())); }else { fieldVO.setHidden(!VciBaseUtil.getBoolean(attrVO.getTabledisplayflag())); } if (attrVO.getAttrTableWidth() != null && attrVO.getAttrTableWidth() > 0) { fieldVO.setMinWidth(attrVO.getAttrTableWidth()); fieldVO.setWidth(attrVO.getAttrTableWidth()); } //看看是否有枚举 if ((StringUtils.isNotBlank(attrVO.getEnumString()) && !"[]".equalsIgnoreCase(attrVO.getEnumString())) || StringUtils.isNotBlank(attrVO.getEnumid())) { fieldVO.setFieldType("combox"); fieldVO.setField(fieldVO.getField() + "Text"); fieldVO.setComboxKey(attrVO.getEnumid()); if (StringUtils.isNotBlank(attrVO.getEnumString())) { //指定的下拉框内容 fieldVO.setData(JSONObject.parseArray(attrVO.getEnumString(), KeyValue.class)); if (StringUtils.isBlank(attrVO.getEnumid())) { fieldVO.setComboxKey(fieldVO.getField() + "_data"); } }else { List osEnumItemVOList= enumService.getEnum(attrVO.getEnumid()); fieldVO.setData(osEnumItemVOList); } } //看是否有参照 if (StringUtils.isNotBlank(attrVO.getReferbtmid()) || StringUtils.isNotBlank(attrVO.getReferConfig())) { fieldVO.setFieldType("refer"); fieldVO.setQueryField(fieldVO.getField()); fieldVO.setField(fieldVO.getField() + "name"); fieldVO.setShowField(fieldVO.getField()); if (StringUtils.isNotBlank(attrVO.getReferConfig())) { //配置的内容 fieldVO.setReferConfig(JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class)); } else { UIFormReferVO formReferVO = new UIFormReferVO(); formReferVO.setType("default"); formReferVO.setReferType(attrVO.getReferbtmid()); fieldVO.setReferConfig(formReferVO); } } if (VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(fieldVO.getSortField())) { fieldVO.setField("lcstatus_text"); } Map eventJsMap = new HashMap<>(); //超链接与模板是互斥 if (StringUtils.isNotBlank(attrVO.getTablehref())) { String event = fieldVO.getSortField() + "_href"; eventJsMap.put(event, attrVO.getTablehref()); fieldVO.setTemplet("function(d){ return 'd." + fieldVO.getField() + "';}"); } if (StringUtils.isNotBlank(attrVO.getTabledisplayjs())) { //直接写function(d){ return xxxxx;} fieldVO.setTemplet(attrVO.getTabledisplayjs()); } if (StringUtils.isBlank(fieldVO.getTemplet()) && VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(attrVO.getAttributedatatype())) { fieldVO.setTemplet("function(d){return $webUtil.formateBoolean(d." + fieldVO.getField() + ");}"); } fieldVO.setOptionJsMap(eventJsMap); fieldVO.setStyle(attrVO.getTabledisplaystyle()); //列表里不允许直接编辑 fieldVO.setDateFormate(attrVO.getCodedateformat()); return fieldVO; } /** * 密级的字段 */ public static final String SECRET_FILED = "secretgrade"; /** * 模板属性转换为表单的字段 * * @param attrVO 模板属性 * @param btmType 业务类型 * @return 表单的字段 */ @Override public UIFormItemVO templateAttr2FormField(CodeClassifyTemplateAttrVO attrVO, String btmType) { UIFormItemVO itemVO = new UIFormItemVO(); if (SECRET_FILED.equalsIgnoreCase(attrVO.getId())) { attrVO.setEnumid(OsEnumServiceImpl.MY_DATA_SECRET); } itemVO.setField(attrVO.getId()); itemVO.setText(attrVO.getName()); itemVO.setType(vciFieldTypeMap.getOrDefault(attrVO.getAttributedatatype(), "text")); if (VciBaseUtil.getBoolean(attrVO.getTextareaflag())) { itemVO.setType("textarea"); } if (VciFieldTypeEnum.VTLong.name().equalsIgnoreCase(attrVO.getAttributedatatype()) || VciFieldTypeEnum.VTInteger.name().equalsIgnoreCase(attrVO.getAttributedatatype()) || VciFieldTypeEnum.VTDouble.name().equalsIgnoreCase(attrVO.getAttributedatatype())) { itemVO.setVerify("number"); } itemVO.setReadOnly(VciBaseUtil.getBoolean(attrVO.getReadonlyflag())); itemVO.setKeyAttr(VciBaseUtil.getBoolean(attrVO.getKeyattrflag())); itemVO.setRequired(VciBaseUtil.getBoolean(attrVO.getRequireflag())); itemVO.setDefaultValue(attrVO.getDefaultvalue()); itemVO.setDateFormate(attrVO.getCodedateformat()); itemVO.setHidden(!VciBaseUtil.getBoolean(attrVO.getFormdisplayflag())); itemVO.setVerify(attrVO.getVerifyrule()); itemVO.setPrefix(attrVO.getPrefixvalue()); itemVO.setSuffix(attrVO.getSuffixvalue()); itemVO.setTooltips(attrVO.getExplain()); itemVO.setSelectLibFlag(attrVO.getLibraryIdentification()); //看看是否有枚举 if ((StringUtils.isNotBlank(attrVO.getEnumString()) && !"[]".equalsIgnoreCase(attrVO.getEnumString())) || StringUtils.isNotBlank(attrVO.getEnumid())) { itemVO.setType("combox"); itemVO.setComboxKey(attrVO.getEnumid()); if (StringUtils.isNotBlank(attrVO.getEnumString())) { //指定的下拉框内容 itemVO.setData(JSONObject.parseArray(attrVO.getEnumString(), KeyValue.class)); if (StringUtils.isBlank(attrVO.getEnumid())) { itemVO.setComboxKey(itemVO.getField() + "_data"); } } } //看是否有参照 if (StringUtils.isNotBlank(attrVO.getReferbtmid()) || StringUtils.isNotBlank(attrVO.getReferConfig())) { itemVO.setType("refer"); itemVO.setShowField(itemVO.getField() + "name"); if (StringUtils.isNotBlank(attrVO.getReferConfig())) { //配置的内容 itemVO.setReferConfig(JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class)); } else { UIFormReferVO formReferVO = new UIFormReferVO(); formReferVO.setType("default"); formReferVO.setReferType(attrVO.getReferbtmid()); itemVO.setReferConfig(formReferVO); } } //如果是组合规则,分类注入的,显示为只读 if (StringUtils.isNotBlank(attrVO.getComponentrule())) { itemVO.setReadOnly(true); itemVO.setTooltips("本属性为组合规则"); itemVO.setRequired(false); } if (StringUtils.isNotBlank(attrVO.getClassifyinvokeattr())) { itemVO.setReadOnly(!VciBaseUtil.getBoolean(attrVO.getClassifyinvokeeditflag())); itemVO.setTooltips("本属性是分类注入"); itemVO.setRequired(false); } if (VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(itemVO.getField())) { //是生命周期状态 itemVO.setType("combox"); itemVO.setComboxKey(btmType + LC_STATUS_SUBFIX); } return itemVO; } /** * 属性类型与js中的字段类型的映射 */ private static Map vciFieldTypeMap = new HashMap() {{ put(VciFieldTypeEnum.VTString.name(), "text"); put(VciFieldTypeEnum.VTInteger.name(), "text"); put(VciFieldTypeEnum.VTLong.name(), "text"); put(VciFieldTypeEnum.VTDouble.name(), "text"); put(VciFieldTypeEnum.VTClob.name(), "text"); put(VciFieldTypeEnum.VTBoolean.name(), "truefalse"); put(VciFieldTypeEnum.VTDateTime.name(), "datetime"); put(VciFieldTypeEnum.VTDate.name(), "datetime"); put(VciFieldTypeEnum.VTTime.name(), "datetime"); put(VciFieldTypeEnum.VTFilePath.name(), "file"); }}; /** * 标记流程中业务数据是否通过 * * @param oid 业务数据主键 * @param btmName 业务类型 * @param pass 是否通过 * @return 执行结果 */ @Override public BaseResult markDataPassing(String oid, String btmName, Boolean pass) { VciBaseUtil.alertNotNull(oid, "业务数据主键", btmName, "业务类型", pass, "标记类型"); boolean flag = false; try { ClientBusinessObjectOperation operation = new ClientBusinessObjectOperation(); ClientBusinessObject data = operation.readBusinessObjectById(oid, btmName); if (data == null || StringUtils.isBlank(data.getOid())) { return BaseResult.fail(DATA_OID_NOT_EXIST); } data.setAttributeValue("passing", String.valueOf(pass)); flag = operation.updateBuinessObject(data); } catch (VCIError e) { e.printStackTrace(); } if (flag) { return BaseResult.success(); } else { return BaseResult.fail("标记失败"); } } /** * 使用分类的主键获取业务数据 * * @param btmType 业务类型 * @param queryObject 查询对象 * @return 表格的显示对象值 */ @Override public DataGrid> getTableDataByExecutionId(String btmType, BaseQueryObject queryObject) { VciBaseUtil.alertNotNull(btmType, "业务类型"); if (queryObject == null) { queryObject = new BaseQueryObject(); } if (queryObject.getConditionMap() == null) { queryObject.setConditionMap(new HashMap<>()); } Map conditionMap = queryObject.getConditionMap(); PageHelper pageHelper = queryObject.getPageHelper(); if (!conditionMap.containsKey("oid")) { throw new VciBaseException("业务数据主键不能为空"); } List oidList = VciBaseUtil.str2List(conditionMap.get("oid")); Map oidMap = new HashMap<>(); if (conditionMap.get("oid").contains(",")) { oidMap.put("oid", QueryOptionConstant.IN +"("+ VciBaseUtil.toInSql(oidList.toArray(new String[0])) + ")"); } else { oidMap.put("oid", conditionMap.get("oid")); } if (CollectionUtils.isEmpty(oidMap)) { throw new VciBaseException("业务数据主键不能为空"); } List cbos = boService.queryCBO(btmType, oidMap); if (CollectionUtils.isEmpty(cbos)) { throw new VciBaseException("未找到业务数据"); } ClientBusinessObject cbo = cbos.get(0); String templateOid = cbo.getAttributeValue("CODETEMPLATEOID"); Map templateOidMap = new HashMap<>(); templateOidMap.put("oid", templateOid); List templateDOList = boService.queryObject(CodeClassifyTemplateDO.class, templateOidMap); templateOidMap.clear(); templateOidMap.put("CLASSIFYTEMPLATEOID",templateOid); List attrDOList = boService.queryObject(CodeClassifyTemplateAttrDO.class, templateOidMap); if (CollectionUtils.isEmpty(templateDOList)) { logger.error("找不到业务数据关联的模板,模板主键:" + templateOid); throw new VciBaseException("找不到业务数据关联的模板"); } CodeClassifyTemplateVO templateVO = templateService.codeClassifyTemplateDO2VO(templateDOList.get(0)); templateVO.setAttributes(templateAttrService.codeClassifyTemplateAttrDO2VOs(attrDOList)); try { if (oidList.size() > 1){ DataGrid> allDataGrid = new DataGrid<>(); List> allData = new ArrayList<>(); oidList.forEach(oid -> { Map condition = new HashMap<>(); condition.put("oid",oid); DataGrid> dataGrid = queryGrid(btmType, templateVO, condition, pageHelper); allData.addAll(dataGrid.getData()); }); allDataGrid.setData(allData); return allDataGrid; }else { return queryGrid(btmType, templateVO, conditionMap, pageHelper); } } catch (Exception e) { System.out.println(e.getMessage()); return null; } } /** * 批量保存流程执行页面修改的内容 * * @param orderDTOList 编码相关的信息,不需要码段的信息 * @return 执行结果 */ @Override public BaseResult batchUpdateCode(List orderDTOList) { VciBaseUtil.alertNotNull(orderDTOList,"编码申请相关的属性内容"); orderDTOList.forEach(orderDTO -> { VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性的内容都为空", orderDTO.getOid(), "数据主键", orderDTO.getCodeClassifyOid(), "主题库分类的主键"); }); Map orderDTOMap = orderDTOList.stream().filter(orderDTO -> orderDTO != null && StringUtils.isNotBlank(orderDTO.getOid())).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); List updateList = new ArrayList<>(); // 应该都是一个分类下的业务数据,找第一条的就行 CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTOList.get(0).getCodeClassifyOid()); Map cboOidMap = new HashMap<>(); if (CollectionUtils.isEmpty(orderDTOMap.keySet())){ throw new VciBaseException(DATA_OID_NOT_EXIST); } cboOidMap.put("oid",QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(orderDTOMap.keySet().toArray(new String[0])) + ")"); List cboList = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), cboOidMap); if (CollectionUtils.isEmpty(cboList)){ throw new VciBaseException(DATA_OID_NOT_EXIST); } BatchCBO batchCBO = new BatchCBO(); CodeClassifyTemplateVO firstTemplateVO = templateService.getObjectHasAttrByOid(orderDTOMap.values().stream().findFirst().get().getTemplateOid()); Map cboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t)); orderDTOMap.keySet().stream().forEach(oid -> { CodeOrderDTO orderDTO = orderDTOMap.get(oid); ClientBusinessObject cbo = cboMap.get(oid); if (!cbo.getTs().contains(VciDateUtil.date2Str(orderDTO.getTs(), VciDateUtil.DateTimeFormat))) { throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试"); } if (!CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(cbo.getLcStatus()) && !orderDTO.isEditInProcess()) { throw new VciBaseException("数据不是{0}的状态,不允许修改", new String[]{CodeDefaultLC.EDITING.getText()}); } //1. 判断必输项 CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid()); checkRequiredAttrOnOrder(templateVO, orderDTO); //2.先注入,再组合,最后校验 switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO); //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的 switchComponentAttrOnOrder(templateVO, orderDTO); //4.校验规则 checkVerifyOnOrder(templateVO, orderDTO); //5.判断关键属性 checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO); //6.校验枚举的内容是否正确 checkEnumOnOrder(templateVO, orderDTO); //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储 switchDateAttrOnOrder(templateVO, orderDTO); //默认的内容不能变,所以只需要拷贝自定义的相关属性即可 copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true); //企业码和集团码的不修改 cbo.setDescription(orderDTO.getDescription()); cbo.setName(orderDTO.getName()); try { cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription()); cbo.setAttributeValue("name", orderDTO.getName()); } catch (VCIError e) { e.printStackTrace(); } batchCBO.getUpdateCbos().add(cbo); updateList.add(cbo); }); boService.persistenceBatch(batchCBO); batchSaveSelectChar(firstTemplateVO, cboList); return BaseResult.success(); } /** * 使用分类的编号路径,获取表格的相关定义 * * @param codeClassifyIdPath 分类的编号路径,必须是从顶层节点开始,xxx/yy/zz这样的格式 * @param functionId 功能的编号 * @return UI相关的信息(仅包含表格) */ @Override public MdmUIInfoVO getUIInfoByClassifyIdPath(String codeClassifyIdPath, String functionId) { CodeClassifyVO classifyVO = classifyService.getObjectByIdPath(codeClassifyIdPath); if(classifyVO !=null){ return getUIInfoByClassifyOid(classifyVO.getOid(),functionId); } return null; } /** * 使用分类的编号路径,获取表单的相关定义 * * @param idPath 编号的路径,必须从顶层节点开始,xx/yyy/zz * @return UI相关的信息(仅包含表单) */ @Override public MdmUIInfoVO getFormDefineByClassifyIdPath(String idPath) { CodeClassifyVO classifyVO = classifyService.getObjectByIdPath(idPath); if(classifyVO !=null){ return getFormDefineByClassifyOid(classifyVO.getOid()); } return null; } }