diff --git a/anrui-buscenter/anrui-buscenter-api/src/main/java/com/yxt/anrui/buscenter/api/bussalesorderreturnveh/ReturnPushVo.java b/anrui-buscenter/anrui-buscenter-api/src/main/java/com/yxt/anrui/buscenter/api/bussalesorderreturnveh/ReturnPushVo.java new file mode 100644 index 0000000000..dac8eaa2d6 --- /dev/null +++ b/anrui-buscenter/anrui-buscenter-api/src/main/java/com/yxt/anrui/buscenter/api/bussalesorderreturnveh/ReturnPushVo.java @@ -0,0 +1,16 @@ +package com.yxt.anrui.buscenter.api.bussalesorderreturnveh; + +import lombok.Data; + +/** + * @description: + * @author: dimengzhe + * @date: 2025/4/3 + **/ +@Data +public class ReturnPushVo { + + private String billNo; + + private String materialCode; +} diff --git a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.java b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.java index bba2c1aa9a..cfb4fbaa5b 100644 --- a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.java +++ b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.java @@ -29,8 +29,10 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.yxt.anrui.buscenter.api.bussalesorderreturnveh.ReturnPushVo; import com.yxt.anrui.buscenter.api.bussalesorderreturnvehapply.BusSalesOrderReturnVehApplyByOrderSidVo; import com.yxt.anrui.buscenter.api.bussalesorderreturnvehapply.BusSalesOrderReturnVehApplyDetailsVo; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; @@ -86,4 +88,6 @@ public interface BusSalesOrderReturnVehApplyMapper extends BaseMapper listPageByOrderSid(String orderSid); int updateByBorrowSid(String s); + + ReturnPushVo selectByVinSid(String vehSid); } \ No newline at end of file diff --git a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.xml b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.xml index 24615f8a1d..d59a49288a 100644 --- a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.xml +++ b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.xml @@ -77,4 +77,11 @@ update anrui_buscenter.bus_sales_order_borrower set state = 0 where salesOrderSid = #{s} + + \ No newline at end of file diff --git a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyService.java b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyService.java index 463deec5bd..748f9b37f6 100644 --- a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyService.java +++ b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyService.java @@ -51,6 +51,7 @@ import com.yxt.anrui.base.common.utils.domain.BillNo; import com.yxt.anrui.buscenter.api.bussalesorder.BusSalesOrder; import com.yxt.anrui.buscenter.api.bussalesorderborrower.BusSalesOrderBorrowerDetailsVo; import com.yxt.anrui.buscenter.api.bussalesorderborrower.BusSalesOrderBorrowerFeign; +import com.yxt.anrui.buscenter.api.bussalesorderreturnveh.ReturnPushVo; import com.yxt.anrui.buscenter.api.bussalesorderreturnvehapply.*; import com.yxt.anrui.buscenter.api.bussalesorderreturnvehapply.flow.BusSalesOrderReturnVehApplyTaskQuery; import com.yxt.anrui.buscenter.api.bussalesorder.app.order.AppOrderDetailsVo; @@ -82,6 +83,7 @@ import com.yxt.anrui.fin.api.finuncollectedreceivablesdetailed.StateQuery; import com.yxt.anrui.fin.api.finvehicleinvoice.FinVehicleInvoiceFeign; import com.yxt.anrui.fin.api.kingdee.FinKingDeeFeign; import com.yxt.anrui.fin.api.kingdee.bdcustomer.BdCustomer; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; import com.yxt.anrui.fin.api.kingdee.salesreturn.SalesReturn; import com.yxt.anrui.flowable.api.flow.FlowableFeign; import com.yxt.anrui.flowable.api.flow.UpdateFlowFieldVo; @@ -670,8 +672,10 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService vehicleList = new ArrayList<>(); BusSalesOrder finalBusSalesOrderOne = busSalesOrderService.fetchBySid(orderSid); //---------------------修改车辆持久状态------------------------- - SalesReturn salesReturn = new SalesReturn(); - List salesReturnDetails = new ArrayList<>(); + /* SalesReturn salesReturn = new SalesReturn(); + List salesReturnDetails = new ArrayList<>();*/ + SalOutStockPushSalReturnStock salOutStockPushSalReturnStock = new SalOutStockPushSalReturnStock(); + List salesReturnDetailDtoList = new ArrayList<>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //-----------------生成销售退货单号---------------------------- ResultBean orgSidByPath = sysStaffOrgFeign.getOrgSidByPath(finalBusSalesOrderOne.getOrgSidPath()); @@ -690,15 +694,15 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService returnVos = baseVehicleOutFeign.selectByVehReturn(vehSid, busSalesOrderReturnVehApply.getContractNo()).getData(); @@ -713,24 +717,24 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService draftSalesReturnOrders(@RequestBody @Valid SalesReturn salesReturn); +// ResultBean draftSalesReturnOrders(@RequestBody @Valid SalesReturn salesReturn); + ResultBean draftSalesReturnOrders(@RequestBody @Valid SalOutStockPushSalReturnStock salReturnStock) throws Exception; } diff --git a/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeignFallBack.java b/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeignFallBack.java index d9bbea601b..65371bce1a 100644 --- a/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeignFallBack.java +++ b/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeignFallBack.java @@ -19,6 +19,7 @@ import com.yxt.anrui.fin.api.kingdee.orgorganizations.OrgOrganizations; import com.yxt.anrui.fin.api.kingdee.otherarreceivable.OtherReceivable; import com.yxt.anrui.fin.api.kingdee.purmrb.PurMrb; import com.yxt.anrui.fin.api.kingdee.push.STKInStockPushPurmrb; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; import com.yxt.anrui.fin.api.kingdee.salesreturn.SalesReturn; import com.yxt.anrui.fin.api.kingdee.saloutstock.SalOutStock; import com.yxt.anrui.fin.api.kingdee.stkinstock.StkInStock; @@ -329,7 +330,7 @@ implements FinKingDeeFeign{ } @Override - public ResultBean draftSalesReturnOrders(SalesReturn salesReturn) { + public ResultBean draftSalesReturnOrders(SalOutStockPushSalReturnStock salesReturn) { return null; } diff --git a/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/push/SalOutStockPushSalReturnStock.java b/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/push/SalOutStockPushSalReturnStock.java new file mode 100644 index 0000000000..68d6d7910a --- /dev/null +++ b/anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/push/SalOutStockPushSalReturnStock.java @@ -0,0 +1,38 @@ +package com.yxt.anrui.fin.api.kingdee.push; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.yxt.common.core.dto.Dto; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @description: + * @author: dimengzhe + * @date: 2025/3/31 + **/ +@Data +public class SalOutStockPushSalReturnStock { + + private List stockDtoList; + + @Data + public static class SalesReturnDetailDto implements Dto { + + private static final long serialVersionUID = -7455578363694683720L; + @NotBlank + @JsonProperty("FMaterialId") + private String FMaterialId; + + @NotBlank + @JsonProperty("FEntryId") // 修正字段名:分录内码 + private String FEntryId; // 原始出库单分录内码 + + @ApiModelProperty("销售出库单单据编码") + private String billNo; + } + + +} diff --git a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/FinKingDeeFeignRest.java b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/FinKingDeeFeignRest.java index a3dd3f395e..05de48e610 100644 --- a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/FinKingDeeFeignRest.java +++ b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/FinKingDeeFeignRest.java @@ -24,6 +24,7 @@ import com.yxt.anrui.fin.api.kingdee.orgorganizations.OrgOrganizations; import com.yxt.anrui.fin.api.kingdee.otherarreceivable.OtherReceivable; import com.yxt.anrui.fin.api.kingdee.purmrb.PurMrb; import com.yxt.anrui.fin.api.kingdee.push.STKInStockPushPurmrb; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; import com.yxt.anrui.fin.api.kingdee.salesreturn.SalesReturn; import com.yxt.anrui.fin.api.kingdee.saloutstock.SalOutStock; import com.yxt.anrui.fin.api.kingdee.stkinstock.StkInStock; @@ -46,6 +47,8 @@ import com.yxt.anrui.fin.biz.kingdee.costadjustmentsbill.CostAdjustmentsBillServ import com.yxt.anrui.fin.biz.kingdee.orgorganizations.OrgOrganizationsService; import com.yxt.anrui.fin.biz.kingdee.otherreceivablebill.OtherReceivableBillService; import com.yxt.anrui.fin.biz.kingdee.purmrb.PurMrbService; +import com.yxt.anrui.fin.biz.kingdee.push.PushReturnService; +import com.yxt.anrui.fin.biz.kingdee.push.PushReturnService2; import com.yxt.anrui.fin.biz.kingdee.push.PushService; import com.yxt.anrui.fin.biz.kingdee.receivablebill.ReceivableBillService; import com.yxt.anrui.fin.biz.kingdee.salesreturn.SalesReturnOrdersService; @@ -198,7 +201,8 @@ public class FinKingDeeFeignRest implements FinKingDeeFeign { * 销售退货单 */ @Autowired - private SalesReturnOrdersService salesReturnOrdersService; +// private SalesReturnOrdersService salesReturnOrdersService; + private PushReturnService2 pushReturnService; /** * 销售退货单 @@ -1995,9 +1999,13 @@ public class FinKingDeeFeignRest implements FinKingDeeFeign { } @Override - public ResultBean draftSalesReturnOrders(SalesReturn salesReturn) { + /* public ResultBean draftSalesReturnOrders(SalesReturn salesReturn) { log.info("FinKingDeeFeignRest-draftSalesReturnOrders:{}", JSONObject.toJSONString(salesReturn)); return salesReturnOrdersService.salesReturnOrdersService(salesReturn); + }*/ + public ResultBean draftSalesReturnOrders(SalOutStockPushSalReturnStock salReturnStock) throws Exception { + log.info("FinKingDeeFeignRest-draftSalesReturnOrders:{}", JSONObject.toJSONString(salReturnStock)); + return pushReturnService.getReturnStock(salReturnStock); } @ApiOperation("暂存收款单的接口") diff --git a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/KingdeePushRequest.java b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/KingdeePushRequest.java new file mode 100644 index 0000000000..5360eac61c --- /dev/null +++ b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/KingdeePushRequest.java @@ -0,0 +1,67 @@ +package com.yxt.anrui.fin.biz.kingdee.push; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: 下推所需参数 + * @author: dimengzhe + * @date: 2025/4/3 + **/ +@Data +public class KingdeePushRequest { + + /** + * 1.formid:业务对象表单Id,字符串类型(必录) + * 2.data:Json格式数据(详情参考Json格式数据)(必录) + * 2.1.Ids:单据内码集合,字符串类型,格式:"Id1,Id2,..."(使用内码时必录) + * 2.2.Numbers:单据编码集合,数组类型,格式:[No1,No2,...](使用编码时必录) + * 2.3.EntryIds:分录内码集合,逗号分隔(分录下推时必录),注(按分录下推时,单据内码和编码不需要填,否则按整单下推) + * 2.4.RuleId:转换规则内码,字符串类型(未启用默认转换规则时,则必录) + * 2.5.TargetBillTypeId:目标单据类型内码,字符串类型(非必录) + * 2.6.TargetOrgId:目标组织内码,整型(非必录) + * 2.7.TargetFormId:目标单据FormId,字符串类型,(启用默认转换规则时,则必录) + * 2.8.IsEnableDefaultRule:是否启用默认转换规则,布尔类型,默认false(非必录) + * 2.9.CustomParams:自定义参数,字典类型,格式:"{key1:value1,key2:value2,...}"(非必录) ,注(传到转换插件的操作选项中,平台不会解析里面的值) + *

