ialbert 2022-12-20 17:57:00 +03:00
parent 94f878c0b4
commit fd7ee9a989
29 changed files with 524 additions and 65 deletions

View file

@ -9,14 +9,17 @@ import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest;
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer;
import ru.spcex.platform.classes.base.interfaces.WithSecuritySymbol;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.text.TextUtil;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurityNewRequest> {
public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurityNewRequest>, WithSecuritySymbol {
@ApiModelProperty(value = "Дата начала действия", example = "2022-01-20")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow")
@JsonDeserialize(using = LocalDateDeserializer.class)
@ -48,9 +51,24 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.startDate == null)
return List.of(new EnumMessage(BackEndError.ValidationError, "startDate"));
else return Collections.emptyList();
errors.add(new EnumMessage(BackEndError.ValidationError, "startDate"));
if (this.endDate == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "endDate"));
if (this.nominalValue == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "nominalValue"));
if (TextUtil.isEmpty(nominalCurrency))
errors.add(new EnumMessage(BackEndError.ValidationError, "nominalCurrency"));
if (TextUtil.isEmpty(instrumentType))
errors.add(new EnumMessage(BackEndError.ValidationError, "instrumentType"));
if (TextUtil.isEmpty(fullName))
errors.add(new EnumMessage(BackEndError.ValidationError, "fullName"));
if (TextUtil.isEmpty(securitySymbol))
errors.add(new EnumMessage(BackEndError.ValidationError, "securitySymbol"));
if (this.lotSize == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "lotSize"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@Override

View file

@ -5,12 +5,19 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityUpdateRequest;
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer;
import ru.spcex.platform.classes.base.interfaces.WithId;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.text.TextUtil;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecurityUpdateRequest>, WithId {
@ApiModelProperty(hidden = true)
@ -56,6 +63,26 @@ public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecur
return req;
}
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.startDate == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "startDate"));
if (this.endDate == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "endDate"));
if (this.nominalValue == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "nominalValue"));
if (TextUtil.isEmpty(nominalCurrency))
errors.add(new EnumMessage(BackEndError.ValidationError, "nominalCurrency"));
if (TextUtil.isEmpty(instrumentType))
errors.add(new EnumMessage(BackEndError.ValidationError, "instrumentType"));
if (TextUtil.isEmpty(fullName))
errors.add(new EnumMessage(BackEndError.ValidationError, "fullName"));
if (this.lotSize == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "lotSize"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@ApiModelProperty(hidden = true)
@Override
public ActionType getActionType() {

View file

@ -43,6 +43,7 @@ public class RequestStatusController {
}
RequestInfoResponse response = new RequestInfoResponse();
response.setStatus(singleObjectByID.getStatus());
response.setMessage(singleObjectByID.getMessage());
return response;
}
}

View file

@ -43,6 +43,7 @@ public class RequestInfoAccepter extends QueueConsumer implements InitializingBe
return;
}
requestInfo.setStatus(statusInfo.getStatus());
requestInfo.setMessage(statusInfo.getMessage());
requestInfoImdg.update(requestInfo);
}
}

View file

