ialbert 2026-05-07 12:37:14 +03:00
parent 7b0c48f785
commit a980ff8a0c
3 changed files with 202 additions and 15 deletions

View file

@ -49,6 +49,7 @@ import static ru.spcex.platform.imdg.api.predicate.specific.IdEqualPredicate.byI
import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector;
import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.imdg.validation.LogPrefixId; import ru.spcex.platform.imdg.validation.LogPrefixId;
import ru.spcex.platform.imdg.validation.rule.CollectionByPredicate;
import ru.spcex.platform.imdg.validation.rule.PresentById; import ru.spcex.platform.imdg.validation.rule.PresentById;
import ru.spcex.platform.imdg.validation.rule.PresentByPredicate; import ru.spcex.platform.imdg.validation.rule.PresentByPredicate;
import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.EnumMessage;
@ -455,7 +456,7 @@ public class ValidationConfig {
.store(OrderCurrencyValidationStored.TCR) .store(OrderCurrencyValidationStored.TCR)
.build(); .build();
var counterOrderPresent = PresentByPredicate var counterOrderPresentV2 = CollectionByPredicate
.builder(r -> { .builder(r -> {
OrderCurrency oc = ctx.getStoredObject(OrderCurrencyValidationStored.OrderCurrency); OrderCurrency oc = ctx.getStoredObject(OrderCurrencyValidationStored.OrderCurrency);
ImdgPredicateBuilder pb = orderCurrencyImdg.predicateBuilder(); ImdgPredicateBuilder pb = orderCurrencyImdg.predicateBuilder();
@ -470,6 +471,7 @@ public class ValidationConfig {
.mapName(IMDGDistributedNames.Map_OrderCurrency) .mapName(IMDGDistributedNames.Map_OrderCurrency)
.errorProvider(r -> recordNotFound("counter OrderCurrency")) .errorProvider(r -> recordNotFound("counter OrderCurrency"))
.store(OrderCurrencyValidationStored.CounterOrderCurrency) .store(OrderCurrencyValidationStored.CounterOrderCurrency)
.greaterOrEquals(1)
.build(); .build();
//fixme проверить что tcr.getCompanyId() = companyId из запроса? //fixme проверить что tcr.getCompanyId() = companyId из запроса?
@ -481,7 +483,7 @@ public class ValidationConfig {
OrderCurrencyCompanyNotChanged.INSTANCE, OrderCurrencyCompanyNotChanged.INSTANCE,
//OrderCurrencyByCompanyAndTcrAlreadyPresent.getInstance(OrderCompanyUpdateRequest.class), //OrderCurrencyByCompanyAndTcrAlreadyPresent.getInstance(OrderCompanyUpdateRequest.class),
OrderCurrencyPLBLCheck.INSTANCE, OrderCurrencyPLBLCheck.INSTANCE,
counterOrderPresent); counterOrderPresentV2);
}; };
} }
@ -502,7 +504,7 @@ public class ValidationConfig {
.store(OrderCurrencyValidationStored.OrderCurrency) .store(OrderCurrencyValidationStored.OrderCurrency)
.build(); .build();
var counterOrderPresent = PresentByPredicate var counterOrderPresentV2 = CollectionByPredicate
.builder(r -> { .builder(r -> {
OrderCurrency oc = ctx.getStoredObject(OrderCurrencyValidationStored.OrderCurrency); OrderCurrency oc = ctx.getStoredObject(OrderCurrencyValidationStored.OrderCurrency);
ImdgPredicateBuilder pb = orderCurrencyImdg.predicateBuilder(); ImdgPredicateBuilder pb = orderCurrencyImdg.predicateBuilder();
@ -517,11 +519,12 @@ public class ValidationConfig {
.mapName(IMDGDistributedNames.Map_OrderCurrency) .mapName(IMDGDistributedNames.Map_OrderCurrency)
.errorProvider(r -> recordNotFound("counter OrderCurrency")) .errorProvider(r -> recordNotFound("counter OrderCurrency"))
.store(OrderCurrencyValidationStored.CounterOrderCurrency) .store(OrderCurrencyValidationStored.CounterOrderCurrency)
.greaterOrEquals(1)
.build(); .build();
return new ValidatorImpl<>(ctx, return new ValidatorImpl<>(ctx,
orderCurrencyPresent, orderCurrencyPresent,
counterOrderPresent); counterOrderPresentV2);
}; };
} }

View file

@ -4,8 +4,10 @@ import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.Producer;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -362,7 +364,7 @@ public class OrderCurrencyListener extends QueueConsumer implements Initializing
OrderCurrency order = validator.getStored(OrderCurrencyValidationStored.OrderCurrency); OrderCurrency order = validator.getStored(OrderCurrencyValidationStored.OrderCurrency);
Company company = validator.getStored(OrderCurrencyValidationStored.Company); Company company = validator.getStored(OrderCurrencyValidationStored.Company);
TradingClearingRegistry tcr = validator.getStored(OrderCurrencyValidationStored.TCR); TradingClearingRegistry tcr = validator.getStored(OrderCurrencyValidationStored.TCR);
OrderCurrency counterOrder = validator.getStored(OrderCurrencyValidationStored.CounterOrderCurrency); Collection<OrderCurrency> counterOrders = validator.getStored(OrderCurrencyValidationStored.CounterOrderCurrency);
order.setCompanyId(payload.getCompanyId()); order.setCompanyId(payload.getCompanyId());
order.setTradingClearingRegistryId(payload.getTradingClearingRegistryId()); order.setTradingClearingRegistryId(payload.getTradingClearingRegistryId());
@ -371,14 +373,18 @@ public class OrderCurrencyListener extends QueueConsumer implements Initializing
order.setTradingCode(company.getTradingCode()); order.setTradingCode(company.getTradingCode());
order.setUpdated(now); order.setUpdated(now);
counterOrder.setCounterPartyId(payload.getCompanyId()); log.info("updating OrderCurrency[{}, {}]", order.getId(),
counterOrder.setCounterTradingCode(company.getTradingCode()); counterOrders.stream().map(OrderCurrency::getId).map(Object::toString).collect(Collectors.joining(",")));
counterOrder.setQuantityLot(new BigDecimal(payload.getQuantityLot()));
counterOrder.setUpdated(now);
log.info("updating OrderCurrency[{}, {}]", order.getId(), counterOrder.getId());
orderCurrencyImdg.update(order); orderCurrencyImdg.update(order);
orderCurrencyImdg.update(counterOrder);
counterOrders.forEach(counterOrder -> {
counterOrder.setCounterPartyId(payload.getCompanyId());
counterOrder.setCounterTradingCode(company.getTradingCode());
counterOrder.setQuantityLot(new BigDecimal(payload.getQuantityLot()));
counterOrder.setUpdated(now);
orderCurrencyImdg.update(counterOrder);
}
);
return null; return null;
} }
@ -390,11 +396,12 @@ public class OrderCurrencyListener extends QueueConsumer implements Initializing
return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(error.get())); return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(error.get()));
} }
OrderCurrency order = validator.getStored(OrderCurrencyValidationStored.OrderCurrency); OrderCurrency order = validator.getStored(OrderCurrencyValidationStored.OrderCurrency);
OrderCurrency counterOrder = validator.getStored(OrderCurrencyValidationStored.CounterOrderCurrency); Collection<OrderCurrency> counterOrders = validator.getStored(OrderCurrencyValidationStored.CounterOrderCurrency);
log.info("deleting OrderCurrency[{}, {}]", order.getId(), counterOrder.getId()); log.info("deleting OrderCurrency[{}, {}]", order.getId(),
counterOrders.stream().map(OrderCurrency::getId).map(Object::toString).collect(Collectors.joining(",")));
reject(order); reject(order);
reject(counterOrder); counterOrders.forEach(this::reject);
return null; return null;
} }

