ialbert 2023-02-06 20:06:34 +03:00
parent 0e8ea7b595
commit 09605b610d

View file

@ -4,6 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.generated.ClearingMemberCategory;
import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.sdf.SDf03; import ru.clearing.classes.statics.data.sdf.SDf03;
import ru.clearing.classes.statics.data.sdf.SDf11; import ru.clearing.classes.statics.data.sdf.SDf11;
@ -13,20 +14,25 @@ import ru.spcex.clearing.platform.messaging.domain.cud.clearing.SdfClearingReque
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.builder.Sdf03Builder; import ru.spcex.clearing.service.builder.Sdf03Builder;
import ru.spcex.clearing.service.builder.Sdf11Builder; import ru.spcex.clearing.service.builder.Sdf11Builder;
import ru.spcex.clearing.service.order.PaymentBatchInfo;
import ru.spcex.clearing.service.order.PaymentInstructionSorter; import ru.spcex.clearing.service.order.PaymentInstructionSorter;
import ru.spcex.platform.enumeration.ClearingCategory;
import ru.spcex.platform.enumeration.TransactionStatus; import ru.spcex.platform.enumeration.TransactionStatus;
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.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component @Component
public class SdfCreatorBySTLDPayment { public class SdfCreatorBySTLDPayment {
private Logger log = LoggerFactory.getLogger(getClass()); private Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<PaymentInstruction> paymentImdgs; private final Imdg<PaymentInstruction> paymentImdgs;
private final Imdg<ClearingMemberCategory> clearingMemberCategoryImdg;
private final ImdgId idGenerator; private final ImdgId idGenerator;
private final PaymentInstructionSorter senderGroupSorter; private final PaymentInstructionSorter senderGroupSorter;
private final Imdg<SDf03> sdf03Imdg; private final Imdg<SDf03> sdf03Imdg;
@ -36,6 +42,7 @@ public class SdfCreatorBySTLDPayment {
@Autowired @Autowired
public SdfCreatorBySTLDPayment(ImdgProvider imdgProvider, PaymentInstructionSorter senderGroupSorter, KafkaSender kafkaSender) { public SdfCreatorBySTLDPayment(ImdgProvider imdgProvider, PaymentInstructionSorter senderGroupSorter, KafkaSender kafkaSender) {
this.paymentImdgs = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); this.paymentImdgs = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
this.clearingMemberCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
this.sdf03Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf03, SDf03.class); this.sdf03Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf03, SDf03.class);
this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class); this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class);
this.idGenerator = imdgProvider.getImdgIdGenerator(); this.idGenerator = imdgProvider.getImdgIdGenerator();
@ -43,76 +50,134 @@ public class SdfCreatorBySTLDPayment {
this.kafkaSender = kafkaSender; this.kafkaSender = kafkaSender;
} }
public void createSdfFromPaymentInstructionSTLD() { public void createSdfFromPaymentInstructionSTLD() {
final boolean[] anyError = {false};
//generationId для созадаваемых Sdf03/Sdf11 //generationId для созадаваемых Sdf03/Sdf11
Long generationId = idGenerator.nextId(); Long generationId = idGenerator.nextId();
//выгружаем PaymentInstructions с нужным статусом //выгружаем PaymentInstructions с нужным статусом
Collection<PaymentInstruction> paymentInstructionFound = paymentImdgs.getCollectionObjectsByFieldValues( Collection<PaymentInstruction> paymentInstructionFound = paymentImdgs.getCollectionObjectsByFieldValues(
Map.of("transactionStatus", TransactionStatus.stld.getKey())); Map.of("transactionStatus", TransactionStatus.stld.getKey()));
log.info("Found {} PaymentInstruction by status {}", paymentInstructionFound.size(), TransactionStatus.stld.getKey()); log.info("Found {} PaymentInstruction by status {}", paymentInstructionFound.size(), TransactionStatus.stld.getKey());
List<AbstractMap.SimpleEntry<Long, PaymentBatchInfo>> paymentBySenderLst = new ArrayList<>(); /*Map<GroupWrapper, List<PaymentInstruction>> byOrder = */
paymentInstructionFound.stream() List<Map.Entry<GroupWrapper, Collection<List<PaymentInstruction>>>> allEntries = paymentInstructionFound.stream().flatMap(paymentInstruction -> {
//группируем по компаниям ClearingCategory clearingCategory = getClearingCategory(paymentInstruction);
.sorted(Comparator.comparing(PaymentInstruction::getSenderId)) Long senderId = paymentInstruction.getSenderId();
.collect(Collectors.groupingBy(PaymentInstruction::getSenderId)) if (senderId == null) {
return Stream.empty();
} else {
return Stream.of(new Pair<>(new GroupWrapper(clearingCategory, senderId), paymentInstruction));
}
//группируем по equals/hashCode группы
}).collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList())))
.entrySet() .entrySet()
.stream() .stream()
//результатом работы senderGroupSorter будет Map<senderId -> PaymentBatchInfo> //сортируем по группе compareTo
//PaymentBatchInfo содержит возможную ошибку, при необходимости отсортированные Payment .sorted(Map.Entry.comparingByKey())
//тип ClearingMemberCategory //преобразуем поток entry<group, list<paymentInstruction>>, разбиваем список на группы по senderId
.forEachOrdered(entry -> { .map((Function<Map.Entry<GroupWrapper, List<PaymentInstruction>>, Map.Entry<GroupWrapper, Collection<List<PaymentInstruction>>>>) entry -> {
Long senderId = entry.getKey(); Collection<List<PaymentInstruction>> values = entry.getValue().stream().collect(Collectors.groupingBy(PaymentInstruction::getSenderId)).values();
List<PaymentInstruction> pmtInstrcs = entry.getValue(); return new AbstractMap.SimpleEntry<>(entry.getKey(), values);
List<PaymentBatchInfo> senderInfos = senderGroupSorter.sortCompanyPayments(generationId, senderId, pmtInstrcs); }).toList();
for (PaymentBatchInfo senderInfo:senderInfos) {
if (senderInfo.getError() != null) { allEntries.forEach(entry -> {
anyError[0] = true; log.info("Group category {}, index {}", entry.getKey().category, entry.getKey().getSortIndex());
} GroupWrapper group = entry.getKey();
paymentBySenderLst.add(new AbstractMap.SimpleEntry<>(senderId, senderInfo)); Collection<List<PaymentInstruction>> bySenderGroups = entry.getValue();
} for (List<PaymentInstruction> bySenderGroup : bySenderGroups) {
}); Long senderIdSpecificToGroup = bySenderGroup.iterator().next().getSenderId();
//save SDF03/SDF11 log.info("Group senderId {}", senderIdSpecificToGroup);
log.debug("Sending save {} sdf03/sdf11", paymentBySenderLst.size()); saveSdfAnSendToKafka(senderIdSpecificToGroup, group.category, bySenderGroup, generationId);
for (var entry : paymentBySenderLst) { }
PaymentBatchInfo senderPayments = entry.getValue(); });
saveSdfAnSendToKafka(senderPayments, generationId); allEntries.forEach(entry -> {
} //category group
//update PaymentInstruction.transactionStatus GroupWrapper group = entry.getKey();
for (var entry : paymentBySenderLst) { log.info("updating transactionStatus Group category {} index {}",
PaymentBatchInfo batch = entry.getValue(); group.category, group.getSortIndex());
//все PaymentInstruction.transactionStatus в batch с error != null TransactionStatus stat;
//уже проапдейтились в методе sortCompanyPayments if (group.category.equals(ClearingCategory.I)
if (batch.getError() == null) { || group.category.equals(ClearingCategory.V)
TransactionStatus stat = anyError[0] ? TransactionStatus.notSent : TransactionStatus.sent; || group.category.equals(ClearingCategory.B)) {
batch.getOrderedPaymentInstructions() stat = TransactionStatus.sent;
.forEach(paymentInstruction -> { } else {
stat = TransactionStatus.notSent;
}
entry.getValue()
.forEach(senderInstructions -> {
senderInstructions.forEach(paymentInstruction -> {
paymentInstruction.setTransactionStatus(stat.getKey()); paymentInstruction.setTransactionStatus(stat.getKey());
paymentImdgs.update(paymentInstruction); paymentImdgs.update(paymentInstruction);
}); });
} });
} });
} }
private void saveSdfAnSendToKafka(PaymentBatchInfo batch, Long generationId) { private void saveSdfAnSendToKafka(Long senderId, ClearingCategory category, List<PaymentInstruction> batch, Long generationId) {
SdfClearingRequest kafkaMessage = new SdfClearingRequest(); SdfClearingRequest kafkaMessage = new SdfClearingRequest();
kafkaMessage.setGroupId(generationId); kafkaMessage.setGroupId(generationId);
Long requestId = null; Long requestId = null;
switch (batch.getCategoryD()) { if (category.equals(ClearingCategory.I) || category.equals(ClearingCategory.V)) {
case I -> { batch.stream()
batch.getOrderedPaymentInstructions() .map(paymentInstruction -> Sdf03Builder.buildSdf03(paymentInstruction, generationId))
.map(paymentInstruction -> Sdf03Builder.buildSdf03(paymentInstruction, generationId)) .forEach(sdf03Imdg::insert);
.forEach(sdf03Imdg::insert); requestId = kafkaSender.sendRequestToQueue(Consts.SDF03_PROCESS, kafkaMessage);
requestId = kafkaSender.sendRequestToQueue(Consts.SDF03_PROCESS, kafkaMessage); } else if (category.equals(ClearingCategory.B)) {
} batch.stream()
case B -> { .map(paymentInstruction -> Sdf11Builder.buildSdf11(paymentInstruction, generationId))
batch.getOrderedPaymentInstructions() .forEach(sdf11Imdg::insert);
.map(paymentInstruction -> Sdf11Builder.buildSdf11(paymentInstruction, generationId)) requestId = kafkaSender.sendRequestToQueue(Consts.SDF11_PROCESS, kafkaMessage);
.forEach(sdf11Imdg::insert); } else {
requestId = kafkaSender.sendRequestToQueue(Consts.SDF11_PROCESS, kafkaMessage); log.error("Unknown action (sdf03/sdf11) senderId {}, generationId {}, category {}", senderId, generationId, category);
}
} }
log.debug("Send to kafka command, CategoryD={}, requestId={}", batch.getCategoryD(), requestId); log.debug("Send to kafka command, CategoryD={}, requestId={}", category, requestId);
}
private static class GroupWrapper implements Comparable<GroupWrapper> {
private Long senderId;
private ClearingCategory category;
public GroupWrapper(ClearingCategory clearingCategory, Long senderId) {
this.category = clearingCategory;
this.senderId = senderId;
}
private Integer getSortIndex() {
if (category == ClearingCategory.I)
return 0;
if (senderId == 1L)
return 1;
if (category == ClearingCategory.V)
return 2;
if (category == ClearingCategory.B)
return 3;
return 4;
}
@Override
public int compareTo(GroupWrapper o) {
Integer thisIndex = getSortIndex();
Integer otherIndex = o.getSortIndex();
return thisIndex.compareTo(otherIndex);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GroupWrapper that = (GroupWrapper) o;
return Objects.equals(getSortIndex(), that.getSortIndex());
}
@Override
public int hashCode() {
return getSortIndex();
}
}
private ClearingCategory getClearingCategory(PaymentInstruction paymentInstruction) {
ClearingMemberCategory category = clearingMemberCategoryImdg.getSingleObjectByFieldValues(
Map.of("companyId", paymentInstruction.getSenderId()));
return IEnumKey.getEnumByKeyOrUndefined(ClearingCategory.class,
category.getClearingMemberCategory());
} }
} }