Browse Source

同一个客户多个销售出库单下推销售退货单

master
dimengzhe 3 weeks ago
parent
commit
a16e4963e4
  1. 16
      anrui-buscenter/anrui-buscenter-api/src/main/java/com/yxt/anrui/buscenter/api/bussalesorderreturnveh/ReturnPushVo.java
  2. 4
      anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.java
  3. 7
      anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.xml
  4. 45
      anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyService.java
  5. 4
      anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeign.java
  6. 3
      anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeignFallBack.java
  7. 38
      anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/push/SalOutStockPushSalReturnStock.java
  8. 12
      anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/FinKingDeeFeignRest.java
  9. 67
      anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/KingdeePushRequest.java
  10. 34
      anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushCastToKingDeeBillFields.java
  11. 51
      anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnRest.java
  12. 158
      anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService.java
  13. 271
      anrui-fin/anrui-fin-biz/src/main/java/com/yxt/anrui/fin/biz/kingdee/push/PushReturnService2.java

16
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;
}

4
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<BusSalesOr
List<BusSalesOrderReturnVehApplyByOrderSidVo> listPageByOrderSid(String orderSid);
int updateByBorrowSid(String s);
ReturnPushVo selectByVinSid(String vehSid);
}

7
anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorderreturnvehapply/BusSalesOrderReturnVehApplyMapper.xml

@ -77,4 +77,11 @@
<update id="updateByBorrowSid">
update anrui_buscenter.bus_sales_order_borrower set state = 0 where salesOrderSid = #{s}
</update>
<select id="selectByVinSid" resultType="com.yxt.anrui.buscenter.api.bussalesorderreturnveh.ReturnPushVo">
SELECT ba.billNo,bo.materialCode
FROM base_vehicle_out bo
left join base_vehicle_out_apply ba on ba.sid = bo.mainSid
where bo.materialTypeKey = '001' and bo.isDelete = 0 and bo.vinSid = #{vehSid}
</select>
</mapper>

