clearing-service http://jira.mfd.msk:8088/browse/CLS-200 Сверка VerificationResult
This commit is contained in:
parent
f61f28eb7b
commit
6032bba359
5 changed files with 357 additions and 145 deletions
|
|
@ -0,0 +1,93 @@
|
||||||
|
package ru.clearing.classes.statics.data.clearing;
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
import ru.clearing.classes.objects.BusinessObject;
|
||||||
|
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
|
||||||
|
public class VerificationResult extends BusinessObject {
|
||||||
|
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
private String clearingCode;
|
||||||
|
private Long accountId;
|
||||||
|
private BigDecimal inSum;
|
||||||
|
private BigDecimal outIntSum;
|
||||||
|
private BigDecimal outExtSum;
|
||||||
|
private BigDecimal diffSum;
|
||||||
|
private Long generationId;
|
||||||
|
private String generationStatus;
|
||||||
|
private String resultStatus;
|
||||||
|
|
||||||
|
public String getClearingCode() {
|
||||||
|
return clearingCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClearingCode(String clearingCode) {
|
||||||
|
this.clearingCode = clearingCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountId(Long accountId) {
|
||||||
|
this.accountId = accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getInSum() {
|
||||||
|
return inSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInSum(BigDecimal inSum) {
|
||||||
|
this.inSum = inSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getOutIntSum() {
|
||||||
|
return outIntSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutIntSum(BigDecimal outIntSum) {
|
||||||
|
this.outIntSum = outIntSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getOutExtSum() {
|
||||||
|
return outExtSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutExtSum(BigDecimal outExtSum) {
|
||||||
|
this.outExtSum = outExtSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getDiffSum() {
|
||||||
|
return diffSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDiffSum(BigDecimal diffSum) {
|
||||||
|
this.diffSum = diffSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getGenerationId() {
|
||||||
|
return generationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGenerationId(Long generationId) {
|
||||||
|
this.generationId = generationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGenerationStatus() {
|
||||||
|
return generationStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGenerationStatus(String generationStatus) {
|
||||||
|
this.generationStatus = generationStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResultStatus() {
|
||||||
|
return resultStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResultStatus(String resultStatus) {
|
||||||
|
this.resultStatus = resultStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,8 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import ru.clearing.classes.objects.BusinessObject;
|
import ru.clearing.classes.objects.BusinessObject;
|
||||||
import ru.clearing.classes.statics.data.account.Account;
|
import ru.clearing.classes.statics.data.account.Account;
|
||||||
|
import ru.clearing.classes.statics.data.clearing.VerificationResult;
|
||||||
|
import ru.clearing.classes.statics.data.company.Company;
|
||||||
import ru.clearing.classes.statics.data.sdf.SDf01;
|
import ru.clearing.classes.statics.data.sdf.SDf01;
|
||||||
import ru.clearing.classes.statics.data.account.AccountBalance;
|
import ru.clearing.classes.statics.data.account.AccountBalance;
|
||||||
import ru.clearing.classes.statics.data.sdf.SDf03;
|
import ru.clearing.classes.statics.data.sdf.SDf03;
|
||||||
|
|
@ -19,9 +21,13 @@ import ru.spcex.platform.classes.base.interfaces.WithId;
|
||||||
import ru.spcex.platform.enumeration.AccountType;
|
import ru.spcex.platform.enumeration.AccountType;
|
||||||
import ru.spcex.platform.enumeration.ResultStatuses;
|
import ru.spcex.platform.enumeration.ResultStatuses;
|
||||||
import ru.spcex.platform.imdg.api.Imdg;
|
import ru.spcex.platform.imdg.api.Imdg;
|
||||||
|
import ru.spcex.platform.imdg.api.ImdgId;
|
||||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||||
|
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -34,57 +40,125 @@ import java.util.stream.Collectors;
|
||||||
public class VerificationResultComponent {
|
public class VerificationResultComponent {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
// private final ImdgProvider imdgProvider;
|
private final ImdgProvider imdgProvider;
|
||||||
private Imdg<SDf01> sdf01Imdg;
|
private Imdg<SDf01> sdf01Imdg;
|
||||||
private Imdg<AccountBalance> accountBalanceImdg;
|
private Imdg<AccountBalance> accountBalanceImdg;
|
||||||
private Imdg<Account> accountImdg;
|
private Imdg<Account> accountImdg;
|
||||||
|
private Imdg<Company> companyImdg;
|
||||||
|
|
||||||
|
private ImdgId idGenerator;
|
||||||
|
private Imdg<VerificationResult> verificationResultImdg;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public VerificationResultComponent(ImdgProvider imdgProvider
|
public VerificationResultComponent(ImdgProvider imdgProvider) {
|
||||||
) {
|
this.imdgProvider = imdgProvider;
|
||||||
// this.imdgProvider = imdgProvider;
|
|
||||||
this.sdf01Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class);
|
this.sdf01Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class);
|
||||||
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
|
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
|
||||||
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
|
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
|
||||||
|
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||||
|
|
||||||
//this.idGenerator = imdgProvider.getImdgIdGenerator();
|
this.idGenerator = imdgProvider.getImdgIdGenerator();
|
||||||
|
this.verificationResultImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_VerificationResult, VerificationResult.class);
|
||||||
//this.kafkaSender = KafkaSender kafkaSender
|
//this.kafkaSender = KafkaSender kafkaSender
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void executeRevision() {
|
protected void executeRevision() {
|
||||||
|
log.debug("Prepare verification, get data...");
|
||||||
Collection<SDf01> allSDf01 = sdf01Imdg.getAllValues();
|
Collection<SDf01> allSDf01 = sdf01Imdg.getAllValues();
|
||||||
Collection<AccountBalance> allAccountBalance = accountBalanceImdg.getAllValues();
|
Collection<AccountBalance> allAccountBalance = accountBalanceImdg.getAllValues();
|
||||||
Collection<Account> allAccount = accountImdg.getAllValues();
|
Collection<Account> allAccount = accountImdg.getAllValues();
|
||||||
|
log.debug("Execute verification.");
|
||||||
executeRevision(allSDf01, allAccountBalance, allAccount);
|
executeRevision(allSDf01, allAccountBalance, allAccount);
|
||||||
|
log.debug("All verification was done.");
|
||||||
//todo результат logic... см. как было в корпе?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void executeRevision(Collection<SDf01> allSDf01, Collection<AccountBalance> allAccountBalance, Collection<Account> allAccount) {
|
protected void executeRevision(Collection<SDf01> allSDf01, Collection<AccountBalance> allAccountBalance, Collection<Account> allAccount) {
|
||||||
// 1. Сумму по остаткам
|
// 1. Сумму по остаткам
|
||||||
List<Object/*verificationResult*/> vResLst = new ArrayList<>();
|
List<VerificationResult> vResLst = new ArrayList<>();
|
||||||
/* todo use:
|
|
||||||
<verificationResult name="Результаты сверки" destination="verification-results" class="com.spicex.Static." table="verification_result">
|
Map<Long, List<AccountBalance>> companyAccountBalance = indexList(allAccountBalance, AccountBalance::getCompanyId);
|
||||||
<clearingCode type="2" length="255" name="Код участника клиринга" shortname="Клиринговый код" searchable="true" sortable="true" visible="true"/>
|
Map<Long, List<Account>> companyAccount = indexList(allAccount, Account::getCompanyId);
|
||||||
<accountId type="1" name="Счет УК, по которому проводится сверка" shortname="Счет УК" searchable="true" sortable="true"/>
|
Map<Long, List<SDf01>> companySDf01;
|
||||||
<inSum type="11" name="Входящая сумма остатков" shortname="Остатки" visible="true" searchable="true" sortable="true"/>
|
|
||||||
<outIntSum type="11" name="Исходящая сумма остатков, полученная в КС" shortname="Остатки, полученные в КС" visible="true" searchable="true" sortable="true"/>
|
|
||||||
<outExtSum type="11" name="Исходящая сумма остатков из отчета ПРЦ" shortname="Остатки, полученные из ПРЦ" visible="true" searchable="true" sortable="true"/>
|
|
||||||
<diffSum type="11" name="Сумма расхождений" shortname="Сумма расхождений" visible="true" searchable="true" sortable="true"/>
|
|
||||||
<generationId type="1" name="Идентификатор взаимодействия" shortname="ID взаимодействия" searchable="true" sortable="true"/>
|
|
||||||
<generationStatus type="12" name="Общий статус сверки" shortname="Статус" searchable="true" sortable="true" visible="true" link="resultStatus"/>
|
|
||||||
<resultStatus type="12" name="Статус сверки" shortname="Статус" searchable="true" sortable="true" visible="true" link="resultStatus"/>
|
|
||||||
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
|
|
||||||
<createdAt type="4" name="Дата и время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
|
|
||||||
<updatedAt type="4" name="Дата и время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
|
|
||||||
</verificationResult>
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
|
Map<String, Long> indexCompanyIdByAccount = new HashMap<>();
|
||||||
|
for (Account account : allAccount) {
|
||||||
|
if (account.getAccount() != null && account.getCompanyId() != null) {
|
||||||
|
indexCompanyIdByAccount.put(account.getAccount(), account.getCompanyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
companySDf01 = indexList(allSDf01, sDf01 -> indexCompanyIdByAccount.get(sDf01.getAccount()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Long> allPresentCompanyId = new HashSet<>();
|
||||||
|
allPresentCompanyId.addAll(companyAccountBalance.keySet());
|
||||||
|
allPresentCompanyId.addAll(companyAccount.keySet());
|
||||||
|
allPresentCompanyId.addAll(companySDf01.keySet());
|
||||||
|
log.info("Found {} AccountBalance, {} Account, {} SDf01 for {} companyId's.",
|
||||||
|
allAccountBalance.size(), allAccount.size(), allSDf01.size(), allPresentCompanyId.size());
|
||||||
|
for (Long companyId : allPresentCompanyId) {
|
||||||
|
Company company = companyImdg.getSingleObjectByID(companyId);
|
||||||
|
if (company == null) {
|
||||||
|
log.warn("Company {} not found! Ignore verification for this.", companyId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<AccountBalance> localCompanyAccountBalance = companyAccountBalance.get(companyId);
|
||||||
|
List<Account> localCompanyAccount = companyAccount.get(companyId);
|
||||||
|
List<SDf01> localCompanySDf01 = companySDf01.get(companyId);
|
||||||
|
if (localCompanyAccountBalance == null) localCompanyAccountBalance = new ArrayList<>();
|
||||||
|
if (localCompanyAccount == null) localCompanyAccount = new ArrayList<>();
|
||||||
|
if (localCompanySDf01 == null) localCompanySDf01 = new ArrayList<>();
|
||||||
|
log.debug("Verification company[{}] with {} AccountBalance, {} Account, {} SDf01.",
|
||||||
|
companyId, localCompanyAccountBalance.size(), localCompanyAccount.size(),
|
||||||
|
localCompanySDf01.size());
|
||||||
|
try {
|
||||||
|
List<VerificationResult> result = checkOnCompany(company,
|
||||||
|
localCompanySDf01, localCompanyAccountBalance, localCompanyAccount);
|
||||||
|
log.trace("For company {} get {} ResultStatuses record", companyId, result.size());
|
||||||
|
for (VerificationResult rItem : result) {
|
||||||
|
verificationResultImdg.insert(rItem);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error verification for company {}: {}",
|
||||||
|
companyId, ExceptionUtils.getStackTrace(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param forCompany
|
||||||
|
* @param accountId Account.id by Account.account
|
||||||
|
* @return new
|
||||||
|
*/
|
||||||
|
VerificationResult newVerification(Company forCompany, Long accountId) {
|
||||||
|
VerificationResult vResult = new VerificationResult();
|
||||||
|
vResult.setId(idGenerator.nextId()); // imdg
|
||||||
|
vResult.setCreated(Instant.now());
|
||||||
|
if (forCompany != null) {
|
||||||
|
vResult.setClearingCode(forCompany.getClearingCode());
|
||||||
|
}
|
||||||
|
if (accountId != null) {
|
||||||
|
vResult.setAccountId(accountId); // accountId bigint = Из accountBalance.account
|
||||||
|
}
|
||||||
|
return vResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<VerificationResult> checkOnCompany(Company forCompany, Collection<SDf01> allSDf01,
|
||||||
|
Collection<AccountBalance> allAccountBalance,
|
||||||
|
Collection<Account> allAccount) {
|
||||||
|
ArrayList<VerificationResult> checks = new ArrayList<>();
|
||||||
|
|
||||||
|
Map<String, Long> indexAccountIdByAccount = new HashMap<>();
|
||||||
|
for (Account account : allAccount) {
|
||||||
|
if (account.getAccount() != null) {
|
||||||
|
indexAccountIdByAccount.put(account.getAccount(), account.getCompanyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // 1.70 verificationResult
|
||||||
Map<String, SDf01> indexSDf01 = index(allSDf01, SDf01::getAccount);
|
Map<String, SDf01> indexSDf01 = index(allSDf01, SDf01::getAccount);
|
||||||
for (AccountBalance account : allAccountBalance) {
|
for (AccountBalance account : allAccountBalance) {
|
||||||
VerificationResult vResult = new VerificationResult();
|
VerificationResult vResult = newVerification(forCompany, indexAccountIdByAccount.get(account.getAccount()));
|
||||||
vResult.setAccountId(account.getAccountId());
|
checks.add(vResult);
|
||||||
|
|
||||||
SDf01 document = indexSDf01.get(account.getAccount());
|
SDf01 document = indexSDf01.get(account.getAccount());
|
||||||
if (document == null) {
|
if (document == null) {
|
||||||
|
|
@ -100,9 +174,14 @@ public class VerificationResultComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BigDecimal balance = account.getCloseBalanceAmount() == null ? BigDecimal.ZERO : account.getCloseBalanceAmount();
|
BigDecimal balance = account.getCloseBalanceAmount() == null ? BigDecimal.ZERO : account.getCloseBalanceAmount();
|
||||||
//todo сравнить правильно, remainder там без точек. remainder==balance
|
// сравнить remainder==balance
|
||||||
BigDecimal diff = balance.subtract(remainder).abs();
|
BigDecimal diff = balance.subtract(remainder).setScale(2, RoundingMode.HALF_UP).abs();
|
||||||
vResult.setDiffSum(diff);
|
vResult.setDiffSum(diff);
|
||||||
|
vResult.setInSum(account.getOpenBalanceAmount());
|
||||||
|
vResult.setOutIntSum(account.getCloseBalanceAmount());
|
||||||
|
vResult.setOutExtSum(remainder);
|
||||||
|
//todo похоже надо группировку по String account сделать, сверить с ТЗ.
|
||||||
|
log.trace("company[{}] AccountBalance[{}] diff = {}", forCompany.getId(), account.getId(), diff);
|
||||||
if (BigDecimal.ZERO.compareTo(diff) == 0) {
|
if (BigDecimal.ZERO.compareTo(diff) == 0) {
|
||||||
vResult.setResultStatus(ResultStatuses.success.getKey());
|
vResult.setResultStatus(ResultStatuses.success.getKey());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -115,7 +194,6 @@ public class VerificationResultComponent {
|
||||||
// 2.1 Номера торговых/клиринговых счетов, соответствующие загруженным в КС
|
// 2.1 Номера торговых/клиринговых счетов, соответствующие загруженным в КС
|
||||||
// -sDf01.deal = account.account & accountType=CLRN & accountStatus=UNBL
|
// -sDf01.deal = account.account & accountType=CLRN & accountStatus=UNBL
|
||||||
{
|
{
|
||||||
// Map<String, SDf01> indexSDf01 = index(allSDf01, SDf01::getDeal);
|
|
||||||
Set<String> sDf01Keys = allSDf01.stream()
|
Set<String> sDf01Keys = allSDf01.stream()
|
||||||
.filter(sdf01 -> sdf01.getDeal() != null)
|
.filter(sdf01 -> sdf01.getDeal() != null)
|
||||||
.map(sdf01 -> sdf01.getDeal())
|
.map(sdf01 -> sdf01.getDeal())
|
||||||
|
|
@ -126,35 +204,46 @@ public class VerificationResultComponent {
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
boolean isOk = sDf01Keys.size() == accountKeys.size() &&
|
boolean isOk = sDf01Keys.size() == accountKeys.size() &&
|
||||||
sDf01Keys.containsAll(accountKeys) && accountKeys.containsAll(sDf01Keys);
|
sDf01Keys.containsAll(accountKeys) && accountKeys.containsAll(sDf01Keys);
|
||||||
// for (Account account:allAccount) {
|
|
||||||
// if (AccountType.Clrn.equalsByKey(account.getAccountType()) & "UNBL".equals(account.getAccountStatus())) {
|
VerificationResult vResult = newVerification(forCompany, null);
|
||||||
// // todo use enum/const ?
|
checks.add(vResult);
|
||||||
// SDf01 document = indexSDf01.get(account.getAccount());
|
if (isOk) {
|
||||||
// if (document == null) {
|
vResult.setResultStatus(ResultStatuses.success.getKey());
|
||||||
// //todo найдено несоответствие.
|
} else {
|
||||||
// } else {
|
vResult.setResultStatus(ResultStatuses.notSuccess.getKey());
|
||||||
// }
|
}
|
||||||
// }
|
log.trace("Control summ 1, count: sDf01Keys={}, accountKeys={}; check result:{}",
|
||||||
// }
|
sDf01Keys.size(), accountKeys.size(), vResult.getResultStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.2 Количество торговых/клиринговых счетов, соответствующие загруженным в КС - COUNT[sDf01.deal] = COUNT [account.account]
|
// 2.2 Количество торговых/клиринговых счетов, соответствующие загруженным в КС - COUNT[sDf01.deal] = COUNT [account.account]
|
||||||
{
|
{
|
||||||
long countSDf01 = allSDf01.stream().filter(sDf01 -> sDf01.getDeal() != null).count();
|
long countSDf01 = allSDf01.stream().filter(sDf01 -> sDf01.getDeal() != null).count();
|
||||||
long countAccount = allAccount.stream().filter(account -> account.getAccount() != null).count();
|
long countAccount = allAccount.stream().filter(account -> account.getAccount() != null).count();
|
||||||
log.info("countSDf01={}, countAccount={}", countSDf01 ,countAccount);
|
boolean isOk = countSDf01 == countAccount;
|
||||||
//todo countSDf01 != countAccount
|
VerificationResult vResult = newVerification(forCompany, null);
|
||||||
|
checks.add(vResult);
|
||||||
|
if (isOk) {
|
||||||
|
vResult.setResultStatus(ResultStatuses.success.getKey());
|
||||||
|
} else {
|
||||||
|
vResult.setResultStatus(ResultStatuses.notSuccess.getKey());
|
||||||
|
}
|
||||||
|
log.trace("countSDf01={}, countAccount={}, result: {}",
|
||||||
|
countSDf01, countAccount, vResult.getResultStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.3 Суммарный остаток по счетам
|
// 2.3 Суммарный остаток по счетам
|
||||||
{
|
{
|
||||||
//todo не понял условия [sDf01.account = accountBalance.account]
|
Map<String, BigDecimal> summOfSDf01 = new HashMap<>();
|
||||||
long summSDf01 = 0;
|
|
||||||
for (SDf01 document : allSDf01) {
|
for (SDf01 document : allSDf01) {
|
||||||
if (StringUtils.isEmpty(document.getRemainder())) {
|
if (StringUtils.isEmpty(document.getRemainder())) {
|
||||||
try {
|
try {
|
||||||
long value = Long.parseLong(document.getRemainder());
|
String account = document.getAccount();
|
||||||
summSDf01 += value;
|
BigDecimal value = new BigDecimal(document.getRemainder());
|
||||||
|
BigDecimal a = summOfSDf01.get(account);
|
||||||
|
if (a == null) a = BigDecimal.ZERO;
|
||||||
|
a = a.add(value);
|
||||||
|
summOfSDf01.put(account, a);
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
log.warn("SDf01[{}].remainder=\"{}\" is not parseable: {}",
|
log.warn("SDf01[{}].remainder=\"{}\" is not parseable: {}",
|
||||||
document.getId(), document.getRemainder(), nfe.getMessage());
|
document.getId(), document.getRemainder(), nfe.getMessage());
|
||||||
|
|
@ -163,29 +252,55 @@ public class VerificationResultComponent {
|
||||||
log.debug("SDf01[{}].remainder is null or empty", document.getId());
|
log.debug("SDf01[{}].remainder is null or empty", document.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long summAccount = 0;
|
Map<String, BigDecimal> summOfAccountBalance = new HashMap<>();
|
||||||
for (AccountBalance account : allAccountBalance) {
|
for (AccountBalance account : allAccountBalance) {
|
||||||
if (account.getCloseBalanceAmount() != null) {
|
if (account.getCloseBalanceAmount() != null) {
|
||||||
long value = account.getCloseBalanceAmount().longValue();
|
String accountKey = account.getAccount();
|
||||||
summAccount += value;
|
BigDecimal value = account.getCloseBalanceAmount();
|
||||||
|
;
|
||||||
|
BigDecimal a = summOfAccountBalance.get(accountKey);
|
||||||
|
if (a == null) a = BigDecimal.ZERO;
|
||||||
|
a = a.add(value);
|
||||||
|
summOfAccountBalance.put(accountKey, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// todo summSDf01==summAccount теперь с точностью и погрешностью сравнений проблема.
|
// summSDf01==summAccount
|
||||||
|
Set<String> allAccountStr = new HashSet<>();
|
||||||
|
allAccountStr.addAll(summOfSDf01.keySet());
|
||||||
|
allAccountStr.addAll(summOfAccountBalance.keySet());
|
||||||
|
for (String account : allAccountStr) {
|
||||||
|
BigDecimal fromBalance = summOfAccountBalance.get(account);
|
||||||
|
BigDecimal fromSDf01 = summOfSDf01.get(account);
|
||||||
|
if (fromBalance == null)
|
||||||
|
fromBalance = BigDecimal.ZERO;
|
||||||
|
else
|
||||||
|
fromBalance = fromBalance.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
if (fromSDf01 == null)
|
||||||
|
fromSDf01 = BigDecimal.ZERO;
|
||||||
|
else
|
||||||
|
fromSDf01 = fromSDf01.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
BigDecimal diff = fromBalance.subtract(fromSDf01).setScale(2, RoundingMode.HALF_UP).abs();
|
||||||
|
|
||||||
|
VerificationResult vResult = newVerification(forCompany, indexAccountIdByAccount.get(account));
|
||||||
|
checks.add(vResult);
|
||||||
|
if (BigDecimal.ZERO.compareTo(diff) == 0) {
|
||||||
|
vResult.setResultStatus(ResultStatuses.success.getKey());
|
||||||
|
} else {
|
||||||
|
vResult.setResultStatus(ResultStatuses.notSuccess.getKey());
|
||||||
|
}
|
||||||
|
vResult.setDiffSum(diff);
|
||||||
|
vResult.setOutExtSum(fromSDf01);
|
||||||
|
log.trace("for comapny[{}], account \"{}\" summ of fromSDf01={}, of fromBalance={}; result {}",
|
||||||
|
forCompany.getId(), account, fromSDf01, fromBalance, vResult.getResultStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Сверка остатков по клиринговым счетам СПВБ
|
boolean hasMissmatch = checks.stream()
|
||||||
{
|
.anyMatch(check -> ResultStatuses.notSuccess.equalsByKey(check.getResultStatus()));
|
||||||
//todo не понял [sDf01.account = accountBalance.account & accountType=INFO]
|
final String finalStatus = hasMissmatch ? ResultStatuses.notSuccess.getKey() : ResultStatuses.success.getKey();
|
||||||
}
|
log.trace("For company {} set GenerationStatus = {}", forCompany.getId(), finalStatus);
|
||||||
}
|
for (VerificationResult check : checks) check.setGenerationStatus(finalStatus);
|
||||||
|
return checks;
|
||||||
|
|
||||||
protected void onSuccessRevisionResult() {
|
|
||||||
//todo 17.1 - Сообщение пользователю об успешной сверке
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onDetectDiffRevisionResult() {
|
|
||||||
//todo 17.2 - Сообщение пользователю в случае выявления расхождений
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -211,89 +326,14 @@ public class VerificationResultComponent {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo to classes: VerificationResult!
|
public static <K, V extends WithId> Map<K, List<V>> indexList(Collection<V> from, Function<V, K> indexFieldExtractor) {
|
||||||
static class VerificationResult extends BusinessObject {
|
Map<K, List<V>> index = new HashMap<>();
|
||||||
private String clearingCode; // type="2"
|
for (V obj : from) {
|
||||||
private Long accountId; // type="1"
|
K key = indexFieldExtractor.apply(obj);
|
||||||
private BigDecimal inSum; // type="11"
|
List<V> lst = index.computeIfAbsent(key, (_key_) -> new ArrayList<>());
|
||||||
private BigDecimal outIntSum; // type="11"
|
lst.add(obj);
|
||||||
private BigDecimal outExtSum; // type="11"
|
|
||||||
private BigDecimal diffSum; // type="11"
|
|
||||||
private Long generationId; // type="1"
|
|
||||||
private String generationStatus; // type="12"
|
|
||||||
private String resultStatus; // type="12"
|
|
||||||
|
|
||||||
public String getClearingCode() {
|
|
||||||
return clearingCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClearingCode(String clearingCode) {
|
|
||||||
this.clearingCode = clearingCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getAccountId() {
|
|
||||||
return accountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccountId(Long accountId) {
|
|
||||||
this.accountId = accountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getInSum() {
|
|
||||||
return inSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInSum(BigDecimal inSum) {
|
|
||||||
this.inSum = inSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getOutIntSum() {
|
|
||||||
return outIntSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutIntSum(BigDecimal outIntSum) {
|
|
||||||
this.outIntSum = outIntSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getOutExtSum() {
|
|
||||||
return outExtSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutExtSum(BigDecimal outExtSum) {
|
|
||||||
this.outExtSum = outExtSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getDiffSum() {
|
|
||||||
return diffSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDiffSum(BigDecimal diffSum) {
|
|
||||||
this.diffSum = diffSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getGenerationId() {
|
|
||||||
return generationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGenerationId(Long generationId) {
|
|
||||||
this.generationId = generationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGenerationStatus() {
|
|
||||||
return generationStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGenerationStatus(String generationStatus) {
|
|
||||||
this.generationStatus = generationStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getResultStatus() {
|
|
||||||
return resultStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResultStatus(String resultStatus) {
|
|
||||||
this.resultStatus = resultStatus;
|
|
||||||
}
|
}
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package ru.spcex.clearing.imdg.object;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.clearing.classes.statics.data.clearing.VerificationResult;
|
||||||
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
|
import ru.spcex.clearing.imdg.base.TemplateMapStore;
|
||||||
|
import ru.spcex.platform.utils.time.TimeUtil;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class VerificationResultMapStore extends TemplateMapStore<VerificationResult> {
|
||||||
|
|
||||||
|
public VerificationResultMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMapName() {
|
||||||
|
return IMDGDistributedNames.Map_VerificationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableName() {
|
||||||
|
return "VERIFICATION_RESULT";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getFields() {
|
||||||
|
return new String[]{
|
||||||
|
"CLEARING_CODE", "ACCOUNT_ID", "IN_SUM", "OUT_INT_SUM", "OUT_EXT_SUM", "DIFF_SUM", "GENERATION_ID", "GENERATION_STATUS", "RESULT_STATUS",
|
||||||
|
"ID", "CREATED_AT", "UPDATED_AT"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VerificationResult objectReader(ResultSet resultSet) throws SQLException {
|
||||||
|
VerificationResult object = new VerificationResult();
|
||||||
|
object.setClearingCode(resultSet.getObject("CLEARING_CODE", String.class));
|
||||||
|
object.setAccountId(resultSet.getObject("ACCOUNT_ID", Long.class));
|
||||||
|
object.setInSum(resultSet.getObject("IN_SUM", BigDecimal.class));
|
||||||
|
object.setOutIntSum(resultSet.getObject("OUT_INT_SUM", BigDecimal.class));
|
||||||
|
object.setOutExtSum(resultSet.getObject("OUT_EXT_SUM", BigDecimal.class));
|
||||||
|
object.setDiffSum(resultSet.getObject("DIFF_SUM", BigDecimal.class));
|
||||||
|
object.setGenerationId(resultSet.getObject("GENERATION_ID", Long.class));
|
||||||
|
object.setGenerationStatus(resultSet.getObject("GENERATION_STATUS", String.class));
|
||||||
|
object.setResultStatus(resultSet.getObject("RESULT_STATUS", String.class));
|
||||||
|
object.setId(resultSet.getObject("ID", Long.class));
|
||||||
|
object.setCreated(getInstantFromTimestamp(resultSet, "CREATED_AT"));
|
||||||
|
object.setUpdated(getInstantFromTimestamp(resultSet, "UPDATED_AT"));
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] objectToField(VerificationResult object) {
|
||||||
|
Object[] args = new Object[]{
|
||||||
|
object.getClearingCode(),
|
||||||
|
object.getAccountId(),
|
||||||
|
object.getInSum(),
|
||||||
|
object.getOutIntSum(),
|
||||||
|
object.getOutExtSum(),
|
||||||
|
object.getDiffSum(),
|
||||||
|
object.getGenerationId(),
|
||||||
|
object.getGenerationStatus(),
|
||||||
|
object.getResultStatus(),
|
||||||
|
object.getId(),
|
||||||
|
TimeUtil.toDateFromInstant(object.getCreated()),
|
||||||
|
TimeUtil.toDateFromInstant(object.getUpdated())
|
||||||
|
};
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package ru.spcex.clearing.imdg.structure;
|
package ru.spcex.clearing.imdg.structure;
|
||||||
|
|
||||||
import ru.clearing.classes.statics.data.account.*;
|
import ru.clearing.classes.statics.data.account.*;
|
||||||
|
import ru.clearing.classes.statics.data.clearing.VerificationResult;
|
||||||
import ru.clearing.classes.statics.data.company.Company;
|
import ru.clearing.classes.statics.data.company.Company;
|
||||||
import ru.clearing.classes.statics.data.company.CompanyHistory;
|
import ru.clearing.classes.statics.data.company.CompanyHistory;
|
||||||
import ru.clearing.classes.statics.data.company.CompanyRoleSet;
|
import ru.clearing.classes.statics.data.company.CompanyRoleSet;
|
||||||
|
|
@ -77,6 +78,7 @@ public class RunnableMapNamesForTesting {
|
||||||
new SettingOperation("setAmount", new Class[]{BigDecimal.class}, new Object[]{new BigDecimal("23.22")})));
|
new SettingOperation("setAmount", new Class[]{BigDecimal.class}, new Object[]{new BigDecimal("23.22")})));
|
||||||
businessObjectAndBusinessEventForCheckMapStores.add(new BusinessObjectAndBusinessEventForCheckMapStore<>(IMDGDistributedNames.Map_UserConnect, UserConnect.class));
|
businessObjectAndBusinessEventForCheckMapStores.add(new BusinessObjectAndBusinessEventForCheckMapStore<>(IMDGDistributedNames.Map_UserConnect, UserConnect.class));
|
||||||
businessObjectAndBusinessEventForCheckMapStores.add(new BusinessObjectAndBusinessEventForCheckMapStore<>(IMDGDistributedNames.Map_User, User.class));
|
businessObjectAndBusinessEventForCheckMapStores.add(new BusinessObjectAndBusinessEventForCheckMapStore<>(IMDGDistributedNames.Map_User, User.class));
|
||||||
|
businessObjectAndBusinessEventForCheckMapStores.add(new BusinessObjectAndBusinessEventForCheckMapStore<>(IMDGDistributedNames.Map_VerificationResult, VerificationResult.class));
|
||||||
|
|
||||||
//dictionary
|
//dictionary
|
||||||
dictionaryObjectForCheckMapStores.add(new DictionaryObjectForCheckMapStore<>(IMDGDistributedNames.Map_AccountStatusDictionary, AccountStatusDictionary.class));
|
dictionaryObjectForCheckMapStores.add(new DictionaryObjectForCheckMapStore<>(IMDGDistributedNames.Map_AccountStatusDictionary, AccountStatusDictionary.class));
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,9 @@ public final class IMDGDistributedNames {
|
||||||
public static final String Map_ReportRegister = "Map_ReportRegister";
|
public static final String Map_ReportRegister = "Map_ReportRegister";
|
||||||
public static final String Map_ContractRegister = "Map_ContractRegister";
|
public static final String Map_ContractRegister = "Map_ContractRegister";
|
||||||
public static final String Map_OrderRegister = "Map_OrderRegister";
|
public static final String Map_OrderRegister = "Map_OrderRegister";
|
||||||
|
public static final String Map_VerificationResult = "Map_VerificationResult";
|
||||||
|
|
||||||
public static final String MAP_SEQUENCE_NAME = "MAP_SEQUENCE_NAME"; // todo вынести idGenerator отдельно и завернуть в метод, чтобы не напрямую обращаться.
|
public static final String MAP_SEQUENCE_NAME = "MAP_SEQUENCE_NAME";
|
||||||
|
|
||||||
private IMDGDistributedNames() {
|
private IMDGDistributedNames() {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue