上划和付款单增加sap凭证红冲

This commit is contained in:
yuxueliang0813 2025-08-01 11:32:06 +08:00
parent cf1a6e0fcc
commit 800b80a416
2 changed files with 276 additions and 3 deletions

View File

@ -20,14 +20,15 @@ import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.util.StringUtils;
import kd.sdk.plugin.Plugin;
import shjh.jhzj7.fi.fi.utils.ApiUtils;
import shjh.jhzj7.fi.fi.utils.EsbUtils;
import shjh.jhzj7.fi.fi.utils.JhzjUtils;
import shjh.jhzj7.fi.fi.utils.SysUtils;
import shjh.jhzj7.fi.fi.utils.domin.ResponseData;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static shjh.jhzj7.fi.fi.utils.SapUtils.*;
@ -35,10 +36,16 @@ import static shjh.jhzj7.fi.fi.utils.SapUtils.*;
/**
* 付款单推送SAP凭证操作插件
* shjh_cas_paybill_ext
* 0801增加sap凭证红冲处理
*/
public class PaybillPushSapOperation extends AbstractOperationServicePlugIn implements Plugin {
private static final String userName = "bos_user";//用户
private static final String INTERFACE_ID = "ReversalVoucher";//识别被调接口并进行路由-SAP反清账
private static final String RECEIVER_ID = "SAP";//定义的发送者
private static final String API_URL = System.getProperty("url_a");//sap相关接口地址
private static final String KEY_RED_PUSH = "redpunch";//sap红冲凭证的操作标记
@Override
public void onAddValidators(AddValidatorsEventArgs e) {
@ -78,6 +85,18 @@ public class PaybillPushSapOperation extends AbstractOperationServicePlugIn impl
}
}
}
}else if(KEY_RED_PUSH.equals(operateKey)){
//sap凭证红冲处理 前置校验
ExtendedDataEntity[] entities = this.getDataEntities();
for (ExtendedDataEntity entity : entities) {
DynamicObject prinfo = entity.getDataEntity();
prinfo = BusinessDataServiceHelper.loadSingle(prinfo.getPkValue(), "cas_paybill");
//判断付款处理单是否已生成金蝶凭证
if(!prinfo.getBoolean("shjh_ispushsap")){
this.addErrorMessage(entity, "未推送过SAP无需红冲");
return;
}
}
}
}
});
@ -820,9 +839,136 @@ public class PaybillPushSapOperation extends AbstractOperationServicePlugIn impl
this.operationResult.addErrorInfo(operateErrorInfo);
}
}
}else if(KEY_RED_PUSH.equals(operationKey)){
//sap凭证红冲处理
DynamicObject[] dos = e.getDataEntities();
DynamicObject prinfo = null;//付款处理单
JSONObject sapReturnData;
String billNumber;
StringBuilder message = new StringBuilder();
for (int i = 0; i < dos.length; i++) {
prinfo = BusinessDataServiceHelper.loadSingle(dos[i].getPkValue(), dos[i].getDataEntityType().getName());
if(prinfo.getBoolean("shjh_ispushsap")){
//如果付款处理单已推送sap才需要红冲
billNumber = prinfo.getString("billno");//单号
HashMap<String, String> responseHead = ApiUtils.buildHead(INTERFACE_ID,RECEIVER_ID);
HashMap<String, Object> responseBody = this.assembleRequest(billNumber, prinfo, message);
try {
String response = ApiUtils.sendPost(responseHead, responseBody, API_URL);
if (!EsbUtils.isEmpty(response)) {
boolean success = ApiUtils.parseResponse(response, billNumber, responseBody, "SAP反清账或冲销", message);
if (success){
//sap红冲凭证成功反写sap凭证号和推送标记
sapReturnData = JSONObject.parseObject(response);
JSONObject data = sapReturnData.getJSONObject("data");
JSONArray rows = data.getJSONArray("IT_ITEM");
JSONObject resultData = rows.getJSONObject(0);
String key = resultData.getString("OBJ_KEY");
if(EsbUtils.isEmpty(key)){
message.append("付款处理【").append(billNumber).append("】:").append("SAP返回的OBJ_KEY为空").append("\n");
}else{
//sap红冲凭证号根据返回值更新
prinfo.set("shjh_hcsappzh",key.length() >= 10 ? key.substring(0, 10) : key);
prinfo.set("shjh_ispushsap",false);//sap已推送标记-置为false让后续可以再推蓝字凭证
prinfo.set("shjh_credentialnum",null);//sap凭证号置为空
prinfo.set("shjh_sapfiscalyear",null);//sap年度置为空
SaveServiceHelper.update(prinfo);
}
}
}else{
message.append("付款处理【").append(billNumber).append("】:").append("SAP返回值为空").append("\n");
}
} catch (IOException ex) {
message.append("付款处理【").append(billNumber).append("】:").append(ex.getMessage()).append("\n");
// logger.info("调用付款红冲凭证接口异常"+message);
}
}
}
if (message.length() != 0){
OperateErrorInfo operateErrorInfo = new OperateErrorInfo();
operateErrorInfo.setMessage(String.valueOf(message));
operateErrorInfo.setErrorLevel(kd.bos.entity.validate.ErrorLevel.Error.name());
operateErrorInfo.setPkValue(prinfo.getPkValue());
this.operationResult.addErrorInfo(operateErrorInfo);
}
}
}
/**
* 请求头组装
* @param billNumber 单据编号
* @param recBill 付款处理
* @return
*/
private HashMap<String, Object> assembleRequest(String billNumber, DynamicObject recBill, StringBuilder message){
HashMap<String, Object> responseBody = null;
try {
// 生成唯一事务ID
String rootContextId = UUID.randomUUID().toString();
// 获取当前请求时间格式为 yyyy-MM-dd HH:mm:ss.SSS
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String requestTime = sdf.format(new Date());
responseBody = new HashMap<>(5);
responseBody.put("rootContextID", rootContextId);
responseBody.put("requestTime", requestTime);
HashMap<String, Object> data = new HashMap<>(1);
List<Map<String, Object>> IT_ITEM = new ArrayList<>(1);
//用户名-从红冲单上获取人员当前操作人可能是定时任务
DynamicObject userinfo = BusinessDataServiceHelper.loadSingleFromCache(RequestContext.get().getCurrUserId(), userName);
String oaUser = userinfo.getString("shjh_oauser");
//冲销原因
Map<String, Object> IT_ITEMS = new HashMap<>(6);
//红冲所需参数从红字付款单上获取红单上保留了原蓝字付款单的凭证号和会计年度
String BUKRS = "";
if (null != recBill.getDynamicObject("openorg")) {
BUKRS = recBill.getDynamicObject("openorg").getString("number");
}
if (StringUtils.isEmpty(BUKRS)) {
BUKRS = recBill.getDynamicObject("org").getString("number");
}
IT_ITEMS.put("BUKRS",BUKRS);//公司代码
IT_ITEMS.put("BELNR",recBill.getString("shjh_credentialnum"));//会计凭证编号
IT_ITEMS.put("GJAHR",recBill.getString("shjh_sapfiscalyear"));//会计年度
IT_ITEMS.put("STGRD","04");//冲销原因 跨期冲销默认04冲销日期必传
if(EsbUtils.isEmpty(oaUser)){
IT_ITEMS.put("UNAME","资金系统");//用户名
}else{
IT_ITEMS.put("UNAME",oaUser);//用户名
}
SimpleDateFormat sdfdate = new SimpleDateFormat("yyyy-MM-dd");
Date budate = getVoucherDate(recBill);
if(budate == null){
budate = recBill.getDate("bizdate");
if(budate == null){
IT_ITEMS.put("BUDAT",sdfdate.format(new Date()));//凭证中的过帐日期
}else{
IT_ITEMS.put("BUDAT",sdfdate.format(budate));//凭证中的过帐日期
}
}else {
IT_ITEMS.put("BUDAT",sdfdate.format(budate));//凭证中的过帐日期
}
IT_ITEM.add(IT_ITEMS);
data.put("IT_ITEM", IT_ITEM);
responseBody.put("data", data);
} catch (Exception e) {
message.append("付款处理【").append(billNumber).append("】:").append(e.getMessage()).append("\n");
EsbUtils.saveLog(billNumber, INTERFACE_ID, null, e.getMessage(), false, KEY_RED_PUSH, "数据异常");
}
return responseBody;
}
private Date getVoucherDate(DynamicObject bill){
//获得付款单对应的凭证记账日期
QFilter q1 = new QFilter("sourcebill", QCP.equals, bill.getPkValue());
QFilter q2 = new QFilter("billstatus",QCP.equals,"C");
DynamicObject gl_voucher = BusinessDataServiceHelper.loadSingle("gl_voucher",
"id,billno,bookeddate", new QFilter[]{q1, q2});
if(gl_voucher != null){
return gl_voucher.getDate("bookeddate");
}
return null;
}
private boolean isWB(DynamicObject bill){
//如果异币种支付= 异币种支付= 且付款币种不等于人民币取明细行中的 应付折本币
if(bill.getBoolean("isdiffcur") || !"CNY".equals(bill.getString("currency.number"))){

View File

@ -18,20 +18,24 @@ import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import shjh.jhzj7.fi.fi.utils.ApiUtils;
import shjh.jhzj7.fi.fi.utils.EsbUtils;
import shjh.jhzj7.fi.fi.utils.JhzjUtils;
import shjh.jhzj7.fi.fi.utils.SapUtils;
import shjh.jhzj7.fi.fi.utils.domin.ResponseData;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.*;
/**
* 上划处理
* shjh_fca_transupbill_ext
* 0801增加sap凭证红冲处理
*/
public class TransupbillOperation extends AbstractOperationServicePlugIn implements Plugin {
@ -42,6 +46,12 @@ public class TransupbillOperation extends AbstractOperationServicePlugIn impleme
private static final String ccName = "bos_costcenter";//成本中心
private static final String glbdName = "gl_assist_bd";//核算项目组合纵表
private static final String INTERFACE_ID = "ReversalVoucher";//识别被调接口并进行路由-SAP反清账
private static final String RECEIVER_ID = "SAP";//定义的发送者
private static final String API_URL = System.getProperty("url_a");//sap相关接口地址
private static final String KEY_RED_PUSH = "redpunch";//sap红冲凭证的操作标记
private final static Log logger = LogFactory.getLog(TransdownbillOperation.class);
@Override
@ -62,6 +72,21 @@ public class TransupbillOperation extends AbstractOperationServicePlugIn impleme
e.setCancel(true);
}
}
}else if(KEY_RED_PUSH.equals(eok)){
//sap凭证红冲处理 前置校验
DynamicObject[] dos = e.getDataEntities();
DynamicObject prinfo;
for (int i = 0; i < dos.length; i++) {
prinfo = BusinessDataServiceHelper.loadSingle(dos[i].getPkValue(), dos[i].getDataEntityType().getName());
//判断上划处理单是否已生成金蝶凭证
if(!prinfo.getBoolean("isvoucher")){
e.setCancelMessage(prinfo.getString("billno") + "未生成金蝶凭证无法推送SAP红冲凭证");
e.setCancel(true);
}else if(!prinfo.getBoolean("shjh_sendsap")){
e.setCancelMessage(prinfo.getString("billno") + "未推送过SAP无需红冲");
e.setCancel(true);
}
}
}
}
@ -99,9 +124,111 @@ public class TransupbillOperation extends AbstractOperationServicePlugIn impleme
}
}
}
}else if(KEY_RED_PUSH.equals(eok)){
//sap凭证红冲处理
DynamicObject[] dos = e.getDataEntities();
DynamicObject prinfo = null;//上划处理单
JSONObject sapReturnData;
String billNumber;
StringBuilder message = new StringBuilder();
for (int i = 0; i < dos.length; i++) {
prinfo = BusinessDataServiceHelper.loadSingle(dos[i].getPkValue(), dos[i].getDataEntityType().getName());
if(prinfo.getBoolean("shjh_sendsap")){
//如果上划处理单已推送sap才需要红冲
billNumber = prinfo.getString("billno");//单号
HashMap<String, String> responseHead = ApiUtils.buildHead(INTERFACE_ID,RECEIVER_ID);
HashMap<String, Object> responseBody = this.assembleRequest(billNumber, prinfo, message);
try {
String response = ApiUtils.sendPost(responseHead, responseBody, API_URL);
if (!EsbUtils.isEmpty(response)) {
boolean success = ApiUtils.parseResponse(response, billNumber, responseBody, "SAP反清账或冲销", message);
if (success){
//sap红冲凭证成功反写sap凭证号和推送标记
sapReturnData = JSONObject.parseObject(response);
JSONObject data = sapReturnData.getJSONObject("data");
JSONArray rows = data.getJSONArray("IT_ITEM");
JSONObject resultData = rows.getJSONObject(0);
String key = resultData.getString("OBJ_KEY");
if(EsbUtils.isEmpty(key)){
message.append("上划处理【").append(billNumber).append("】:").append("SAP返回的OBJ_KEY为空").append("\n");
}else{
//sap红冲凭证号根据返回值更新
prinfo.set("shjh_hcsappzh",key.length() >= 10 ? key.substring(0, 10) : key);
prinfo.set("shjh_sendsap",false);//sap已推送标记-置为false让后续可以再推蓝字凭证
prinfo.set("shjh_sappzh",null);//sap凭证号置为空
prinfo.set("shjh_sapyear",null);//sap年度置为空
SaveServiceHelper.update(prinfo);
}
}
}else{
message.append("上划处理【").append(billNumber).append("】:").append("SAP返回值为空").append("\n");
}
} catch (IOException ex) {
message.append("上划处理【").append(billNumber).append("】:").append(ex.getMessage()).append("\n");
logger.info("调用上划红冲凭证接口异常"+message);
}
}
}
if (message.length() != 0){
OperateErrorInfo operateErrorInfo = new OperateErrorInfo();
operateErrorInfo.setMessage(String.valueOf(message));
operateErrorInfo.setErrorLevel(kd.bos.entity.validate.ErrorLevel.Error.name());
operateErrorInfo.setPkValue(prinfo.getPkValue());
this.operationResult.addErrorInfo(operateErrorInfo);
}
}
}
/**
* 请求头组装
* @param billNumber 单据编号
* @param recBill 上划处理
* @return
*/
private HashMap<String, Object> assembleRequest(String billNumber, DynamicObject recBill, StringBuilder message){
HashMap<String, Object> responseBody = null;
try {
// 生成唯一事务ID
String rootContextId = UUID.randomUUID().toString();
// 获取当前请求时间格式为 yyyy-MM-dd HH:mm:ss.SSS
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String requestTime = sdf.format(new Date());
responseBody = new HashMap<>(5);
responseBody.put("rootContextID", rootContextId);
responseBody.put("requestTime", requestTime);
HashMap<String, Object> data = new HashMap<>(1);
List<Map<String, Object>> IT_ITEM = new ArrayList<>(1);
//用户名-从红冲单上获取人员当前操作人可能是定时任务
DynamicObject userinfo = BusinessDataServiceHelper.loadSingleFromCache(RequestContext.get().getCurrUserId(), userName);
String oaUser = userinfo.getString("shjh_oauser");
//冲销原因
Map<String, Object> IT_ITEMS = new HashMap<>(6);
//红冲所需参数从红字上划单上获取红单上保留了原蓝字上划单的凭证号和会计年度
IT_ITEMS.put("BELNR",recBill.getString("shjh_sappzh"));//会计凭证编号
IT_ITEMS.put("BUKRS",recBill.getString("company.number"));//公司代码
IT_ITEMS.put("GJAHR",recBill.getString("shjh_sapyear"));//会计年度
IT_ITEMS.put("STGRD","04");//冲销原因 跨期冲销默认04冲销日期必传
if(EsbUtils.isEmpty(oaUser)){
IT_ITEMS.put("UNAME","资金系统");//用户名
}else{
IT_ITEMS.put("UNAME",oaUser);//用户名
}
SimpleDateFormat sdfdate = new SimpleDateFormat("yyyy-MM-dd");
if(recBill.getDate("transbilldate") == null){
IT_ITEMS.put("BUDAT",sdfdate.format(new Date()));//凭证中的过帐日期
}else {
IT_ITEMS.put("BUDAT",sdfdate.format(recBill.getDate("transbilldate")));//凭证中的过帐日期
}
IT_ITEM.add(IT_ITEMS);
data.put("IT_ITEM", IT_ITEM);
responseBody.put("data", data);
} catch (Exception e) {
message.append("上划处理【").append(billNumber).append("】:").append(e.getMessage()).append("\n");
EsbUtils.saveLog(billNumber, INTERFACE_ID, null, e.getMessage(), false, KEY_RED_PUSH, "数据异常");
}
return responseBody;
}
private JSONObject sendBlueVoucher(DynamicObject prinfo, Map<String, String> sapMap){
//SAP上划处理单凭证接口入参组装和调用
JSONObject IS_HEADER = new JSONObject();//抬头