+ * 二、Json格式数据: + * {\"Ids\":\"\",\"Numbers\":[],\"EntryIds\":\"\",\"RuleId\":\"\",\"TargetBillTypeId\":\"\",\"TargetOrgId\":\"0\",\"TargetFormId\":\"\",\"IsEnableDefaultRule\":\"false\",\"CustomParams\":{}} + */ + @JsonProperty("formId") + private String formId; + + @JsonProperty("data") + private PushData data = new PushData(); + + @Data + public static class PushData { + @JsonProperty("Ids") + private String ids = ""; + + @JsonProperty("Numbers") + private List numbers = new ArrayList<>(); + + @JsonProperty("EntryIds") + private String entryIds = ""; + + @JsonProperty("RuleId") + private String ruleId; + @JsonProperty("TargetBillTypeId") + private String TargetBillTypeId = ""; + @JsonProperty("TargetOrgId") + private String TargetOrgId = "0"; + @JsonProperty("TargetFormId") + private String TargetFormId; + @JsonProperty("IsDraftWhenSaveFail") + private String IsDraftWhenSaveFail = "false"; + @JsonProperty("IsEnableDefaultRule") + private String IsEnableDefaultRule = "false"; + @JsonProperty("CustomParams") + private Map CustomParams = new HashMap<>(); + } +} diff --git a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushCastToKingDeeBillFields.java b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushCastToKingDeeBillFields.java index ac60e6f433..759c41f8e0 100644 --- a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushCastToKingDeeBillFields.java +++ b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushCastToKingDeeBillFields.java @@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.yxt.anrui.fin.api.kingdee.push.Push; import com.yxt.anrui.fin.biz.kingdee.KingDeeUtils; import org.slf4j.Logger; @@ -58,4 +60,36 @@ public class PushCastToKingDeeBillFields { //对模板字段赋值 根据传递进来的map数据的集合进行赋值 return jsonObj.toJSONString(); } + + /** + * 构造金蝶需要的数据结构--下推 + * @param push + * @param isfr 是否整单下推 + * @return + */ + public static String getKingDeeData2(Push push, boolean isfr) { + ObjectMapper mapper = new ObjectMapper(); + KingdeePushRequest request = new KingdeePushRequest(); + request.setFormId(push.getFormid()); + + KingdeePushRequest.PushData data = request.getData(); + data.setRuleId(push.getRuleId()); + data.setTargetFormId(push.getTargetFormId()); + + if (isfr) { + // 整单下推 + data.getNumbers().add(push.getNumbers()); // 自动处理null + } else { + // 部分下推 + data.setEntryIds(push.getEntryIds()); + } + + try { + String json = mapper.writeValueAsString(request); + log.info("Generated JSON: {}", json); + return json; + } catch (JsonProcessingException e) { + throw new RuntimeException("JSON生成失败", e); + } + } } \ No newline at end of file diff --git a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnRest.java b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnRest.java new file mode 100644 index 0000000000..806fbc72fc --- /dev/null +++ b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnRest.java @@ -0,0 +1,51 @@ +package com.yxt.anrui.fin.biz.kingdee.push; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; +import com.yxt.common.core.result.ResultBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +/** + * @description: 销售出库单下推到销售退货单测试 + * @author: dimengzhe + * @date: 2025/4/2 + **/ +@RestController +@RequestMapping("/pushreturn") +public class PushReturnRest { + + @Autowired + private PushReturnService pushReturnService; + @Autowired + private PushReturnService2 pushReturnService2; + + @GetMapping("getReturnStock") + public ResultBean getReturnStock() throws Exception { + SalOutStockPushSalReturnStock salOutStockPushSalReturnStock = new SalOutStockPushSalReturnStock(); + List detailDtoList = new ArrayList<>(); + SalOutStockPushSalReturnStock.SalesReturnDetailDto salesReturnDetailDto = new SalOutStockPushSalReturnStock.SalesReturnDetailDto(); + salesReturnDetailDto.setBillNo("XSCKD1012025030023"); + salesReturnDetailDto.setFMaterialId("SR011469"); + detailDtoList.add(salesReturnDetailDto); + salesReturnDetailDto = new SalOutStockPushSalReturnStock.SalesReturnDetailDto(); + salesReturnDetailDto.setBillNo("XSCKD1012025030022"); + salesReturnDetailDto.setFMaterialId("SR011471"); + detailDtoList.add(salesReturnDetailDto); + salOutStockPushSalReturnStock.setStockDtoList(detailDtoList); + return pushReturnService2.getReturnStock(salOutStockPushSalReturnStock); + } + + @GetMapping("getReturnStockEntry") + public JSONArray getReturnStockEntry() throws Exception { + String billNo = "XSTHD001987"; + JSONArray getSalReturnStockEntrys = pushReturnService2.getSalReturnStockEntrys(billNo); + return getSalReturnStockEntrys; + } +} diff --git a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService.java b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService.java new file mode 100644 index 0000000000..92a4d61f01 --- /dev/null +++ b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService.java @@ -0,0 +1,158 @@ +package com.yxt.anrui.fin.biz.kingdee.push; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yxt.anrui.fin.api.kingdee.KingDeeBillId; +import com.yxt.anrui.fin.api.kingdee.KingDeeBillUrl; +import com.yxt.anrui.fin.api.kingdee.push.Push; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; +import com.yxt.anrui.fin.biz.kingdee.FinKingDeeService; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.result.ResultBean; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @description: 每个销售出库单推送一个销售退货单 + * @author: dimengzhe + * @date: 2025/3/31 + **/ +@Service +public class PushReturnService extends FinKingDeeService { + + + public ResultBean getReturnStock(SalOutStockPushSalReturnStock salOutStockPushSalReturnStock) throws Exception { + ResultBean rb = ResultBean.fireFail(); + Map> groupedByBillNo = salOutStockPushSalReturnStock.getStockDtoList() + .stream() + .collect(Collectors.groupingBy(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getBillNo)); + // 3. 循环处理每个出库单 + for (Map.Entry> entry : groupedByBillNo.entrySet()) { + String billNo = entry.getKey(); + List details = entry.getValue(); + String[] materialIds = details.stream() + .map(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getFMaterialId) + .toArray(String[]::new); + + + // 构建下推请求 + Push push = new Push(); + push.setFormid(KingDeeBillId.SAL_OUTSTOCK.getID()); + push.setRuleId("OutStock-SalReturnStock"); + push.setTargetFormId(KingDeeBillId.SAL_RETURNSTOCK.getID()); + push.setEntryIds(String.join(",", materialIds)); + push.setNumbers(billNo); + String kingDeeData = createKingDeeDate(push, billNo); + //业务表的主表数据集合 + try { + ResultBean resultBeans = accessKingDeeInterface(KingDeeBillId.SAL_RETURNSTOCK.getID(), + kingDeeData, KingDeeBillUrl.PUSH_URL.getURL()); + if (!resultBeans.getSuccess()) { + log.info("下推失败!"); + return rb.setMsg("下推失败!"); + } + String data = resultBeans.getData(); + /* ResultBean submit = submit(KingDeeBillId.SAL_RETURNSTOCK.getID(), data); + if (!submit.getSuccess()) { + return rb.setCode(KingDeeCode.SUBMIT.getCode()).setMsg(KingDeeCode.SUBMIT.getMsg()); + }*/ + + } catch (Exception e) { + e.printStackTrace(); + } + + } + return rb.success(); + } + + private String createKingDeeDate(Push push, String billNo) throws Exception { + JSONArray outStockEntryS = getSalOutStockEntrys(billNo); + String entryIds = push.getEntryIds(); + String[] split = entryIds.split(","); + if (split.length > outStockEntryS.size()) { + return ""; + } + String kingDeeData = ""; + if (split.length == outStockEntryS.size()) {//物料数量相等 说明是整单下推退货单 + kingDeeData = PushCastToKingDeeBillFields.getKingDeeData(push, true); + } else { + String sb = getEntryIds(outStockEntryS, split); + if (sb.length() == 0) { + return ""; + } + entryIds = sb; + log.info("substring:{}", entryIds); + push.setEntryIds(entryIds); + kingDeeData = PushCastToKingDeeBillFields.getKingDeeData(push, false); + } + return kingDeeData; + } + + private String getEntryIds(JSONArray outStockEntryS, String[] materialIds) { + Set materialIdSet = Arrays.stream(materialIds) + .map(String::trim) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toSet()); + + if (materialIdSet.isEmpty()) { + return ""; + } + + // 2. 提取匹配的EntryIds + return extractPairs(outStockEntryS).stream() + .filter(pair -> pair.containsKey("Value") && pair.get("Value") != null) + .filter(pair -> materialIdSet.contains(pair.get("Value").toString().trim())) + .map(pair -> pair.get("Id").toString()) + .filter(Objects::nonNull) + .collect(Collectors.joining(",")); + } + + /** + * 从JSON数组提取ID和物料ID对 + * + * @param array JSON数组 + * @return 包含ID和物料ID对的列表 + */ + public List> extractPairs(JSONArray array) { + ArrayList> strs = new ArrayList<>(); + for (int i = 0; i < array.size(); i++) {//解析查询的入库单返回的数据 + JSONObject o = (JSONObject) array.get(i); + + JSONObject materialId = (JSONObject) o.get("MaterialID"); + JSONArray Names = (JSONArray) materialId.get("Name"); + JSONObject Name = (JSONObject) Names.get(0); + String Value = (String) Name.get("Value"); + int Id = (int) o.get("Id"); + log.info("Value:{}", Value); + log.info("Id:{}", Id); + Map map = new HashMap<>(); + map.put("Value", Value); + map.put("Id", Id + ""); + strs.add(map); + } + return strs; + } + + + private JSONArray getSalOutStockEntrys(String billNo) throws Exception { + String stk = getGetKDForNumbers(KingDeeBillId.SAL_OUTSTOCK.getID(), billNo); + ResultBean resultBean = accessKingDeeInterface(KingDeeBillId.SAL_OUTSTOCK.getID(), + stk, KingDeeBillUrl.VIEW_URL.getURL()); + log.info("stk:{}", stk); + log.info("resultBean:{}", resultBean); + String data = resultBean.getData(); + JSONObject jsonObject = JSONObject.parseObject(data); + JSONObject result = (JSONObject) jsonObject.get("Result"); + log.info("result:{}", result); + JSONObject result2 = (JSONObject) result.get("Result"); + log.info("result2:{}", result2); + + JSONArray outStockEntryS = (JSONArray) result2.get("SAL_OUTSTOCKENTRY"); + log.info("outStockEntryS:{}", outStockEntryS); + log.info("size:{}", outStockEntryS.size()); + return outStockEntryS; + } +} diff --git a/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService2.java b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService2.java new file mode 100644 index 0000000000..e434623f27 --- /dev/null +++ b/anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService2.java @@ -0,0 +1,271 @@ +package com.yxt.anrui.fin.biz.kingdee.push; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yxt.anrui.fin.api.kingdee.KingDeeBillId; +import com.yxt.anrui.fin.api.kingdee.KingDeeBillUrl; +import com.yxt.anrui.fin.api.kingdee.KingDeeCode; +import com.yxt.anrui.fin.api.kingdee.push.Push; +import com.yxt.anrui.fin.api.kingdee.push.SalOutStockPushSalReturnStock; +import com.yxt.anrui.fin.biz.kingdee.FinKingDeeService; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.result.ResultBean; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @description: 同一个客户的多个销售出库单推送一个销售退货单 + * @author: dimengzhe + * @date: 2025/4/2 + **/ +@Service +public class PushReturnService2 extends FinKingDeeService { + + public ResultBean getReturnStock(SalOutStockPushSalReturnStock salOutStockPushSalReturnStock) throws Exception { + ResultBean rb = ResultBean.fireFail(); + + // 1. 收集所有物料ID和出库单号 + List allDetails = salOutStockPushSalReturnStock.getStockDtoList(); + + // 2. 获取所有出库单号(去重) + Set billNos = allDetails.stream() + .map(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getBillNo) + .collect(Collectors.toSet()); + + // 3. 获取所有出库单的Entry信息 + Map map = getBillNoToEntriesMap(billNos, allDetails); + + String entryIds = getEntryIds(billNos, map); + + // 5. 构建下推请求 + Push push = new Push(); + push.setFormid(KingDeeBillId.SAL_OUTSTOCK.getID()); + push.setRuleId("OutStock-SalReturnStock"); + push.setTargetFormId(KingDeeBillId.SAL_RETURNSTOCK.getID()); + push.setNumbers(String.join(",", billNos)); // 设置多个出库单号 + push.setEntryIds(String.join(",", entryIds)); // 设置原始分录内码 + + // 6. 创建金蝶数据 + String kingDeeData = PushCastToKingDeeBillFields.getKingDeeData2(push, false); + if (kingDeeData == null || kingDeeData.isEmpty()) { + log.error("创建金蝶数据失败,billNos: {}", billNos); + return rb.setMsg("创建金蝶数据失败"); + } + + // 7. 调用金蝶接口 + try { + ResultBean resultBeans = accessKingDeeInterface( + KingDeeBillId.SAL_RETURNSTOCK.getID(), + kingDeeData, + KingDeeBillUrl.PUSH_URL.getURL()); + + if (!resultBeans.getSuccess()) { + log.error("下推失败! billNos: {}, 错误信息: {}", billNos, resultBeans.getMsg()); + return rb.setMsg("下推失败: " + resultBeans.getMsg()); + } + + String data = resultBeans.getData(); + // 1. 使用安全解析方式 + JSONObject jsonObject = JSONObject.parseObject(data); + // 2. 安全获取ID(带完整异常处理) + int id = Optional.ofNullable(jsonObject.getJSONObject("Result")) + .map(result -> result.getJSONObject("ResponseStatus")) + .map(response -> response.getJSONArray("SuccessEntitys")) + .filter(array -> !array.isEmpty()) + .map(array -> array.getJSONObject(0)) + .map(entity -> entity.getInteger("Id")) + .orElseThrow(() -> new Exception("无法从金蝶响应中获取有效ID")); + + // 3. 记录关键日志 + log.info("成功解析金蝶响应 | 单据ID: {}", id); + if (log.isDebugEnabled()) { + log.debug("完整响应数据: {}", StringUtils.abbreviate(data, 200)); + } + + // 4. 提交操作 + ResultBean submitResult = submit(KingDeeBillId.SAL_RETURNSTOCK.getID(), String.valueOf(id)); + if (!submitResult.getSuccess()) { + log.warn("单据提交失败 | 单据ID: {}, 错误: {}", id, submitResult.getMsg()); + return rb.setCode(KingDeeCode.SUBMIT.getCode()) + .setData(submitResult.getData()); + } + + // 5. 审核操作(使用解析后的ID而非原始data) + ResultBean auditResult = audit(KingDeeBillId.SAL_RETURNSTOCK.getID(), String.valueOf(id)); + if (!auditResult.getSuccess()) { + log.warn("单据审核失败 | 单据ID: {}, 错误: {}", id, auditResult.getMsg()); + return rb.setCode(KingDeeCode.AUDIT.getCode()) + .setData(auditResult.getData()); + } + + log.info("单据处理成功 | 单据ID: {}", id); + return resultBeans; + } catch (Exception e) { + log.error("调用金蝶接口异常", e); + throw e; + } + } + + /** + * 根据出库单号和物料ID映射获取Entry IDs + * + * @param billNos 出库单号集合 + * @param map 出库单号到物料ID数组的映射 + * @return 包含所有匹配Entry IDs的StringBuilder + */ + private String getEntryIds(Set billNos, Map map) { + List allEntryIds = new ArrayList<>(); + for (String billNo : billNos) { + // 1. 预处理物料IDs + Set materialIdSet = new HashSet<>(); + String[] materialIds = map.getOrDefault(billNo, new String[0]); + for (String materialId : materialIds) { + if (materialId != null && StringUtils.isNotBlank(materialId)) { + materialIdSet.add(materialId.trim()); + } + } + // 2. 查询分录信息 + try { + JSONArray outStockEntryS = getSalOutStockEntrys(billNo); + List> extractPairs = extractPairs(outStockEntryS); + List matchedEntryIds = new ArrayList<>(); + for (int i = 0; i < extractPairs.size(); i++) { + Map pair = extractPairs.get(i); + if (!pair.containsKey("Value") || pair.get("Value") == null) { + continue; // 跳过无效条目 + } + + String value = pair.get("Value").toString().trim(); + if (materialIdSet.contains(value)) { + Object id = pair.get("Id"); + if (id != null) { + matchedEntryIds.add(id.toString()); + } + } + + } + if (!matchedEntryIds.isEmpty()) { + allEntryIds.add(String.join(",", matchedEntryIds)); + } + } catch (Exception e) { + log.error("获取出库单分录信息失败,billNo: {}", billNo, e); + } + } + return String.join(",", allEntryIds); + } + + /** + * 从JSON数组提取ID和物料ID对 + * + * @param array JSON数组 + * @return 包含ID和物料ID对的列表 + */ + public List> extractPairs(JSONArray array) { + ArrayList> strs = new ArrayList<>(); + for (int i = 0; i < array.size(); i++) {//解析查询的入库单返回的数据 + JSONObject o = (JSONObject) array.get(i); + + JSONObject materialId = (JSONObject) o.get("MaterialID"); + JSONArray Names = (JSONArray) materialId.get("Name"); + JSONObject Name = (JSONObject) Names.get(0); + String Value = (String) Name.get("Value"); + int Id = (int) o.get("Id"); + log.info("Value:{}", Value); + log.info("Id:{}", Id); + Map map = new HashMap<>(); + map.put("Value", Value); + map.put("Id", Id + ""); + strs.add(map); + } + return strs; + } + + + /** + * 根据出库单号(billNo)获取对应的物料ID数组(materialIds) + * + * @param billNos 出库单号集合 + * @param allDetails 所有明细数据 + * @return Map 其中key是出库单号,value是该出库单对应的物料ID数组 + */ + private Map getBillNoToEntriesMap(Set billNos, + List allDetails) { + + // 1. 按出库单号分组明细数据 + Map> groupedByBillNo = allDetails.stream() + .collect(Collectors.groupingBy(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getBillNo)); + + // 2. 转换为Map格式 + Map result = new HashMap<>(); + + for (Map.Entry> entry : groupedByBillNo.entrySet()) { + String billNo = entry.getKey(); + List details = entry.getValue(); + + // 提取物料ID数组 + String[] materialIds = details.stream() + .map(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getFMaterialId) + .toArray(String[]::new); + + result.put(billNo, materialIds); + } + + // 3. 确保所有billNos都有对应的entry(即使为空数组) + for (String billNo : billNos) { + result.putIfAbsent(billNo, new String[0]); + } + + return result; + } + + /** + * 获取出库单分录信息 + */ + private JSONArray getSalOutStockEntrys(String billNo) throws Exception { + String stk = getGetKDForNumbers(KingDeeBillId.SAL_OUTSTOCK.getID(), billNo); + ResultBean resultBean = accessKingDeeInterface( + KingDeeBillId.SAL_OUTSTOCK.getID(), + stk, + KingDeeBillUrl.VIEW_URL.getURL()); + + if (!resultBean.getSuccess()) { + log.error("获取出库单分录信息失败,billNo: {}, 错误: {}", billNo, resultBean.getMsg()); + return null; + } + + try { + JSONObject jsonObject = JSONObject.parseObject(resultBean.getData()); + JSONObject result = jsonObject.getJSONObject("Result"); + JSONObject result2 = result.getJSONObject("Result"); + return result2.getJSONArray("SAL_OUTSTOCKENTRY"); + } catch (Exception e) { + log.error("解析出库单分录信息异常,billNo: {}", billNo, e); + return null; + } + } + + public JSONArray getSalReturnStockEntrys(String billNo) throws Exception { + String stk = getGetKDForNumbers(KingDeeBillId.SAL_RETURNSTOCK.getID(), billNo); + ResultBean resultBean = accessKingDeeInterface( + KingDeeBillId.SAL_RETURNSTOCK.getID(), + stk, + KingDeeBillUrl.VIEW_URL.getURL()); + + if (!resultBean.getSuccess()) { + log.error("获取出库单分录信息失败,billNo: {}, 错误: {}", billNo, resultBean.getMsg()); + return null; + } + + try { + JSONObject jsonObject = JSONObject.parseObject(resultBean.getData()); + JSONObject result = jsonObject.getJSONObject("Result"); + JSONObject result2 = result.getJSONObject("Result"); + return result2.getJSONArray("SAL_RETURNSTOCKENTRY"); + } catch (Exception e) { + log.error("解析出库单分录信息异常,billNo: {}", billNo, e); + return null; + } + } +}