@ -5,8 +5,8 @@ import org.springframework.stereotype.Component;
import ru.clearing.platform.dictionary.AbstractDictionary;
import ru.spcex.clearing.backendapi.controller.request.cud.schedule.LauncherNew;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.backendapi.service.validation.rules.LauncherNewValidationRule;
import ru.spcex.clearing.backendapi.service.validation.rules.PresentById;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.platform.classes.base.SpcexObjectBase;
@ -14,9 +14,11 @@ import ru.spcex.platform.classes.base.interfaces.WithId;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.imdg.validation.rule.PresentById;
import ru.spcex.platform.utils.validation.IValidator;
import ru.spcex.platform.utils.validation.ValidatorImpl;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@ -35,10 +37,6 @@ public class ActionValidationProvider implements InitializingBean {
@Override
public void afterPropertiesSet() {
getImdg(IMDGDistributedNames.Map_TaskDictionary, AbstractDictionary.class);
getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, SpcexObjectBase.class);
getImdg(IMDGDistributedNames.Map_Relation, SpcexObjectBase.class);
validators.put(Consts.DESTINATION_MONEY_MARKET_SECURITY_UPDATE, idPresent(IMDGDistributedNames.Map_MoneyMarketSecurity));
validators.put(Consts.DESTINATION_MONEY_MARKET_SECURITY_DELETE, idPresent(IMDGDistributedNames.Map_MoneyMarketSecurity));
validators.put(Consts.DESTINATION_RELATION_UPDATE, idPresent(IMDGDistributedNames.Map_Relation));
@ -53,21 +51,35 @@ public class ActionValidationProvider implements InitializingBean {
return null;
}
private <T extends IAction<?>> Function<T, IValidator> defaultConstructor(Class<T> clazz, Imdg<?>... imdgs) {
return iAcc -> {
ImdgValidationContext<T> ctx = new ImdgValidationContext<>();
ctx.setValidatedObject(iAcc);
Arrays.stream(imdgs).forEach(imdg -> ctx.addImdg(imdg.getMapName(), imdg));
return new ValidatorImpl<>(ctx);
};
}
private <T extends IAction<?> & WithId> Function<T, IValidator> idPresent(String mapName) {
Imdg<SpcexObjectBase> targetMap = getImdg(mapName, SpcexObjectBase.class);
return iAction -> {
ImdgValidationContext<T> ctx = new ImdgValidationContext<>();
ctx.setValidatedObject(iAction);
ctx.addImdg(mapName, targetMap);
ValidatorImpl<ImdgValidationContext<T>> iValidator = new ValidatorImpl<>(ctx);
iValidator.addRule(new PresentById(getImdg(mapName, SpcexObjectBase.class)));
iValidator.addRule(new PresentById(mapName, BackEndError.ResourceNotFound));
return iValidator;
};
}
private Function<LauncherNew, IValidator> taskRunnerNew() {
Imdg<AbstractDictionary> tskDctnrImdg = getImdg(IMDGDistributedNames.Map_TaskDictionary, AbstractDictionary.class);
return taskRunnerNew -> {
ImdgValidationContext<LauncherNew> ctx = new ImdgValidationContext<>();
ctx.setValidatedObject(taskRunnerNew);
ctx.addImdg(IMDGDistributedNames.Map_TaskDictionary, getImdg(IMDGDistributedNames.Map_TaskDictionary, AbstractDictionary.class));
ctx.addImdg(IMDGDistributedNames.Map_TaskDictionary, tskDctnrImdg);
ValidatorImpl<ImdgValidationContext<LauncherNew>> iValidator = new ValidatorImpl<>(ctx);
iValidator.addRule(LauncherNewValidationRule.knownTaskDictionary);
return iValidator;

View file

@ -1,28 +0,0 @@
package ru.spcex.clearing.backendapi.service.validation.rules;
import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.classes.base.interfaces.WithId;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
public class PresentById implements IValidationRule<ImdgValidationContext<WithId>> {
private final Imdg<SpcexObjectBase> map;
public PresentById(Imdg<SpcexObjectBase> map) {
this.map = map;
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<WithId> context) {
WithId actionById = context.getValidatedObject();
if (map.getSingleObjectByID(actionById.getId()) == null) {
return of(BackEndError.ResourceNotFound, actionById.getId());
} else {
return empty();
}
}
}

View file

@ -3,16 +3,12 @@ package ru.spcex.clearing.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import java.util.Arrays;
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
@Configuration
public class MessageResolverConfig {
@Bean
public IMessageResolver messageResolver() {
return errorMessage -> {
if (errorMessage == null) return "null";
return String.format("(%d) args %s", errorMessage.getSubject().getId(), Arrays.toString(errorMessage.getArgs()));
};
return new SimpleMessageResolver();
}
}

View file

@ -0,0 +1,24 @@
package ru.spcex.clearing.securities.component;
import ru.clearing.classes.statics.data.misc.Listing;
import ru.clearing.classes.statics.data.misc.MoneyMarketSecurity;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest;
import ru.spcex.platform.enumeration.Market;
import ru.spcex.platform.enumeration.Status;
import java.math.BigDecimal;
public class ListingBuilder {
public Listing byNewMms(MoneyMarketSecurity mms, MoneyMarketSecurityNewRequest mmsReq) {
Listing listing = new Listing();
listing.setCreated(mms.getCreated());
listing.setSecurityId(mms.getId());
listing.setLotSize(BigDecimal.valueOf(mmsReq.getLotSize()));
listing.setMarket(Market.mkrs.getKey());
listing.setSymbolCode(mms.getSecuritySymbol());
listing.setSymbolName(mms.getFullName());
listing.setTradingCurrency(mms.getNominalCurrency());
listing.setWorkflowStatus(Status.Active.getKey());
return listing;
}
}

View file

@ -0,0 +1,14 @@
package ru.spcex.clearing.securities.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
@Configuration
public class ErrorResolverConfig {
@Bean
public IMessageResolver messageResolver() {
return new SimpleMessageResolver();
}
}

View file

@ -0,0 +1,21 @@
package ru.spcex.clearing.securities.errors;
import ru.spcex.platform.utils.enumeration.IEnumId;
public enum SecuritiesError implements IEnumId {
WrongFieldValue(1004L),
InstrumentAlreadyExists(1010L),
InstrumentNotActive(1012L),
InstrumentNotFound(1011L),
;
private final Long id;
SecuritiesError(Long id) {
this.id = id;
}
@Override
public Long getId() {
return id;
}
}

View file

@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.misc.Listing;
import ru.clearing.classes.statics.data.misc.MoneyMarketSecurity;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
@ -16,29 +17,48 @@ import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSe
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityUpdateRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfo;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.platform.messaging.service.Status;
import ru.spcex.clearing.securities.component.ListingBuilder;
import ru.spcex.clearing.securities.validation.ValidationProvider;
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.ImdgTransaction;
import ru.spcex.platform.imdg.validation.Stored;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
@Service
public class MoneyMarketSecurityService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<MoneyMarketSecurity> moneyMarketSecurityMap;
private final Imdg<Listing> listingImdg;
private final ImdgProvider imdgProvider;
private final ImdgId idGenerator;
private final ValidationProvider validation;
private final IMessageResolver messageResolver;
private final ListingBuilder listingBuilder = new ListingBuilder();
@Autowired
public MoneyMarketSecurityService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
ImdgProvider imdgProvider) {
public MoneyMarketSecurityService(Consumer<String, Object> kafkaQueue,
Producer<String, Object> kafkaProducer,
ImdgProvider imdgProvider,
ValidationProvider validation,
IMessageResolver messageResolver) {
super(kafkaQueue, kafkaProducer);
this.validation = validation;
this.moneyMarketSecurityMap = imdgProvider.getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class);
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
this.imdgProvider = imdgProvider;
this.idGenerator = imdgProvider.getImdgIdGenerator();
this.messageResolver = messageResolver;
}
@Override
@ -59,23 +79,32 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
@Override
public void afterPropertiesSet() {
callback(MoneyMarketSecurityNewRequest.class)
.setConsumer(this::newMoneyMarket)
.setFunction(this::newMoneyMarket)
.forDestination(Consts.DESTINATION_MONEY_MARKET_SECURITY_NEW, callbacks::put);
callback(MoneyMarketSecurityUpdateRequest.class)
.setConsumer(this::updateMoneyMarket)
.setFunction(this::updateMoneyMarket)
.forDestination(Consts.DESTINATION_MONEY_MARKET_SECURITY_UPDATE, callbacks::put);
callback(CommonDeleteRequest.class)
.setConsumer(this::deleteMoneyMarket)
.setFunction(this::deleteMoneyMarket)
.forDestination(Consts.DESTINATION_MONEY_MARKET_SECURITY_DELETE, callbacks::put);
imdgProvider.waitAvailable();
init();
}
private void newMoneyMarket(BaseRequest<MoneyMarketSecurityNewRequest> userRequest) {
// Imdg<RequestInfo> requestInfoImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class);
// RequestInfo reqInfo = requestInfoImdg.getSingleObjectByID(userRequest.getId());
private RequestInfoUpdate newMoneyMarket(BaseRequest<MoneyMarketSecurityNewRequest> userRequest) {
ImdgTransaction transaction = imdgProvider.newTransaction();
MoneyMarketSecurityNewRequest req = userRequest.getRequestPayload();
Optional<EnumMessage> validationError = validation.mmsNewValidator()
.apply(req)
.tillFirstError();
if (validationError.isPresent()) {
String errorMsg = messageResolver.resolve(validationError.get());
log.error("cannot process MoneyMarketSecurityNewRequest id={}: {}", userRequest.getId(), errorMsg);
return new RequestInfoUpdate()
.setId(userRequest.getId())
.setStatus(Status.Error)
.setMessage(errorMsg);
}
log.debug("MoneyMarketSecurityNewRequest received");
MoneyMarketSecurity mms = new MoneyMarketSecurity();
mms.setId(idGenerator.nextId());
@ -92,10 +121,11 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
try {
transaction.beginTransaction();
Imdg<MoneyMarketSecurity> moneyMarketSecurityMap = transaction.getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class);
Imdg<RequestInfo> reqInfoMap = transaction.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class);
Imdg<Listing> listingMap = transaction.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
//одним скопом выполняем реквест
moneyMarketSecurityMap.insert(mms);
// RequestInfo.update(reqInfo, Status.Success, "success");
Listing listing = listingBuilder.byNewMms(mms, req);
listingMap.insert(listing);
//и сохраняем обновленный
// reqInfoMap.insert(reqInfo);
transaction.commitTransaction();
@ -105,13 +135,25 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
// requestInfoImdg.insert(reqInfo);
}
log.debug("successfully processed, request id {}, new object id {}", userRequest.getId(), mms.getId());
return null; // default success
}
private void updateMoneyMarket(BaseRequest<MoneyMarketSecurityUpdateRequest> userRequest) {
private RequestInfoUpdate updateMoneyMarket(BaseRequest<MoneyMarketSecurityUpdateRequest> userRequest) {
MoneyMarketSecurityUpdateRequest req = userRequest.getRequestPayload();
log.debug("MoneyMarketSecurityUpdateRequest received id = {}", req.getId());
MoneyMarketSecurity mms = moneyMarketSecurityMap.getSingleObjectByID(req.getId());
mms.setUpdated(Instant.now());
IValidator validator = validation.mmsUpdateValidator().apply(req);
Optional<EnumMessage> validationError = validator.tillFirstError();
if (validationError.isPresent()) {
String errorMsg = messageResolver.resolve(validationError.get());
log.error("cannot process MoneyMarketSecurityUpdateRequest id={}: {}", userRequest.getId(), errorMsg);
return new RequestInfoUpdate()
.setId(userRequest.getId())
.setStatus(Status.Error)
.setMessage(errorMsg);
}
MoneyMarketSecurity mms = validator.getStored(Stored.PresentById);
Instant updateTime = Instant.now();
mms.setUpdated(updateTime);
mms.setStartDate(req.getStartDate());
mms.setEndDate(req.getEndDate());
mms.setNominalValue(req.getNominalValue() != null ? BigDecimal.valueOf(req.getNominalValue()) : null);
@ -119,12 +161,43 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
mms.setInstrumentType(req.getInstrumentType());
mms.setFullName(req.getFullName());
moneyMarketSecurityMap.update(mms);
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId()));
if (listing == null) {
log.error("MoneyMarketSecurityUpdateRequest id {} couldn't find listing with securityId {}", req.getId(), mms.getId());
return null;
}
listing.setLotSize(BigDecimal.valueOf(req.getLotSize()));
listing.setUpdated(updateTime);
listingImdg.update(listing);
return null;
}
private void deleteMoneyMarket(BaseRequest<CommonDeleteRequest> userRequest) {
private RequestInfoUpdate deleteMoneyMarket(BaseRequest<CommonDeleteRequest> userRequest) {
CommonDeleteRequest req = userRequest.getRequestPayload();
log.debug("CommonDeleteRequest received id = {}", req.getId());
MoneyMarketSecurity mms = moneyMarketSecurityMap.getSingleObjectByID(req.getId());
moneyMarketSecurityMap.delete(mms);
IValidator validator = validation.mmsDeleteValidator().apply(req);
Optional<EnumMessage> validationError = validator.tillFirstError();
if (validationError.isPresent()) {
String errorMsg = messageResolver.resolve(validationError.get());
log.error("cannot process CommonDeleteRequest id={}: {}", userRequest.getId(), errorMsg);
return new RequestInfoUpdate()
.setId(userRequest.getId())
.setStatus(Status.Error)
.setMessage(errorMsg);
}
MoneyMarketSecurity mms = validator.getStored(Stored.PresentById);
mms.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
Instant.now();
mms.setUpdated(Instant.now());
moneyMarketSecurityMap.update(mms);
Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId()));
if (listing == null) {
log.error("CommonDeleteRequest id {} couldn't find listing with securityId {}", req.getId(), mms.getId());
return null;
}
listing.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey());
listing.setUpdated(Instant.now());
listingImdg.update(listing);
return null;
}
}

