ZwServiceImpl.java 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. package com.malk.zhiwei.service.impl;
  2. import cn.hutool.http.HttpUtil;
  3. import com.alibaba.fastjson.JSON;
  4. import com.alibaba.fastjson.JSONArray;
  5. import com.alibaba.fastjson.JSONObject;
  6. import com.fasterxml.jackson.core.JsonProcessingException;
  7. import com.google.gson.Gson;
  8. import com.google.gson.JsonObject;
  9. import com.kingdee.bos.webapi.entity.IdentifyInfo;
  10. import com.kingdee.bos.webapi.entity.RepoRet;
  11. import com.kingdee.bos.webapi.sdk.K3CloudApi;
  12. import com.malk.server.aliwork.YDConf;
  13. import com.malk.server.aliwork.YDParam;
  14. import com.malk.server.common.McR;
  15. import com.malk.server.common.VenR;
  16. import com.malk.server.dingtalk.DDConf;
  17. import com.malk.server.dingtalk.DDR;
  18. import com.malk.service.aliwork.YDClient;
  19. import com.malk.service.dingtalk.DDClient;
  20. import com.malk.utils.PublicUtil;
  21. import com.malk.utils.UtilHttp;
  22. import com.malk.utils.UtilMap;
  23. import com.malk.zhiwei.config.KDWebApiConf;
  24. import com.malk.zhiwei.entity.BillQuery;
  25. import com.malk.zhiwei.entity.CustomerModel;
  26. import com.malk.zhiwei.entity.FNumber;
  27. import com.malk.zhiwei.service.ZwService;
  28. import lombok.SneakyThrows;
  29. import lombok.extern.slf4j.Slf4j;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.stereotype.Service;
  32. import java.util.*;
  33. import java.util.stream.Collectors;
  34. @Service
  35. @Slf4j
  36. public class ZwServiceImpl implements ZwService {
  37. @Autowired
  38. private KDWebApiConf kdWebApiConf;
  39. @Autowired
  40. private YDConf ydConf;
  41. @Autowired
  42. private DDConf ddConf;
  43. @Autowired
  44. private DDClient ddClient;
  45. private static String ERP_URL="http://10.0.0.208:80";
  46. private static String ERP_NAME="064";
  47. private static String ERP_PASSWORD="";
  48. private static String ERP_PILOT="PILOT2001";
  49. // http://10.0.0.208:30104/MobileService.asmx?op=GETPILOTLIST
  50. // {"PILOTLIST":[
  51. // {"NAME":"PILOT2001","ZTNAME":"2001测试"},
  52. // {"NAME":"PILOT2002","ZTNAME":"2002CS-BYD"},
  53. // {"NAME":"PILOT2023","ZTNAME":"20232023"},
  54. // {"NAME":"PILOT2024","ZTNAME":"20242024"}]}
  55. private static String ERP_LOGIN_KEY="2025062710430311152101098";
  56. private static String ERP_OP_PRODUCT="Anyv_View_PRODUCT";
  57. private static String ERP_OP_PRODCLAS="Anyv_View_PRODCLAS";
  58. private static String ERP_OP_CUSTOMER="Anyv_View_CUSTOMER";
  59. public static void main(String[] args) {
  60. // {"CODE":"CP000201","clasName":"成品","CNAME":"MPP-20P","SPEC":"600*500*1.8±0.3"},{"CODE":"CP000809","clasName":"成品","CNAME":"阻燃MPP-25P-灰色","SPEC":"1400*1100*3+1-0.5"},{"CODE":"CP001362","clasName":"成品","CNAME":"阻燃MPP-15P","SPEC":"2480*222*3.5±0.2"},{"CODE":"TCP000023","clasName":"成品","CNAME":"POE05灰(李宁)","SPEC":"1850*800*6"}
  61. JSONObject jsonObject = queryData(ERP_OP_PRODUCT,"clasName = '成品'",ERP_PILOT);
  62. // {"CODE":"KH0681","CNAME":"耐玛体育","ABBR":"耐玛体育"},{"CODE":"KH0022","CNAME":"上海浩魁材料科技有限公司","ABBR":"浩魁"}
  63. // JSONObject jsonObject = queryData(ERP_OP_CUSTOMER,"");
  64. // saveSaleOrder("{\"CODE\":\"KH0681\",\"SUPP\":\"KH0681\",\"STAFFCODE\":\"admin\",\"VERIFICATION\":\"False\",\"PRODLIST\":[{\"ERI\":\"0GZ29ZUKV401HCBI\",\"CODE\":\"O220902002\",\"CODE1\":\"\",\"PROD\":\"CP000201\",\"GWN\":\"WXYL\",\"VPNO\":\"X220703\",\"QTY\":1,\"confirm\":0}]}");
  65. // saveDeliveryOrder("{\"CODE\":\"KH0681\",\"STAFFCODE\":\"admin\",\"VERIFICATION\":\"False\",\"PRODLIST\":[{\"ERI\":\"\",\"CODE\":\"O250627010\",\"PROD\":\"CP000201\",\"GWN\":\"WXYL\",\"VPNO\":\"X220703\",\"QTY\":1,\"confirm\":0}]}");
  66. }
  67. private static String erpLogin(String erpPilot){
  68. String xmlResponse=HttpUtil.get(ERP_URL+"/MobileService.asmx/login?name="+ERP_NAME+"&password="+ERP_PASSWORD+"&pilot="+erpPilot);
  69. int jsonStart = xmlResponse.indexOf("{");
  70. int jsonEnd = xmlResponse.lastIndexOf("}");
  71. String jsonStr = xmlResponse.substring(jsonStart, jsonEnd + 1);
  72. JSONObject jsonObject = JSONObject.parseObject(jsonStr);
  73. log.info("登录结果:{}",jsonObject);
  74. return jsonObject.getJSONObject("USER").getString("Key");
  75. }
  76. private static JSONObject queryData(String op,String where,String erpPilot){
  77. String xmlResponse=HttpUtil.get(ERP_URL+"/MobileService.asmx/"+op+"?KEY="+erpLogin(erpPilot)+"&field=&userid="+ERP_NAME+"&where="+where+"&pilot="+erpPilot);
  78. int jsonStart = xmlResponse.indexOf("{");
  79. int jsonEnd = xmlResponse.lastIndexOf("}");
  80. String jsonStr = xmlResponse.substring(jsonStart, jsonEnd + 1);
  81. JSONObject jsonObject = JSONObject.parseObject(jsonStr);
  82. log.info("查询结果:{}",jsonObject);
  83. return jsonObject;
  84. }
  85. private static JSONObject saveSaleOrder(String data,String erpPilot){
  86. String xmlResponse=HttpUtil.get(ERP_URL+"/MobileService.asmx/Anyv_GenForm_ORDCORD1?KEY="+erpLogin(erpPilot)+"&userid="+ERP_NAME+"&Data="+data+"&pilot="+erpPilot);
  87. System.out.println(xmlResponse);
  88. int jsonStart = xmlResponse.indexOf("{");
  89. int jsonEnd = xmlResponse.lastIndexOf("}");
  90. String jsonStr = xmlResponse.substring(jsonStart, jsonEnd + 1);
  91. JSONObject jsonObject = JSONObject.parseObject(jsonStr);
  92. log.info("保存结果:{}",jsonObject);
  93. return jsonObject;
  94. }
  95. @Override
  96. public JSONObject saveSaleOrder(Map formData) {
  97. // 数据转换
  98. JSONObject dataObj = new JSONObject();
  99. dataObj.put("CODE", UtilMap.getString(formData,"textField_mcefftni"));// 单号
  100. dataObj.put("SUPP",UtilMap.getString(formData,"textField_mcefftni"));// 客户代码
  101. dataObj.put("STAFFCODE",UtilMap.getString(formData,"textField_mcefftnj"));
  102. dataObj.put("VERIFICATION","False");
  103. List<Map> list=UtilMap.getList(formData,"tableField_mcefftnk");
  104. List<Map> dataList=new ArrayList<>();
  105. for (Map map : list) {
  106. Map tempMap=new HashMap();
  107. tempMap.put("ERI",""); // 销售订单副档ERI或出货通知单副档ERI
  108. tempMap.put("CODE", UtilMap.getString(map,"textField_mcefftnl")); // 销售订单编号
  109. tempMap.put("CODE1", "");// 出货通知单编号
  110. tempMap.put("PROD", UtilMap.getString(map,"textField_mcefftnn"));// 产品代码
  111. tempMap.put("GWN", UtilMap.getString(map,"textField_mcefftno"));// 仓库代码
  112. tempMap.put("VPNO", UtilMap.getString(map,"textField_mcefftnp"));// 产品批号
  113. tempMap.put("QTY", UtilMap.getString(map,"numberField_mcefftnr"));// 产品数量
  114. tempMap.put("confirm", "0");
  115. dataList.add(tempMap);
  116. }
  117. dataObj.put("PRODLIST",dataList);
  118. String data=JSONObject.toJSONString(dataObj);
  119. log.info("入参:{}",data);
  120. // 调用接口
  121. JSONObject result=saveSaleOrder(data,UtilMap.getString(formData,"textField_mdr1v1di"));
  122. JSONArray codes=result.getJSONArray("page");
  123. String id=codes.getJSONObject(0).getString("CODE");
  124. JSONObject result1=new JSONObject();
  125. result1.put("textField_me17f355",id); // erp单号
  126. result1.put("result",result);
  127. return result1;
  128. }
  129. private static JSONObject saveDeliveryOrder(String data,String erpPilot){
  130. String xmlResponse=HttpUtil.get(ERP_URL+"/MobileService.asmx/Anyv_GenForm_STKSHIPNOTE1?KEY="+erpLogin(erpPilot)+"&userid="+ERP_NAME+"&Data="+data+"&pilot="+erpPilot);
  131. System.out.println(xmlResponse);
  132. int jsonStart = xmlResponse.indexOf("{");
  133. int jsonEnd = xmlResponse.lastIndexOf("}");
  134. String jsonStr = xmlResponse.substring(jsonStart, jsonEnd + 1);
  135. JSONObject jsonObject = JSONObject.parseObject(jsonStr);
  136. log.info("保存结果:{}",jsonObject);
  137. return jsonObject;
  138. }
  139. @Override
  140. public JSONObject saveDeliveryOrder(Map formData) {
  141. // 数据转换
  142. JSONObject dataObj = new JSONObject();
  143. dataObj.put("CODE", UtilMap.getString(formData,"textField_mcefftni"));// 客户代码
  144. dataObj.put("STAFFCODE",UtilMap.getString(formData,"textField_mcefftnj"));
  145. dataObj.put("VERIFICATION","False");
  146. List<Map> list=UtilMap.getList(formData,"tableField_mcefftnk");
  147. List<Map> dataList=new ArrayList<>();
  148. for (Map map : list) {
  149. Map tempMap=new HashMap();
  150. tempMap.put("ERI",""); // 销售订单副档ERI或出货通知单副档ERI
  151. tempMap.put("CODE", UtilMap.getString(map,"textField_mcefftnl")); // 销售订单编号
  152. tempMap.put("PROD", UtilMap.getString(map,"textField_mcefftnn"));// 产品代码
  153. tempMap.put("GWN", UtilMap.getString(map,"textField_mcefftno"));// 仓库代码
  154. tempMap.put("VPNO", UtilMap.getString(map,"textField_mcefftnp"));// 产品批号
  155. tempMap.put("QTY", UtilMap.getString(map,"numberField_mcefftnr"));// 产品数量
  156. tempMap.put("confirm", "0");
  157. dataList.add(tempMap);
  158. }
  159. dataObj.put("PRODLIST",dataList);
  160. String data=JSONObject.toJSONString(dataObj);
  161. log.info("入参:{}",data);
  162. JSONObject result=saveDeliveryOrder(data,UtilMap.getString(formData,"textField_mdr1v1di"));
  163. JSONArray codes=result.getJSONArray("page");
  164. String id=codes.getJSONObject(0).getString("CODE");
  165. JSONObject result1=new JSONObject();
  166. result1.put("textField_me17f355",id); // erp单号
  167. result1.put("result",result);
  168. return result1;
  169. // for (int i = 0; i < list.size(); i++) {
  170. // Map tempMap=new HashMap();
  171. // tempMap.put("textField_mdqsatd4",UtilMap.getString(list.get(i),"textField_mdqs9oqa"));
  172. // tempMap.put("textField_mdwpe4m6","发货");
  173. // tempMap.put("textField_mdwpe4m7",UtilMap.getString(formData,"textField_mdwqclqh"));
  174. // if(codes.size() >= i){
  175. // tempMap.put("textField_mdqsatd5",codes.getJSONObject(i).getString("CODE"));
  176. // }
  177. // ydClient.operateData(YDParam.builder().formUuid("FORM-E999482BC03547D89A435F5441A46F1ANR0R").formDataJson(JSONObject.toJSONString(tempMap)).build(), YDConf.FORM_OPERATION.create);
  178. // }
  179. // return result;
  180. // 调用接口
  181. }
  182. @Autowired
  183. private YDClient ydClient;
  184. @Override
  185. public void syncProduct(String id,String erpPilot) {
  186. JSONObject jsonObject = queryData(ERP_OP_PRODUCT,"clasName = '成品'"+ (PublicUtil.isNull(id)?"":("and CODE = '"+id+"'")),erpPilot);
  187. JSONArray data = jsonObject.getJSONArray("data");
  188. log.info("data.size():{}",data.size());
  189. for (int i = 0; i < data.size(); i++) {
  190. JSONObject dataObj = data.getJSONObject(i);
  191. String productId=UtilMap.getString(dataObj,"CODE");
  192. Map saveMap=UtilMap.map("textField_mcijetil, textField_l43jpnsf, textField_l43jpnsh","selectField_me6qde0j",productId,dataObj.getString("CNAME"),dataObj.getString("SPEC"),erpPilot);
  193. try {
  194. ydClient.operateData(YDParam.builder().formUuid("FORM-4A7B1A62CCFC4D758AB98ADE3F97D40COYO2")
  195. .searchCondition(JSONObject.toJSONString(UtilMap.map("textField_mcijetil", productId)))
  196. .formDataJson(JSONObject.toJSONString(saveMap)).build(), YDConf.FORM_OPERATION.upsert);
  197. }catch (Exception e){
  198. e.printStackTrace();
  199. }
  200. }
  201. }
  202. @SneakyThrows
  203. @Override
  204. public McR savecustomer(String instanceId) throws JsonProcessingException {
  205. log.info("客户宜搭实例id:{}",instanceId);
  206. Map data = (Map) ydClient.queryData(YDParam.builder().formInstId(instanceId)
  207. .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
  208. .userId(ddConf.getOperator()).build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
  209. FNumber zd = new FNumber(data.get("selectField_mnft99ue").toString());//终端
  210. FNumber syb = new FNumber(data.get("selectField_mnft99ud").toString());//事业部
  211. FNumber hy = new FNumber(data.get("textField_mnfujcak").toString());//行业
  212. FNumber sktj = new FNumber(data.get("textField_mnfujcaf").toString());//收款条件
  213. FNumber xsbm = new FNumber(data.get("textField_mnfujcac").toString());//销售部门
  214. FNumber xsy = new FNumber(data.get("textField_mnfujcad").toString());//销售员
  215. String kh = data.get("textField_lqanqe6j").toString();// 客户
  216. Object empObj = data.get("employeeField_lqanqe6n");
  217. String ywy = "";//业务员
  218. if (empObj instanceof JSONArray) {
  219. JSONArray empArray = (JSONArray) empObj;
  220. if (!empArray.isEmpty()) {
  221. ywy = empArray.getString(0);
  222. }
  223. } else if (empObj != null) {
  224. ywy = empObj.toString();
  225. }
  226. String nsdjhc = data.get("textField_llujklkq").toString();//纳税登记号
  227. CustomerModel customerModel = new CustomerModel(kh,sktj,hy,syb,zd,ywy,nsdjhc,xsbm,xsy);
  228. return saveToAudit("BD_Customer", customerModel);
  229. }
  230. @SneakyThrows
  231. @Override
  232. public void product() {
  233. K3CloudApi client = new K3CloudApi(initIden());
  234. int startRow = 0;
  235. int limit = 2000;
  236. BillQuery billQuery = new BillQuery();
  237. billQuery.setFormId("BD_MATERIAL");//产品信息
  238. //编码 名称 规格型号 旧物料编码 物料分组 物料属性 基本单位 长 宽 高 体积 面积 密度 标准工时
  239. billQuery.setFieldKeys("FCreateOrgId.FNumber,FApproveDate,FNumber,FName,FSpecification,FOldNumber,FMaterialGroup,FErpClsID,FBaseUnitId,FLENGTH,FWIDTH,FHEIGHT,FVOLUME,F_UNW_Qty_r03,F_UNW_Qty_6yt,FPerUnitStandHour");
  240. List<Map> filterString = new ArrayList<>();
  241. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",3,"","","0"));//审核日期在今天之前N天以后
  242. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FCreateOrgId.FNumber","67","101","","","0"));//创建组织为101 研发中心
  243. billQuery.setFilterString(filterString);
  244. billQuery.setLimit(limit);
  245. billQuery.setStartRow(startRow);
  246. String result=client.billQuery(JSONObject.toJSONString(billQuery));
  247. JSONArray jsonArray = JSONArray.parseArray(result);
  248. // 遍历每条物料记录
  249. for (int i = 0; i < jsonArray.size(); i++) {
  250. JSONObject item = jsonArray.getJSONObject(i);
  251. // 取出各个字段(注意类型转换)
  252. String number = item.getString("FNumber");
  253. String name = item.getString("FName");
  254. String spec = item.getString("FSpecification");
  255. String oldNumber = item.getString("FOldNumber");
  256. Integer materialGroup = item.getInteger("FMaterialGroup");
  257. String erpClsId = item.getString("FErpClsID");
  258. Integer baseUnitId = item.getInteger("FBaseUnitId");
  259. Double length = item.getDouble("FLENGTH");
  260. Double width = item.getDouble("FWIDTH");
  261. Double height = item.getDouble("FHEIGHT");
  262. Double volume = item.getDouble("FVOLUME");
  263. Double area = item.getDouble("F_UNW_Qty_r03");
  264. Double density = item.getDouble("F_UNW_Qty_6yt");
  265. Double standHour = item.getDouble("FPerUnitStandHour");
  266. //TODO:向宜搭插入数据
  267. String sc = "textField_l43jpnsf, textField_mcijetil, textField_l43jpnsh, textField_mnhe1ryw, textField_mnhe1rz1, textField_mnhe1rz2, textField_mnhe1rz7, textField_mnhe1rzm," +
  268. " textField_mnhe1rzg, textField_mnhe1rzh, textField_mnhe1rzi, textField_mnhe1rzj, textField_mnhe1rzk, textField_mnhe1rzl";//名称 编码 规格 旧编码 物料分组 物料属性 基本单位 标准工时 长 宽 高 体积 面积 密度
  269. List<Map> conditions = Arrays.asList( YDConf.searchCondition_TextFiled("textField_mcijetil", number, "eq"));
  270. Map formData = UtilMap.map(sc,name,number,spec,oldNumber,materialGroup,erpClsId,baseUnitId,length,width,height,volume,area,density,standHour);
  271. ydClient.operateData(YDParam.builder()
  272. .formUuid("FORM-4A7B1A62CCFC4D758AB98ADE3F97D40COYO2")
  273. .searchCondition(JSONObject.toJSONString(conditions))
  274. .formDataJson(JSONObject.toJSONString(formData))
  275. .build(),YDConf.FORM_OPERATION.upsert);
  276. }
  277. log.info("产品信息已同步");
  278. }
  279. @SneakyThrows
  280. @Override
  281. public void purchaseOrder(){
  282. K3CloudApi client = new K3CloudApi(initIden());
  283. int startRow = 0;
  284. int limit = 2000;
  285. BillQuery billQuery = new BillQuery();
  286. billQuery.setFormId("SAL_SaleOrder");//销售订单
  287. //[主表] FSaleOrgId销售组织 FSaleDeptId销售部门 FBillNo单据编号 FCustId客户 F_UNW_Text_ct1客户订单号 FSettleCurrId结算币别 FSalerId销售员 FDate日期 FRecConditionId收款条件
  288. //[明细表] FMaterialId物料编码 FMaterialName物料名称 FMaterialModel规格型号 FMapId客户物料编码 F_UNW_BaseProperty_uow客户物料规格 FUnitID销售单位 FQty销售数量 FPriceUnitQty计价数量 FPrice单价 FTaxPrice含税单价 FEntryTaxRate税率 FEntryTaxAmount税额 FAmount金额 FAllAmount价税合计 FDeliveryDate要货日期 FSettleOrgIds结算组织 FIsFree是否赠品
  289. billQuery.setFieldKeys("FSaleOrgId.FName,FSaleDeptId.FName,FBillNo,FCustId.FName,F_UNW_Text_ct1,FSettleCurrId.FName,FSalerId.FName,FDate,FRecConditionId.FName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FMapId.FNumber,F_UNW_BaseProperty_uow,FUnitID.FName,FQty,FPriceUnitQty,FPrice,FTaxPrice,FEntryTaxRate,FEntryTaxAmount,FAmount,FAllAmount,FDeliveryDate,FSettleOrgIds.FName,FIsFree");
  290. List<Map> filterString = new ArrayList<>();
  291. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
  292. billQuery.setFilterString(filterString);
  293. billQuery.setLimit(limit);
  294. billQuery.setStartRow(startRow);
  295. String result=client.billQuery(JSONObject.toJSONString(billQuery));
  296. JSONArray jsonArray = JSONArray.parseArray(result);
  297. // 按 FBillNo 分组
  298. Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
  299. for (int i = 0; i < jsonArray.size(); i++) {
  300. JSONObject item = jsonArray.getJSONObject(i);
  301. String billNo = item.getString("FBillNo");
  302. groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
  303. }
  304. // 组装最终结果
  305. List<Map<String, Object>> orderList = new ArrayList<>();
  306. for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
  307. List<JSONObject> rows = entry.getValue();
  308. JSONObject firstRow = rows.get(0);
  309. // 主表 Map
  310. Map<String, Object> orderMap = new LinkedHashMap<>();
  311. orderMap.put("textField_mniksrqa", firstRow.getString("FBillNo"));//单据编号
  312. orderMap.put("textField_mniksrq4", firstRow.getString("FSaleOrgId.FName")); // 销售组织
  313. orderMap.put("textField_mniksrq5", firstRow.getString("FSaleDeptId.FName")); // 销售组织
  314. orderMap.put("textField_mniksrqb", firstRow.getString("FCustId.FName")); // 客户
  315. orderMap.put("textField_mniksrqe", firstRow.getString("F_UNW_Text_ct1")); // 客户订单号
  316. orderMap.put("textField_mniksrqf", firstRow.getString("FSettleCurrId.FName")); // 结算币别
  317. orderMap.put("textField_mniksrqk", firstRow.getString("FSalerId.FName")); // 销售员
  318. String fDateRaw = firstRow.getString("FDate");
  319. String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
  320. orderMap.put("textField_mniksrql", formattedDate); // 日期
  321. orderMap.put("textField_mniksrqm", firstRow.getString("FRecConditionId.FName")); // 收款条件
  322. // 明细数组
  323. List<Map<String, Object>> details = new ArrayList<>();
  324. for (JSONObject row : rows) {
  325. Map<String, Object> detailMap = new LinkedHashMap<>();
  326. detailMap.put("textField_mniksrqo", row.getString("FMaterialId.FNumber"));//物料编码
  327. detailMap.put("textField_mniksrqp", row.getString("FMaterialName"));//物料名称
  328. detailMap.put("textField_mniksrqq", row.getString("FMaterialModel"));//规格型号
  329. detailMap.put("textField_mniksrqr", row.getString("FMapId.FNumber"));//客户物料编码
  330. detailMap.put("textField_mniksrqs", row.getString("F_UNW_BaseProperty_uow"));//客户物料规格
  331. detailMap.put("textField_mniksrqt", row.getString("FUnitID.FName"));//销售单位
  332. detailMap.put("numberField_mniksrqv", row.getString("FQty"));//销售数量
  333. detailMap.put("numberField_mniksrqw", row.getString("FPriceUnitQty"));//计价数量
  334. detailMap.put("numberField_mniksrqx", row.getString("FPrice"));//单价
  335. detailMap.put("numberField_mniksrqy", row.getString("FTaxPrice"));//含税单价
  336. detailMap.put("numberField_mniksrqz", row.getString("FEntryTaxRate"));//税率
  337. detailMap.put("numberField_mniksrr0", row.getString("FEntryTaxAmount"));//税额
  338. detailMap.put("numberField_mniksrr1", row.getString("FAmount"));//金额
  339. detailMap.put("numberField_mniksrr2", row.getString("FAllAmount"));//价税合计
  340. String deliveryRaw = row.getString("FDeliveryDate");
  341. String formattedDelivery = (deliveryRaw != null && deliveryRaw.contains("T")) ? deliveryRaw.split("T")[0] : deliveryRaw;
  342. detailMap.put("textField_mniksrr3", formattedDelivery);//要货日期
  343. detailMap.put("textField_mniksrr4", row.getString("FSettleOrgIds.FName"));//结算组织
  344. detailMap.put("radioField_mniksrr6", row.getString("FAmount").equals("true") ? "是" : "否");//是否赠品
  345. details.add(detailMap);
  346. }
  347. orderMap.put("tableField_mniksrqn", details);
  348. /*写入宜搭*/
  349. List<Map> conditions = Arrays.asList( YDConf.searchCondition_TextFiled("textField_mniksrqa", firstRow.getString("FBillNo"), "eq"));
  350. ydClient.operateData(YDParam.builder()
  351. .formUuid("FORM-7B112A3733EC412FB27D56D8AC242E5BHIL4")
  352. .searchCondition(JSONObject.toJSONString(conditions))
  353. .formDataJson(JSONObject.toJSONString(orderMap))
  354. .build(), YDConf.FORM_OPERATION.upsert).toString();
  355. orderList.add(orderMap);
  356. }
  357. log.info("销售订单已同步");
  358. }
  359. @SneakyThrows
  360. @Override
  361. public void deliveryOrder() throws JsonProcessingException {
  362. K3CloudApi client = new K3CloudApi(initIden());
  363. int startRow = 0;
  364. int limit = 2000;
  365. BillQuery billQuery = new BillQuery();
  366. billQuery.setFormId("SAL_DELIVERYNOTICE");//发货通知单
  367. //[主表] FBillNo单据编号 FDate日期 FSettleCurrId结算币别 FSaleOrgId销售组织 FSaleDeptId销售部门 FSalesManID销售员 F_UNW_Base_tr7发货客户 F_UNW_CheckBox_xjs是否委外
  368. //[明细表] FCustMatName客户物料名称 FCustMatID客户物料编码 FMaterialID物料编码 F_UNW_BaseProperty_3tm客户物料规格型号 FMaterialName物料名称 FMateriaModel型号规格 FUnitID销售单位 FQty销售数量 FIsFree是否赠品 FDeliveryDate要货日期 FDeliveryLoc交货地点 F_UNW_Text_8dq客户订单号
  369. billQuery.setFieldKeys("FBillNo,FDate,FSettleCurrId.FName,FSaleOrgId.FName,FSaleDeptId.FName,FSalesManID.FName,F_UNW_Base_tr7.FName,F_UNW_CheckBox_xjs,FCustMatName,FCustMatID.FNumber,FMaterialID.FNumber,F_UNW_BaseProperty_3tm,FMaterialName,FMateriaModel,FUnitID.FName,FQty,FIsFree,FDeliveryDate,FDeliveryLoc.FName,F_UNW_Text_8dq");
  370. List<Map> filterString = new ArrayList<>();
  371. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
  372. billQuery.setFilterString(filterString);
  373. billQuery.setLimit(limit);
  374. billQuery.setStartRow(startRow);
  375. String result=client.billQuery(JSONObject.toJSONString(billQuery));
  376. JSONArray jsonArray = JSONArray.parseArray(result);
  377. // 按 FBillNo 分组
  378. Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
  379. for (int i = 0; i < jsonArray.size(); i++) {
  380. JSONObject item = jsonArray.getJSONObject(i);
  381. String billNo = item.getString("FBillNo");
  382. groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
  383. }
  384. // 组装最终结果
  385. List<Map<String, Object>> orderList = new ArrayList<>();
  386. for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
  387. List<JSONObject> rows = entry.getValue();
  388. JSONObject firstRow = rows.get(0);
  389. // 主表 Map
  390. Map<String, Object> orderMap = new LinkedHashMap<>();
  391. orderMap.put("textField_mnj0cqqp", firstRow.getString("FBillNo"));//单据编号
  392. String fDateRaw = firstRow.getString("FDate");
  393. String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
  394. orderMap.put("textField_mnj0cqqq", formattedDate); // 日期
  395. orderMap.put("textField_mnj0cqqr", firstRow.getString("FSettleCurrId.FName")); // 结算币别
  396. orderMap.put("textField_mnj0cqqw", firstRow.getString("FSaleOrgId.FName")); // 销售组织
  397. orderMap.put("textField_mnj0cqqx", firstRow.getString("FSaleDeptId.FName")); // 销售部门
  398. orderMap.put("textField_mnj0cqqy", firstRow.getString("FSalesManID.FName")); // 销售员
  399. orderMap.put("textField_mnj0cqr3", firstRow.getString("F_UNW_Base_tr7.FName")); // 发货客户
  400. orderMap.put("radioField_mnj0cqr4", firstRow.getString("F_UNW_CheckBox_xjs").equals("true") ? "是" : "否" ); // 是否委外
  401. // 明细数组
  402. List<Map<String, Object>> details = new ArrayList<>();
  403. for (JSONObject row : rows) {
  404. Map<String, Object> detailMap = new LinkedHashMap<>();
  405. detailMap.put("textField_mnj0cqr6", row.getString("FCustMatName"));//客户物料名称
  406. detailMap.put("textField_mnj0cqr7", row.getString("FCustMatID.FNumber"));//客户物料编码
  407. detailMap.put("textField_mnj0cqr8", row.getString("FMaterialID.FNumber"));//物料编码
  408. detailMap.put("textField_mnj0cqr9", row.getString("F_UNW_BaseProperty_3tm"));//客户物料规格型号
  409. detailMap.put("textField_mnj0cqra", row.getString("FMaterialName"));//物料名称
  410. detailMap.put("textField_mnj0cqrb", row.getString("FMateriaModel"));//规格型号
  411. detailMap.put("textField_mnj0cqrc", row.getString("FUnitID.FName"));//销售单位
  412. detailMap.put("numberField_mnj0cqrd", row.getString("FQty"));//销售数量
  413. detailMap.put("radioField_mnj0cqre", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
  414. String rawDeliveryDate = row.getString("FDeliveryDate");
  415. String formattedDeliveryDate = rawDeliveryDate != null ? rawDeliveryDate.replace("T", " ") : null;
  416. detailMap.put("textField_mnj0cqrf", formattedDeliveryDate);//要货日期
  417. detailMap.put("textField_mnj0cqrg", row.getString("FDeliveryLoc.FName"));//交货地点
  418. detailMap.put("textField_mnj0cqrh", row.getString("F_UNW_Text_8dq"));//客户订单号
  419. details.add(detailMap);
  420. }
  421. orderMap.put("tableField_mnj0cqr5", details);
  422. /*写入宜搭*/
  423. List<Map> conditions = Arrays.asList( YDConf.searchCondition_TextFiled("textField_mnj0cqqp", firstRow.getString("FBillNo"), "eq"));
  424. ydClient.operateData(YDParam.builder()
  425. .formUuid("FORM-50CEB72455534364BF9A97C8A49A3A46TBLI")
  426. .searchCondition(JSONObject.toJSONString(conditions))
  427. .formDataJson(JSONObject.toJSONString(orderMap))
  428. .build(), YDConf.FORM_OPERATION.upsert).toString();
  429. orderList.add(orderMap);
  430. }
  431. log.info("发货通知单已同步");
  432. }
  433. @SneakyThrows
  434. @Override
  435. public void returnForm() throws JsonProcessingException {
  436. K3CloudApi client = new K3CloudApi(initIden());
  437. int startRow = 0;
  438. int limit = 2000;
  439. BillQuery billQuery = new BillQuery();
  440. billQuery.setFormId("SAL_RETURNSTOCK");//退货单
  441. //[主表] FBillNo单据编号 FDate日期 FRetcustId退货客户 FSettleCurrId结算币别 FSaleOrgId销售组织 FSaledeptid销售部门 FSalesManId销售员
  442. //[明细表] FMapId客户物料编码 FMapName客户物料名称 FMaterialId物料编码 FMaterialName物料名称 FMaterialModel型号规格 FF100001厚度 FSalUnitID销售单位 FSalUnitQty销售数量 FIsFree是否赠品 FDeliveryDate退货日期 FReturnType退货类型 FPrice单价 FTaxPrice含税单价 FNote备注
  443. billQuery.setFieldKeys("FBillNo,FDate,FRetcustId.FName,FSettleCurrId.FName,FSaleOrgId.FName,FSaledeptid.FName,FSalesManId.FName,FMapId.FNumber,FMapName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FAuxpropId.FF100001,FSalUnitID.FName,FSalUnitQty,FIsFree,FDeliveryDate,FReturnType.FDataValue,FPrice,FTaxPrice,FNote");
  444. List<Map> filterString = new ArrayList<>();
  445. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",30,"","","0"));//审核日期在今天之前N天以后
  446. billQuery.setFilterString(filterString);
  447. billQuery.setLimit(limit);
  448. billQuery.setStartRow(startRow);
  449. String result=client.billQuery(JSONObject.toJSONString(billQuery));
  450. JSONArray jsonArray = JSONArray.parseArray(result);
  451. // 按 FBillNo 分组
  452. Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
  453. for (int i = 0; i < jsonArray.size(); i++) {
  454. JSONObject item = jsonArray.getJSONObject(i);
  455. String billNo = item.getString("FBillNo");
  456. groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
  457. }
  458. // 组装最终结果
  459. List<Map<String, Object>> orderList = new ArrayList<>();
  460. for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
  461. List<JSONObject> rows = entry.getValue();
  462. JSONObject firstRow = rows.get(0);
  463. // 主表 Map
  464. Map<String, Object> orderMap = new LinkedHashMap<>();
  465. orderMap.put("textField_mnmru1xp", firstRow.getString("FBillNo"));//单据编号
  466. String fDateRaw = firstRow.getString("FDate");
  467. String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
  468. orderMap.put("textField_mnmru1xq", formattedDate); // 日期
  469. orderMap.put("textField_mnmru1xr", firstRow.getString("FRetcustId.FName")); // 退货客户
  470. orderMap.put("textField_mnmru1y0", firstRow.getString("FSettleCurrId.FName")); // 结算币别
  471. orderMap.put("textField_mnmru1y1", firstRow.getString("FSaleOrgId.FName")); // 销售组织
  472. orderMap.put("textField_mnmru1y2", firstRow.getString("FSaledeptid.FName")); // 销售部门
  473. orderMap.put("textField_mnmru1y3", firstRow.getString("FSalesManId.FName")); // 销售员
  474. // 明细数组
  475. List<Map<String, Object>> details = new ArrayList<>();
  476. for (JSONObject row : rows) {
  477. Map<String, Object> detailMap = new LinkedHashMap<>();
  478. detailMap.put("textField_mnmru1y9", row.getString("FMapId.FNumber"));//客户物料编码
  479. detailMap.put("textField_mnmru1ya", row.getString("FMapName"));//客户物料名称
  480. detailMap.put("textField_mnmru1yb", row.getString("FMaterialId.FNumber"));//物料编码
  481. detailMap.put("textField_mnmru1yc", row.getString("FMaterialName"));//物料名称
  482. detailMap.put("textField_mnmru1yd", row.getString("FMaterialModel"));//规格型号
  483. detailMap.put("textField_mnmru1ye", row.getString("FAuxpropId.FF100001"));//厚度
  484. detailMap.put("textField_mnmru1yf", row.getString("FSalUnitID.FName"));//销售单位
  485. detailMap.put("numberField_mnmru1yg", row.getString("FSalUnitQty"));//销售数量
  486. detailMap.put("radioField_mnmru1yh", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
  487. String rawDeliveryDate = row.getString("FDeliveryDate");
  488. String formattedDeliveryDate = rawDeliveryDate != null ? rawDeliveryDate.replace("T", " ") : null;
  489. detailMap.put("textField_mnmru1yi", formattedDeliveryDate);//退货日期
  490. detailMap.put("textField_mnmru1yj", row.getString("FReturnType.FDataValue"));//退货类型
  491. detailMap.put("numberField_mnmru1yk", row.getString("FPrice"));//单价
  492. detailMap.put("numberField_mnmru1yl", row.getString("FTaxPrice"));//含税单价
  493. detailMap.put("textField_mnmru1ym", row.getString("FNote"));//备注
  494. details.add(detailMap);
  495. }
  496. orderMap.put("tableField_mnmru1y8", details);
  497. /*写入宜搭*/
  498. List<Map> conditions = Arrays.asList( YDConf.searchCondition_TextFiled("textField_mnmru1xp", firstRow.getString("FBillNo"), "eq"));
  499. ydClient.operateData(YDParam.builder()
  500. .formUuid("FORM-48ADB8AA7FEF4821929BFE8FE5B623E42OKY")
  501. .searchCondition(JSONObject.toJSONString(conditions))
  502. .formDataJson(JSONObject.toJSONString(orderMap))
  503. .build(), YDConf.FORM_OPERATION.upsert).toString();
  504. orderList.add(orderMap);
  505. }
  506. log.info("退货单已同步");
  507. }
  508. @SneakyThrows
  509. @Override
  510. public void replenishmentOrder() throws JsonProcessingException {
  511. K3CloudApi client = new K3CloudApi(initIden());
  512. int startRow = 0;
  513. int limit = 2000;
  514. BillQuery billQuery = new BillQuery();
  515. billQuery.setFormId("SAL_SaleOrder"); // 销售订单
  516. // 字段查询与销售订单一致,包含 FIsFree
  517. billQuery.setFieldKeys("FSaleOrgId.FName,FSaleDeptId.FName,FBillNo,FCustId.FName,F_UNW_Text_ct1,FSettleCurrId.FName,FSalerId.FName,FDate,FRecConditionId.FName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FMapId.FNumber,F_UNW_BaseProperty_uow,FUnitID.FName,FQty,FPriceUnitQty,FPrice,FTaxPrice,FEntryTaxRate,FEntryTaxAmount,FAmount,FAllAmount,FDeliveryDate,FSettleOrgIds.FName,FIsFree");
  518. List<Map> filterString = new ArrayList<>();
  519. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic", "FApproveDate", "265", 1, "", "", "0"));
  520. billQuery.setFilterString(filterString);
  521. billQuery.setLimit(limit);
  522. billQuery.setStartRow(startRow);
  523. String result = client.billQuery(JSONObject.toJSONString(billQuery));
  524. JSONArray jsonArray = JSONArray.parseArray(result);
  525. // 按 FBillNo 分组,并过滤出赠品明细
  526. Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
  527. for (int i = 0; i < jsonArray.size(); i++) {
  528. JSONObject item = jsonArray.getJSONObject(i);
  529. // 判断是否赠品:注意金蝶返回的 FIsFree 可能是布尔值或字符串 "true"/"false"
  530. boolean isFree = false;
  531. Object freeObj = item.get("FIsFree");
  532. if (freeObj instanceof Boolean) {
  533. isFree = (Boolean) freeObj;
  534. } else if (freeObj instanceof String) {
  535. isFree = "true".equalsIgnoreCase((String) freeObj);
  536. }
  537. // 只处理赠品行
  538. if (isFree) {
  539. String billNo = item.getString("FBillNo");
  540. groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
  541. }
  542. }
  543. // 组装最终结果(仅包含有赠品行明细的订单)
  544. List<Map<String, Object>> orderList = new ArrayList<>();
  545. for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
  546. List<JSONObject> rows = entry.getValue();
  547. JSONObject firstRow = rows.get(0); // 取该订单的第一条赠品行(主表字段相同)
  548. // 主表 Map
  549. Map<String, Object> orderMap = new LinkedHashMap<>();
  550. orderMap.put("textField_mniksrqa", firstRow.getString("FBillNo")); // 单据编号
  551. orderMap.put("textField_mniksrq4", firstRow.getString("FSaleOrgId.FName")); // 销售组织
  552. orderMap.put("textField_mniksrq5", firstRow.getString("FSaleDeptId.FName")); // 销售部门
  553. orderMap.put("textField_mniksrqb", firstRow.getString("FCustId.FName")); // 客户
  554. orderMap.put("textField_mniksrqe", firstRow.getString("F_UNW_Text_ct1")); // 客户订单号
  555. orderMap.put("textField_mniksrqf", firstRow.getString("FSettleCurrId.FName")); // 结算币别
  556. orderMap.put("textField_mniksrqk", firstRow.getString("FSalerId.FName")); // 销售员
  557. String fDateRaw = firstRow.getString("FDate");
  558. String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
  559. orderMap.put("textField_mniksrql", formattedDate); // 日期
  560. orderMap.put("textField_mniksrqm", firstRow.getString("FRecConditionId.FName")); // 收款条件
  561. // 明细数组(仅包含赠品行)
  562. List<Map<String, Object>> details = new ArrayList<>();
  563. for (JSONObject row : rows) {
  564. Map<String, Object> detailMap = new LinkedHashMap<>();
  565. detailMap.put("textField_mniksrqo", row.getString("FMaterialId.FNumber")); // 物料编码
  566. detailMap.put("textField_mniksrqp", row.getString("FMaterialName")); // 物料名称
  567. detailMap.put("textField_mniksrqq", row.getString("FMaterialModel")); // 规格型号
  568. detailMap.put("textField_mniksrqr", row.getString("FMapId.FNumber")); // 客户物料编码
  569. detailMap.put("textField_mniksrqs", row.getString("F_UNW_BaseProperty_uow")); // 客户物料规格
  570. detailMap.put("textField_mniksrqt", row.getString("FUnitID.FName")); // 销售单位
  571. detailMap.put("numberField_mniksrqv", row.getString("FQty")); // 销售数量
  572. detailMap.put("numberField_mniksrqw", row.getString("FPriceUnitQty")); // 计价数量
  573. detailMap.put("numberField_mniksrqx", row.getString("FPrice")); // 单价
  574. detailMap.put("numberField_mniksrqy", row.getString("FTaxPrice")); // 含税单价
  575. detailMap.put("numberField_mniksrqz", row.getString("FEntryTaxRate")); // 税率
  576. detailMap.put("numberField_mniksrr0", row.getString("FEntryTaxAmount")); // 税额
  577. detailMap.put("numberField_mniksrr1", row.getString("FAmount")); // 金额
  578. detailMap.put("numberField_mniksrr2", row.getString("FAllAmount")); // 价税合计
  579. String deliveryRaw = row.getString("FDeliveryDate");
  580. String formattedDelivery = (deliveryRaw != null && deliveryRaw.contains("T")) ? deliveryRaw.split("T")[0] : deliveryRaw;
  581. detailMap.put("textField_mniksrr3", formattedDelivery); // 要货日期
  582. detailMap.put("textField_mniksrr4", row.getString("FSettleOrgIds.FName")); // 结算组织
  583. // 赠品标记:这里明细一定是赠品,直接设为"是"
  584. detailMap.put("radioField_mniksrr6", "是");
  585. details.add(detailMap);
  586. }
  587. orderMap.put("tableField_mniksrqn", details);
  588. // 写入宜搭补货单表单
  589. List<Map> conditions = Arrays.asList(
  590. YDConf.searchCondition_TextFiled("textField_mniksrqa", firstRow.getString("FBillNo"), "eq")
  591. );
  592. ydClient.operateData(YDParam.builder()
  593. .formUuid("FORM-837E203B7DCA4B09A9618AA8F584CC45UDFX")
  594. .searchCondition(JSONObject.toJSONString(conditions))
  595. .formDataJson(JSONObject.toJSONString(orderMap))
  596. .build(), YDConf.FORM_OPERATION.upsert).toString();
  597. orderList.add(orderMap);
  598. }
  599. log.info("补货单已同步,共 {} 个订单包含赠品明细", orderList.size());
  600. }
  601. @SneakyThrows
  602. @Override
  603. public void invoice() throws JsonProcessingException {
  604. K3CloudApi client = new K3CloudApi(initIden());
  605. int startRow = 0;
  606. int limit = 2000;
  607. BillQuery billQuery = new BillQuery();
  608. billQuery.setFormId("AR_receivable");//开票单
  609. //[主表] FBillTypeID单据类型 FCUSTOMERID客户 FSALEERID销售员 FSetAccountType立账类型 FBillNo单据编号 FCURRENCYID币别 FSETTLEORGID结算组织 FDATE业务日期 FENDDATE_H到期日 FDocumentStatus单据状态 FPayConditon收款条件 FSALEDEPTID销售部门 F_UNW_Text_u4s发票号
  610. //[明细表] FMATERIALID 物料编码 FCustMatID客户物料编码 FCustMatName客户物料名称 F_UNW_BaseProperty_lad规格型号 FMaterialName物料名称 FPRICEUNITID计价单位 FPriceQty计价数量 FEntryTaxRate税率 FF100001厚度 FBASICUNITQTY计价基本数量 FLot批号 FORDERNUMBER销售订单号 FORDERENTRYSEQ销售订单行号 FSalQty销售数量 FSalUnitId销售单位 FIsFree是否赠品
  611. billQuery.setFieldKeys("FBillTypeID.FName,FCUSTOMERID.FName,FSALEERID.FName,FSetAccountType,FBillNo,FCURRENCYID.FName,FSETTLEORGID.FName,FDATE,FENDDATE_H,FDocumentStatus,FPayConditon.FName,FSALEDEPTID.FName,F_UNW_Text_u4s,FMATERIALID.FNumber,FCustMatID.FNumber,FCustMatName,F_UNW_BaseProperty_lad,FMaterialName,FPRICEUNITID.FName,FPriceQty,FEntryTaxRate,FAuxpropId.FF100001,FBASICUNITQTY,FLot.FNumber,FORDERNUMBER,FORDERENTRYSEQ,FSalQty,FSalUnitId.FName,FIsFree");
  612. List<Map> filterString = new ArrayList<>();
  613. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
  614. billQuery.setFilterString(filterString);
  615. billQuery.setLimit(limit);
  616. billQuery.setStartRow(startRow);
  617. String result=client.billQuery(JSONObject.toJSONString(billQuery));
  618. JSONArray jsonArray = JSONArray.parseArray(result);
  619. // 按 FBillNo 分组
  620. Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
  621. for (int i = 0; i < jsonArray.size(); i++) {
  622. JSONObject item = jsonArray.getJSONObject(i);
  623. String billNo = item.getString("FBillNo");
  624. groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
  625. }
  626. // 组装最终结果
  627. List<Map<String, Object>> orderList = new ArrayList<>();
  628. for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
  629. List<JSONObject> rows = entry.getValue();
  630. JSONObject firstRow = rows.get(0);
  631. // ========== 新增:检查发票号,无发票号则跳过 ==========
  632. String invoiceNo = firstRow.getString("F_UNW_Text_u4s");
  633. if (invoiceNo == null || invoiceNo.trim().isEmpty()) {
  634. log.info("单据编号 {} 无发票号,跳过同步", firstRow.getString("FBillNo"));
  635. continue;
  636. }
  637. // =================================================
  638. // 主表 Map
  639. Map<String, Object> orderMap = new LinkedHashMap<>();
  640. orderMap.put("textField_mno1zcb2", firstRow.getString("FBillTypeID.FName"));//单据类型
  641. orderMap.put("textField_mno1zcb3", firstRow.getString("FCUSTOMERID.FName")); // 客户
  642. orderMap.put("textField_mno1zcb4", firstRow.getString("FSALEERID.FName")); // 销售员
  643. String FSetAccountType = "";
  644. switch (firstRow.getString("FSetAccountType")){
  645. case "1":
  646. FSetAccountType = "业务应收";break;
  647. case "2":
  648. FSetAccountType = "暂估应收";break;
  649. case "3":
  650. FSetAccountType = "财务应收";break;
  651. }
  652. orderMap.put("textField_mno1zcb5", FSetAccountType); // 立账类型
  653. orderMap.put("textField_mno1zcbb", firstRow.getString("FBillNo")); // 单据编号
  654. orderMap.put("textField_mno1zcbc", firstRow.getString("FCURRENCYID.FName")); // 币别
  655. orderMap.put("textField_mno1zcbd", firstRow.getString("FSETTLEORGID.FName")); // 结算组织
  656. String fDateRaw = firstRow.getString("FDATE");
  657. String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
  658. orderMap.put("textField_mno1zcbe", formattedDate); // 业务日期
  659. String fDateRaw_A = firstRow.getString("FENDDATE_H");
  660. String formattedDate_A = (fDateRaw_A != null && fDateRaw_A.contains("T")) ? fDateRaw_A.split("T")[0] : fDateRaw_A;
  661. orderMap.put("textField_mno1zcbk", formattedDate_A); // 到期日
  662. orderMap.put("textField_mno1zcbl", firstRow.getString("FPayConditon.FName")); // 收款条件
  663. String FDocumentStatus = "";
  664. switch (firstRow.getString("FDocumentStatus")){
  665. case "A":
  666. FDocumentStatus = "创建";break;
  667. case "B":
  668. FDocumentStatus = "审核中";break;
  669. case "C":
  670. FDocumentStatus = "已审核";break;
  671. case "D":
  672. FDocumentStatus = "重新审核";break;
  673. case "Z":
  674. FDocumentStatus = "暂存";break;
  675. }
  676. orderMap.put("textField_mno1zcbm", FDocumentStatus); // 单据状态
  677. orderMap.put("textField_mno1zcbn", firstRow.getString("FSALEDEPTID.FName")); // 销售部门
  678. orderMap.put("textField_mno1zcbt", invoiceNo); // 发票号(已确保非空)
  679. // 明细数组
  680. List<Map<String, Object>> details = new ArrayList<>();
  681. for (JSONObject row : rows) {
  682. Map<String, Object> detailMap = new LinkedHashMap<>();
  683. detailMap.put("textField_mno1zcbv", row.getString("FMATERIALID.FNumber"));//物料编码
  684. detailMap.put("textField_mno1zcbw", row.getString("FCustMatID.FNumber"));//客户物料编码
  685. detailMap.put("textField_mno1zcbx", row.getString("FCustMatName"));//客户物料名称
  686. detailMap.put("textField_mno1zcby", row.getString("F_UNW_BaseProperty_lad"));//规格型号
  687. detailMap.put("textField_mno1zcbz", row.getString("FMaterialName"));//物料名称
  688. detailMap.put("textField_mno1zcc0", row.getString("FPRICEUNITID.FName"));//计价单位
  689. detailMap.put("numberField_mno1zcc2", row.getString("FPriceQty"));//计价数量
  690. detailMap.put("numberField_mno1zcc3", row.getString("FEntryTaxRate"));//税率(%)
  691. detailMap.put("textField_mno1zcc5", row.getString("FAuxpropId.FF100001"));//厚度
  692. detailMap.put("numberField_mno1zcc6", row.getString("FBASICUNITQTY"));//计价基本数量
  693. detailMap.put("textField_mno1zcc7", row.getString("FLot.FNumber"));//批号
  694. detailMap.put("textField_mno1zcc8", row.getString("FORDERNUMBER"));//销售订单号
  695. detailMap.put("textField_mno1zcc9", row.getString("FORDERENTRYSEQ"));//销售订单行号
  696. detailMap.put("numberField_mno1zcca", row.getString("FSalQty"));//销售数量
  697. detailMap.put("textField_mno1zccb", row.getString("FSalUnitId.FName"));//销售单位
  698. detailMap.put("radioField_mno1zccc", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
  699. details.add(detailMap);
  700. }
  701. orderMap.put("tableField_mno1zcbu", details);
  702. /*写入宜搭*/
  703. List<Map> conditions = Arrays.asList(YDConf.searchCondition_TextFiled("textField_mno1zcbb", firstRow.getString("FBillNo"), "eq"));
  704. ydClient.operateData(YDParam.builder()
  705. .formUuid("FORM-CEF87B7F64004AE1A1D9A2A3A8EC4986O1VK")
  706. .searchCondition(JSONObject.toJSONString(conditions))
  707. .formDataJson(JSONObject.toJSONString(orderMap))
  708. .build(), YDConf.FORM_OPERATION.upsert).toString();
  709. orderList.add(orderMap);
  710. }
  711. log.info("开票单已同步");
  712. }
  713. @SneakyThrows
  714. @Override
  715. public void receivableNote() throws JsonProcessingException {
  716. K3CloudApi client = new K3CloudApi(initIden());
  717. int startRow = 0;
  718. int limit = 2000;
  719. BillQuery billQuery = new BillQuery();
  720. billQuery.setFormId("AR_receivable"); // 应收单
  721. billQuery.setFieldKeys("FBillTypeID.FName,FCUSTOMERID.FName,FSALEERID.FName,FSetAccountType,FBillNo,FCURRENCYID.FName,FSETTLEORGID.FName,FDATE,FENDDATE_H,FDocumentStatus,FPayConditon.FName,FSALEDEPTID.FName,F_UNW_Text_u4s,FMATERIALID.FNumber,FCustMatID.FNumber,FCustMatName,F_UNW_BaseProperty_lad,FMaterialName,FPRICEUNITID.FName,FPriceQty,FEntryTaxRate,FAuxpropId.FF100001,FBASICUNITQTY,FLot.FNumber,FORDERNUMBER,FORDERENTRYSEQ,FSalQty,FSalUnitId.FName,FIsFree");
  722. List<Map> filterString = new ArrayList<>();
  723. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0")); // 审核日期条件
  724. billQuery.setFilterString(filterString);
  725. billQuery.setLimit(limit);
  726. billQuery.setStartRow(startRow);
  727. String result = client.billQuery(JSONObject.toJSONString(billQuery));
  728. JSONArray jsonArray = JSONArray.parseArray(result);
  729. // 按 FBillNo 分组
  730. Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
  731. for (int i = 0; i < jsonArray.size(); i++) {
  732. JSONObject item = jsonArray.getJSONObject(i);
  733. String billNo = item.getString("FBillNo");
  734. groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
  735. }
  736. // 组装并同步到宜搭(应收单表单)
  737. List<Map<String, Object>> orderList = new ArrayList<>();
  738. for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
  739. List<JSONObject> rows = entry.getValue();
  740. JSONObject firstRow = rows.get(0);
  741. // 二次确认:发票号必须为空(有发票号的跳过)
  742. String invoiceNo = firstRow.getString("F_UNW_Text_u4s");
  743. if (invoiceNo != null && !invoiceNo.trim().isEmpty()) {
  744. log.info("单据编号 {} 含有发票号,不符合应收单同步条件(需要无发票号),跳过", firstRow.getString("FBillNo"));
  745. continue;
  746. }
  747. // 组装主表数据
  748. Map<String, Object> orderMap = new LinkedHashMap<>();
  749. orderMap.put("textField_mno1zcb2", firstRow.getString("FBillTypeID.FName")); // 单据类型
  750. orderMap.put("textField_mno1zcb3", firstRow.getString("FCUSTOMERID.FName")); // 客户
  751. orderMap.put("textField_mno1zcb4", firstRow.getString("FSALEERID.FName")); // 销售员
  752. // 立账类型转换
  753. String FSetAccountType = "";
  754. switch (firstRow.getString("FSetAccountType")){
  755. case "1": FSetAccountType = "业务应收"; break;
  756. case "2": FSetAccountType = "暂估应收"; break;
  757. case "3": FSetAccountType = "财务应收"; break;
  758. }
  759. orderMap.put("textField_mno1zcb5", FSetAccountType);//立账类型
  760. orderMap.put("textField_mno1zcbb", firstRow.getString("FBillNo")); // 单据编号
  761. orderMap.put("textField_mno1zcbc", firstRow.getString("FCURRENCYID.FName")); // 币别
  762. orderMap.put("textField_mno1zcbd", firstRow.getString("FSETTLEORGID.FName")); // 结算组织
  763. String fDateRaw = firstRow.getString("FDATE");
  764. String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
  765. orderMap.put("textField_mno1zcbe", formattedDate); // 业务日期
  766. String fDateRaw_A = firstRow.getString("FENDDATE_H");
  767. String formattedDate_A = (fDateRaw_A != null && fDateRaw_A.contains("T")) ? fDateRaw_A.split("T")[0] : fDateRaw_A;
  768. orderMap.put("textField_mno1zcbk", formattedDate_A); // 到期日
  769. orderMap.put("textField_mno1zcbl", firstRow.getString("FPayConditon.FName"));// 收款条件
  770. // 单据状态转换
  771. String FDocumentStatus = "";
  772. switch (firstRow.getString("FDocumentStatus")){
  773. case "A": FDocumentStatus = "创建"; break;
  774. case "B": FDocumentStatus = "审核中"; break;
  775. case "C": FDocumentStatus = "已审核"; break;
  776. case "D": FDocumentStatus = "重新审核"; break;
  777. case "Z": FDocumentStatus = "暂存"; break;
  778. }
  779. orderMap.put("textField_mno1zcbm", FDocumentStatus);//单据状态
  780. orderMap.put("textField_mno1zcbn", firstRow.getString("FSALEDEPTID.FName")); // 销售部门
  781. orderMap.put("textField_mno1zcbt", ""); // 留空
  782. // 明细数组(字段映射请对应应收单明细表)
  783. List<Map<String, Object>> details = new ArrayList<>();
  784. for (JSONObject row : rows) {
  785. Map<String, Object> detailMap = new LinkedHashMap<>();
  786. detailMap.put("textField_mno1zcbv", row.getString("FMATERIALID.FNumber"));//物料编码
  787. detailMap.put("textField_mno1zcbw", row.getString("FCustMatID.FNumber"));//客户物料编码
  788. detailMap.put("textField_mno1zcbx", row.getString("FCustMatName"));//客户物料名称
  789. detailMap.put("textField_mno1zcby", row.getString("F_UNW_BaseProperty_lad"));//规格型号
  790. detailMap.put("textField_mno1zcbz", row.getString("FMaterialName"));//物料名称
  791. detailMap.put("textField_mno1zcc0", row.getString("FPRICEUNITID.FName"));//计价单位
  792. detailMap.put("numberField_mno1zcc2", row.getString("FPriceQty"));//计价数量
  793. detailMap.put("numberField_mno1zcc3", row.getString("FEntryTaxRate"));//税率(%)
  794. detailMap.put("textField_mno1zcc5", row.getString("FAuxpropId.FF100001"));//厚度
  795. detailMap.put("numberField_mno1zcc6", row.getString("FBASICUNITQTY"));//计价基本数量
  796. detailMap.put("textField_mno1zcc7", row.getString("FLot.FNumber"));//批号
  797. detailMap.put("textField_mno1zcc8", row.getString("FORDERNUMBER"));//销售订单号
  798. detailMap.put("textField_mno1zcc9", row.getString("FORDERENTRYSEQ"));//销售订单行号
  799. detailMap.put("numberField_mno1zcca", row.getString("FSalQty"));//销售数量
  800. detailMap.put("textField_mno1zccb", row.getString("FSalUnitId.FName"));//销售单位
  801. detailMap.put("radioField_mno1zccc", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
  802. details.add(detailMap);
  803. }
  804. orderMap.put("tableField_mno1zcbu", details);
  805. // 写入宜搭
  806. List<Map> conditions = Arrays.asList(
  807. YDConf.searchCondition_TextFiled("textField_mno1zcbb", firstRow.getString("FBillNo"), "eq")
  808. );
  809. ydClient.operateData(YDParam.builder()
  810. .formUuid("FORM-5A0062877EC246959CE85BC7418D1204229L")
  811. .searchCondition(JSONObject.toJSONString(conditions))
  812. .formDataJson(JSONObject.toJSONString(orderMap))
  813. .build(), YDConf.FORM_OPERATION.upsert).toString();
  814. orderList.add(orderMap);
  815. }
  816. log.info("应收单(无发票号)已同步,共处理 {} 张单据", orderList.size());
  817. }
  818. @SneakyThrows
  819. @Override
  820. public void customer() throws JsonProcessingException {
  821. K3CloudApi client = new K3CloudApi(initIden());
  822. int startRow = 0;
  823. int limit = 2000;
  824. BillQuery billQuery = new BillQuery();
  825. billQuery.setFormId("BD_Customer");//客户
  826. //客户编码 客户名称 业务员 销售员 销售部门 收款条件 行业 事业部 终端 纳税人登记号
  827. billQuery.setFieldKeys("FNumber,FName,F_UNW_Text_6mb,FSELLER.FName,FSALDEPTID.FName,FRECCONDITIONID.FName,F_UNW_Assistant_mo2.FDataValue,F_UNW_Assistant_9zp.FNumber,F_UNW_Assistant_qov.FNumber,FTAXREGISTERCODE");
  828. List<Map> filterString = new ArrayList<>();
  829. // filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",3,"","","0"));//审核日期在今天之前N天以后
  830. filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FCreateOrgId.FNumber","67","100","","","0"));//创建组织为100 宁波致微新材料科技有限公司
  831. billQuery.setFilterString(filterString);
  832. billQuery.setLimit(limit);
  833. billQuery.setStartRow(startRow);
  834. String result=client.billQuery(JSONObject.toJSONString(billQuery));
  835. JSONArray jsonArray = JSONArray.parseArray(result);
  836. // 遍历每条物料记录
  837. for (int i = 0; i < jsonArray.size(); i++) {
  838. JSONObject item = jsonArray.getJSONObject(i);
  839. // 取出各个字段(注意类型转换)
  840. String bm = item.getString("FNumber");//客户编码
  841. String khmc = item.getString("FName");//客户名称
  842. String ywy = item.getString("F_UNW_Text_6mb");//业务员
  843. Map body = new HashMap();
  844. body.put("queryWord",ywy);
  845. body.put("offset",0);
  846. body.put("size",10);
  847. body.put("fullMatchField",1);
  848. String doPost = UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/users/search", ddClient.initTokenHeader(), null, body);
  849. JSONObject resp = JSON.parseObject(doPost);
  850. JSONArray ywy_array = resp != null ? resp.getJSONArray("list") : null;
  851. String xsbm = item.getString("FSALDEPTID.FName");//销售部门
  852. Map body_A = new HashMap();
  853. body_A.put("queryWord",xsbm);
  854. body_A.put("offset",0);
  855. body_A.put("size",10);
  856. // 获取部门搜索结果
  857. String doPost_A = UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/departments/search", ddClient.initTokenHeader(), null, body_A);
  858. JSONObject respA = JSON.parseObject(doPost_A);
  859. JSONArray aaary = respA != null ? respA.getJSONArray("list") : null;
  860. List<String> xsbm_array = new ArrayList<>();
  861. if (aaary != null && !aaary.isEmpty()) {
  862. xsbm_array = aaary.stream()
  863. .map(Object::toString)
  864. .collect(Collectors.toList());
  865. }
  866. // 如果未查到部门,xsbm_array 保持为空列表
  867. String sktj = item.getString("FRECCONDITIONID.FName");//收款条件
  868. String hy = item.getString("F_UNW_Assistant_mo2.FDataValue");//行业
  869. String syb = item.getString("F_UNW_Assistant_9zp.FNumber");//事业部
  870. String zd = item.getString("F_UNW_Assistant_qov.FNumber");//终端
  871. String sh = item.getString("FTAXREGISTERCODE");//纳税登记号
  872. //TODO:向宜搭插入数据
  873. // String sc = "textField_mnr290ot, employeeField_lqanqe6n_id, employeeField_lqanqe6n_id, departmentSelectField_lympbaya, selectField_mnft99uc, selectField_lqanqe6t, selectField_mnft99ud, selectField_mnft99ue,textField_mn2k7pjl,textField_llujklkq";
  874. String sc = "textField_mnr290ot, textField_lqanqe6j, employeeField_lqanqe6n, departmentSelectField_lympbaya, selectField_lqanqe6t, selectField_mnft99uc, selectField_mnft99ud, selectField_mnft99ue, textField_mn2k7pjl, textField_llujklkq";
  875. List<Map> conditions = Arrays.asList( YDConf.searchCondition_TextFiled("textField_lqanqe6j", khmc, "eq"));//根据客户名称
  876. Map formData = UtilMap.map(sc,bm,khmc,ywy_array,xsbm_array,hy,sktj,syb,zd,sh,sh);
  877. ydClient.operateData(YDParam.builder()
  878. .formUuid("FORM-A4C9F5F35B48419A9C607D3408ECAB02A7FL")
  879. .searchCondition(JSONObject.toJSONString(conditions))
  880. .formDataJson(JSONObject.toJSONString(formData))
  881. .build(),YDConf.FORM_OPERATION.upsert);
  882. }
  883. log.info("客户已同步");
  884. }
  885. private McR saveToAudit(String formid, Object object) throws Exception {
  886. JSONObject resultObj = new JSONObject();
  887. K3CloudApi client = new K3CloudApi(initIden());
  888. String result=client.save(formid,JSONObject.toJSONString(UtilMap.map("Model",object)));
  889. resultObj.put("save",result);
  890. Gson gson = new Gson();
  891. RepoRet sRet = gson.fromJson(result, RepoRet.class);
  892. if (sRet.isSuccessfully()) {
  893. JsonObject jsonData = new JsonObject();
  894. jsonData.addProperty("Ids", sRet.getResult().getId());
  895. String result2=client.submit(formid, jsonData.toString());
  896. resultObj.put("save",result2);
  897. RepoRet sRet2 = gson.fromJson(result, RepoRet.class);
  898. if (sRet2.isSuccessfully()) {
  899. JsonObject jsonData3 = new JsonObject();
  900. jsonData3.addProperty("Ids", sRet2.getResult().getId());
  901. String result3 = client.audit(formid, jsonData3.toString());
  902. RepoRet repoRet3 = gson.fromJson(result3, RepoRet.class);
  903. if (repoRet3.getResult().getResponseStatus().isIsSuccess()) {
  904. log.info("审批通过,新增完成");
  905. return McR.success(resultObj);
  906. }
  907. }
  908. }
  909. return McR.error("203",JSONObject.toJSONString(resultObj));
  910. }
  911. private IdentifyInfo initIden(){
  912. //注意 1:此处不再使用参数形式传入用户名及密码等敏感信息,改为在登录配置文件中设置。
  913. //注意 2:必须先配置第三方系统登录授权信息后,再进行业务操作,详情参考各语言版本SDK介绍中的登录配置文件说明。
  914. //读取配置,初始化SDK
  915. IdentifyInfo iden = new IdentifyInfo();
  916. iden.setUserName(kdWebApiConf.getXKDApiUserName());
  917. iden.setAppId(kdWebApiConf.getXKDApiAppID());
  918. iden.setdCID(kdWebApiConf.getXKDApiAcctID());
  919. iden.setAppSecret(kdWebApiConf.getXKDApiAppSec());
  920. iden.setServerUrl(kdWebApiConf.getXKDApiServerUrl());
  921. return iden;
  922. }
  923. /*TODO:钉钉获取应用token*/
  924. public McR Accesstoken() throws JsonProcessingException{
  925. HashMap body = new HashMap();
  926. body.put("appKey","dinga81qkwb0sqxqnviw");
  927. body.put("appSecret","IvePeLbMMxAzIr228RaGcOxgSSOuJ0trbenX3BbahjeLFA2YeaFv0W9F_6Ar5G0P");
  928. String doGet = UtilHttp.doPost("https://oapi.dingtalk.com/v1.0/oauth2/accessToken", null, null,body);
  929. JSONObject jsonObject = JSONObject.parseObject(doGet);
  930. String accessToken = jsonObject.getString("access_token");
  931. log.info("accessToken:{}",accessToken);
  932. return McR.success(accessToken);
  933. }
  934. }