View file

@ -0,0 +1,177 @@
package ru.spcex.platform.imdg.validation.rule;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
public class CollectionByPredicate<T> implements IValidationRule<ImdgValidationContext<T>> {
private static final Logger log = LoggerFactory.getLogger(CollectionByPredicate.class);
private final String mapName;
private final Function<T, EnumMessage> errorProvider;
private final Function<T, ImdgPredicate> predicateProvider;
private final Enum<?> storeEnabled;
private Integer precise;
private Integer min;
private Integer max;
private CollectionByPredicate(
String mapName,
Function<T, ImdgPredicate> predicateProvider,
Function<T, EnumMessage> errorProvider,
Enum<?> storeEnabled
) {
this.mapName = mapName;
this.errorProvider = errorProvider;
this.storeEnabled = storeEnabled;
this.predicateProvider = predicateProvider;
}
public void setPrecise(Integer precise) {
this.precise = precise;
}
public void setMin(Integer min) {
this.min = min;
}
public void setMax(Integer max) {
this.max = max;
}
public static <T> PredicateStep<T> builder(Function<T, ImdgPredicate> predicateProvider) {
return new Builder<>(predicateProvider);
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<T> context) {
T validatedObject = context.getValidatedObject();
Imdg<SpcexObjectBase> targetMap = context.obtainMap(mapName, SpcexObjectBase.class);
ImdgPredicate predicate = predicateProvider.apply(validatedObject);
Collection<SpcexObjectBase> obj = targetMap.getCollectionObjectsByPredicate(predicate);
String specificMsg = "[too many...]";
if (obj.size() <= 20) {
specificMsg = obj
.stream()
.map(SpcexObjectBase::getId)
.map(Object::toString)
.collect(Collectors.joining(",", "[", "]"));
}
log.debug("objects found by predicate [{}]: size {}, ids {}", predicate, obj.size(), specificMsg);
if (precise != null && obj.size() != precise) {
log.debug("predicate: {}; expected size: {}, actual: {}", predicate, precise, obj.size());
return Optional.of(errorProvider.apply(validatedObject));
}
if (max != null && obj.size() > max) {
log.debug("predicate: {}; more objects found ({}) than expected ({})", predicate, obj.size(), max);
return Optional.of(errorProvider.apply(validatedObject));
}
if (min != null && obj.size() < min) {
log.debug("predicate: {}; fewer objects were found ({}) than expected ({}) ", predicate, obj.size(), min);
return Optional.of(errorProvider.apply(validatedObject));
}
if (storeEnabled != null) {
context.storeObject(storeEnabled, obj);
}
return Optional.empty();
}
public interface PredicateStep<T> {
MapStep<T> mapName(String mapName);
}
public interface MapStep<T> {
OptionsStep<T> errorProvider(Function<T, EnumMessage> errorProvider);
}
public interface OptionsStep<T> {
OptionsStep<T> store(Enum<?> storeEnabled);
OptionsStep<T> precise(int number);
OptionsStep<T> greaterOrEquals(int number);
OptionsStep<T> lessThanOrEquals(int number);
CollectionByPredicate<T> build();
}
private static class Builder<T>
implements PredicateStep<T>, MapStep<T>, OptionsStep<T> {
private final Function<T, ImdgPredicate> predicateProvider;
private String mapName;
private Function<T, EnumMessage> errorProvider;
private Enum<?> storeEnabled;
private int precise;
private int min;
private int max;
private Builder(Function<T, ImdgPredicate> predicateProvider) {
this.predicateProvider = predicateProvider;
}
@Override
public MapStep<T> mapName(String mapName) {
this.mapName = mapName;
return this;
}
@Override
public OptionsStep<T> errorProvider(Function<T, EnumMessage> errorProvider) {
this.errorProvider = errorProvider;
return this;
}
@Override
public OptionsStep<T> store(Enum<?> storeEnabled) {
this.storeEnabled = storeEnabled;
return this;
}
@Override
public OptionsStep<T> precise(int number) {
this.precise = number;
return this;
}
@Override
public OptionsStep<T> greaterOrEquals(int number) {
this.min = number;
return this;
}
@Override
public OptionsStep<T> lessThanOrEquals(int number) {
this.max = number;
return this;
}
@Override
public CollectionByPredicate<T> build() {
CollectionByPredicate<T> rule = new CollectionByPredicate<>(
mapName,
predicateProvider,
errorProvider,
storeEnabled
);
rule.setMax(max);
rule.setMin(min);
rule.setPrecise(precise);
return rule;
}
}
}