View file

@ -0,0 +1,66 @@
package ru.spcex.clearing.securities.validation;
import org.springframework.stereotype.Component;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityUpdateRequest;
import ru.spcex.clearing.securities.errors.SecuritiesError;
import ru.spcex.clearing.securities.validation.rule.EndDtAfterStartDt;
import ru.spcex.clearing.securities.validation.rule.MmsNewValidationRule;
import ru.spcex.clearing.securities.validation.rule.MmsUpdateValidationRule;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.imdg.validation.rule.PresentById;
import ru.spcex.platform.utils.validation.IValidator;
import ru.spcex.platform.utils.validation.ValidatorImpl;
import java.util.function.Function;
@Component
public class ValidationProvider {
private final Imdg<SpcexObjectBase> mmsMap;
public ValidationProvider(ImdgProvider imdgProvider) {
this.mmsMap = imdgProvider.getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, SpcexObjectBase.class);
}
public Function<MoneyMarketSecurityNewRequest, IValidator> mmsNewValidator() {
return mmsRequest -> {
ImdgValidationContext<MoneyMarketSecurityNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(mmsRequest);
context.addImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, mmsMap);
return new ValidatorImpl<>(context,
EndDtAfterStartDt.instance(MoneyMarketSecurityNewRequest.class),
MmsNewValidationRule.SecuritySymbolUniq
);
};
}
public Function<MoneyMarketSecurityUpdateRequest, IValidator> mmsUpdateValidator() {
return mmsRequest -> {
ImdgValidationContext<MoneyMarketSecurityUpdateRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(mmsRequest);
context.addImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, mmsMap);
return new ValidatorImpl<>(context,
EndDtAfterStartDt.instance(MoneyMarketSecurityUpdateRequest.class),
new PresentById(IMDGDistributedNames.Map_MoneyMarketSecurity, SecuritiesError.InstrumentNotFound, true),
MmsUpdateValidationRule.StatusIsActive
);
};
}
public Function<CommonDeleteRequest, IValidator> mmsDeleteValidator() {
return mmsRequest -> {
ImdgValidationContext<CommonDeleteRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(mmsRequest);
context.addImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, mmsMap);
return new ValidatorImpl<>(context,
new PresentById(IMDGDistributedNames.Map_MoneyMarketSecurity, SecuritiesError.InstrumentNotFound, true)
);
};
}
}

