Browse Source

Merge remote-tracking branch 'origin/master'

“lqy 1 week ago
parent
commit
3c1c5dfdb0

+ 41 - 4
mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdHuaGaoServiceImpl.java

@@ -109,7 +109,7 @@ public class KdHuaGaoServiceImpl implements KdHuaGaoService {
             do {
                 pageNumber++;
 
-                ddrNew = ydClient.queryData(YDParam.builder()
+                ddrNew = retryQueryData(YDParam.builder()
                         .formUuid("FORM-3B2E5C93D7E6494B9AD920B48A90159F7DZ4")
                         .searchFieldJson(JSONObject.toJSONString(UtilMap.map("numberField_mev270x6, numberField_mev270x5, textField_mev2ers5", Arrays.asList(year,year), Arrays.asList(month,month), weekOfMonth)))
                         .pageNumber(pageNumber)
@@ -232,7 +232,7 @@ public class KdHuaGaoServiceImpl implements KdHuaGaoService {
             }
 
             //删除宜搭历史最新库存信息
-            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
+            List<Map> data = (List<Map>) retryQueryData(YDParam.builder()
                     .formUuid("FORM-4CB51E04B8344622BE880C9D573F68CANKWU")
                     .searchFieldJson(JSONObject.toJSONString(UtilMap.map("numberField_mev270x6, numberField_mev270x5",Arrays.asList(year,year), Arrays.asList(month,month))))
                     .build(), YDConf.FORM_QUERY.retrieve_list).getData();
@@ -250,7 +250,7 @@ public class KdHuaGaoServiceImpl implements KdHuaGaoService {
                         .build(), YDConf.FORM_OPERATION.delete_batch);
             }
 
-            List<Map> data2 = (List<Map>) ydClient.queryData(YDParam.builder()
+            List<Map> data2 = (List<Map>) retryQueryData(YDParam.builder()
                     .formUuid("FORM-5764CC3F6D964FD3A165BD7D4D75999FO8NQ")
                     .searchFieldJson(JSONObject.toJSONString(UtilMap.map("numberField_mev270x6",Arrays.asList(year,year))))
                     .build(), YDConf.FORM_QUERY.retrieve_list).getData();
@@ -1236,11 +1236,12 @@ public class KdHuaGaoServiceImpl implements KdHuaGaoService {
 
                 return result;
             } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
                 if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
                     attempt++;
                     // 线程睡眠3秒
                     try {
-                        Thread.sleep(3000);
+                        Thread.sleep(5000);
                         log.info("尝试第{}次,param:{},FORM_OPERATION:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formOperation,e.getMessage());
                     } catch (InterruptedException ie) {
                         Thread.currentThread().interrupt(); // 重新设置中断状态
@@ -1258,4 +1259,40 @@ public class KdHuaGaoServiceImpl implements KdHuaGaoService {
         throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_OPERATION:{}"+formOperation);
     }
 
+
+    //自带重试的queryData方法
+    private DDR_New retryQueryData(YDParam param, YDConf.FORM_QUERY formQuery) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        DDR_New result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.queryData(param, formQuery);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_QUERY:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formQuery,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_QUERY:{},异常信息:{}", JSONObject.toJSONString(param), formQuery,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_QUERY:{}"+formQuery);
+    }
 }

+ 3 - 3
mjava-huagao/src/test/java/com/malk/huagao/YyYdTest.java

@@ -114,9 +114,9 @@ public class YyYdTest {
 
     @Test
     public void test3() {
-        LocalDateTime startTime= LocalDate.now().minusDays(6).atTime(LocalTime.MIN);
-        LocalDateTime endTime= LocalDate.now().minusDays(4).atTime(LocalTime.MIN);
-//        LocalDateTime endTime= LocalDate.now().atTime(LocalTime.MIN);
+        LocalDateTime startTime= LocalDate.now().minusDays(4).atTime(LocalTime.MIN);
+//        LocalDateTime endTime= LocalDate.now().minusDays(4).atTime(LocalTime.MIN);
+        LocalDateTime endTime= LocalDate.now().atTime(LocalTime.MIN);
 
         huaGaoService.syncKqData(startTime,endTime);
     }

+ 37 - 5
mjava-siku/src/main/java/com/malk/siku/controller/SikuController.java

@@ -40,10 +40,10 @@ public class SikuController {
      * @param map
      * @return
      */
-    /*@PostMapping("/saveYpClient")
+    @PostMapping("/saveYpClient")
     public McR saveYpClient(@RequestBody Map map){
         return sikuService.saveYpClient(map);
-    }*/
+    }
 
     /**
      * 开票申请单导入和更新
@@ -55,10 +55,32 @@ public class SikuController {
         return sikuService.saveYpApplication(map);
     }
 
-    //每刻云票回款回调
+    /**
+     * 报销单导入(采购需求&结算)
+     * @param map
+     * @return
+     */
+    @PostMapping("/saveBxReimbursement")
+    public McR saveBxReimbursement(@RequestBody Map map){
+        return sikuService.saveBxReimbursement(map);
+    }
+
+    /**
+     * 报销单导入2(直接采购结算单)
+     * @param map
+     * @return
+     */
+    @PostMapping("/saveBxReimbursement2")
+    public McR saveBxReimbursement2(@RequestBody Map map){
+        return sikuService.saveBxReimbursement2(map);
+    }
+
+    //每刻云票收款单核销回调
     @PostMapping("/receive/callback")
     public McR callback(@RequestBody Map map){
-        log.info("每刻云票回款回调:{}", JSONObject.toJSONString(map));
+        log.info("每刻云票收款单核销回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack(map);
 
         return McR.success();
     }
@@ -68,7 +90,17 @@ public class SikuController {
     public McR callback2(@RequestBody Map map){
         log.info("每刻云票开票回调:{}",JSONObject.toJSONString(map));
 
-        sikuService.invoiceWriteBack(map);
+        sikuService.invoiceWriteBack2(map);
+
+        return McR.success();
+    }
+
+    //每刻报销报销单完成回调
+    @PostMapping("/reimbursement/callback")
+    public McR callback3(@RequestBody Map map){
+        log.info("每刻报销报销单完成回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack3(map);
 
         return McR.success();
     }

+ 10 - 0
mjava-siku/src/main/java/com/malk/siku/service/SikuService.java

@@ -9,5 +9,15 @@ public interface SikuService {
 
     McR saveYpApplication(Map map);
 
+    void invoiceWriteBack2(Map map);
+
+    McR saveBxReimbursement(Map map);
+
+    McR saveYpClient(Map map);
+
     void invoiceWriteBack(Map map);
+
+    void invoiceWriteBack3(Map map);
+
+    McR saveBxReimbursement2(Map map);
 }

+ 453 - 24
mjava-siku/src/main/java/com/malk/siku/service/impl/SikuServiceImpl.java

@@ -8,11 +8,11 @@ import com.malk.service.aliwork.YDClient;
 import com.malk.siku.service.SikuService;
 import com.malk.siku.utils.MkBxUtil;
 import com.malk.siku.utils.MkYpUtil;
-import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.io.FileOutputStream;
@@ -27,6 +27,12 @@ public class SikuServiceImpl implements SikuService {
     @Autowired
     private YDClient ydClient;
 
+    @Value(value = "${mk.downloadFilePath}")
+    private String downloadFilePath;
+
+    @Value(value = "${mk.downloadUrl}")
+    private String downloadUrl;
+
     @Override
     public McR saveTradingPartner(Map map) {
         String formInstId = UtilMap.getString(map, "formInstId");
@@ -50,29 +56,41 @@ public class SikuServiceImpl implements SikuService {
             partner.put("readOnly", false);//是否只读,默认false。如果为true,那么在每刻系统中往来单位的所有信息(如权限范围、收款账户等)均无法修改。(接口更新操作不受限制)
             partner.put("reMark", "");//往来单位备注
             partner.put("enabled", true);//是否启用(true:启用;false:禁用)。若该参数为空,新增则默认为true,更新则保持系统内状态。
-
-
         }else {
-            //供应商
+            //供应商
             String hzlx = UtilMap.getString(formData, "radioField_mketkvw7");
 
-            partner.put("partnerName", "供应商");//所属分类名称
+            partner.put("parentBizCode", "GYS");//所属分类业务编码
             partner.put("name", "Free".equals(hzlx) ? UtilMap.getString(formData,"textField_mkkixdd6") : UtilMap.getString(formData,"textField_mketkvv0"));//往来单位中文名
             partner.put("partnerType", "供应商");//往来关系,可选值为:"供应商"、"客户"、"供应商,客户"(既是供应商又是客户的情况下以中文逗号分隔(供应商在前))
             partner.put("partnerProperty", "Free".equals(hzlx) ? "个体工商户" : "公司");//往来性质,可选值为:"公司"、"个体工商户"
-            partner.put("businessCode", UtilMap.getString(formData,"serialNumberField_mkddjwy2"));//往来单位编码,不超过50个字符
+            partner.put("businessCode", UtilMap.getString(formData,"serialNumberField_mketkvw4"));//往来单位编码,不超过50个字符
             partner.put("taxNumber", "Free".equals(hzlx) ? "" : UtilMap.getString(formData,"textField_mketkvxo"));//税务登记号,不超过200个字符
             partner.put("readOnly", false);//是否只读,默认false。如果为true,那么在每刻系统中往来单位的所有信息(如权限范围、收款账户等)均无法修改。(接口更新操作不受限制)
             partner.put("reMark", "");//往来单位备注
-            partner.put("enabled", UtilMap.getBoolean(formData,"radioField_mketkvw8"));//是否启用(true:启用;false:禁用)。若该参数为空,新增则默认为true,更新则保持系统内状态。
+            partner.put("enabled", "启用".equals(UtilMap.getString(formData,"radioField_mketkvw8")));//是否启用(true:启用;false:禁用)。若该参数为空,新增则默认为true,更新则保持系统内状态。
         }
 
         Map body = new HashMap();
         body.put("partnerList", Arrays.asList(partner));
 
-        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://ng.maycur.com/api/openapi/tradingPartner/batch/save", MkBxUtil.initTokenHeader(), null, body));
+        Map result = MkBxUtil.saveTradingPartner(body);
+
+        //保存供应商账户
+        if ("供应商".equals(type)){
+            Map account = new HashMap();
+            account.put("businessCode",UtilMap.getString(formData,"serialNumberField_mketkvw4"));
 
-        log.info("Result:",result);
+            Map accountItem = new HashMap();
+            accountItem.put("accountName",UtilMap.getString(formData,"textField_mketkvxa"));//账户名称
+            accountItem.put("accountNumber",UtilMap.getString(formData,"textField_mketkvxc"));//账号
+            accountItem.put("bankBranchName",UtilMap.getString(formData,"textField_mketkvx8"));//分支行
+            accountItem.put("accountType","BANK");
+
+            account.put("accounts",Arrays.asList(accountItem));
+
+            MkBxUtil.saveAccount(Arrays.asList(account));
+        }
 
         return McR.success();
     }
@@ -88,24 +106,31 @@ public class SikuServiceImpl implements SikuService {
         Map application = new HashMap();
         application.put("formSubTypeBizCode","KPSQD");//单据编码(云票系统内维护的)
         application.put("bizCode", UtilMap.getString(formData,"serialNumberField_mknspz75"));//外部系统中的开票申请单业务编码。必须系统内唯一,用于判断开票申请单是否已导入。
-        Map clientLegalEntityOaDto = new HashMap();//客户开票信息对象
+
+        application.put("clientBizCode",UtilMap.getString(formData,"textField_mkxpe3fj"));//收票方bizCode(客户的业务编码(云票系统内维护的))与收票方开票信息字段二选一必填
+
+        /*Map clientLegalEntityOaDto = new HashMap();//收票方开票信息(不在云票系统内维护的)与收票方bizCode(客户的业务编码)二选一必填且优先级高于收票方bizCode(客户的业务编码)(也就是当两字段都有值时,忽略客户的业务编码)
         clientLegalEntityOaDto.put("invoiceTitle",UtilMap.getString(formData,"selectField_mkxmix7e"));//名称
         clientLegalEntityOaDto.put("dutyParagraph",UtilMap.getString(formData,"textField_mm2wj87l"));//税号
         clientLegalEntityOaDto.put("account",UtilMap.getString(formData,"textField_mm2wj87u"));//账号
         clientLegalEntityOaDto.put("bankBranchName",UtilMap.getString(formData,"textField_mm2wj87t"));//银行
-        application.put("clientLegalEntityOaDto",clientLegalEntityOaDto);
+
+        application.put("clientLegalEntityOaDto",clientLegalEntityOaDto);*/
+
         application.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mm2wj87x"));//公司主体code(后续传税号)
         application.put("estimatedDate",System.currentTimeMillis());//预计开票时间
         String fplx = UtilMap.getString(formData, "selectField_mkdnuvem");//发票类型
         String estimatedInvoiceType = "";
-        switch (fplx){
-            case "应/免税普票":estimatedInvoiceType = "ELECTRONIC_VAT";break;//增值税普通发票(电子)
-            case "专票":estimatedInvoiceType = "ELECTRONIC_SPACIAL_VAT";break;//增值税电子专用发票
-            case "红冲":break;
-            case "形式发票":break;
-            case "收据":break;
-            default:break;
+        if (!"红冲".equals(fplx)){
+            estimatedInvoiceType = getEstimatedInvoiceType(fplx, estimatedInvoiceType);
+            application.put("hasRedInvoice",false);//是否负数发票
+            application.put("redInvoiceReason",UtilMap.getString(formData,"textareaField_mmelm9xt"));//红冲原因
+        }else {
+            String lzfplx = UtilMap.getString(formData, "textField_mm2wj87n");//蓝字发票类型
+            estimatedInvoiceType = getEstimatedInvoiceType(lzfplx, estimatedInvoiceType);
+            application.put("hasRedInvoice",true);//是否负数发票
         }
+
         application.put("estimatedInvoiceType",estimatedInvoiceType);//发票类型
 
         application.put("phoneNumber",UtilMap.getString(formData,"textField_mkdo0azf"));//收票人电话
@@ -115,7 +140,7 @@ public class SikuServiceImpl implements SikuService {
         Map item = new HashMap();
         item.put("productBizCode","1001");//产品bizcode
         item.put("invoiceName",UtilMap.getString(formData,"textField_mkgarw4d"));//开票名称
-        item.put("taxPercent",UtilMap.getDouble(formData,"numberField_mkgkboht"));//税率
+        item.put("taxPercent",UtilMap.getDouble(formData,"numberField_mkgkboht")/100);//税率
         item.put("quantity",1);//数量
         item.put("forexName","CNY");//币种
         item.put("exchangeRate",1);//外汇汇率
@@ -124,13 +149,26 @@ public class SikuServiceImpl implements SikuService {
 
         application.put("items",Arrays.asList(item));
 
-        Map result = MkYpUtil.application_oa(Arrays.asList(application));
+        Map result = MkYpUtil.application(Arrays.asList(application));
 
         return McR.success();
     }
 
+    private static String getEstimatedInvoiceType(String fplx, String estimatedInvoiceType) {
+        switch (fplx){
+            case "应/免税普票":
+                estimatedInvoiceType = "ELECTRONIC_VAT";break;//电子发票(普通发票)(税号开通全电)
+            case "专票":
+                estimatedInvoiceType = "ELECTRONIC_SPACIAL_VAT";break;//电子发票(增值税专票)(税号开通全电)
+            case "红冲":break;
+            case "形式发票":break;
+            case "收据":break;
+            default:break;
+        } return estimatedInvoiceType;
+    }
+
     @Override
-    public void invoiceWriteBack(Map map) {
+    public void invoiceWriteBack2(Map map) {
         //获取发票信息
         Map calloutParams = UtilMap.getMap(map, "calloutParams");
         Map bizData = UtilMap.getMap(calloutParams, "bizData");
@@ -151,11 +189,11 @@ public class SikuServiceImpl implements SikuService {
 
         if (Strings.isNotBlank(pdfUrl)){
             String fileName = invoiceNumber + ".pdf";
-            String downloadPath = "d:\\" + fileName;
+            String downloadPath = downloadFilePath + fileName;
             downloadFile(pdfUrl,downloadPath);//下载pdf发票
 
-            String downloadUri = "http://localhost:8080/api/siku/files/"+fileName+"?option=download" + fileName;
-            String previewUri = "http://localhost:8080/api/siku/files/"+fileName+"?option=preview" + fileName;
+            String downloadUri = downloadUrl + "/files/" + fileName + "?option=download" + fileName;
+            String previewUri = downloadUrl + "/files/"+fileName+"?option=preview" + fileName;
 
             Map attachmentField = new HashMap();
             attachmentField.put("downloadUrl",downloadUri);
@@ -174,6 +212,397 @@ public class SikuServiceImpl implements SikuService {
                 .build(), YDConf.FORM_OPERATION.upsert);
     }
 
+    @Override
+    public McR saveBxReimbursement(Map map) {
+        String formInstId = UtilMap.getString(map, "formInstId");
+
+        Map formData = ydClient.queryData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+
+        Map body = new HashMap();
+        body.put("formCode",UtilMap.getString(formData,"serialNumberField_mkkmij3o"));//有值时会使用该值作为单据号
+        body.put("formSubTypeBizCode","FT208629766551519240");//表单类型的业务编号  todo 暂时写死 FT208629766551519240 宜搭支付单
+        body.put("submittedUserEmployeeId","002");//提单人工号 todo 暂时写死 002 wzy
+        body.put("reimburseName",UtilMap.getString(formData,"textareaField_mmbmohr9"));//报销事由
+        body.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mmd6hio7"));//公司抬头编码
+        body.put("coverUserEmployeeId","002");//承担人工号 todo 暂时写死 002 wzy
+        body.put("coverDepartmentBizCode","DI203800035494740082");//承担部门编码 todo 暂时写死 DI203800035494740082
+
+        Map customObject = new HashMap();
+        customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkdf8q8q"));}});//落地结束时间
+        customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkkkw298"));}});//预计支付日期
+        customObject.put("CF6",UtilMap.getString(formData,"radioField_mkf2quln"));////free  是;否
+        customObject.put("CF5","是".equals(UtilMap.getString(formData,"radioField_mkf2quln")) ? "1" : "2");//代垫付  是:1  ;  否:2
+        customObject.put("CF2",UtilMap.getString(formData,"selectField_mkdedkv7"));//项目所属事业部
+        customObject.put("CF1",UtilMap.getString(formData,"textField_mkkmij50"));//项目
+
+        body.put("customObject",customObject);
+
+        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
+
+        List<String> expenseCodes = new ArrayList<>();
+        List<Map> collectionSchedule = new ArrayList<>();
+
+        List<Map> expenseList = new ArrayList<>();
+
+        if ("常规需求".equals(type)){
+            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细
+
+            for (Map result : detailList) {
+                Map item = new HashMap();
+
+                Map consumeAmount = new HashMap();
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij5e")));//结算金额
+                consumeAmount.put("currency","CNY");
+
+                item.put("consumeAmount",consumeAmount);
+                item.put("corpExpense",true);//是否对公费用,需要填写true
+                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
+                item.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//往来单位业务编码
+
+                Map consumeLocation = new HashMap();
+                consumeLocation.put("cityPair",null);
+                consumeLocation.put("location","110001");
+                item.put("consumeLocation",consumeLocation);
+
+                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+
+                expenseList.add(item);
+
+
+                Map collectionScheduleItem = new HashMap();
+                Map payeeAccount = new HashMap();
+                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mkkmij6z"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mkkmij6y"));//银行账户
+                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
+                payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
+                collectionScheduleItem.put("payeeAccount",payeeAccount);
+                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//收款往来单位编码
+                collectionScheduleItem.put("amountRatio",0);//收款比例
+                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
+                collectionScheduleItem.put("collectionType","BANK");//支付类型
+
+                collectionSchedule.add(collectionScheduleItem);
+            }
+        }else {
+            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细
+
+            for (Map result : detailList) {
+                Map item = new HashMap();
+
+                Map consumeAmount = new HashMap();
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij6p")));//结算金额
+                consumeAmount.put("currency","CNY");
+
+                item.put("consumeAmount",consumeAmount);
+                item.put("corpExpense",true);//是否对公费用,需要填写true
+                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
+                item.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//往来单位业务编码
+
+                Map consumeLocation = new HashMap();
+                consumeLocation.put("cityPair",null);
+                consumeLocation.put("location","110001");
+                item.put("consumeLocation",consumeLocation);
+
+                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+
+                expenseList.add(item);
+
+
+                Map collectionScheduleItem = new HashMap();
+                Map payeeAccount = new HashMap();
+                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mketkvxa"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mketkvxc"));//银行账户
+                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
+                payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
+                collectionScheduleItem.put("payeeAccount",payeeAccount);
+                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//收款往来单位编码
+                collectionScheduleItem.put("amountRatio",0);//收款比例
+                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
+                collectionScheduleItem.put("collectionType","BANK");//支付类型
+
+                collectionSchedule.add(collectionScheduleItem);
+            }
+        }
+
+        //报销单费用导入
+        Map body2 = new HashMap();
+        body2.put("employeeId","002");//需要导入的对应员工的工号
+        body2.put("expenseList",expenseList);
+
+        expenseCodes = MkBxUtil.receiveExpense(body2);
+
+        body.put("expenseCodes",expenseCodes);//费用类型业务编码
+        body.put("collectionSchedule",collectionSchedule);//多人收款,如果已填充该字段,则无需填充上方的收款账户字段,若传多人收款,则paymentSceneBizCode参数必填
+        body.put("paymentSceneBizCode","DGYSSK");//多人收款场景(支付场景)表单业务编码,需要填写多人收款时必填
+
+        body.put("stagingFlag",false);////暂存标识,默认为false表示不暂存
+
+        Map result = MkBxUtil.receiveReimburse(body);
+
+        return McR.success();
+    }
+
+    @Override
+    public McR saveYpClient(Map map) {
+        String formInstId = UtilMap.getString(map, "formInstId");
+
+        Map formData = ydClient.queryData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+
+        Map customerObj = new HashMap();
+        customerObj.put("bizCode",UtilMap.getString(formData,"serialNumberField_mkddjwy2"));//客户编码, 系统内唯一。
+        customerObj.put("name",UtilMap.getString(formData,"textField_mkddjwy3"));//客户名称,系统内唯一
+        customerObj.put("type","CORP");//客户类型: CORP (公司,默认), SELF_EMPLOYED(个体经营商)
+        customerObj.put("nameAutoCode",false);
+        customerObj.put("status","ENABLED");//客户状态:DISABLED("禁用" ,默认) ENABLED("启用")
+
+        List<Map> contacts = new ArrayList<>();
+        List<Map> contactList = UtilMap.getList(formData, "tableField_mkddjwyv");
+        for (Map contact : contactList) {
+            Map contactObj = new HashMap();
+            contactObj.put("name",UtilMap.getString(contact,"textField_mkddjwyw"));//联系人姓名
+            contactObj.put("phoneNumber",UtilMap.getString(contact,"textField_mkddjwyx"));//联系电话
+            contactObj.put("position",UtilMap.getString(contact,"textField_mkg8toy9"));//职位
+
+            contacts.add(contactObj);
+        }
+        customerObj.put("contacts",contacts);//联系人列表
+
+        List<Map> invoiceTitles = new ArrayList<>();
+        Map invoiceTitle = new HashMap();
+        invoiceTitle.put("invoiceTitle",UtilMap.getString(formData,"textField_mkddjwyr"));//发票抬头
+        invoiceTitle.put("dutyParagraph",UtilMap.getString(formData,"textField_mkddjwys"));//税号
+        invoiceTitle.put("bizCode",UtilMap.getString(formData,"textField_mkddjwys"));//业务编码
+        invoiceTitle.put("bankBranchName",UtilMap.getString(formData,"textField_mkddjwyt"));//开户行
+        invoiceTitle.put("account",UtilMap.getString(formData,"textField_mkddjwyu"));//银行账户
+        invoiceTitles.add(invoiceTitle);
+        customerObj.put("invoiceTitles",invoiceTitles);//发票抬头列表
+
+        MkYpUtil.saveClient(Arrays.asList(customerObj));
+
+        return McR.success();
+    }
+
+    @Override
+    public void invoiceWriteBack(Map map) {
+        Map calloutParams = UtilMap.getMap(map, "calloutParams");
+
+        Map bizData = UtilMap.getMap(calloutParams, "bizData");
+
+        List<Map> relatedDocuments = UtilMap.getList(bizData, "relatedDocuments");
+
+        for (Map relatedDocument : relatedDocuments) {
+            String formType = UtilMap.getString(relatedDocument, "formType");
+
+            if ("RECEIVABLE_AR".equals(formType)){
+                String bizCode = UtilMap.getString(relatedDocument, "bizCode");
+
+                //应收单查询
+                Map body = new HashMap();
+                body.put("bizCodes",Arrays.asList(bizCode));
+                body.put("pageNum",1);
+                body.put("pageSize",1);
+
+                Map receivable = MkYpUtil.searchReceivable(body).get(0);
+
+                Map invoice = ((List<Map>) UtilMap.getList(receivable, "invoiceList")).get(0);
+
+                String invoiceNumber = UtilMap.getString(invoice, "invoiceNumber");//发票号码
+
+                Double receivedAmount = UtilMap.getDouble(receivable, "receivedAmount");//已收金额
+
+                ydClient.operateData(YDParam.builder()
+                        .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
+                        .searchCondition(JSONObject.toJSONString(UtilMap.map("textField_mkxripc6",invoiceNumber)))
+                        .formDataJson(JSONObject.toJSONString(UtilMap.map("numberField_ml8t9c4u",receivedAmount)))
+                        .build(), YDConf.FORM_OPERATION.upsert);
+
+                return;
+            }
+
+        }
+
+    }
+
+    @Override
+    public void invoiceWriteBack3(Map map) {
+        String formCode = UtilMap.getString(map, "formCode");
+
+        Map formData = UtilMap.getMap(map, "formData");
+
+        Map baseAmount = UtilMap.getMap(formData, "baseAmount");
+
+        Map value = UtilMap.getMap(baseAmount, "value");
+
+        String text = UtilMap.getString(value, "text");
+
+        double amt = Double.parseDouble(text);
+
+        if (formCode.contains("需求")){
+            //采购需求&结算
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
+                    .formDataJson(JSONObject.toJSONString(UtilMap.map("numberField_mkf2qumf",amt)))
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o",formCode)))
+                    .build(), YDConf.FORM_OPERATION.upsert);
+        }else {
+            //直接采购结算单
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-1AFEDDA034C74F0DB18FA60C941CB56EHUUG")
+                    .formDataJson(JSONObject.toJSONString(UtilMap.map("numberField_mkf2qumf",amt)))
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o",formCode)))
+                    .build(), YDConf.FORM_OPERATION.upsert);
+        }
+
+    }
+
+    @Override
+    public McR saveBxReimbursement2(Map map) {
+        String formInstId = UtilMap.getString(map, "formInstId");
+
+        Map formData = ydClient.queryData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+
+        Map body = new HashMap();
+        body.put("formCode",UtilMap.getString(formData,"serialNumberField_mkkmij3o"));//有值时会使用该值作为单据号
+        body.put("formSubTypeBizCode","FT208629766551519240");//表单类型的业务编号  todo 暂时写死 FT208629766551519240 宜搭支付单
+        body.put("submittedUserEmployeeId","002");//提单人工号 todo 暂时写死 002 wzy
+        body.put("reimburseName",UtilMap.getString(formData,"textareaField_mmbmohr9"));//报销事由
+        body.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mmd6hio7"));//公司抬头编码
+        body.put("coverUserEmployeeId","002");//承担人工号 todo 暂时写死 002 wzy
+        body.put("coverDepartmentBizCode","DI203800035494740082");//承担部门编码 todo 暂时写死 DI203800035494740082
+
+        Map customObject = new HashMap();
+        customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkdf8q8q"));}});//落地结束时间
+        customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkkkw298"));}});//预计支付日期
+        customObject.put("CF6",UtilMap.getString(formData,"radioField_mkf2quln"));////free  是;否
+        customObject.put("CF5","是".equals(UtilMap.getString(formData,"radioField_mkf2quln")) ? "1" : "2");//代垫付  是:1  ;  否:2
+        customObject.put("CF2",UtilMap.getString(formData,"selectField_mkdedkv7"));//项目所属事业部
+        customObject.put("CF1",UtilMap.getString(formData,"textField_mkkmij50"));//项目
+
+        body.put("customObject",customObject);
+
+        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
+
+        List<String> expenseCodes = new ArrayList<>();
+        List<Map> collectionSchedule = new ArrayList<>();
+
+        List<Map> expenseList = new ArrayList<>();
+
+        if ("常规采购".equals(type)){
+            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细
+
+            for (Map result : detailList) {
+                Map item = new HashMap();
+
+                Map consumeAmount = new HashMap();
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij5e")));//结算金额
+                consumeAmount.put("currency","CNY");
+
+                item.put("consumeAmount",consumeAmount);
+                item.put("corpExpense",true);//是否对公费用,需要填写true
+                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
+                item.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//往来单位业务编码
+
+                Map consumeLocation = new HashMap();
+                consumeLocation.put("cityPair",null);
+                consumeLocation.put("location","110001");
+                item.put("consumeLocation",consumeLocation);
+
+                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+
+                expenseList.add(item);
+
+
+                Map collectionScheduleItem = new HashMap();
+                Map payeeAccount = new HashMap();
+                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mkkmij6z"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mkkmij6y"));//银行账户
+                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
+                payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
+                collectionScheduleItem.put("payeeAccount",payeeAccount);
+                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//收款往来单位编码
+                collectionScheduleItem.put("amountRatio",0);//收款比例
+                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
+                collectionScheduleItem.put("collectionType","BANK");//支付类型
+
+                collectionSchedule.add(collectionScheduleItem);
+            }
+        }else {
+            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细
+
+            for (Map result : detailList) {
+                Map item = new HashMap();
+
+                Map consumeAmount = new HashMap();
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij6p")));//结算金额
+                consumeAmount.put("currency","CNY");
+
+                item.put("consumeAmount",consumeAmount);
+                item.put("corpExpense",true);//是否对公费用,需要填写true
+                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
+                item.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//往来单位业务编码
+
+                Map consumeLocation = new HashMap();
+                consumeLocation.put("cityPair",null);
+                consumeLocation.put("location","110001");
+                item.put("consumeLocation",consumeLocation);
+
+                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+
+                expenseList.add(item);
+
+
+                Map collectionScheduleItem = new HashMap();
+                Map payeeAccount = new HashMap();
+                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mketkvxa"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mketkvxc"));//银行账户
+                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
+                payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
+                collectionScheduleItem.put("payeeAccount",payeeAccount);
+                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//收款往来单位编码
+                collectionScheduleItem.put("amountRatio",0);//收款比例
+                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
+                collectionScheduleItem.put("collectionType","BANK");//支付类型
+
+                collectionSchedule.add(collectionScheduleItem);
+            }
+        }
+
+        //报销单费用导入
+        Map body2 = new HashMap();
+        body2.put("employeeId","002");//需要导入的对应员工的工号
+        body2.put("expenseList",expenseList);
+
+        expenseCodes = MkBxUtil.receiveExpense(body2);
+
+        body.put("expenseCodes",expenseCodes);//费用类型业务编码
+        body.put("collectionSchedule",collectionSchedule);//多人收款,如果已填充该字段,则无需填充上方的收款账户字段,若传多人收款,则paymentSceneBizCode参数必填
+        body.put("paymentSceneBizCode","DGYSSK");//多人收款场景(支付场景)表单业务编码,需要填写多人收款时必填
+
+        body.put("stagingFlag",false);////暂存标识,默认为false表示不暂存
+
+        Map result = MkBxUtil.receiveReimburse(body);
+
+        return McR.success();
+    }
+
     //文件下载到本地
     private void downloadFile(String downloadUri,String downloadPath){
         try {

+ 50 - 0
mjava-siku/src/main/java/com/malk/siku/utils/MkBxUtil.java

@@ -9,7 +9,9 @@ import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -73,6 +75,54 @@ public class MkBxUtil {
 
     }
 
+    //保存往来单位
+    public static Map saveTradingPartner(Object body){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/tradingPartner/batch/save", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        return result;
+    }
+
+    //保存往来单位
+    public static Map saveAccount(Object body){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/tradingPartner/batch/account/save", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        return result;
+    }
+
+    //报销单导入
+    public static Map receiveReimburse(Object body){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/receive/reimburse", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        return result;
+    }
+
+    //报销单费用导入
+    public static List<String> receiveExpense(Object body){
+        log.info("body:{}",JSONObject.toJSONString(body));
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/receive/expense", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        List<String> expenseCodes = new ArrayList<>();
+
+        List<Map> successData = UtilMap.getList(data, "successData");
+
+        for (Map successDatum : successData) {
+            expenseCodes.add(UtilMap.getString(successDatum,"expenseCode"));
+        }
+
+        return expenseCodes;
+    }
+
+
     private static String getSecret(String appCode, String appSecret, long timeMillis){
         log.info("time:{}",timeMillis);
 

+ 25 - 2
mjava-siku/src/main/java/com/malk/siku/utils/MkYpUtil.java

@@ -10,6 +10,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -73,8 +74,8 @@ public class MkYpUtil {
 
     }
 
-
-    public static Map application_oa(Object body){
+    //开票通知单导入
+    public static Map application(Object body){
         Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/ar/openapi/application_oa/batch", MkYpUtil.initTokenHeader(), null, body,(Map) null));
 //        Map result = (Map) JSONObject.parse(UtilHttp.doRequest(UtilHttp.METHOD.POST, "https://" + host + "/api/ar/openapi/application_oa/batch", MkYpUtil.initTokenHeader(), null, body));
 
@@ -83,6 +84,28 @@ public class MkYpUtil {
         return result;
     }
 
+    //保存云票客户
+    public static Map saveClient(Object body){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/ar/openapi/client/batch", MkYpUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        return result;
+    }
+
+    //应收单查询
+    public static List<Map> searchReceivable(Object body){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/ar/openapi/receivable_oa/search", MkYpUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        List<Map> data2 = UtilMap.getList(data, "data");
+
+        return data2;
+    }
+
     private static String getSecret(String appCode, String appSecret, long timeMillis){
         log.info("time:{}",timeMillis);
 

+ 1 - 0
mjava-siku/src/main/resources/application-dev.yml

@@ -35,4 +35,5 @@ mk:
     appCode: AP53EP1SVDS1N9
     appSecret: qF4nm3nPnyXYcrWcr5jl
   downloadFilePath: d:\\
+  downloadUrl: http://localhost:9037/api/siku/
 

+ 2 - 1
mjava-siku/src/main/resources/application-prod.yml

@@ -34,4 +34,5 @@ mk:
   yp:
     appCode: AP53EP1SVDS1N9
     appSecret: qF4nm3nPnyXYcrWcr5jl
-
+  downloadFilePath: /home/server/siku/file/
+  downloadUrl: https://poc.cloudpure.cn/api/siku/

+ 1 - 1
mjava-siku/src/main/resources/application.yml

@@ -1,6 +1,6 @@
 spring:
   profiles:
-    active: dev
+    active: prod
   servlet:
     multipart:
       max-file-size: 100MB

+ 4 - 4
mjava-siku/src/test/java/com.malk.siku/SkTest.java

@@ -14,14 +14,14 @@ public class SkTest {
     @Test
     public void getSecret(){
         //每刻报销-测试环境
-        String appCode="AP52Y01LHHTAP9";
-        String appSecret="N4WuERLteAUPaWebnsHy";
+        /*String appCode="AP52Y01LHHTAP9";
+        String appSecret="N4WuERLteAUPaWebnsHy";*/
 
 
 
         //每刻云票-测试环境
-        /*String appCode="AP53EP1SVDS1N9";
-        String appSecret="qF4nm3nPnyXYcrWcr5jl";*/
+        String appCode="AP53EP1SVDS1N9";
+        String appSecret="qF4nm3nPnyXYcrWcr5jl";
 
         long timeMillis = System.currentTimeMillis();
         log.info("time:{}",timeMillis);