http://jira.mfd.msk:8088/browse/CLS-25 http://jira.mfd.msk:8088/browse/CLS-26 начало http://jira.mfd.msk:8088/browse/CLS-29 - написал выборку данных для формирования частей отчёта. TO DO

This commit is contained in:
AKurakin 2022-12-20 15:04:24 +03:00
parent 94f878c0b4
commit c4734252df
9 changed files with 354 additions and 34 deletions

View file

@ -4,12 +4,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.spcex.clearing.reports.reports.AbstractReport;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
public abstract class ReportDataCollector<T extends AbstractReport> {
public abstract class ReportDataCollector<T extends AbstractReport, R> {
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy'T'HH:mm:ss");
@ -20,15 +21,15 @@ public abstract class ReportDataCollector<T extends AbstractReport> {
* T extends ReportWithPeriod
* @return
*/
abstract public List<T> collectReportWithPeriod(LocalDate startDate, LocalDate endDate);
abstract public R collectReportWithPeriod(LocalDate startDate, LocalDate endDate);
/**
* T extends ReportWithClearingStatus
* @param startDate
* @param endDate
* @return
*/
abstract public List<T> collectReportWithClearingStatus(LocalDate startDate, LocalDate endDate, String clearingStatus);
// /**
// * T extends ReportWithClearingStatus
// * @param startDate
// * @param endDate
// * @return
// */
// abstract public List<T> collectReportWithClearingStatus(LocalDate startDate, LocalDate endDate, String clearingStatus);
/**
*
@ -38,4 +39,15 @@ public abstract class ReportDataCollector<T extends AbstractReport> {
* @return
*/
abstract public String getFileName(LocalDate startDate, LocalDate endDate, LocalDateTime dateTimeNow);
protected String toString(Long val) {
if (val == null) return null;
return val.toString();
}
protected String toString(Instant val) {
if (val == null) return null;
return DATE_TIME_FORMATTER.format(val);//todo проверить работает ли - юниттест.
}
}

View file

@ -11,17 +11,22 @@ import ru.clearing.platform.dictionary.ClearingStatusDictionary;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.reports.reports.bt_17_1.ReportBR_0420315_P1;
import ru.spcex.clearing.reports.services.ReportDataCollector;
import ru.spcex.platform.enumeration.ClearingCategory;
import ru.spcex.platform.enumeration.ClearingStatus;
import ru.spcex.platform.enumeration.Market;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class Bt17_1_collector extends ReportDataCollector<ReportBR_0420315_P1> {
public class Bt17_1_P1_collector extends ReportDataCollector<ReportBR_0420315_P1, List<ReportBR_0420315_P1>> {
protected static final List<String> ALLOW_CLEARING_MEMBER_CATEGORY = Arrays.asList(ClearingCategory.I.getKey(), ClearingCategory.V.getKey());
protected static final String ALLOW_CLEARING_STATUS = ClearingStatus.OK.getKey();
private Imdg<Company> companyImdg;
private Imdg<LiabilitiesClaimsAssets> liabilitiesClaimsAssetsImdg;
private Imdg<ClearingMemberCategory> clearingMemberCategoryImdg;
@ -29,7 +34,7 @@ public class Bt17_1_collector extends ReportDataCollector<ReportBR_0420315_P1> {
private Imdg<Listing> listingImdg;
@Autowired
public Bt17_1_collector(ImdgProvider imdgProvider) {
public Bt17_1_P1_collector(ImdgProvider imdgProvider) {
companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
liabilitiesClaimsAssetsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class);
clearingMemberCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
@ -46,41 +51,69 @@ public class Bt17_1_collector extends ReportDataCollector<ReportBR_0420315_P1> {
String ql = String.format("'%s' <= refundDate and refundDate <= '%s'", startDate, endDate);
Collection<LiabilitiesClaimsAssets> liabilities = liabilitiesClaimsAssetsImdg.getCollectionObjectsBySQL(ql);
for (LiabilitiesClaimsAssets liability : liabilities) {
ClearingStatusDictionary allowClearingStatus = clearingStatusDictionaryImdg.getSingleObjectByFieldValues(Map.of("code", ALLOW_CLEARING_STATUS));
if (allowClearingStatus == null) {
throw new IllegalStateException("ClearingStatusDictionary with code=\"" + ALLOW_CLEARING_STATUS + "\" not fount");
}
final Long allowClearingStatusId = allowClearingStatus.getId(); // "OK"
Collection<LiabilitiesClaimsAssets> filteredLiabilities = liabilities.stream()
.filter(liability -> allowClearingStatusId.equals(liability.getClearingStatus()))
.collect(Collectors.toList());
Map<Long, List<LiabilitiesClaimsAssets>> indexByCompany = MapUtil.indexList(filteredLiabilities, LiabilitiesClaimsAssets::getCompanyId);
for (LiabilitiesClaimsAssets liability : filteredLiabilities) {
final Long companyId = liability.getCompanyId();
Company company = companyImdg.getSingleObjectByID(companyId);
if (company != null) {
ClearingMemberCategory cmc = clearingMemberCategoryImdg.getSingleObjectByFieldValues(Map.of("companyId", companyId));
if (cmc == null || !Arrays.asList("I", "V", "I,V").contains(cmc.getClearingMemberCategory())) {
//todo уточнить фильтр need filter by I, V?
String checkCategory = cmc == null? null : cmc.getClearingMemberCategory();
if (!ALLOW_CLEARING_MEMBER_CATEGORY.contains(cmc.getClearingMemberCategory())) {
// фильтруются <> I, V
log.trace("Filtered ClearingMemberCategory[{}].ClearingMemberCategory={}",
cmc == null ? null : cmc.getId(), cmc == null ? null : cmc.getClearingMemberCategory());
continue;
}
ClearingStatusDictionary clearingStatus = clearingStatusDictionaryImdg.getSingleObjectByID(liability.getClearingStatus());
if (clearingStatus == null || !ClearingStatus.OK.getKey().equals(clearingStatus.getCode())) {
continue;
}
// ClearingStatusDictionary clearingStatus = clearingStatusDictionaryImdg.getSingleObjectByID(liability.getClearingStatus());
// if (clearingStatus == null || !ALLOW_CLEARING_STATUS.contains(clearingStatus.getCode())) {
// // фильтруются <> "OK" уже была, never
// log.warn("Found after filter LiabilitiesClaimsAssets[{}].getClearingStatus={}", liability.getId(), liability.getClearingStatus());
// continue;
// }
ReportBR_0420315_P1 reportBR_0420315_p1 = new ReportBR_0420315_P1(startDate, endDate,
"BR",
cmc.getClearingMemberCategory(),
clearingStatus.getCode());
ALLOW_CLEARING_STATUS //clearingStatus.getCode() "OK"
);
Listing listing;
{
Map qParam = new HashMap<>();
qParam.put("market", "MKRS"); // todo use const
qParam.put("market", Market.MKRS.getKey());
qParam.put("securityId", liability.getSecurityId());
listing = listingImdg.getSingleObjectByFieldValues(qParam);
}
// liability.getPrice()// todo как там с учётом валют это делать?
Integer contractorQty = StringUtils.isEmpty(liability.getContract()) ? 0 : 1; // todo то суммировать надо. Связь похоже много к 1. // liability.getContract() В данное поле необходимо записать общее количество исполненных договоров, шт. элемент contract из бизнес-объекта liabilitiesClaimsAssets
BigDecimal liabilitiesAmount = liability.getPrice() == null ? BigDecimal.ZERO : liability.getPrice(); // todo как правильно считать?
ReportBR_0420315_P1.Info_0420315_P1 info_0420315_p1 = new ReportBR_0420315_P1.Info_0420315_P1("companyId",
List<LiabilitiesClaimsAssets> allContract = indexByCompany.get(companyId);
long contractorQty;
double liabilitiesAmount = 0;
{
HashSet<String> collectedToSumm = new HashSet<>(); // чтобы дважды не посчитать 1 и тот же контракт
for (LiabilitiesClaimsAssets lContract : allContract) {
if (lContract.getPrice()!=null && StringUtils.isNotEmpty(lContract.getContract())
&& !collectedToSumm.contains(lContract.getContract())) {
collectedToSumm.add(lContract.getContract());
liabilitiesAmount += lContract.getLiabilitiesQuantity().doubleValue();
}
}
contractorQty = collectedToSumm.size();
}
ReportBR_0420315_P1.Info_0420315_P1 info_0420315_p1 = new ReportBR_0420315_P1.Info_0420315_P1(company.getId().toString(),
company.getFullName(),
listing == null ? null : listing.getMarket(),
contractorQty.toString(),
liabilitiesAmount.toString());
String.valueOf(contractorQty),
String.valueOf(liabilitiesAmount));
reportBR_0420315_p1.getRows().add(info_0420315_p1);
result.add(reportBR_0420315_p1);
@ -90,11 +123,6 @@ public class Bt17_1_collector extends ReportDataCollector<ReportBR_0420315_P1> {
return result;
}
@Override
public List<ReportBR_0420315_P1> collectReportWithClearingStatus(LocalDate startDate, LocalDate endDate, String clearingStatus) {
throw new IllegalStateException("clearingStatus not supported by this class");
}
@Override
public String getFileName(LocalDate startDate, LocalDate endDate, LocalDateTime dateTimeNow) {

View file

@ -0,0 +1,62 @@
package ru.spcex.clearing.reports.services.collector;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.transaction.data.execution.LiabilitiesClaimsAssets;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.reports.reports.bt_17_1.ReportBR_0420315_P2;
import ru.spcex.clearing.reports.services.ReportDataCollector;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
@Component
public class Bt17_1_P2_collector extends ReportDataCollector<ReportBR_0420315_P2, ReportBR_0420315_P2> {
private Imdg<LiabilitiesClaimsAssets> liabilitiesClaimsAssetsImdg;
@Autowired
public Bt17_1_P2_collector(ImdgProvider imdgProvider) {
liabilitiesClaimsAssetsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class);
}
@Override
public ReportBR_0420315_P2 collectReportWithPeriod(LocalDate startDate, LocalDate endDate) {
if (startDate.isAfter(endDate)) {
throw new IllegalArgumentException("startDate(" + startDate + ") > endDate(" + endDate + ")");
}
String ql = String.format("'%s' <= refundDate and refundDate <= '%s'", startDate, endDate);
Collection<LiabilitiesClaimsAssets> liabilities = liabilitiesClaimsAssetsImdg.getCollectionObjectsBySQL(ql);
long contractorQty;
double liabilitiesAmount = 0;
{
HashSet<String> collectedToSumm = new HashSet<>();
for (LiabilitiesClaimsAssets lContract : liabilities) {
if (lContract.getPrice() != null && StringUtils.isNotEmpty(lContract.getContract())
&& !collectedToSumm.contains(lContract.getContract())) {
collectedToSumm.add(lContract.getContract());
liabilitiesAmount += lContract.getLiabilitiesQuantity().doubleValue();
}
}
contractorQty = collectedToSumm.size();
}
ReportBR_0420315_P2 reportBR_0420315_p2 = new ReportBR_0420315_P2(startDate, endDate,
"BR",
String.valueOf(contractorQty),
String.valueOf(liabilitiesAmount));
return reportBR_0420315_p2;
}
@Override
public String getFileName(LocalDate startDate, LocalDate endDate, LocalDateTime dateTimeNow) {
return String.format("REPBR.0420315.P2.%s-%s.%s", DATE_FORMATTER.format(startDate), DATE_FORMATTER.format(endDate),
DATE_TIME_FORMATTER.format(dateTimeNow));
}
}

View file

@ -0,0 +1,76 @@
package ru.spcex.clearing.reports.services.collector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.company.relation.Relation;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.reports.reports.bt_17_2.ReportBR_0420317;
import ru.spcex.clearing.reports.services.ReportDataCollector;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
@Component
public class Bt17_2_collector extends ReportDataCollector<ReportBR_0420317, ReportBR_0420317> {
private Imdg<Company> companyImdg;
private Imdg<Relation> relationImdg;
private Imdg<CompanySymbols> companySymbolsImdg;
@Autowired
public Bt17_2_collector(ImdgProvider imdgProvider) {
companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
relationImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
}
@Override
public ReportBR_0420317 collectReportWithPeriod(LocalDate startDate, LocalDate endDate) {
if (startDate.isAfter(endDate)) {
throw new IllegalArgumentException("startDate(" + startDate + ") > endDate(" + endDate + ")");
}
String ql = String.format("'%s' <= updated and updated <= '%s' and service='MKR'", startDate, endDate);
// todo обговорить про updatedAt updated, todo enum MKR
Collection<Relation> relations = relationImdg.getCollectionObjectsBySQL(ql);
ReportBR_0420317 reportBR_0420317 = new ReportBR_0420317(startDate, endDate, "BR");
for (Relation relation: relations) {
Company company = relation.getConsumerId() == null ? null : companyImdg.getSingleObjectByID(relation.getConsumerId());
if (company == null) {
log.warn("Company.id={} not found for relation.id={}", relation.getConsumerId(), relation.getId());
continue;
}
CompanySymbols companySymbol = companySymbolsImdg.getSingleObjectByFieldValues(Map.of(
"companySymbol", "INN",//todo use enum, todo ИНН или TIN участника клиринга
"companyId", company.getId()
));
ReportBR_0420317.Info_0420317 info_0420317 = new ReportBR_0420317.Info_0420317(
company.getClearingCode(),
toString(relation.getSupplierId()),
relation.getService(), // todo "relationServiceId",
relation.getServiceStatus(),
toString(relation.getUpdated()),
company.getFullName(),
companySymbol == null ? null : companySymbol.getCompanySymbolValue(),
company.getProfile().getCountryCode(),
relation.getComment()
);
reportBR_0420317.getRows().add(info_0420317);
}
return reportBR_0420317;
}
@Override
public String getFileName(LocalDate startDate, LocalDate endDate, LocalDateTime dateTimeNow) {
return String.format("REPBR.0420317.%s-%s.%s", DATE_FORMATTER.format(startDate), DATE_FORMATTER.format(endDate),
DATE_TIME_FORMATTER.format(dateTimeNow));
}
}

View file

@ -0,0 +1,64 @@
package ru.spcex.clearing.reports.services.collector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.company.relation.Relation;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.reports.reports.bt_17_2.ReportBR_0420317;
import ru.spcex.clearing.reports.reports.bt_17_5.ReportBR_0420312_P1;
import ru.spcex.clearing.reports.services.ReportDataCollector;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Map;
@Component
public class Bt17_5_P1_collector extends ReportDataCollector<ReportBR_0420312_P1, ReportBR_0420312_P1> {
private Imdg<Company> companyImdg;
private Imdg<Relation> relationImdg;
private Imdg<CompanySymbols> companySymbolsImdg;
@Autowired
public Bt17_5_P1_collector(ImdgProvider imdgProvider) {
companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
relationImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
}
@Override
public ReportBR_0420312_P1 collectReportWithPeriod(LocalDate startDate, LocalDate endDate) {
if (startDate.isAfter(endDate)) {
throw new IllegalArgumentException("startDate(" + startDate + ") > endDate(" + endDate + ")");
}
// TODO ВСЁ по CLS-29...
String ql = String.format("'%s' <= updated and updated <= '%s' and service='MKR'", startDate, endDate);
// todo обговорить про updatedAt updated, todo enum MKR
Collection<Relation> relations = relationImdg.getCollectionObjectsBySQL(ql);
ReportBR_0420312_P1 reportBR_0420312P1 = new ReportBR_0420312_P1(LocalDate.now(),
LocalDate.now(),
"companyClearingCode",
"BR",
"liabilitesClaimsAssetsCompanyId",
"liabilitesClaimsAssetsFullName",
"companySymbolCode",
"companySymbolValue",
"companyInfoCountryCode",
"clearingMemberCategory");
return reportBR_0420312P1;
}
@Override
public String getFileName(LocalDate startDate, LocalDate endDate, LocalDateTime dateTimeNow) {
return String.format("REPBR.0420312_р1-1.%s-%s.%s", DATE_FORMATTER.format(startDate), DATE_FORMATTER.format(endDate),
DATE_TIME_FORMATTER.format(dateTimeNow));
}
}

View file

@ -0,0 +1,33 @@
package ru.spcex.clearing.reports.services.collector;
import ru.spcex.platform.classes.base.interfaces.WithId;
import java.util.*;
import java.util.function.Function;
public class MapUtil {
public static <K, V extends WithId> Map<K, V> index(Collection<V> from, Function<V, K> indexFieldExtractor) {
Map<K, V> index = new HashMap<>();
for (V obj : from) {
K key = indexFieldExtractor.apply(obj);
V exist = index.put(key, obj);
if (exist != null) {
throw new IllegalStateException(String.format("%s with id=%s,%s has duplicate key=\"{}\"",
exist.getClass().getSimpleName(), exist.getId(), obj.getId(), key
));
}
}
return index;
}
public static <K, V extends WithId> Map<K, List<V>> indexList(Collection<V> from, Function<V, K> indexFieldExtractor) {
Map<K, List<V>> index = new HashMap<>();
for (V obj : from) {
K key = indexFieldExtractor.apply(obj);
List<V> lst = index.computeIfAbsent(key, (_key_) -> new ArrayList<>());
lst.add(obj);
}
return index;
}
}

View file

@ -2,7 +2,7 @@ package ru.spcex.clearing.reports.services.impl;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import ru.spcex.clearing.reports.services.collector.Bt17_1_collector;
import ru.spcex.clearing.reports.services.collector.Bt17_1_P1_collector;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -13,7 +13,7 @@ class Bt17_1_collectorTest {
@Test
void getFileName() {
Bt17_1_collector collector = Mockito.mock(Bt17_1_collector.class);
Bt17_1_P1_collector collector = Mockito.mock(Bt17_1_P1_collector.class);
Mockito.when(collector.getFileName(Mockito.any(),Mockito.any(),Mockito.any())).thenCallRealMethod();
String str = collector.getFileName(LocalDate.of(2020,1,1),

View file

@ -0,0 +1,27 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
/**
* CLEARING_CATEGORY_DICTIONARY
*/
public enum ClearingCategory implements IEnumKey {
C("C"), // Категория «Ц» - Банк России
B("B"), // Категория «Б» - Кредитная организация ДР
F("F"), // Категория «Ф» - Участник рынка РЦБ
I("I"), // Категория «И» - Инициатор по ТБС
V("V"), // Категория «В» - Инициатор по ТКС
T("T"), // Категория «Т» - Участник товарного рынка
K("K"); // Категория «К» - Участник клиринга - Контроллер
private final String key;
ClearingCategory(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}

View file

@ -0,0 +1,18 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum Market implements IEnumKey {
MKRS("MKRS"); // Денежный рынок МКР
private final String key;
Market(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}