View file

@ -0,0 +1,28 @@
package ru.spcex.clearing.securities.validation.rule;
import ru.spcex.clearing.securities.errors.SecuritiesError;
import ru.spcex.platform.classes.base.interfaces.WithEndDt;
import ru.spcex.platform.classes.base.interfaces.WithStartDt;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
public class EndDtAfterStartDt<T extends WithStartDt & WithEndDt> implements IValidationRule<ImdgValidationContext<T>> {
public EndDtAfterStartDt() {}
public static <T1 extends WithStartDt & WithEndDt> EndDtAfterStartDt<T1> instance(Class<T1> clazz) {
return new EndDtAfterStartDt<>();
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<T> context) {
T validatedObject = context.getValidatedObject();
if (validatedObject.getEndDate().isBefore(validatedObject.getStartDate())) {
return of(SecuritiesError.WrongFieldValue, "endDate");
}
return empty();
}
}

View file

@ -0,0 +1,37 @@
package ru.spcex.clearing.securities.validation.rule;
import ru.clearing.classes.statics.data.misc.MoneyMarketSecurity;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest;
import ru.spcex.clearing.securities.errors.SecuritiesError;
import ru.spcex.platform.enumeration.Status;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Map;
import java.util.Optional;
public enum MmsNewValidationRule implements IValidationRule<ImdgValidationContext<MoneyMarketSecurityNewRequest>> {
SecuritySymbolUniq() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<MoneyMarketSecurityNewRequest> context) {
MoneyMarketSecurityNewRequest action = context.getValidatedObject();
Imdg<MoneyMarketSecurity> mmsImdg = context.obtainMap(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class);
MoneyMarketSecurity mms = mmsImdg.getSingleObjectByFieldValues(Map.of(
"securitySymbol", action.getSecuritySymbol(),
"workflowStatus", Status.Active.getKey()));
if (mms != null) {
return of(SecuritiesError.InstrumentAlreadyExists);
} else {
return empty();
}
}
};
@Override
public String ruleName() {
return "MmsNewValidationRule." + name();
}
}