45
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<BusSa
List<BusSalesOrderVehicle> vehicleList = new ArrayList<>();
BusSalesOrder finalBusSalesOrderOne = busSalesOrderService.fetchBySid(orderSid);
//---------------------修改车辆持久状态-------------------------
SalesReturn salesReturn = new SalesReturn();
List<SalesReturn.SalesReturnDetailDto> salesReturnDetails = new ArrayList<>();
/* SalesReturn salesReturn = new SalesReturn();
List<SalesReturn.SalesReturnDetailDto> salesReturnDetails = new ArrayList<>();*/
SalOutStockPushSalReturnStock salOutStockPushSalReturnStock = new SalOutStockPushSalReturnStock();
List<SalOutStockPushSalReturnStock.SalesReturnDetailDto> salesReturnDetailDtoList = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//-----------------生成销售退货单号----------------------------
ResultBean<String> orgSidByPath = sysStaffOrgFeign.getOrgSidByPath(finalBusSalesOrderOne.getOrgSidPath());
@ -690,15 +694,15 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService<BusSa
if (null != vehicleSelectVo) {
if (StringUtils.isNotBlank(vehicleSelectVo.getVehicleStateValue())) {
if ("出库".equals(vehicleSelectVo.getVehicleStateValue())) {
SalesReturn.SalesReturnDetailDto salesReturnDetailDto = new SalesReturn.SalesReturnDetailDto();
// SalesReturn.SalesReturnDetailDto salesReturnDetailDto = new SalesReturn.SalesReturnDetailDto();
BusSalesReturnOrdersDto busSalesReturnOrdersDto = new BusSalesReturnOrdersDto();
busSalesReturnOrdersDto.setVinSid(vehSid);
busSalesReturnOrdersDto.setOrgSidPath(finalBusSalesOrderOne.getOrgSidPath());
busSalesReturnOrdersDto.setVinNo(busSalesOrderReturnVehDetailsVo.getVinNo());
if (StringUtils.isNotBlank(vehicleSelectVo.getOrgCode())) {
salesReturn.setFSaleOrgId(vehicleSelectVo.getOrgCode());
/*salesReturn.setFSaleOrgId(vehicleSelectVo.getOrgCode());
salesReturn.setFStockOrgId(vehicleSelectVo.getOrgCode());
salesReturnDetailDto.setFOwnerId(vehicleSelectVo.getOrgCode());
salesReturnDetailDto.setFOwnerId(vehicleSelectVo.getOrgCode());*/
busSalesReturnOrdersDto.setSaleOrgId(vehicleSelectVo.getOrgCode());
}
List<BaseSalesReturnVo> returnVos = baseVehicleOutFeign.selectByVehReturn(vehSid, busSalesOrderReturnVehApply.getContractNo()).getData();
@ -713,24 +717,24 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService<BusSa
busSalesReturnOrdersDto.setMaterialCode(returnVo.getMaterialCode());
busSalesReturnOrdersDto.setIsFree("0");
busSalesReturnOrdersDto.setRealQty(realQty);
salesReturnDetailDto.setFMaterialId(returnVo.getMaterialCode());
/* salesReturnDetailDto.setFMaterialId(returnVo.getMaterialCode());
salesReturnDetailDto.setFIsFree("false");
salesReturnDetailDto.setFRealQty(realQty);
salesReturnDetailDto.setFUnitID("liang");
salesReturnDetailDto.setFDeliveryDate(sdf.format(new Date()));
salesReturn.setFDate(sdf.format(new Date()));
salesReturn.setFDate(sdf.format(new Date()));*/
}
if (StringUtils.isNotBlank(returnVo.getCustomerNo())) {
salesReturn.setCustomerNo(returnVo.getCustomerNo());
// salesReturn.setCustomerNo(returnVo.getCustomerNo());
busSalesReturnOrdersDto.setCustomerNo(returnVo.getCustomerNo());
}
if (StringUtils.isNotBlank(billNo)) {
salesReturn.setBillNo(billNo);
// salesReturn.setBillNo(billNo);
busSalesReturnOrdersDto.setBillNo(billNo);
}
busSalesReturnOrdersService.saveReturnOrders(busSalesReturnOrdersDto);
salesReturnDetailDto.setFOwnerTypeId("业务组织");
salesReturnDetails.add(salesReturnDetailDto);
/* salesReturnDetailDto.setFOwnerTypeId("业务组织");
salesReturnDetails.add(salesReturnDetailDto);*/
}
}
@ -747,6 +751,18 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService<BusSa
busDeliveredApplyDetailsService.updateIsDel(vehSid);
//删除推送的单车返利管理
scmVehRebateFeign.delByVehSid2(vehSid,busSalesOrderReturnVehApply.getUseOrgSid(),"029");
//对已经出库的车推送销售退货单----------2025-04-03
SalOutStockPushSalReturnStock.SalesReturnDetailDto salesReturnDetailDto = new SalOutStockPushSalReturnStock.SalesReturnDetailDto();
ReturnPushVo returnPushVo = baseMapper.selectByVinSid(vehSid);
if(returnPushVo != null){
salesReturnDetailDto.setFMaterialId(returnPushVo.getMaterialCode());
salesReturnDetailDto.setBillNo(returnPushVo.getBillNo());
salesReturnDetailDtoList.add(salesReturnDetailDto);
}
}
//------------------------修改车辆持久状态--------------------------
BusSalesOrderVehicle busSalesOrderVehicle = busSalesOrderVehicleService.fetchBySid(busSalesOrderReturnVehDetailsVo.getBusVinSid());
@ -809,10 +825,15 @@ public class BusSalesOrderReturnVehApplyService extends MybatisBaseService<BusSa
try {
//----------------------------推送金蝶销售退货单---------------------------------
salesReturnDetails.removeAll(Collections.singleton(null));
/* salesReturnDetails.removeAll(Collections.singleton(null));
if (!salesReturnDetails.isEmpty()) {
salesReturn.setSalesReturnDetails(salesReturnDetails);
finKingDeeFeign.draftSalesReturnOrders(salesReturn);
}*/
salesReturnDetailDtoList.removeAll(Collections.singleton(null));
if(!salesReturnDetailDtoList.isEmpty()){
salOutStockPushSalReturnStock.setStockDtoList(salesReturnDetailDtoList);
finKingDeeFeign.draftSalesReturnOrders(salOutStockPushSalReturnStock);
}
} catch (Exception e) {
e.printStackTrace();

4
anrui-fin/anrui-fin-api/src/main/java/com/yxt/anrui/fin/api/kingdee/FinKingDeeFeign.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;
@ -361,6 +362,7 @@ public interface FinKingDeeFeign {
@ApiOperation("下推销售退货单的接口")
@PostMapping("/draftSalesReturnOrders")
@ResponseBody
ResultBean<String> draftSalesReturnOrders(@RequestBody @Valid SalesReturn salesReturn);
// ResultBean<String> draftSalesReturnOrders(@RequestBody @Valid SalesReturn salesReturn);
ResultBean<String> draftSalesReturnOrders(@RequestBody @Valid SalOutStockPushSalReturnStock salReturnStock) throws Exception;
}

3
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<String> draftSalesReturnOrders(SalesReturn salesReturn) {
public ResultBean<String> draftSalesReturnOrders(SalOutStockPushSalReturnStock salesReturn) {
return null;
}

38
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<SalesReturnDetailDto> 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;
}
}

12
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<String> draftSalesReturnOrders(SalesReturn salesReturn) {
/* public ResultBean<String> draftSalesReturnOrders(SalesReturn salesReturn) {
log.info("FinKingDeeFeignRest-draftSalesReturnOrders:{}", JSONObject.toJSONString(salesReturn));
return salesReturnOrdersService.salesReturnOrdersService(salesReturn);
}*/
public ResultBean<String> draftSalesReturnOrders(SalOutStockPushSalReturnStock salReturnStock) throws Exception {
log.info("FinKingDeeFeignRest-draftSalesReturnOrders:{}", JSONObject.toJSONString(salReturnStock));
return pushReturnService.getReturnStock(salReturnStock);
}
@ApiOperation("暂存收款单的接口")

67
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.dataJson格式数据详情参考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,...}"非必录 传到转换插件的操作选项中平台不会解析里面的值
* <p>
* 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<String> 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<String, Object> CustomParams = new HashMap<>();
}
}

34
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);
}
}
}

51
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<String> getReturnStock() throws Exception {
SalOutStockPushSalReturnStock salOutStockPushSalReturnStock = new SalOutStockPushSalReturnStock();
List<SalOutStockPushSalReturnStock.SalesReturnDetailDto> 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;
}
}

158
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<String> getReturnStock(SalOutStockPushSalReturnStock salOutStockPushSalReturnStock) throws Exception {
ResultBean<String> rb = ResultBean.fireFail();
Map<String, List<SalOutStockPushSalReturnStock.SalesReturnDetailDto>> groupedByBillNo = salOutStockPushSalReturnStock.getStockDtoList()
.stream()
.collect(Collectors.groupingBy(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getBillNo));
// 3. 循环处理每个出库单
for (Map.Entry<String, List<SalOutStockPushSalReturnStock.SalesReturnDetailDto>> entry : groupedByBillNo.entrySet()) {
String billNo = entry.getKey();
List<SalOutStockPushSalReturnStock.SalesReturnDetailDto> 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<String> resultBeans = accessKingDeeInterface(KingDeeBillId.SAL_RETURNSTOCK.getID(),
kingDeeData, KingDeeBillUrl.PUSH_URL.getURL());
if (!resultBeans.getSuccess()) {
log.info("下推失败!");
return rb.setMsg("下推失败!");
}
String data = resultBeans.getData();
/* ResultBean<String> 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<String> 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<Map<String, String>> extractPairs(JSONArray array) {
ArrayList<Map<String, String>> 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<String, String> 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<String> 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;
}
}

271
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<String> getReturnStock(SalOutStockPushSalReturnStock salOutStockPushSalReturnStock) throws Exception {
ResultBean<String> rb = ResultBean.fireFail();
// 1. 收集所有物料ID和出库单号
List<SalOutStockPushSalReturnStock.SalesReturnDetailDto> allDetails = salOutStockPushSalReturnStock.getStockDtoList();
// 2. 获取所有出库单号(去重)
Set<String> billNos = allDetails.stream()
.map(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getBillNo)
.collect(Collectors.toSet());
// 3. 获取所有出库单的Entry信息
Map<String, String[]> 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<String> 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<String> 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<String> 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<String> billNos, Map<String, String[]> map) {
List<String> allEntryIds = new ArrayList<>();
for (String billNo : billNos) {
// 1. 预处理物料IDs
Set<String> 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<Map<String, String>> extractPairs = extractPairs(outStockEntryS);
List<String> matchedEntryIds = new ArrayList<>();
for (int i = 0; i < extractPairs.size(); i++) {
Map<String, String> 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<Map<String, String>> extractPairs(JSONArray array) {
ArrayList<Map<String, String>> 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<String, String> 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<String, String [ ]> 其中key是出库单号value是该出库单对应的物料ID数组
*/
private Map<String, String[]> getBillNoToEntriesMap(Set<String> billNos,
List<SalOutStockPushSalReturnStock.SalesReturnDetailDto> allDetails) {
// 1. 按出库单号分组明细数据
Map<String, List<SalOutStockPushSalReturnStock.SalesReturnDetailDto>> groupedByBillNo = allDetails.stream()
.collect(Collectors.groupingBy(SalOutStockPushSalReturnStock.SalesReturnDetailDto::getBillNo));
// 2. 转换为Map<String, String[]>格式
Map<String, String[]> result = new HashMap<>();
for (Map.Entry<String, List<SalOutStockPushSalReturnStock.SalesReturnDetailDto>> entry : groupedByBillNo.entrySet()) {
String billNo = entry.getKey();
List<SalOutStockPushSalReturnStock.SalesReturnDetailDto> 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<String> 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<String> 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;
}
}
}
Loading…
Cancel
Save