|
@@ -0,0 +1,427 @@
|
|
|
+package nckd.jimin.jyyy.bd.task.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import kd.bos.basedata.service.BaseDataServiceImpl;
|
|
|
+import kd.bos.dataentity.entity.DynamicObject;
|
|
|
+import kd.bos.db.DB;
|
|
|
+import kd.bos.ext.fi.plugin.ArApConvert.util.EmptyUtils;
|
|
|
+import kd.bos.logging.Log;
|
|
|
+import kd.bos.logging.LogFactory;
|
|
|
+import kd.bos.orm.query.QCP;
|
|
|
+import kd.bos.orm.query.QFilter;
|
|
|
+import kd.bos.servicehelper.BusinessDataServiceHelper;
|
|
|
+import kd.bos.servicehelper.operation.SaveServiceHelper;
|
|
|
+import kd.bos.util.StringUtils;
|
|
|
+import nckd.jimin.jyyy.bd.task.SynSapService;
|
|
|
+import nckd.jimin.jyyy.bd.task.SyncSapUtils;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+public class SynSapServiceImpl implements SynSapService {
|
|
|
+
|
|
|
+ protected static final Long DEFAULT_ORG_ID = 100000L;
|
|
|
+ private static final Log logger = LogFactory.getLog(SynSapServiceImpl.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ *同步成本中心
|
|
|
+ * @param companyCode
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, String> synCostCenterForSap(String companyCode) {
|
|
|
+ Map<String, String> result = new HashMap<>();
|
|
|
+ logger.info("同步SAP主数据_成本");
|
|
|
+ String data = SyncSapUtils.getCostCenterData(companyCode);
|
|
|
+ String url = "costcenter";
|
|
|
+ logger.info("同步SAP主数据_成本,参数:" + data);
|
|
|
+ String response = SyncSapUtils.postDataToSAP(url, data);
|
|
|
+ if(StringUtils.isEmpty(response)){
|
|
|
+ result.put("code", "300");
|
|
|
+ result.put("msg", "同步SAP主数据_成本,同步失败");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ JSONObject rData = JSONObject.parseObject(response);
|
|
|
+ String etype = rData.getString("E_TYPE");
|
|
|
+
|
|
|
+ if(!"S".equals(etype)){
|
|
|
+ result.put("code", "301");
|
|
|
+ result.put("msg", "同步SAP主数据_成本,E_TYPE:"+etype+",错误信息:"+rData.getString("E_MESSGE"));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject rEtItem = rData.getJSONObject("ET_ITEM");
|
|
|
+ if(rEtItem == null){
|
|
|
+ result.put("code", "302");
|
|
|
+ result.put("msg", "同步SAP主数据_成本,ET_ITEM参数为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONArray rItemArray = rEtItem.getJSONArray("item");
|
|
|
+ if(rItemArray == null){
|
|
|
+ result.put("code", "303");
|
|
|
+ result.put("msg", "同步SAP主数据_成本,item参数为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> costNumList = new ArrayList<String>();
|
|
|
+ for(int i = 0; i < rItemArray.size(); ++i) {
|
|
|
+ JSONObject item = rItemArray.getJSONObject(i);
|
|
|
+ String number = item.getString("KOSTL");
|
|
|
+ costNumList.add(number);
|
|
|
+ }
|
|
|
+ //取组织对象
|
|
|
+ QFilter qf = new QFilter("number", QCP.equals, companyCode);
|
|
|
+ DynamicObject companyDyn = BusinessDataServiceHelper.loadSingle("bos_org", new QFilter[]{qf});
|
|
|
+
|
|
|
+ QFilter qFilter = new QFilter("number", QCP.in, costNumList);
|
|
|
+ // QFilter qFilter1 = new QFilter("accountorg.number", QCP.equals, companyCode);
|
|
|
+ DynamicObject[] costDyns = BusinessDataServiceHelper.load("bos_costcenter", "id,masterid,number,name,accountorg,orgduty,status,enable", new QFilter[]{qFilter});
|
|
|
+ Map<String, DynamicObject> costMap =
|
|
|
+ Arrays.stream(costDyns)
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ detail -> detail.getString("number"),
|
|
|
+ detail -> detail, // 整个 DynamicObject 作为 value
|
|
|
+ (existing, replacement) -> existing // 保留前面的值
|
|
|
+ ));
|
|
|
+ ArrayList<DynamicObject> costList = new ArrayList<>();
|
|
|
+ StringBuilder err = new StringBuilder();
|
|
|
+
|
|
|
+ for(int i = 0; i < rItemArray.size(); ++i) {
|
|
|
+ JSONObject item = rItemArray.getJSONObject(i);
|
|
|
+ String number = item.getString("KOSTL");
|
|
|
+
|
|
|
+ String name = item.getString("KTEXT");
|
|
|
+ if(StringUtils.isEmpty(number) || StringUtils.isEmpty(name)){
|
|
|
+ err.append("/n 存在项目编号或名称为空, " + number + name);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(EmptyUtils.isNotEmpty(number)){
|
|
|
+ DynamicObject dyn = costMap.get(number);
|
|
|
+ if(dyn == null){
|
|
|
+ dyn = BusinessDataServiceHelper.newDynamicObject("bos_costcenter");
|
|
|
+ long Id = DB.genLongId("t_bos_costcenter");
|
|
|
+ dyn.set("id", Id);
|
|
|
+ dyn.set("number", number); // 编号
|
|
|
+ dyn.set("accountorg", companyDyn);//核算组织
|
|
|
+ String orgduty=item.getString("KTEXT");
|
|
|
+ if(EmptyUtils.isNotEmpty(orgduty)){
|
|
|
+
|
|
|
+ String orgdutyValue=orgduty.substring(orgduty.length()-1);
|
|
|
+
|
|
|
+ switch (orgdutyValue){
|
|
|
+ case "V"://销售
|
|
|
+ dyn.set("orgduty", "3");
|
|
|
+ break;
|
|
|
+ case "L"://管理
|
|
|
+ dyn.set("orgduty", "1");
|
|
|
+ break;
|
|
|
+ case "F"://制造
|
|
|
+ dyn.set("orgduty", "4");
|
|
|
+ break;
|
|
|
+ case "E"://研发
|
|
|
+ dyn.set("orgduty", "2");
|
|
|
+ break;
|
|
|
+ default://其他
|
|
|
+ dyn.set("orgduty", "5");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dyn.set("name", item.getString("KTEXT"));////项目名称
|
|
|
+ dyn.set("status", "C"); ///单据状态
|
|
|
+ dyn.set("enable", "1"); //使用状态
|
|
|
+ logger.info("同步SAP主数据_成本,id:"+dyn.getLong("id")+" -->"+Long.valueOf(dyn.getString("id")));
|
|
|
+ dyn.set("masterid",Long.valueOf(dyn.getString("id")));
|
|
|
+ costList.add(dyn);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(costList.size()>0) {
|
|
|
+ Object[] save = SaveServiceHelper.save(costList.toArray(new DynamicObject[0]));
|
|
|
+ int length = save.length;
|
|
|
+ logger.info("同步[成本]完成,本次新增数量:{},"+err, length);
|
|
|
+ result.put("code", "200");
|
|
|
+ result.put("msg", "同步SAP主数据_成本,执行成功,本次同步数量"+length+err);
|
|
|
+ }else{
|
|
|
+ result.put("code", "304");
|
|
|
+ result.put("msg", "同步SAP主数据_"+err);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步SAP主数据中的项目信息
|
|
|
+ *
|
|
|
+ * 本方法负责从SAP系统同步项目相关的主数据,处理并保存到当前系统中
|
|
|
+ * 它首先从SAP获取项目数据,然后解析这些数据,并与系统中已存在的项目信息进行对比和更新
|
|
|
+ * 如果项目在系统中不存在,则会创建新的项目记录;如果存在,则更新项目信息
|
|
|
+ *
|
|
|
+ * 1、根据 SAP 项目编码判断层级
|
|
|
+ * 编码中的2010、2060 代表公司 1级项目(编码无点)按全局共享,2级项目阶段,按02、.03判断私分配隔(私有)
|
|
|
+ * 需要代码自动判断创建1级项目
|
|
|
+ * 注意需要单独处理项目t_bd_project_u表数据,否则不能在界面查询出来
|
|
|
+ *
|
|
|
+ * @param companyCode 公司代码,用于过滤特定公司的项目信息
|
|
|
+ * @return 返回一个包含同步结果的Map,包括状态码(code)和消息(msg)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, String> synProjectForSap(String companyCode) {
|
|
|
+ BaseDataServiceImpl baseDataService = new BaseDataServiceImpl();
|
|
|
+ Map<String, String> result = new HashMap<>();
|
|
|
+ logger.info("同步SAP主数据_项目");
|
|
|
+ String data = SyncSapUtils.getProjectData(companyCode);
|
|
|
+ String url = "project";
|
|
|
+ logger.info("同步SAP主数据_项目,参数:" + data);
|
|
|
+ String response = SyncSapUtils.postDataToSAP(url, data);
|
|
|
+
|
|
|
+ if(StringUtils.isEmpty(response)){
|
|
|
+ result.put("code", "300");
|
|
|
+ result.put("msg", "同步SAP主数据_项目,同步失败");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ JSONObject rData = JSONObject.parseObject(response);
|
|
|
+
|
|
|
+ String etype = rData.getString("E_TYPE");
|
|
|
+
|
|
|
+ if(!"S".equals(etype)){
|
|
|
+ result.put("code", "301");
|
|
|
+ result.put("msg", "同步SAP主数据_项目,E_TYPE:"+etype+",错误信息:"+rData.getString("E_MESSGE"));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject rEtItem = rData.getJSONObject("ET_ITEM");
|
|
|
+ if(rEtItem == null){
|
|
|
+ result.put("code", "302");
|
|
|
+ result.put("msg", "同步SAP主数据_项目,ET_ITEM参数为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONArray rItemArray = rEtItem.getJSONArray("item");
|
|
|
+ if(rItemArray == null){
|
|
|
+ result.put("code", "303");
|
|
|
+ result.put("msg", "同步SAP主数据_项目,item参数为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> projectNumList = new ArrayList<String>();
|
|
|
+ for(int i = 0; i < rItemArray.size(); ++i) {
|
|
|
+ JSONObject item = rItemArray.getJSONObject(i);
|
|
|
+ String number = item.getString("POSID");
|
|
|
+ projectNumList.add(number);
|
|
|
+ }
|
|
|
+ //取组织对象
|
|
|
+ QFilter qf = new QFilter("number", QCP.equals, companyCode);
|
|
|
+ DynamicObject companyDyn = BusinessDataServiceHelper.loadSingle("bos_org", new QFilter[]{qf});
|
|
|
+
|
|
|
+ QFilter qFilter = new QFilter("number", QCP.in, projectNumList);
|
|
|
+ QFilter qFilter1 = new QFilter("org.number", QCP.equals, companyCode);
|
|
|
+ DynamicObject[] dyns = BusinessDataServiceHelper.load("bd_project", "id,number,name,fullname,parent,masterid,proleader,org,useorg,createorg,group,status,ctrlstrategy,level,isleaf,department,prostatus,enable", new QFilter[]{qFilter,qFilter1});
|
|
|
+
|
|
|
+ Map<String, DynamicObject> projectMap =
|
|
|
+ Arrays.stream(dyns)
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ detail -> detail.getString("number"),
|
|
|
+ detail -> detail, // 整个 DynamicObject 作为 value
|
|
|
+ (existing, replacement) -> existing // 保留前面的值
|
|
|
+ ));
|
|
|
+
|
|
|
+ ArrayList<DynamicObject> projectList = new ArrayList<>();
|
|
|
+ List<Object[]> useorgList = new ArrayList<>();
|
|
|
+ StringBuilder err = new StringBuilder();
|
|
|
+
|
|
|
+ for(int i = 0; i < rItemArray.size(); ++i) {
|
|
|
+ JSONObject item = rItemArray.getJSONObject(i);
|
|
|
+ String number = item.getString("POSID");
|
|
|
+ String name = item.getString("POST1");
|
|
|
+ if(StringUtils.isEmpty(number) || StringUtils.isEmpty(name)){
|
|
|
+ err.append(" \n存在项目编号或名称为空, " + number + name);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!"CD20210404.2010.22".equals(number)) continue;
|
|
|
+
|
|
|
+ String proleader = item.getString("USR03");
|
|
|
+ String department = item.getString("DEPARTMENT");
|
|
|
+ String type = item.getString("ZBY2");
|
|
|
+ String billstatus = item.getString("STATUS");
|
|
|
+ DynamicObject proleaderDyn = null;
|
|
|
+ DynamicObject departmentDyn = null;
|
|
|
+ DynamicObject typeDyn = null;
|
|
|
+ DynamicObject projectStatusDyn = null;
|
|
|
+ if(StringUtils.isNotEmpty(proleader)){
|
|
|
+ QFilter qf1 = new QFilter("number", QCP.equals, proleader);
|
|
|
+ proleaderDyn = BusinessDataServiceHelper.loadSingle("bos_user", new QFilter[]{qf1});
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotEmpty(department)){
|
|
|
+ QFilter qf1 = new QFilter("number", QCP.equals, department);
|
|
|
+ departmentDyn = BusinessDataServiceHelper.loadSingle("bos_org", new QFilter[]{qf1});
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotEmpty(type)){
|
|
|
+ QFilter qf1 = new QFilter("number", QCP.equals, type);
|
|
|
+ typeDyn = BusinessDataServiceHelper.loadSingle("bd_projectkind", new QFilter[]{qf1});
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotEmpty(billstatus)){
|
|
|
+ QFilter qf1 = new QFilter("nckd_sapprojstatus", QCP.equals, billstatus);
|
|
|
+ projectStatusDyn = BusinessDataServiceHelper.loadSingle("bd_projectstatus", new QFilter[]{qf1});
|
|
|
+ }
|
|
|
+ QFilter qf2 = new QFilter("number", QCP.equals, "SAP");
|
|
|
+ DynamicObject srcSysDyn = BusinessDataServiceHelper.loadSingle("bos_devportal_bizcloud",new QFilter[]{qf2});
|
|
|
+
|
|
|
+ DynamicObject dyn = projectMap.get(number);
|
|
|
+ if(dyn == null){
|
|
|
+ /*
|
|
|
+ * 处理一级项目,来自于项目编码前段编码 BD20200303.2010.07 ,BD20200303为一级项目编码
|
|
|
+ * */
|
|
|
+ DynamicObject parentDyn = null;
|
|
|
+ String parent = SyncSapUtils.getProjectNumberForParent(number);
|
|
|
+ if(StringUtils.isNotEmpty(parent)) {
|
|
|
+
|
|
|
+ parentDyn = BusinessDataServiceHelper.newDynamicObject("bd_project");
|
|
|
+ long Id = DB.genLongId("t_bd_project");
|
|
|
+ parentDyn.set("id", Id);
|
|
|
+ parentDyn.set("masterid",Id);
|
|
|
+ parentDyn.set("number", parent); // 编号
|
|
|
+ parentDyn.set("org", DEFAULT_ORG_ID); //一级项目放在顶层组织下
|
|
|
+ parentDyn.set("createorg", DEFAULT_ORG_ID); //一级项目放在顶层组织下
|
|
|
+ if(EmptyUtils.isNotEmpty(typeDyn)) {
|
|
|
+ parentDyn.set("group", typeDyn); ///项目分类
|
|
|
+ }
|
|
|
+ parentDyn.set("level", 1);
|
|
|
+ parentDyn.set("isleaf", 0);
|
|
|
+ parentDyn.set("status", "C"); ///单据状态
|
|
|
+ parentDyn.set("ctrlstrategy", "5"); //控制策略 自由分配 2 全局共享 5 私有 7
|
|
|
+ parentDyn.set("enable", "1"); //使用状态
|
|
|
+ // parentDyn.set("prostatus", "PASS_S"); //项目状态 PASS通过
|
|
|
+ parentDyn.set("name", parent);
|
|
|
+ parentDyn.set("fullname", parent);
|
|
|
+ if(EmptyUtils.isNotEmpty(proleaderDyn)) {
|
|
|
+ parentDyn.set("proleader", proleaderDyn);
|
|
|
+ }
|
|
|
+ if(EmptyUtils.isNotEmpty(departmentDyn)) {
|
|
|
+ parentDyn.set("department", departmentDyn);
|
|
|
+ }
|
|
|
+ if(EmptyUtils.isNotEmpty(projectStatusDyn)) {
|
|
|
+ parentDyn.set("prostatus", projectStatusDyn);
|
|
|
+ }
|
|
|
+ if(EmptyUtils.isNotEmpty(srcSysDyn)) {
|
|
|
+ parentDyn.set("systemtypebase", srcSysDyn);
|
|
|
+ }
|
|
|
+ projectList.add(parentDyn);
|
|
|
+
|
|
|
+ }
|
|
|
+ /***
|
|
|
+ * 处理二级项目,如果项目编码中包含点,则需要处理上级项目
|
|
|
+ */
|
|
|
+ dyn = BusinessDataServiceHelper.newDynamicObject("bd_project");
|
|
|
+ long Id = DB.genLongId("t_bd_project");
|
|
|
+ dyn.set("id", Id);
|
|
|
+ dyn.set("masterid",Id);
|
|
|
+ if(EmptyUtils.isNotEmpty(parentDyn)){
|
|
|
+ dyn.set("parent", parentDyn);
|
|
|
+ }
|
|
|
+ dyn.set("number", number); // 编号
|
|
|
+ dyn.set("org", companyDyn.getPkValue());
|
|
|
+ dyn.set("level", 2);
|
|
|
+ dyn.set("isleaf", 1);
|
|
|
+ dyn.set("createorg", companyDyn.getPkValue());
|
|
|
+ dyn.set("useorg", companyDyn.getPkValue());
|
|
|
+ if(EmptyUtils.isNotEmpty(typeDyn)) {
|
|
|
+ dyn.set("group", typeDyn); ///项目分类
|
|
|
+ }
|
|
|
+ dyn.set("status", "C"); ///单据状态
|
|
|
+ dyn.set("ctrlstrategy", "7"); //控制策略 自由分配 2 全局共享 5 私有 7
|
|
|
+ dyn.set("enable", "1"); //使用状态
|
|
|
+ //dyn.set("prostatus", "PASS_S"); //项目状态 PASS通过
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 当控制策略为自由分配和私有时,需要单独处理项目t_bd_project_u表数据,否则不能在界面查询出来
|
|
|
+ */
|
|
|
+ Object[] odjs = new Object[]{
|
|
|
+ dyn.get("id"),
|
|
|
+ dyn.get("useorg")
|
|
|
+ };
|
|
|
+ useorgList.add(odjs);
|
|
|
+ }
|
|
|
+ dyn.set("name", item.getString("POST1"));
|
|
|
+ dyn.set("fullname", item.getString("POST1"));
|
|
|
+ if(EmptyUtils.isNotEmpty(proleaderDyn)) {
|
|
|
+ dyn.set("proleader", proleaderDyn);
|
|
|
+ }
|
|
|
+ if(EmptyUtils.isNotEmpty(departmentDyn)) {
|
|
|
+ dyn.set("department", departmentDyn);
|
|
|
+ }
|
|
|
+ if(EmptyUtils.isNotEmpty(projectStatusDyn)) {
|
|
|
+ dyn.set("prostatus", projectStatusDyn);
|
|
|
+ }
|
|
|
+ if(EmptyUtils.isNotEmpty(srcSysDyn)) {
|
|
|
+ dyn.set("systemtypebase", srcSysDyn);
|
|
|
+ }
|
|
|
+ projectList.add(dyn);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(projectList.size()>0) {
|
|
|
+ Object[] save = SaveServiceHelper.save(projectList.toArray(new DynamicObject[0]));
|
|
|
+ int length = save.length;
|
|
|
+ logger.info("同步[项目]完成,本次新增数量:{},"+err, length);
|
|
|
+ result.put("code", "200");
|
|
|
+ result.put("msg", "同步SAP主数据_项目,执行成功,本次同步数量"+length+err);
|
|
|
+ }else{
|
|
|
+ result.put("code", "304");
|
|
|
+ result.put("msg", "同步SAP主数据_错误,"+err);
|
|
|
+ }
|
|
|
+ /***
|
|
|
+ * 需要单独处理项目t_bd_project_u表数据,否则不能在界面查询出来
|
|
|
+ */
|
|
|
+ if (useorgList.size()>0) {
|
|
|
+ baseDataService.savePrivateBaseDataUseRange("bd_project", useorgList);
|
|
|
+ logger.info("同步[项目]完成,t_bd_project_u表");
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, String> synAccountViewForSap(String companyCode) {
|
|
|
+ Map<String, String> result = new HashMap<>();
|
|
|
+
|
|
|
+ String data = SyncSapUtils.getAccountViewData(companyCode);
|
|
|
+ String url = "account";
|
|
|
+ String response = SyncSapUtils.postDataToSAP(url, data);
|
|
|
+
|
|
|
+ if(StringUtils.isEmpty(response)){
|
|
|
+ result.put("code", "300");
|
|
|
+ result.put("msg", "同步失败");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ JSONObject rData = JSONObject.parseObject(response);
|
|
|
+
|
|
|
+ String etype = rData.getString("E_TYPE");
|
|
|
+
|
|
|
+ if(!"S".equals(etype)){
|
|
|
+ result.put("code", "301");
|
|
|
+ result.put("msg", "E_TYPE:"+etype+",错误信息:"+rData.getString("E_MESSGE"));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject rEtItem = rData.getJSONObject("ET_ITEM");
|
|
|
+ if(rEtItem == null){
|
|
|
+ result.put("code", "302");
|
|
|
+ result.put("msg", "ET_ITEM参数为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONArray rItemArray = rEtItem.getJSONArray("item");
|
|
|
+ if(rItemArray == null){
|
|
|
+ result.put("code", "303");
|
|
|
+ result.put("msg", "item参数为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+}
|