View file

@ -0,0 +1,32 @@
package ru.spcex.clearing.securities.validation.rule;
import ru.clearing.classes.statics.data.misc.MoneyMarketSecurity;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityUpdateRequest;
import ru.spcex.clearing.securities.errors.SecuritiesError;
import ru.spcex.platform.enumeration.Status;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.imdg.validation.Stored;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
public enum MmsUpdateValidationRule implements IValidationRule<ImdgValidationContext<MoneyMarketSecurityUpdateRequest>> {
StatusIsActive() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<MoneyMarketSecurityUpdateRequest> context) {
MoneyMarketSecurity mms = context.getStoredObject(Stored.PresentById);
//проверка только если PresentById найдет объект и сохранит его
if (mms != null && !Status.Active.getKey().equals(mms.getWorkflowStatus())) {
return of(SecuritiesError.InstrumentNotActive);
} else {
return empty();
}
}
};
@Override
public String ruleName() {
return "MmsNewValidationRule." + name();
}
}

View file

@ -29,7 +29,9 @@ import ru.spcex.clearing.securities.config.HazelcastInstanceTestConfiguration;
import ru.spcex.clearing.securities.config.HazelcastServiceTestConfiguration;
import ru.spcex.clearing.securities.service.cud.MoneyMarketSecurityService;
import ru.spcex.clearing.securities.utils.MatcherFactory;
import ru.spcex.clearing.securities.validation.ValidationProvider;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
import java.math.BigDecimal;
import java.time.LocalDate;
@ -84,7 +86,8 @@ public class MoneyMarketSecurityServiceDisabled {
private void startService() throws InterruptedException {
MoneyMarketSecurityService keyRateService =
new MoneyMarketSecurityService(kafkaMockQueue, mockProducer, hazelcastService);
new MoneyMarketSecurityService(kafkaMockQueue, mockProducer, hazelcastService,
new ValidationProvider(hazelcastService), new SimpleMessageResolver());
keyRateService.afterPropertiesSet();
}

View file

@ -0,0 +1,7 @@
package ru.spcex.platform.classes.base.interfaces;
import java.time.LocalDate;
public interface WithEndDt {
LocalDate getEndDate();
}

View file

@ -0,0 +1,5 @@
package ru.spcex.platform.classes.base.interfaces;
public interface WithSecuritySymbol {
String getSecuritySymbol();
}

View file

@ -0,0 +1,7 @@
package ru.spcex.platform.classes.base.interfaces;
import java.time.LocalDate;
public interface WithStartDt {
LocalDate getStartDate();
}

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;
}
}

