This commit is contained in:
mzr 2025-03-11 10:55:21 +08:00
parent ff835002e9
commit f7183c871d
2 changed files with 3091 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,661 @@
/*kOCZ2rdZQh+oO4IyZSOXGg0LHHc/urYgAeiJss7fL0A=*/
package nc.vo.glrp.com.verify;
import nc.bs.logging.Logger;
import nc.vo.gateway60.itfs.Currency;
import nc.vo.gateway60.pub.GlBusinessException;
import nc.vo.glcom.shellsort.CShellSort;
import nc.vo.glcom.sorttool.CVoSortTool;
import nc.vo.glrp.pub.VerifyMsg;
import nc.vo.glrp.pub.VoComparer;
import nc.vo.glrp.verify.VerifyDetailKey;
import nc.vo.glrp.verify.VerifyDetailVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
/**
* @author mzr
* @ClassName: MultiMatch
* @Description: 异币种借贷核销实现类
* @date 2013-6-18 下午01:49:19
*/
public class MultiMatch implements IMatchTool {
public IVerifyVO[] m_debitvos;
public IVerifyVO[] m_creditvos;
private VerifyRuleVO m_rulevo;
private List<ILogVO> m_alLogs;
private Hashtable<String, List<IVerifyVO>> m_hash;
private VoComparer m_comparer;
private String pk_accountingbook;
private String pk_user;
private String pk_group;
private UFDate oprDate;
public String getPk_user() {
return this.pk_user;
}
public void setPk_user(String pk_user) {
this.pk_user = pk_user;
}
public String getPk_group() {
return this.pk_group;
}
public void setPk_group(String pk_group) {
this.pk_group = pk_group;
}
public UFDate getOprDate() {
return this.oprDate;
}
public void setOprDate(UFDate oprDate) {
this.oprDate = oprDate;
}
public void setDebitData(IVerifyVO[] debtDataVos) {
this.m_debitvos = debtDataVos;
}
public IVerifyVO[] getDebitData() {
return this.m_debitvos;
}
public void setCreditData(IVerifyVO[] creditDataVo) {
this.m_creditvos = creditDataVo;
}
public IVerifyVO[] getCreditData() {
return this.m_creditvos;
}
public void setRule(VerifyRuleVO rulevo) {
this.m_rulevo = rulevo;
}
public VerifyRuleVO getRule() {
return this.m_rulevo;
}
private Hashtable<String, List<IVerifyVO>> getHash() {
if (this.m_hash == null) {
this.m_hash = new Hashtable();
}
return this.m_hash;
}
private VoComparer getComparer() {
if (this.m_comparer == null) {
this.m_comparer = new VoComparer();
}
return this.m_comparer;
}
/**
* <p>Title: </p>
* <p>Description: </p>
*/
public MultiMatch() {
}
/* ( Javadoc)
* <p>Title: getLogData</p>
* <p>Description: </p>
* @return
* @see nc.vo.glrp.com.verify.IMatchTool#getLogData()
*/
public ILogVO[] getLogData() {
if (this.m_alLogs != null && !this.m_alLogs.isEmpty()) {
try {
ILogVO[] logs = (ILogVO[]) Array.newInstance(this.m_alLogs.get(0).getClass(), this.m_alLogs.size());
logs = (ILogVO[]) this.m_alLogs.toArray(logs);
return logs;
} catch (Exception ex) {
Logger.error(ex.getMessage(), ex);
return null;
}
} else {
return null;
}
}
/* ( Javadoc)
* <p>Title: getToolName</p>
* <p>Description: </p>
* @return
* @see nc.vo.glrp.com.verify.IMatchTool#getToolName()
*/
public String getToolName() {
return "GLMultiMatch";
}
/* ( Javadoc)
* <p>Title: onMatch</p>
* <p>Description: 异币种核销匹配算法 </p>
* @see nc.vo.glrp.com.verify.IMatchTool#onMatch()
*/
public void onMatch() throws Exception {
try {
// 检查借贷方数据为空
checkData();
removeOldData();
perpareData();
boolean bDebitLoop = true;
String shashKey;
bDebitLoop = (getDebitData().length < getCreditData().length);
IVerifyVO[] voloop = bDebitLoop ? getDebitData() : getCreditData();
String[] sObjkeys = bDebitLoop ? getRule().getDebtObjKeys() : getRule().getCreditObjKeys();
UFDouble[] dealMny = new UFDouble[2];// 记录较少的一方的未核销金额
UFDouble[] oppMny = new UFDouble[2];// 记录较多的一方的未核销金额
UFDouble[] verifyMny = new UFDouble[2];// 本次核销金额
if (getRule().getDateName() != null && getRule().getMaxDateError() != null) {
getComparer().setCompareKey(new String[]{getRule().getDateName()});
getComparer().setDaterange(getRule().getMaxDateError().intValue());
}
List<IVerifyVO> alOpp = null;
IVerifyVO voOpp = null;
for (int i = 0; i < voloop.length; i++) {
if (bDebitLoop) {
dealMny[0] = voloop[i].getDebit_Money_Y();
dealMny[1] = voloop[i].getDebit_Money_B();
} else {
dealMny[0] = voloop[i].getCredit_Money_Y();
dealMny[1] = voloop[i].getCredit_Money_B();
}
if (isSettled(dealMny)) {
continue;
}
shashKey = gethashKey(voloop[i], sObjkeys);
try {
alOpp = getHash().get(shashKey);
if (alOpp == null || alOpp.size() == 0) {
continue;
}
} catch (Exception ex) {
continue;
}
for (int j = 0; j < alOpp.size(); ) {
if (isSettled(dealMny)) {// 如果记录较少的一方未核销金额为0则表示改记录已核销完继续下一条记录
break;
}
voOpp = (IVerifyVO) alOpp.get(j);
if (bDebitLoop) {
oppMny[0] = voOpp.getCredit_Money_Y();
oppMny[1] = voOpp.getCredit_Money_B();
} else {
oppMny[0] = voOpp.getDebit_Money_Y();
oppMny[1] = voOpp.getDebit_Money_B();
}
if (isSettled(oppMny)) {
alOpp.remove(j);
continue;
}
if (!existInDateRange(voloop[i], voOpp)) {
j++;
continue;
}
//--add by pangjsh 判断数据方向是否同向
if (!isVerifyEnable(voloop[i], voOpp, bDebitLoop)) {
j++;
continue;
}
/*判断核销金额*/
/*如果是红对兰则按照兰字金额核销*/
for (int m = 0; m < verifyMny.length; m++) {
if (dealMny[m] != null && oppMny[m] != null) {// 取借贷方未核销金额少的作为本次核销金额
verifyMny[m] = dealMny[m].abs().compareTo(oppMny[m].abs()) > 0 ? oppMny[m] : dealMny[m];
} else {
verifyMny[m] = ZERO;
}
}
if (isSettled(verifyMny)) {
j++;
continue;
}
/*形成log回写余额*/
// 计算本次核销后记录较多的一方的未核销金额
if (bDebitLoop) {
m_alLogs.addAll(generateLogs(verifyMny, voloop[i], voOpp));
if (voOpp.getCredit_Money_Y() != null && !verifyMny[0].equals(ZERO)) {
voOpp.setCredit_Money_Y(
voOpp.getCredit_Money_Y().sub(verifyMny[0], verifyMny[0].getPower()));
}
if (voOpp.getCredit_Money_B() != null && !verifyMny[1].equals(ZERO)) {
voOpp.setCredit_Money_B(
voOpp.getCredit_Money_B().sub(verifyMny[1], verifyMny[1].getPower()));
}
} else {
m_alLogs.addAll(generateLogs(verifyMny, voOpp, voloop[i]));
if (voOpp.getDebit_Money_Y() != null && !verifyMny[0].equals(ZERO)) {
voOpp.setDebit_Money_Y(
voOpp.getDebit_Money_Y().sub(verifyMny[0], verifyMny[0].getPower()));
}
if (voOpp.getDebit_Money_B() != null && !verifyMny[1].equals(ZERO)) {
voOpp.setDebit_Money_B(
voOpp.getDebit_Money_B().sub(verifyMny[1], verifyMny[1].getPower()));
}
}
// 计算本次核销后记录较少的一方的未核销金额
for (int n = 0; n < dealMny.length; n++) {
if (dealMny[n] != null && !verifyMny[n].equals(ZERO)) {
dealMny[n] = dealMny[n].sub(verifyMny[n], verifyMny[n].getPower());
}
}
if (bDebitLoop) {
if (isSettled(new UFDouble[]{voOpp.getCredit_Money_Y(),
voOpp.getCredit_Money_B()})) {
alOpp.remove(j);
}
} else {
if (isSettled(new UFDouble[]{voOpp.getDebit_Money_Y(),
voOpp.getDebit_Money_B()})) {
alOpp.remove(j);
}
}
}
/*回写余额*/
if (bDebitLoop) {
voloop[i].setDebit_Money_Y(dealMny[0]);
voloop[i].setDebit_Money_B(dealMny[1]);
} else {
voloop[i].setCredit_Money_Y(dealMny[0]);
voloop[i].setCredit_Money_B(dealMny[1]);
}
}
} catch (Exception e) {
Logger.error(e.getMessage(), e);
throw new GlBusinessException(e.getMessage());
}
}
/**
* @param @throws BusinessException
* @return void
* @throws
* @Title: checkData
* @Description: 检查借贷方数据为空
*/
private void checkData() throws BusinessException {
if (getDebitData() == null || getDebitData().length == 0 || getCreditData() == null || getCreditData().length == 0) {
throw new BusinessException(VerifyMsg.getMSG_NOVERIFYDATA());
}
}
/**
* @param
* @return void
* @throws
* @Title: removeOldData
* @Description: 清除旧数据
*/
private void removeOldData() {
m_alLogs = new ArrayList<ILogVO>();
getHash().clear();
}
/**
* @param @throws Exception
* @return void
* @throws
* @Title: perpareData
* @Description: TODO(准备新数据)
*/
private void perpareData() throws BusinessException {
try {
// 借贷方有数据不存在就返回
if (getDebitData() == null || getDebitData().length == 0 || getCreditData() == null || getCreditData().length == 0) {
return;
}
// 按币种格式化借方金额
for (int i = 0; i < getDebitData().length; i++) {
// todo 1
String currPk = getDebitData()[i].getCurrPk();
getDebitData()[i].setDebit_Money_Y(Currency.formatByCurrType(currPk, getDebitData()[i].getDebit_Money_Y()));
getDebitData()[i].setDebit_Money_B(Currency.formatByCurrType(Currency.getLocalCurrPK(getPk_accountingbook()), getDebitData()[i].getDebit_Money_B()));
}
// 按币种格式化贷方金额
for (int i = 0; i < getCreditData().length; i++) {
// todo 1
String currPk = getCreditData()[i].getCurrPk();
getCreditData()[i].setCredit_Money_Y(Currency.formatByCurrType(currPk, getCreditData()[i].getCredit_Money_Y()));
getCreditData()[i].setCredit_Money_B(Currency.formatByCurrType(Currency.getLocalCurrPK(getPk_accountingbook()), getCreditData()[i].getCredit_Money_B()));
}
// 按规则排序借方数据
sortData(true, getRule().getDebtSortKeys());
// 按规则排序贷方数据
sortData(false, getRule().getCreditSortKeys());
if (getCreditData().length > getDebitData().length) {
fill2Hash(getCreditData(), false);
} else {
fill2Hash(getDebitData(), true);
}
} catch (Exception e) {
Logger.error(e.getMessage(), e);
throw new GlBusinessException(e.getMessage());
}
}
/**
* @param isDebit
* @param sortKeys
* @throws Exception
* @Title: sortData
* @Description: TODO(按照设置的排序字段排序)
*/
private void sortData(boolean isDebit, String[] sortKeys) throws Exception {
if (sortKeys != null && sortKeys.length > 0) {
int[] iIndex = sortKeys[0].equals("prepareddate") ?
new int[]{VerifyDetailKey.VOUCHDATE, VerifyDetailKey.VOUCHERTYPENAME,
VerifyDetailKey.DISP_VOUCHERNO, VerifyDetailKey.DETAILINDEX} :
new int[]{VerifyDetailKey.BUSINESSDATE, VerifyDetailKey.VOUCHERTYPENAME,
VerifyDetailKey.DISP_VOUCHERNO, VerifyDetailKey.DETAILINDEX};
CShellSort objShellSort = new CShellSort();
CVoSortTool objVoSortTool = new CVoSortTool();
objVoSortTool.setSortIndex(iIndex);
objShellSort.sort(isDebit ? getDebitData() : getCreditData(), objVoSortTool, !getRule().getVerifySeq().booleanValue());
} else {
getComparer().setDaterange(0);
getComparer().setAscend(getRule().getVerifySeq().booleanValue());
getComparer().setCompareKey(new String[]{getRule().getDateName()});
Arrays.sort(getDebitData(), getComparer());
}
}
/**
* @param @param vos
* @param @param bDebit
* @return void
* @throws
* @Title: fill2Hash
* @Description: TODO(将数据添加到hash表中)
*/
private void fill2Hash(IVerifyVO[] vos, boolean bDebit) {
// 得到核销部分标准按核销号金额相等末级科目按对账标识码按辅助项中的全部或部分
String[] sKeys = (bDebit ? getRule().getDebtObjKeys() : getRule().getCreditObjKeys());
String sCurrKey = null;
List<IVerifyVO> oCurrValues = null;
for (int i = 0; i < vos.length; i++) {
sCurrKey = gethashKey(vos[i], sKeys);
oCurrValues = getHash().get(sCurrKey);
if (oCurrValues == null) {
oCurrValues = new ArrayList<IVerifyVO>();
}
if (isEqual(vos[i], sKeys)) {
oCurrValues.add(vos[i]);
getHash().put(sCurrKey, oCurrValues);
}
}
}
/**
* @param @param verifyvo
* @param @param skeys
* @param @return
* @return String
* @throws
* @Title: gethashKey
* @Description: TODO(得到hash键值)
*/
private String gethashKey(IVerifyVO verifyvo, String[] skeys) {
StringBuffer shashKey = new StringBuffer();
if (skeys == null || skeys.length <= 0) {
return "null";
}
Object ob = null;
for (int i = 0; i < skeys.length; i++) {
if (skeys[i].equals("Mny")) {
// modified by shipl 2015-11-12 15:26:58 原币相等即可核销
if (verifyvo.getDirect().equals(IVerifyVO.I_DEBIT)) { /*借方*/
ob = verifyvo.getDebit_Money_Y();
shashKey.append("_").append(ob == null ? "null" : ob.toString());
// ob = verifyvo.getDebit_Money_B();
// shashKey.append("_").append(ob == null ? "null" : ob.toString());
} else { /*贷方*/
ob = verifyvo.getCredit_Money_Y();
shashKey.append("_").append(ob == null ? "null" : ob.toString());
// ob = verifyvo.getCredit_Money_B();
// shashKey.append("_").append(ob == null ? "null" : ob.toString());
}
} else {
ob = verifyvo.getAttributeValue(skeys[i]);
shashKey.append("_").append(ob == null ? "null" : ob.toString());
}
}
return shashKey.toString();
}
/**
* @param @param vo 当前待核销的数据
* @param @param sKeys 核销部分标准按核销号金额相等末级科目按对账标识码按辅助项中的全部或部分
* @param @return
* @return boolean
* @throws
* @Title: isEqual
* @Description: TODO(判断数据的辅助核算与自动核销按辅助项中辅助核算是否一致)
*/
private boolean isEqual(IVerifyVO vo, String[] sKeys) {
boolean result = true;
VerifyDetailVO vo1 = (VerifyDetailVO) vo;
if (null != sKeys && sKeys.length > 0) {
for (int i = 0; i < sKeys.length; i++) {
if (null != sKeys[i] && sKeys[i].startsWith("fzhs_")) {
String asstype = sKeys[i].substring(5, 25);
String assvalue = sKeys[i].substring(25);
for (int j = 0; vo1.getAss() != null && j < vo1.getAss().length; j++) {
if (vo1.getAss()[j] != null) {
if (vo1.getAss()[j].getPk_Checktype().equals(asstype)) {
if (!"null".equals(assvalue) && !isExists(vo1.getAss()[j].getPk_Checkvalue(), assvalue)) {
result = false;
break;
}
}
}
}
}
}
}
return result;
}
/**
* @param @param pk_checkvalue 比如pk_checkvalue="100288100000000000K2"
* @param @param assvalue 比如assvalue="100288100000000000K1,100288100000000000K2"
* @param @return
* @return boolean
* @throws
* @Title: isExists
* @Description: TODO(判断pk_checkvalue是否存在于assvalue中)
*/
private boolean isExists(String pk_checkvalue, String assvalue) {
String[] tmpArr = assvalue.split(",");
if (null != tmpArr && tmpArr.length > 0) {
for (int i = 0; i < tmpArr.length; i++) {
if (null != tmpArr[i] && tmpArr[i].equals(pk_checkvalue)) {
return true;
}
}
}
return false;
}
/**
* @param @param vo1
* @param @param vo2
* @param @return
* @return boolean
* @throws
* @Title: existInDateRange
* @Description: TODO(判断两vo是否在核销规则的日期误差天数内)
*/
private boolean existInDateRange(IVerifyVO vo1, IVerifyVO vo2) {
if (getRule().getMaxDateError() != null) {
getComparer().setDaterange(getRule().getMaxDateError().intValue());
getComparer().setCompareKey(new String[]{getRule().getDateName()});
return getComparer().compare(vo1, vo2) == 0 ? true : false;
}
return true;
}
/**
* 功能判断两vo是否数据同向
* 作者逄居升
* 创建时间(2014-6-19 13:05:15)
* 参数<|>
* 返回值
* 算法
*
* @param vo1 nc.vo.glrp.com.verify.IVerifyVO
* @param vo2 nc.vo.glrp.com.verify.IVerifyVO
* @return boolean
*/
private boolean isVerifyEnable(IVerifyVO vo1, IVerifyVO vo2, boolean bDebitLoop) {
if (bDebitLoop) {
UFDouble[] debit = new UFDouble[]{vo1.getDebit_Money_Y(), vo1.getDebit_Money_B()};
UFDouble[] credit = new UFDouble[]{vo2.getCredit_Money_Y(), vo2.getCredit_Money_B()};
for (int i = 0; i < debit.length; i++) {
if ((debit[i].doubleValue() > 0 && credit[i].doubleValue() > 0)
|| (debit[i].doubleValue() < 0 && credit[i].doubleValue() < 0)
|| (debit[i].equals(ZERO) && credit[i].equals(ZERO))) {// 本币原币不一致的可能原币已等于0而本币不等于0
continue;
} else {
return false;
}
}
} else {
UFDouble[] credit = new UFDouble[]{vo1.getCredit_Money_Y(), vo1.getCredit_Money_B()};
UFDouble[] debit = new UFDouble[]{vo2.getDebit_Money_Y(), vo2.getDebit_Money_B()};
for (int i = 0; i < debit.length; i++) {
if ((debit[i].doubleValue() > 0 && credit[i].doubleValue() > 0)
|| (debit[i].doubleValue() < 0 && credit[i].doubleValue() < 0)
|| (debit[i].equals(ZERO) && credit[i].equals(ZERO))) {
continue;
} else {
return false;
}
}
}
return true;
}
/**
* @param @param ufdMny 未核销余额
* @param @return
* @return boolean
* @throws
* @Title: isSettled
* @Description: TODO(判断一条数据的原币和组织本币金额是否已全部核销完)
*/
private boolean isSettled(UFDouble[] ufdMny) {
if (ufdMny == null || ufdMny.length < 1) {
return true;
}
for (int i = 0; i < ufdMny.length; i++) {
if (!ufdMny[i].equals(ZERO)) {
return false;
}
}
return true;
}
/* ( Javadoc)
* <p>Title: getPk_accountingbook</p>
* <p>Description: </p>
* @return
* @see nc.vo.glrp.com.verify.IMatchTool#getPk_accountingbook()
*/
@Override
public String getPk_accountingbook() {
return this.pk_accountingbook;
}
/* ( Javadoc)
* <p>Title: setPk_accountingbook</p>
* <p>Description: </p>
* @param pkAccountingbook
* @see nc.vo.glrp.com.verify.IMatchTool#setPk_accountingbook(java.lang.String)
*/
@Override
public void setPk_accountingbook(String pkAccountingbook) {
this.pk_accountingbook = pkAccountingbook;
}
/**
* @param @param verifyMoney 本次核销金额
* @param @param voDebit 借方数据
* @param @param voCredit 贷方数据
* @param @return
* @return List<ILogVO> 返回借贷方核销日志VO集合
* @throws
* @Title: generateLogs
* @Description: TODO(生成一条借方和一条贷方数据核销的核销日志)
*/
private List<ILogVO> generateLogs(UFDouble[] verifyMoney, IVerifyVO voDebit, IVerifyVO voCredit) {
List<ILogVO> logVOList = new ArrayList<ILogVO>();
// 借方数据核销日志
ILogVO debitLog = LogVOFactory.getNewLogVO(getRule().getLogClassName());
debitLog.setBatchID(getRule().getBatchId());
debitLog.setVerifyObjPK(getRule().getDebitVerifyObj());
debitLog.setOppVerifyObjPK(getRule().getCreditVerifyObj());
debitLog.setData(voDebit);
debitLog.setDataPk(voDebit.getPk());
debitLog.setDebitBalaMny_y(verifyMoney[0]);
debitLog.setDebitBalaMny_b(verifyMoney[1]);
debitLog.setCreDitBalaMny_b(ZERO);
debitLog.setCreDitBalaMny_y(ZERO);
debitLog.setFlag(MainFlag);// todo 1
debitLog.setOppData(voCredit);
debitLog.setOppDataPk(voCredit.getPk());
debitLog.setOprDate(getOprDate());
debitLog.setOprPk(getPk_user());
// debitLog.setOprType(ILogVO.VERIFY);
debitLog.setOprType(2); // 异币种核销 todo 1
debitLog.setPairNum(getRule().getNextPairNum());
debitLog.setPk_group(getPk_group());
logVOList.add(debitLog);
// 贷方数据核销日志
ILogVO creditLog = LogVOFactory.getNewLogVO(getRule().getLogClassName());
creditLog.setBatchID(getRule().getBatchId());
creditLog.setVerifyObjPK(getRule().getCreditVerifyObj());
creditLog.setOppVerifyObjPK(getRule().getDebitVerifyObj());
creditLog.setData(voCredit);
creditLog.setDataPk(voCredit.getPk());
creditLog.setDebitBalaMny_b(ZERO);
creditLog.setDebitBalaMny_y(ZERO);
creditLog.setCreDitBalaMny_y(verifyMoney[0]);
creditLog.setCreDitBalaMny_b(verifyMoney[1]);
creditLog.setFlag(AssFlag);// todo 1
creditLog.setOppData(voDebit);
creditLog.setOppDataPk(voDebit.getPk());
creditLog.setOprDate(getOprDate());
creditLog.setOprPk(getPk_user());
// creditLog.setOprType(ILogVO.VERIFY);
creditLog.setOprType(2); // 异币种核销 todo 1
creditLog.setPairNum(getRule().getPairNum());
creditLog.setPk_group(getPk_group());
logVOList.add(creditLog);
return logVOList;
}
}
/*kOCZ2rdZQh+oO4IyZSOXGg0LHHc/urYgAeiJss7fL0A=*/