ElectAccVoucherServiceEx.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by FernFlower decompiler)
  4. //
  5. package kd.imc.rim.common.service;
  6. import com.alibaba.fastjson.JSON;
  7. import com.alibaba.fastjson.JSONArray;
  8. import com.alibaba.fastjson.JSONObject;
  9. import java.io.ByteArrayInputStream;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.nio.charset.StandardCharsets;
  13. import java.util.Date;
  14. import java.util.Iterator;
  15. import java.util.Map;
  16. import java.util.Objects;
  17. import java.util.concurrent.Future;
  18. import kd.bos.context.RequestContext;
  19. import kd.bos.dataentity.entity.DynamicObject;
  20. import kd.bos.dataentity.resource.ResManager;
  21. import kd.bos.dataentity.utils.ObjectUtils;
  22. import kd.bos.db.tx.TX;
  23. import kd.bos.db.tx.TXHandle;
  24. import kd.bos.dlock.DLock;
  25. import kd.bos.fileservice.FileServiceFactory;
  26. import kd.bos.logging.Log;
  27. import kd.bos.logging.LogFactory;
  28. import kd.bos.orm.query.QFilter;
  29. import kd.bos.servicehelper.BusinessDataServiceHelper;
  30. import kd.bos.servicehelper.QueryServiceHelper;
  31. import kd.bos.servicehelper.operation.SaveServiceHelper;
  32. import kd.bos.threads.ThreadPool;
  33. import kd.bos.threads.ThreadPools;
  34. import kd.bos.util.StringUtils;
  35. import kd.imc.rim.common.constant.InputInvoiceTypeEnum;
  36. import kd.imc.rim.common.constant.ResultContant;
  37. import kd.imc.rim.common.constant.XbrlTypeConstant;
  38. import kd.imc.rim.common.helper.ElectAccVoucherHelper;
  39. import kd.imc.rim.common.helper.RecognitionCheckHelper;
  40. import kd.imc.rim.common.invoice.collector.InvoiceCollectService;
  41. import kd.imc.rim.common.invoice.recognition.listener.IRecognitionListener;
  42. import kd.imc.rim.common.invoice.recognition.listener.RecognitionListenerResult;
  43. import kd.imc.rim.common.invoice.recognitionnew.task.FileUploadAndSignTask;
  44. import kd.imc.rim.common.invoice.save.InvoiceSaveService;
  45. import kd.imc.rim.common.message.exception.MsgException;
  46. import kd.imc.rim.common.utils.*;
  47. import kd.imc.rim.common.utils.extract.ZipExtractUtil;
  48. import kd.imc.rim.file.utils.FileConvertUtils;
  49. import kd.imc.rim.common.utils.FileUtilsEx;
  50. public class ElectAccVoucherServiceEx {
  51. private static Log logger = LogFactory.getLog(ElectAccVoucherService.class);
  52. private static final String awsRecognitionImpl = "kd.imc.rim.common.invoice.recognitionnew.impl.AwsRecognitionService";
  53. private static ThreadPool xbrlUploadThreadPool = ThreadPools.newFixedThreadPool("xbrlUploadThreadPool", 10);
  54. private ElectAccVoucherHelper electAccVoucherHelper = new ElectAccVoucherHelper();
  55. public ElectAccVoucherServiceEx() {
  56. }
  57. public JSONObject dealVoucher(String fileUrl, String fileName, Object orgId, JSONObject businessParam, IRecognitionListener recognitionListener) throws IOException {
  58. JSONObject result = new JSONObject();
  59. boolean isVoucherOrg = checkOrg(orgId);
  60. if (!isVoucherOrg) {
  61. result.put("errcode", "0004");
  62. result.put("description", ResManager.loadKDString("非电子会计凭证试点企业", "ElectAccVoucherService_0", "imc-rim-common", new Object[0]));
  63. return result;
  64. } else if (!StringUtils.isEmpty(fileUrl) && !StringUtils.isEmpty(fileName)) {
  65. logger.info("电子会计凭证解析开始:{}", fileName);
  66. return this.extracted(fileUrl, fileName, orgId, businessParam, recognitionListener);
  67. } else {
  68. return result;
  69. }
  70. }
  71. private JSONObject extracted(String fileUrl, String fileName, Object orgId, JSONObject businessParam, IRecognitionListener recognitionListener) throws IOException {
  72. JSONObject result = new JSONObject();
  73. Map<String, String> configMap = ImcConfigUtil.getValue("rim_recog_check");
  74. String recognitionImplStr = (String)configMap.get("rimpl");
  75. boolean isAwsRecognition = StringUtils.isEmpty(recognitionImplStr) || "kd.imc.rim.common.invoice.recognitionnew.impl.AwsRecognitionService".equals(recognitionImplStr);
  76. RecognitionCheckHelper recognitionCheckHelper = new RecognitionCheckHelper();
  77. FormFileEntity fileEntity = recognitionCheckHelper.getFormFileEntity(fileUrl, fileName);
  78. try {
  79. InputStream fileInputStream = FileServiceFactory.getAttachmentFileService().getInputStream(fileEntity.getFileUrl());
  80. Throwable var13 = null;
  81. try {
  82. byte[] fileByte = FileUtilsEx.getByte(fileInputStream);
  83. String fileType = FileUtilsEx.getFileType(fileName);
  84. Future<JSONObject> xbrlUploadSubmit = null;
  85. if (!"zip".equalsIgnoreCase(fileType)) {
  86. xbrlUploadSubmit = xbrlUploadThreadPool.submit(new FileUploadAndSignTask(fileEntity.getFileUrl(), fileByte, fileEntity.getFileName(), fileEntity.getFileType(), fileEntity.getFileHash(), fileEntity.getSignatureFlag(), RequestContext.get()));
  87. }
  88. JSONObject checkZipFileResult = this.checkZipFile(fileByte, fileType);
  89. if (Objects.nonNull(checkZipFileResult)) {
  90. JSONObject var66 = checkZipFileResult;
  91. return var66;
  92. } else {
  93. long startTime = System.currentTimeMillis();
  94. JSONObject var67;
  95. if (isAwsRecognition) {
  96. result = this.electAccVoucherHelper.getByAwsAPI(orgId, fileByte, fileName);
  97. } else {
  98. result = this.electAccVoucherHelper.getByAnalysis(fileType, fileByte);
  99. boolean signPassFlag = result.getBoolean("signPassFlag");
  100. if (!signPassFlag) {
  101. result.put("errcode", "0004");
  102. result.put("description", ResManager.loadKDString("电子会计凭证验签不通过", "ElectAccVoucherService_1", "imc-rim-common", new Object[0]));
  103. var67 = result;
  104. return var67;
  105. }
  106. }
  107. if (!"0000".equals(result.getString("errcode"))) {
  108. var67 = result;
  109. return var67;
  110. } else {
  111. String xbrlInfo = result.getString("xbrlInfo");
  112. JSONObject resultInvoice = this.electAccVoucherHelper.toInvoiceJson(xbrlInfo, orgId);
  113. if (resultInvoice == null) {
  114. result.put("errcode", "0005");
  115. result.put("description", ResManager.loadKDString("电子会计凭证转换失败", "ElectAccVoucherService_2", "imc-rim-common", new Object[0]));
  116. JSONObject var68 = result;
  117. return var68;
  118. } else {
  119. String voucherFileUrl = getVoucherFileUrl(fileType, fileByte, xbrlInfo);
  120. if (resultInvoice.containsKey("isUploadOriginal") && !resultInvoice.getBoolean("isUploadOriginal") && xbrlUploadSubmit != null) {
  121. uploadGet(xbrlUploadSubmit, resultInvoice);
  122. }
  123. if (resultInvoice.containsKey("isUploadOriginal") && resultInvoice.getBoolean("isUploadOriginal")) {
  124. resultInvoice.put("originalState", "1");
  125. } else if (!"zip".equalsIgnoreCase(fileType)) {
  126. resultInvoice.put("originalState", "1");
  127. resultInvoice.put("originalTime", new Date());
  128. } else {
  129. resultInvoice.put("originalState", "0");
  130. }
  131. String serialNo = resultInvoice.getString("serialNo");
  132. if (StringUtils.isEmpty(serialNo)) {
  133. serialNo = UUID.randomUUID();
  134. resultInvoice.put("serialNo", serialNo);
  135. }
  136. if ("zip".equalsIgnoreCase(fileType)) {
  137. resultInvoice.put("isZipFile", Boolean.TRUE);
  138. }
  139. resultInvoice.put("fileType", FileUtilsEx.convertFileTypeNum(fileType));
  140. resultInvoice.put("fileName", fileName);
  141. TXHandle h = TX.required();
  142. Throwable var26 = null;
  143. try {
  144. String errorMsg;
  145. try {
  146. String xbrlType = resultInvoice.getString("xbrlType");
  147. errorMsg = resultInvoice.getString("invoiceDate");
  148. Long invoiceType = resultInvoice.getLong("invoiceType");
  149. String xbrlName = this.getTargetName(serialNo, xbrlType, invoiceType, errorMsg);
  150. if (xbrlName == null) {
  151. xbrlName = fileName;
  152. }
  153. saveVoucher(serialNo, xbrlName, voucherFileUrl, xbrlType);
  154. resultInvoice = this.saveInvoice(businessParam, resultInvoice, fileUrl, fileByte);
  155. } catch (Throwable var60) {
  156. logger.info("保存电子会计凭证出错:{}", var60);
  157. h.markRollback();
  158. errorMsg = ResManager.loadKDString("电子会计凭证保存异常或者发票数据保存异常,请联系管理员", "ElectAccVoucherService_9", "imc-rim-common", new Object[0]);
  159. if (var60 instanceof MsgException) {
  160. errorMsg = ((MsgException)var60).getErrorMsg();
  161. }
  162. resultInvoice.put("errorMsg", errorMsg);
  163. if (businessParam != null && "1".equals(businessParam.getString("throwSaveError"))) {
  164. throw var60;
  165. }
  166. }
  167. } catch (Throwable var61) {
  168. var26 = var61;
  169. throw var61;
  170. } finally {
  171. if (h != null) {
  172. if (var26 != null) {
  173. try {
  174. h.close();
  175. } catch (Throwable var59) {
  176. var26.addSuppressed(var59);
  177. }
  178. } else {
  179. h.close();
  180. }
  181. }
  182. }
  183. if (resultInvoice.get("mainId") != null) {
  184. DynamicObject invoiceObject = BusinessDataServiceHelper.loadSingle(resultInvoice.get("mainId"), "rim_invoice");
  185. String invoiceType = resultInvoice.getString("invoiceType");
  186. InvoiceSaveService service = InvoiceSaveService.newInstance(invoiceType);
  187. if (service != null) {
  188. service.setMainInvoiceInfo(invoiceObject);
  189. SaveServiceHelper.save(new DynamicObject[]{invoiceObject});
  190. }
  191. }
  192. RecognitionCheckService.setInvoiceSeq(resultInvoice, businessParam, 0, 0);
  193. result.put("errcode", "0000");
  194. result.put("description", ResManager.loadKDString("操作成功", "ElectAccVoucherService_8", "imc-rim-common", new Object[0]));
  195. JSONArray resultArray = new JSONArray();
  196. resultInvoice.put("fileType", FileUtilsEx.convertFileTypeNum(FileUtils.getFileType(fileName)));
  197. resultArray.add(resultInvoice);
  198. result.put("data", resultArray);
  199. RecognitionListenerResult listener = new RecognitionListenerResult(fileUrl, fileName, 1, 1, resultArray);
  200. if (recognitionListener != null) {
  201. recognitionListener.handle(listener);
  202. }
  203. logger.info("电子会计凭证总耗时:{}", System.currentTimeMillis() - startTime);
  204. return result;
  205. }
  206. }
  207. }
  208. } catch (Throwable var63) {
  209. var13 = var63;
  210. throw var63;
  211. } finally {
  212. if (fileInputStream != null) {
  213. if (var13 != null) {
  214. try {
  215. fileInputStream.close();
  216. } catch (Throwable var58) {
  217. var13.addSuppressed(var58);
  218. }
  219. } else {
  220. fileInputStream.close();
  221. }
  222. }
  223. }
  224. } catch (Throwable var65) {
  225. logger.info("解析电子会计凭证出错:{}", var65);
  226. result.put("errcode", "0002");
  227. result.put("description", ResManager.loadKDString("解析电子会计凭证出错", "ElectAccVoucherService_4", "imc-rim-common", new Object[0]));
  228. return result;
  229. }
  230. }
  231. private String getTargetName(String serialNo, String xbrlType, Long invoiceType, String invoiceDate) {
  232. String prefix = "";
  233. if (StringUtils.isNotEmpty(invoiceDate)) {
  234. invoiceDate = invoiceDate.replaceAll("-", "");
  235. }
  236. if (XbrlTypeConstant.AIR_ELE.getCode().equals(xbrlType)) {
  237. prefix = "atr_issuer_";
  238. } else if (XbrlTypeConstant.BANK_RECEIPT.getCode().equals(xbrlType)) {
  239. prefix = "bker_issuer_";
  240. } else if (XbrlTypeConstant.BANK_STATEMENT.getCode().equals(xbrlType)) {
  241. prefix = "bkrs_issuer_";
  242. } else if (XbrlTypeConstant.FINANCIAL.getCode().equals(xbrlType)) {
  243. prefix = "efi_issuer_";
  244. } else if (XbrlTypeConstant.TRAIN_ELE.getCode().equals(xbrlType)) {
  245. prefix = "rai_issuer_";
  246. } else if (XbrlTypeConstant.COVERINGWARRANT.getCode().equals(xbrlType)) {
  247. prefix = "ntrev_gpm_issuer_";
  248. } else if (XbrlTypeConstant.E_VAT.getCode().equals(xbrlType)) {
  249. if (InputInvoiceTypeEnum.ORDINARY_ELECTRON.getCode().equals(invoiceType)) {
  250. prefix = "inv_ord_issuer_";
  251. } else {
  252. prefix = "inv_spcl_issuer_";
  253. }
  254. }
  255. return StringUtils.isEmpty(prefix) ? null : prefix + invoiceDate + '_' + serialNo + ".xml";
  256. }
  257. private JSONObject checkZipFile(byte[] fileByte, String fileType) {
  258. if ("zip".equalsIgnoreCase(fileType)) {
  259. int fileLimit = 2;
  260. Map<String, String> zipFileMap = ZipExtractUtil.extractFileForXml(fileByte);
  261. if (zipFileMap.isEmpty()) {
  262. return ResultContant.createJSONObject("0002", ResManager.loadKDString("解析zip压缩包为空", "ElectAccVoucherService_5", "imc-rim-common", new Object[0]));
  263. }
  264. if (zipFileMap.size() != fileLimit) {
  265. return ResultContant.createJSONObject("0003", String.format(ResManager.loadKDString("解析zip压缩包只包含%1$s个文件", "ElectAccVoucherService_6", "imc-rim-common", new Object[0]), zipFileMap.size()));
  266. }
  267. Iterator var5 = zipFileMap.entrySet().iterator();
  268. while(var5.hasNext()) {
  269. Map.Entry<String, String> map = (Map.Entry)var5.next();
  270. String key = (String)map.getKey();
  271. boolean checkFileType = FileUtils.checkFileType(key, new String[]{"xml", "sign"});
  272. if (!checkFileType) {
  273. return ResultContant.createJSONObject("0003", ResManager.loadKDString("解析zip压缩包只能包含xml/sign文件", "ElectAccVoucherService_7", "imc-rim-common", new Object[0]));
  274. }
  275. }
  276. }
  277. return null;
  278. }
  279. private JSONObject saveInvoice(JSONObject businessParam, JSONObject resultInvoice, String fileUrl, byte[] fileByte) {
  280. Long tax_org = null;
  281. if (null != businessParam) {
  282. resultInvoice.putAll(businessParam);
  283. tax_org = businessParam.getLong("tax_org");
  284. }
  285. if (!ObjectUtils.isEmpty(tax_org)) {
  286. resultInvoice.put("tax_org", tax_org);
  287. }
  288. InvoiceCollectService invoiceCollectService = new InvoiceCollectService();
  289. String fileHash = FileConvertUtils.getSHA256(fileByte);
  290. if (StringUtils.isEmpty(resultInvoice.getString("serialNo"))) {
  291. resultInvoice.put("serialNo", UUID.randomUUID());
  292. }
  293. DLock lock = DLock.create(resultInvoice.getString("invoiceNo") + "saveVoucher", "saveVoucherLock");
  294. Throwable var9 = null;
  295. try {
  296. if (lock.tryLock(10000L)) {
  297. if (!resultInvoice.containsKey("checkStatus")) {
  298. resultInvoice.put("checkStatus", "1");
  299. }
  300. resultInvoice = invoiceCollectService.saveInvoice(resultInvoice, fileUrl, fileHash);
  301. CacheHelper.put(resultInvoice.getString("invoiceNo") + "saveVoucher", resultInvoice.toJSONString(), 10000);
  302. } else {
  303. JSONObject cacheObject = JSON.parseObject(CacheHelper.get(resultInvoice.getString("invoiceNo") + "saveVoucher"));
  304. if (cacheObject != null) {
  305. resultInvoice = cacheObject;
  306. CacheHelper.remove(cacheObject.getString("invoiceNo") + "saveVoucher");
  307. }
  308. }
  309. } catch (Throwable var18) {
  310. var9 = var18;
  311. throw var18;
  312. } finally {
  313. if (lock != null) {
  314. if (var9 != null) {
  315. try {
  316. lock.close();
  317. } catch (Throwable var17) {
  318. var9.addSuppressed(var17);
  319. }
  320. } else {
  321. lock.close();
  322. }
  323. }
  324. }
  325. return resultInvoice;
  326. }
  327. public static boolean checkOrg(Object orgId) {
  328. boolean isVoucherOrg = false;
  329. try {
  330. if (orgId != null) {
  331. DynamicObject orgObject = BusinessDataServiceHelper.loadSingle(orgId, "bdm_org");
  332. if (orgObject != null && "1".equals(orgObject.get("epinfo.isvoucher"))) {
  333. isVoucherOrg = true;
  334. }
  335. }
  336. } catch (Throwable var3) {
  337. logger.info("获取企业电子会计凭证开关出错:{}", var3);
  338. isVoucherOrg = false;
  339. }
  340. return isVoucherOrg;
  341. }
  342. private static String getVoucherFileUrl(String fileType, byte[] fileByte, String xbrlInfo) throws IOException {
  343. String fileUploadUrl;
  344. if ("zip".equalsIgnoreCase(fileType)) {
  345. fileUploadUrl = FileConvertUtils.upload(fileByte, fileType);
  346. } else {
  347. ByteArrayInputStream xbrlStream = new ByteArrayInputStream(xbrlInfo.getBytes(StandardCharsets.UTF_8));
  348. Throwable var5 = null;
  349. try {
  350. fileUploadUrl = FileConvertUtils.upload(FileUtils.getByte(xbrlStream), "xml");
  351. } catch (Throwable var14) {
  352. var5 = var14;
  353. throw var14;
  354. } finally {
  355. if (xbrlStream != null) {
  356. if (var5 != null) {
  357. try {
  358. xbrlStream.close();
  359. } catch (Throwable var13) {
  360. var5.addSuppressed(var13);
  361. }
  362. } else {
  363. xbrlStream.close();
  364. }
  365. }
  366. }
  367. }
  368. return fileUploadUrl;
  369. }
  370. private static void uploadGet(Future<JSONObject> xbrlUploadSubmit, JSONObject resultInvoice) {
  371. try {
  372. JSONObject result = (JSONObject)xbrlUploadSubmit.get();
  373. if (result != null) {
  374. resultInvoice.put("imageUrl", result.getString("imageUrl"));
  375. resultInvoice.put("ofdUrl", result.getString("ofdUrl"));
  376. resultInvoice.put("pdfUrl", result.getString("pdfUrl"));
  377. resultInvoice.put("snapshotUrl", result.getString("imageUrl"));
  378. }
  379. } catch (Exception var3) {
  380. logger.info("电子会计凭证文件上传出错:{}", var3);
  381. }
  382. }
  383. public static void saveVoucher(String serialNo, String xbrlName, String fileUploadUrl, String xbrlType) {
  384. DynamicObject voucherObject = QueryServiceHelper.queryOne("rim_invoice_voucher", "id, serial_no, xbrl_name, xbrl_url, xbrl_type, receive_xbrl_url, receive_xbrl_name, create_time, update_time", new QFilter[]{new QFilter("serial_no", "=", serialNo)});
  385. if (voucherObject == null) {
  386. voucherObject = BusinessDataServiceHelper.newDynamicObject("rim_invoice_voucher");
  387. voucherObject.set("serial_no", serialNo);
  388. voucherObject.set("xbrl_name", xbrlName);
  389. voucherObject.set("xbrl_url", fileUploadUrl);
  390. voucherObject.set("xbrl_type", xbrlType);
  391. voucherObject.set("receive_xbrl_url", "");
  392. voucherObject.set("receive_xbrl_name", "");
  393. voucherObject.set("create_time", new Date());
  394. voucherObject.set("update_time", new Date());
  395. } else {
  396. voucherObject = BusinessDataServiceHelper.loadSingle(voucherObject.get("id"), "rim_invoice_voucher");
  397. voucherObject.set("xbrl_name", xbrlName);
  398. voucherObject.set("xbrl_url", fileUploadUrl);
  399. voucherObject.set("xbrl_type", xbrlType);
  400. voucherObject.set("update_time", new Date());
  401. }
  402. SaveServiceHelper.save(new DynamicObject[]{voucherObject});
  403. }
  404. }