View file

@ -164,6 +164,7 @@ public class ImdgHazelcast<T extends SpcexObjectBase> implements Imdg<T> {
this.hzInstance = hzInstance;
}
@Override
public String getMapName() {
return mapName;
}

View file

@ -6,6 +6,10 @@ import java.util.Collection;
import java.util.Map;
public interface Imdg<T extends SpcexObjectBase> {
default String getMapName() {
throw new UnsupportedOperationException("not implemented name");
}
default void insert(T paramT) {
throw new UnsupportedOperationException("not implemented insert");
}

View file

@ -29,6 +29,9 @@ public class ImdgValidationContext<T> implements IValidatorContext {
return validatedObject;
}
/**
* !!!не использовать один Enum в разных местах
*/
public void storeObject(Enum<?> storedObject, Object anyObject) {
storedObjects.put(storedObject, anyObject);
}

View file

@ -0,0 +1,11 @@
package ru.spcex.platform.imdg.validation;
/**
* !!!не использовать один Enum в разных местах - по энуму на один класс IValidationRule.
*/
public enum Stored {
/**
* если выполняется проверка наличия объекта по Id (см. ru.spcex.platform.imdg.validation.rule.PresentById)
*/
PresentById
}

View file

@ -0,0 +1,43 @@
package ru.spcex.platform.imdg.validation.rule;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.classes.base.interfaces.WithId;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.imdg.validation.Stored;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
public class PresentById implements IValidationRule<ImdgValidationContext<WithId>> {
private final String mapName;
private final IEnumId errorEnum;
private boolean storeEnabled = false;
public PresentById(String mapName, IEnumId errorEnum) {
this.mapName = mapName;
this.errorEnum = errorEnum;
}
public PresentById(String mapName, IEnumId errorEnum, Boolean storeEnabled) {
this.mapName = mapName;
this.errorEnum = errorEnum;
this.storeEnabled = storeEnabled;
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<WithId> context) {
WithId actionById = context.getValidatedObject();
Imdg<SpcexObjectBase> targetMap = context.obtainMap(mapName, SpcexObjectBase.class);
SpcexObjectBase obj = targetMap.getSingleObjectByID(actionById.getId());
if (obj == null) {
return of(errorEnum, actionById.getId());
} else {
if (storeEnabled) {
context.storeObject(Stored.PresentById, obj);
}
return empty();
}
}
}

View file

@ -5,10 +5,12 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer;
import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer;
import ru.spcex.platform.classes.base.interfaces.WithEndDt;
import ru.spcex.platform.classes.base.interfaces.WithStartDt;
import java.time.LocalDate;
public class MoneyMarketSecurityNewRequest {
public class MoneyMarketSecurityNewRequest implements WithStartDt, WithEndDt {
@JsonProperty
@JsonSerialize(using = LocalDateSerializer.class)
@JsonDeserialize(using = LocalDateDeserializer.class)

View file

@ -6,10 +6,12 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer;
import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer;
import ru.spcex.platform.classes.base.interfaces.WithEndDt;
import ru.spcex.platform.classes.base.interfaces.WithStartDt;
import java.time.LocalDate;
public class MoneyMarketSecurityUpdateRequest {
public class MoneyMarketSecurityUpdateRequest implements WithStartDt, WithEndDt {
@JsonProperty
public Long id;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow")

View file

@ -3,20 +3,40 @@ package ru.spcex.clearing.platform.messaging.service;
public class RequestInfoUpdate {
private Long id;
private Status status;
private String message;
public RequestInfoUpdate() {}
public RequestInfoUpdate(Long id, Status status, Long errorId, String message) {
this.id = id;
this.status = status;
this.message = message;
}
public Long getId() {
return id;
}
public void setId(Long id) {
public RequestInfoUpdate setId(Long id) {
this.id = id;
return this;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
public RequestInfoUpdate setStatus(Status status) {
this.status = status;
return this;
}
public String getMessage() {
return message;
}
public RequestInfoUpdate setMessage(String message) {
this.message = message;
return this;
}
}

View file

@ -0,0 +1,11 @@
package ru.spcex.platform.utils.enumeration;
import java.util.Arrays;
public class SimpleMessageResolver implements IMessageResolver {
@Override
public String resolve(EnumMessage errorMessage) {
if (errorMessage == null) return "null";
return String.format("(%d) args %s", errorMessage.getSubject().getId(), Arrays.toString(errorMessage.getArgs()));
}
}