Merge remote-tracking branch 'origin/dev' into CLS-262
This commit is contained in:
commit
b214aa8415
43 changed files with 2319 additions and 189 deletions
|
|
@ -14,6 +14,7 @@ import ru.spcex.clearing.backendapi.controller.request.cud.company.CompanyInfoUp
|
|||
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
|
||||
import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse;
|
||||
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
|
||||
import ru.spcex.clearing.backendapi.controller.response.entity.company.CompanyInfoBackendGetAll;
|
||||
import ru.spcex.clearing.backendapi.meta.GetResponseFactory;
|
||||
import ru.spcex.clearing.backendapi.service.IOperator;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
|
|
@ -53,19 +54,14 @@ public class CompanyInfoController extends AbstractQueueController {
|
|||
}
|
||||
|
||||
@ApiOperation(value = "get all CompanyInfo's.")
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)})
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CompanyInfoBackendGetAll.class)})
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public CommonGetAllResponse getAll() {
|
||||
public CompanyInfoBackendGetAll getAll() {
|
||||
Collection<Map<String, Object>> all = new ArrayList<>();
|
||||
Collection<Company> companies = companyImdg.getAllValues();
|
||||
for (Company company : companies) {
|
||||
if (company.getProfile() != null && company.getProfile().getId() != null) { // пока возвращает "пустой" CompanyInfo если его нет для Company
|
||||
all.add(responseFactory.responseFromObject(company.getProfile()));
|
||||
}
|
||||
}
|
||||
CommonGetAllResponse response = new CommonGetAllResponse();
|
||||
response.fromEntity(all);
|
||||
CompanyInfoBackendGetAll response = new CompanyInfoBackendGetAll();
|
||||
response.fromEntity(companies);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package ru.spcex.clearing.backendapi.controller.response.entity.company;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(description = "Ответ при получении объектов CompanyInfos.")
|
||||
public class CompanyInfoBackendGetAll extends BasicSpcexResponse {
|
||||
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Полезная нагрузка")
|
||||
private CompanyInfoBackendPayload payload = new CompanyInfoBackendPayload();
|
||||
|
||||
private static class CompanyInfoBackendPayload {
|
||||
private List<CompanyInfoBackendGetFields> items = new ArrayList<>();
|
||||
|
||||
public List<CompanyInfoBackendGetFields> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<CompanyInfoBackendGetFields> items) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
||||
|
||||
public CompanyInfoBackendPayload getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public void setPayload(CompanyInfoBackendPayload payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public void fromEntity(Collection<Company> companys) {
|
||||
var payload = this.getPayload();
|
||||
for (var company : companys) {
|
||||
var singleItem = CompanyInfoBackendGetFields.fromEntity(company);
|
||||
payload.getItems().add(singleItem);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
package ru.spcex.clearing.backendapi.controller.response.entity.company;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.profile.CompanyInfo;
|
||||
|
||||
public class CompanyInfoBackendGetFields {
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Идентификатор записи")
|
||||
private Long id;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Идентификатор компании")
|
||||
private Long companyId;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код единоличного исполнительного органа")
|
||||
private String corporationSoleType;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код юрисдикции")
|
||||
private String countryCode;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Описание компании")
|
||||
private String description;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код признака профессионального участника")
|
||||
private String professionalSign;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код вида субъекта")
|
||||
private String legalKind;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код типа организации")
|
||||
private String organizationType;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код резиденции")
|
||||
private String residence;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Краткое наименование компании")
|
||||
private String shortName;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Полное наименование компании")
|
||||
private String fullName;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Краткое наименование компании на английском")
|
||||
private String shortNameEng;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Краткое наименование компании на английском")
|
||||
private String fullNameEng;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код участника торгов")
|
||||
private String tradingCode;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Код участника клиринга")
|
||||
private String clearingCode;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Регистрационный код участника")
|
||||
private String registrationCode;
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Наименование статуса")
|
||||
private String workflowStatus;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getCompanyId() {
|
||||
return companyId;
|
||||
}
|
||||
|
||||
public void setCompanyId(Long companyId) {
|
||||
this.companyId = companyId;
|
||||
}
|
||||
|
||||
public String getCorporationSoleType() {
|
||||
return corporationSoleType;
|
||||
}
|
||||
|
||||
public void setCorporationSoleType(String corporationSoleType) {
|
||||
this.corporationSoleType = corporationSoleType;
|
||||
}
|
||||
|
||||
public String getCountryCode() {
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
public void setCountryCode(String countryCode) {
|
||||
this.countryCode = countryCode;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getProfessionalSign() {
|
||||
return professionalSign;
|
||||
}
|
||||
|
||||
public void setProfessionalSign(String professionalSign) {
|
||||
this.professionalSign = professionalSign;
|
||||
}
|
||||
|
||||
public String getLegalKind() {
|
||||
return legalKind;
|
||||
}
|
||||
|
||||
public void setLegalKind(String legalKind) {
|
||||
this.legalKind = legalKind;
|
||||
}
|
||||
|
||||
public String getOrganizationType() {
|
||||
return organizationType;
|
||||
}
|
||||
|
||||
public void setOrganizationType(String organizationType) {
|
||||
this.organizationType = organizationType;
|
||||
}
|
||||
|
||||
public String getResidence() {
|
||||
return residence;
|
||||
}
|
||||
|
||||
public void setResidence(String residence) {
|
||||
this.residence = residence;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
public void setShortName(String shortName) {
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public void setFullName(String fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getShortNameEng() {
|
||||
return shortNameEng;
|
||||
}
|
||||
|
||||
public void setShortNameEng(String shortNameEng) {
|
||||
this.shortNameEng = shortNameEng;
|
||||
}
|
||||
|
||||
public String getFullNameEng() {
|
||||
return fullNameEng;
|
||||
}
|
||||
|
||||
public void setFullNameEng(String fullNameEng) {
|
||||
this.fullNameEng = fullNameEng;
|
||||
}
|
||||
|
||||
public String getTradingCode() {
|
||||
return tradingCode;
|
||||
}
|
||||
|
||||
public void setTradingCode(String tradingCode) {
|
||||
this.tradingCode = tradingCode;
|
||||
}
|
||||
|
||||
public String getClearingCode() {
|
||||
return clearingCode;
|
||||
}
|
||||
|
||||
public void setClearingCode(String clearingCode) {
|
||||
this.clearingCode = clearingCode;
|
||||
}
|
||||
|
||||
public String getRegistrationCode() {
|
||||
return registrationCode;
|
||||
}
|
||||
|
||||
public void setRegistrationCode(String registrationCode) {
|
||||
this.registrationCode = registrationCode;
|
||||
}
|
||||
|
||||
public String getWorkflowStatus() {
|
||||
return workflowStatus;
|
||||
}
|
||||
|
||||
public void setWorkflowStatus(String workflowStatus) {
|
||||
this.workflowStatus = workflowStatus;
|
||||
}
|
||||
|
||||
public static CompanyInfoBackendGetFields fromEntity(Company company) {
|
||||
if (company == null || company.getProfile() == null) {
|
||||
return null;
|
||||
}
|
||||
CompanyInfo info = company.getProfile();
|
||||
CompanyInfoBackendGetFields fields = new CompanyInfoBackendGetFields();
|
||||
fields.setId(info.getId());
|
||||
fields.setCompanyId(info.getCompanyId());
|
||||
fields.setCorporationSoleType(info.getCorporationSoleType());
|
||||
fields.setCountryCode(info.getCountryCode());
|
||||
fields.setDescription(info.getDescription());
|
||||
fields.setProfessionalSign(info.getProfessionalSign());
|
||||
fields.setLegalKind(info.getLegalKind());
|
||||
fields.setOrganizationType(info.getOrganizationType());
|
||||
fields.setResidence(info.getResidence());
|
||||
fields.setShortNameEng(info.getShortNameEng());
|
||||
fields.setFullNameEng(info.getFullNameEng());
|
||||
|
||||
fields.setShortName(company.getShortName());
|
||||
fields.setFullName(company.getFullName());
|
||||
fields.setTradingCode(company.getTradingCode());
|
||||
fields.setClearingCode(company.getClearingCode());
|
||||
fields.setRegistrationCode(company.getRegistrationCode());
|
||||
fields.setWorkflowStatus(company.getWorkflowStatus());
|
||||
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,10 +36,12 @@ public class TradingClearingRegistryBackendGetFields {
|
|||
@ApiModelProperty(value = "Наименование статуса", example = "ACTV")
|
||||
private String status;
|
||||
|
||||
@JsonProperty("Дата-время создания записи")
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Дата-время создания записи")
|
||||
@JsonSerialize(using = InstantSerializer.class)
|
||||
private Instant createdAt;
|
||||
@JsonProperty("Дата-время изменения записи")
|
||||
@JsonProperty
|
||||
@ApiModelProperty(value = "Дата-время изменения записи")
|
||||
@JsonSerialize(using = InstantSerializer.class)
|
||||
private Instant updatedAt;
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
<companySymbol id="16" code="CLRC" name="Код участника клиринга" shortname="Клиринговый код"/>
|
||||
<companySymbol id="17" code="RGRC" name="Регистрационный код участника" shortname="Регистрационный код"/>
|
||||
<companySymbol id="18" code="UUID" name="Идентификатор во внешней системе" shortname="Внешний идентификатор"/>
|
||||
<companySymbol id="19" code="RDPZ" name="Требуется получение документа о подтверждении открытия депозитного счета" shortname="Подтверждение депозитного счета"/>
|
||||
<companySymbol id="19" code="LICM" name="Лицензия на управление инвестиционными фондами, паевыми инвестиционными фондами, негосударственными пенсионными фондами" shortname="Лицензия на управление фондами"/>
|
||||
<companyRole id="1" code="RPRT" name="Отчетная организация"/>
|
||||
<companyRole id="2" code="CLRH" name="Клиринговая организация"/>
|
||||
<companyRole id="3" code="EXCH" name="Торговая система"/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package ru.spcex.clearing.util.services;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.clearing.platform.dictionary.ErrorCodeDictionary;
|
||||
|
|
@ -25,7 +26,7 @@ public class IMDGMessageResolver implements IMessageResolver {
|
|||
@Override
|
||||
public String resolve(EnumMessage errorMessage) {
|
||||
if (errorMessage == null) return "null";
|
||||
|
||||
try {
|
||||
ErrorCodeDictionary errorDictionary = errorCodeDictionaryIMDG.getSingleObjectByID(errorMessage.getSubject().getId());
|
||||
if (errorDictionary == null) {
|
||||
log.warn("ERROR_CODE_DICTIONARY not found fo id={}", errorMessage.getSubject().getId());
|
||||
|
|
@ -33,5 +34,9 @@ public class IMDGMessageResolver implements IMessageResolver {
|
|||
}
|
||||
String textTemplate = errorDictionary.getName();
|
||||
return String.format(textTemplate, errorMessage.getArgs());
|
||||
} catch (Exception errFormatting) { // MissingFormatArgumentException
|
||||
log.warn("Error in message resolver for error {}: {}", errorMessage.getSubject(), ExceptionUtils.getStackTrace(errFormatting));
|
||||
return String.format("(%d) args %s", errorMessage.getSubject().getId(), Arrays.toString(errorMessage.getArgs()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
package ru.spcex.clearing.company.util;
|
||||
package ru.spcex.clearing.util.services;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.platform.messaging.service.Status;
|
||||
|
|
@ -22,21 +21,28 @@ import java.util.Objects;
|
|||
* callback(CompanyNewRequest.class)
|
||||
* .setFunction( request -> requestHelper.requestFunction(this::createCompany, request))
|
||||
* .forDestination(Consts.DESTINATION_COMPANY_NEW, callbacks::put);
|
||||
*
|
||||
* return requestHelper.makeErrorResponse(CompanyError.GeneralError, ...)
|
||||
*/
|
||||
public class RequestHelper {
|
||||
protected Logger log = LoggerFactory.getLogger(getClass());
|
||||
protected final IMessageResolver messageResolver;
|
||||
protected final IErrorEnumId generalError;
|
||||
|
||||
public RequestHelper(IMessageResolver messageResolver) {
|
||||
public RequestHelper(IMessageResolver messageResolver, IErrorEnumId generalError) {
|
||||
Objects.requireNonNull(messageResolver);
|
||||
this.messageResolver = messageResolver;
|
||||
this.generalError = generalError;
|
||||
Objects.requireNonNull(generalError, "Required generalError enum");
|
||||
}
|
||||
|
||||
public RequestHelper(Logger log, IMessageResolver messageResolver) {
|
||||
public RequestHelper(Logger log, IMessageResolver messageResolver, IErrorEnumId generalError) {
|
||||
Objects.requireNonNull(log);
|
||||
Objects.requireNonNull(messageResolver);
|
||||
this.log = log;
|
||||
this.messageResolver = messageResolver;
|
||||
this.generalError = generalError;
|
||||
Objects.requireNonNull(generalError, "Required generalError enum");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -58,13 +64,14 @@ public class RequestHelper {
|
|||
String message = expectedE.getEnumMsg() == null
|
||||
? expectedE.getMessage()
|
||||
: messageResolver.resolve(expectedE.getEnumMsg());
|
||||
log.info("Response: {}", message);
|
||||
return new RequestInfoUpdate()
|
||||
.setId(userRequest.getId())
|
||||
.setStatus(Status.Error)
|
||||
.setMessage(message);
|
||||
} catch (Exception unexpectedE) {
|
||||
log.error("Error at {}: {} ", command, ExceptionUtils.getStackTrace(unexpectedE));
|
||||
String message = messageResolver.resolve(new EnumMessage(CompanyErrors.GeneralError));
|
||||
String message = messageResolver.resolve(new EnumMessage(generalError));
|
||||
return new RequestInfoUpdate()
|
||||
.setId(userRequest.getId())
|
||||
.setStatus(Status.Error)
|
||||
|
|
@ -74,6 +81,7 @@ public class RequestHelper {
|
|||
|
||||
public RequestInfoUpdate makeErrorResponse(BaseRequest<?> request, EnumMessage msg) {
|
||||
String errorMsg = msg == null? "" : messageResolver.resolve(msg);
|
||||
log.info("Response: {}", errorMsg);
|
||||
return new RequestInfoUpdate()
|
||||
.setId(request.getId())
|
||||
.setStatus(Status.Error)
|
||||
|
|
@ -1,66 +1,216 @@
|
|||
package ru.spcex.clearing.util.services.exchangers;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import ru.spcex.clearing.platform.messaging.domain.ActionType;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountBalanceClearingRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.Sdf04Request;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.platform.messaging.service.Status;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.platform.enumeration.Task;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Синхронный обмен сообщениями с ассинхронным сервисом.
|
||||
* Метод exchange() отправляет сообщение в очередь и дожидается ответа из другой очереди
|
||||
* Метод exchange() отправляет сообщение в очередь и дожидается ответа из другой очереди.
|
||||
* Использовать с осторожностью, т.к. нет возобновления ожидания в случае нештатного выключения модуля при ожидании ответа из kafka.
|
||||
* <p>
|
||||
* <p>
|
||||
* Ожидает из очереди (CommonIdRequest)
|
||||
*
|
||||
* @param <TOut> отправляется в очередь
|
||||
*/
|
||||
public class BiDirectionQueueExchanger<TIn, TOut extends BaseRequest<?>> extends QueueConsumer implements InitializingBean, DisposableBean {
|
||||
public class BiDirectionQueueExchanger<TOut extends BaseRequest<?>> extends QueueConsumer implements Closeable {
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
protected final Object sync = new Object();
|
||||
protected String outQueue;
|
||||
protected String inQueue;
|
||||
protected Class<TIn> listenClass;
|
||||
protected long timeout;
|
||||
private Producer<String, Object> producer;
|
||||
|
||||
protected volatile boolean isTerminated;
|
||||
protected Object syncObject;
|
||||
protected Long lastSentRequestId;
|
||||
protected volatile Long lastResponseId;
|
||||
protected boolean ignoreOtherResponse = true; // Пропускать другие ID, пока не получит lastResponseId==lastSentRequestId
|
||||
|
||||
/**
|
||||
* Синхронно-ассинхронный обмен сообщениями
|
||||
*
|
||||
* @param kafkaQueue
|
||||
* @param kafkaQueue уникальный kafka Consumer (Spring prototype). Нельзя переиспользовать существующие.
|
||||
* @param kafkaProducer
|
||||
* @param outQueue отправляет в очередь
|
||||
* @param inQueue слушает очередь, ожидает ответов
|
||||
* @param listenClass типы объектов из inQueue
|
||||
* @param inQueue слушает очередь/топик, ожидает ответов. Пример: Consts.CONTINUE_CLEARING
|
||||
* @param ignoreOtherResponse true для inQueue=Consts.REQUEST_INFO_UPDATE
|
||||
* @param timeout - максимальное ожидание ответа, в миллисекундах, 0 - неограничено
|
||||
*/
|
||||
public BiDirectionQueueExchanger(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
|
||||
String outQueue,
|
||||
String inQueue, Class<TIn> listenClass,
|
||||
String inQueue,
|
||||
boolean ignoreOtherResponse,
|
||||
long timeout) {
|
||||
super(kafkaQueue, kafkaProducer);
|
||||
super(kafkaQueue);
|
||||
this.producer = kafkaProducer;
|
||||
if (kafkaQueue == null) {
|
||||
throw new IllegalArgumentException("kafkaQueue is empty");
|
||||
}
|
||||
if (kafkaProducer == null) {
|
||||
throw new IllegalArgumentException("kafkaProducer is empty");
|
||||
}
|
||||
if (StringUtils.isEmpty(outQueue)) {
|
||||
throw new IllegalArgumentException("outQueue is empty");
|
||||
}
|
||||
this.outQueue = outQueue;
|
||||
if (StringUtils.isEmpty(inQueue)) {
|
||||
throw new IllegalArgumentException("inQueue is empty");
|
||||
}
|
||||
this.inQueue = inQueue;
|
||||
this.listenClass = listenClass;
|
||||
if (timeout < 0) {
|
||||
timeout = 0;
|
||||
}
|
||||
this.timeout = timeout;
|
||||
this.ignoreOtherResponse = ignoreOtherResponse;
|
||||
|
||||
initReplyListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправить сообщение message в outQueue и дождаться ответа из очереди inQueue
|
||||
*
|
||||
* @param message
|
||||
* @return
|
||||
* @throws InterruptedException
|
||||
* @return request/reply id
|
||||
* @throws InterruptedException или когда поток прерывают, или когда BiDirectionQueueExchanger.close()
|
||||
*/
|
||||
public TOut exchange(TIn message) throws InterruptedException {
|
||||
//todo impl BiDirectionQueueExchanger
|
||||
return null;
|
||||
public Long exchange(TOut message) throws InterruptedException {
|
||||
if (syncObject == null)
|
||||
throw new IllegalStateException("Listener queue not initialized");
|
||||
if (message.getId() == null) {
|
||||
throw new IllegalArgumentException("Required message " + message.getClass().getSimpleName() + ".id is null");
|
||||
}
|
||||
|
||||
//send request to kafka, wait for a reply
|
||||
try {
|
||||
synchronized (syncObject) {
|
||||
Long sentRequestId = sendMessage(message);
|
||||
log.trace("sent request to kafka, requestId: {}", sentRequestId);
|
||||
this.lastSentRequestId = sentRequestId;
|
||||
|
||||
long waitStart = System.currentTimeMillis();
|
||||
long waitTime = timeout;
|
||||
do {
|
||||
try {
|
||||
if (timeout > 0) {
|
||||
syncObject.wait(waitTime);
|
||||
} else {
|
||||
syncObject.wait();
|
||||
}
|
||||
//если на этом месте произошла ошибка - непонятно как обрабатывать
|
||||
//т.к. request на самом деле могла быть проблема с сетью/недоступностью кафки etc.
|
||||
} catch (InterruptedException e) {
|
||||
log.error(ExceptionUtils.getStackTrace(e));
|
||||
throw e;
|
||||
// Thread.currentThread().interrupt();
|
||||
// throw new RuntimeException(e);
|
||||
}
|
||||
waitTime = timeout - (System.currentTimeMillis() - waitStart);
|
||||
if (isTerminated && lastResponseId == null) {
|
||||
log.warn("Terminated waiter {} kafka at thread {}", this, Thread.currentThread().getName());
|
||||
throw new InterruptedException(getClass().getSimpleName() + " closed");
|
||||
}
|
||||
if (ignoreOtherResponse && !sentRequestId.equals(lastResponseId)) {
|
||||
log.debug("Ignore response id={}, we waiting {}.", lastResponseId, sentRequestId);
|
||||
}
|
||||
} while (ignoreOtherResponse && !sentRequestId.equals(lastResponseId) && (timeout > 0 && waitTime > 0));
|
||||
if (!sentRequestId.equals(lastResponseId)) {
|
||||
log.error("FATAL: last response from {} update from Kafka ID was {}, but sent ID was {}",
|
||||
inQueue, lastResponseId, sentRequestId);
|
||||
throw new IllegalStateException("Expected wait till requestId=" + sentRequestId + " but catch lastResponseId=" + lastResponseId);
|
||||
}
|
||||
return sentRequestId;
|
||||
|
||||
}
|
||||
} finally {
|
||||
this.lastSentRequestId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
public void close() {
|
||||
isTerminated = true;
|
||||
if (lastSentRequestId != null) {
|
||||
log.warn("Finished before wait, lastSentRequestId={}", lastSentRequestId);
|
||||
if (syncObject != null) {
|
||||
synchronized (syncObject) {
|
||||
lastResponseId = null;
|
||||
syncObject.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
syncObject = null;
|
||||
log.debug("Listener {} for async exchange {}-{} close", this, outQueue, inQueue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
protected void initReplyListener() {
|
||||
if (syncObject != null) {
|
||||
throw new IllegalStateException("Already initialized");
|
||||
}
|
||||
callback(CommonIdRequest.class)
|
||||
.setConsumer(this::continueWaiting)
|
||||
.forDestination(inQueue, callbacks::put);
|
||||
init();
|
||||
|
||||
syncObject = new Object();
|
||||
isTerminated = false;
|
||||
|
||||
log.debug("Listener {} for async exchange {}-{} ready", this, outQueue, inQueue);
|
||||
}
|
||||
|
||||
protected Long sendMessage(TOut message) throws InterruptedException {
|
||||
Long sentRequestId = message.getId();
|
||||
if (sentRequestId == null) {
|
||||
throw new IllegalArgumentException("Message " + message.getClass().getSimpleName() + " required id.");
|
||||
}
|
||||
try {
|
||||
Future<RecordMetadata> send = producer.send(new ProducerRecord<>(Consts.REQUEST_INFO_UPDATE, message));
|
||||
send.get();
|
||||
return sentRequestId;
|
||||
} catch (InterruptedException e) {
|
||||
log.error("Interrupt when send message, {}", ExceptionUtils.getStackTrace(e));
|
||||
Thread.currentThread().interrupt();
|
||||
throw e;
|
||||
} catch (ExecutionException e) {
|
||||
log.error("Error at send message, {} cause: {}", e.toString(), ExceptionUtils.getStackTrace(e.getCause()));
|
||||
throw new RuntimeException("Send message error", e.getCause());
|
||||
} catch (Exception e) {
|
||||
log.error("Unexpected exception when send message: {}", ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void continueWaiting(BaseRequest<CommonIdRequest> event) {
|
||||
synchronized (syncObject) {
|
||||
CommonIdRequest requestPayload = event.getRequestPayload();
|
||||
log.debug("continueWaiting {} for id={}", inQueue, requestPayload.getId());
|
||||
lastResponseId = requestPayload.getId();
|
||||
syncObject.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.company.util.RequestHelper;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.platform.enumeration.UserRole;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
|
@ -22,7 +22,7 @@ public class BeanConfiguration {
|
|||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public RequestHelper requestHelper(IMessageResolver messageResolver) {
|
||||
return new RequestHelper(messageResolver);
|
||||
return new RequestHelper(messageResolver, CompanyErrors.GeneralError);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
package ru.spcex.clearing.company.config.validation;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.account.ClientCode;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.clearing.platform.dictionary.WorkflowStatusDictionary;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeUpdateRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
|
||||
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
|
||||
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
import ru.spcex.platform.utils.validation.ValidatorImpl;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Configuration
|
||||
public class ClientCodeValidationConfig {
|
||||
|
||||
@Bean("clientCodeNewRequestValidator")
|
||||
public Function<ClientCodeNewRequest, IValidator> clientCodeNewRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
|
||||
return clientCodeUpdateRequest -> {
|
||||
ImdgValidationContext<ClientCodeNewRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(clientCodeUpdateRequest);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry);
|
||||
addImdg.accept(IMDGDistributedNames.Map_WorkflowStatusDictionary);
|
||||
return new ValidatorImpl<>(context,
|
||||
FieldRequiredRule.instance("companyId", ClientCodeNewRequest::getCompanyId, CompanyErrors.RequiredFieldEmpty),
|
||||
IdPresentRule.instance("companyId",
|
||||
ClientCodeNewRequest::getCompanyId,
|
||||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.CompanyNotFound),
|
||||
|
||||
IdPresentRule.instance("moneyAccountId",
|
||||
ClientCodeNewRequest::getMoneyAccountId,
|
||||
IMDGDistributedNames.Map_Account,
|
||||
Account.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.AccountNotFound,
|
||||
false,
|
||||
acc -> Objects.equals(context.getValidatedObject().getCompanyId(), acc.getCompanyId())
|
||||
? null : CompanyErrors.AccountNotFound
|
||||
),
|
||||
IdPresentRule.instance("depoAccountId",
|
||||
ClientCodeNewRequest::getDepoAccountId,
|
||||
IMDGDistributedNames.Map_Account,
|
||||
Account.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.AccountNotFound,
|
||||
false,
|
||||
acc -> Objects.equals(context.getValidatedObject().getCompanyId(), acc.getCompanyId())
|
||||
? null : CompanyErrors.AccountNotFound
|
||||
),
|
||||
|
||||
|
||||
DictionaryPresentRule.instance("stauts",
|
||||
ClientCodeNewRequest::getStatus,
|
||||
IMDGDistributedNames.Map_WorkflowStatusDictionary,
|
||||
WorkflowStatusDictionary.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.DictionaryNotFound,
|
||||
false)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean("clientCodeUpdateRequestValidator")
|
||||
public Function<ClientCodeUpdateRequest, IValidator> clientCodeUpdateRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
|
||||
return clientCodeUpdateRequest -> {
|
||||
ImdgValidationContext<ClientCodeUpdateRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(clientCodeUpdateRequest);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_ClientCode);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry);
|
||||
addImdg.accept(IMDGDistributedNames.Map_WorkflowStatusDictionary);
|
||||
return new ValidatorImpl<ImdgValidationContext<ClientCodeUpdateRequest>>(context,
|
||||
IdPresentRule.instance("id",
|
||||
ClientCodeUpdateRequest::getId,
|
||||
IMDGDistributedNames.Map_ClientCode,
|
||||
ClientCode.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.RecordNotFound
|
||||
),
|
||||
|
||||
FieldRequiredRule.instance("companyId", ClientCodeUpdateRequest::getCompanyId, CompanyErrors.RequiredFieldEmpty),
|
||||
IdPresentRule.instance("companyId",
|
||||
ClientCodeUpdateRequest::getCompanyId,
|
||||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.CompanyNotFound),
|
||||
|
||||
IdPresentRule.instance("moneyAccountId",
|
||||
ClientCodeUpdateRequest::getMoneyAccountId,
|
||||
IMDGDistributedNames.Map_Account,
|
||||
Account.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.AccountNotFound,
|
||||
false,
|
||||
acc -> Objects.equals(context.getValidatedObject().getCompanyId(), acc.getCompanyId())
|
||||
? null : CompanyErrors.AccountNotFound
|
||||
),
|
||||
IdPresentRule.instance("depoAccountId",
|
||||
ClientCodeUpdateRequest::getDepoAccountId,
|
||||
IMDGDistributedNames.Map_Account,
|
||||
Account.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.AccountNotFound,
|
||||
false,
|
||||
acc -> Objects.equals(context.getValidatedObject().getCompanyId(), acc.getCompanyId())
|
||||
? null : CompanyErrors.AccountNotFound
|
||||
),
|
||||
|
||||
DictionaryPresentRule.instance("stauts",
|
||||
ClientCodeUpdateRequest::getStatus,
|
||||
IMDGDistributedNames.Map_WorkflowStatusDictionary,
|
||||
WorkflowStatusDictionary.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.DictionaryNotFound,
|
||||
false)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean("clientCodeDeleteRequestValidator")
|
||||
public Function<CommonDeleteRequest, IValidator> clientCodeDeleteRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
|
||||
return companyDeleteRequest -> {
|
||||
ImdgValidationContext<CommonDeleteRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(companyDeleteRequest);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_ClientCode);
|
||||
return new ValidatorImpl<>(context,
|
||||
// FieldRequiredRule.instance("id", CommonDeleteRequest::getId, CompanyErrors.RequiredFieldEmpty),
|
||||
IdPresentRule.instance("id",
|
||||
CommonDeleteRequest::getId,
|
||||
IMDGDistributedNames.Map_ClientCode,
|
||||
ClientCode.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.RecordNotFound)
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ public class ContactValidationConfig {
|
|||
IMDGDistributedNames.Map_Contact,
|
||||
Contact.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.CompanyNotFound,
|
||||
CompanyErrors.ContactNotFound,
|
||||
contact -> {
|
||||
if (contactUpdateRequest.getContactType() == null) return null;
|
||||
if (!contactUpdateRequest.getContactType().equalsIgnoreCase(contact.getContactType())) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class ProfileDocumentValidationConfig {
|
|||
Company.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.CompanyNotFound,
|
||||
company -> WorkflowStatus.Active.getKey().equals(company.getWorkflowStatus()) ? null : CompanyErrors.CompanyDisabled),
|
||||
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : CompanyErrors.CompanyDisabled),
|
||||
DictionaryPresentRule.instance("documentType",
|
||||
ProfileDocumentNewRequest::getDocumentType,
|
||||
IMDGDistributedNames.Map_DocumentTypeDictionary,
|
||||
|
|
@ -138,7 +138,15 @@ public class ProfileDocumentValidationConfig {
|
|||
IMDGDistributedNames.Map_ProfileDocument,
|
||||
ProfileDocument.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.RecordNotFound)
|
||||
CompanyErrors.RecordNotFound,
|
||||
profileDoc -> {
|
||||
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
|
||||
Company company = companyImdg.getSingleObjectByID(profileDoc.getCompanyId());
|
||||
if (company == null) {
|
||||
return CompanyErrors.CompanyNotFound;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
package ru.spcex.clearing.company.config.validation;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.relation.Relation;
|
||||
import ru.clearing.platform.dictionary.ClearingCategoryDictionary;
|
||||
import ru.clearing.platform.dictionary.WorkflowStatusDictionary;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.RelationNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.RelationUpdateRequest;
|
||||
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
|
||||
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
import ru.spcex.platform.utils.validation.ValidatorImpl;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Configuration
|
||||
public class RelationValidationConfig {
|
||||
|
||||
@Bean("relationNewRequestValidation")
|
||||
public Function<RelationNewRequest, IValidator> relationNewRequestValidator(
|
||||
Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation
|
||||
) {
|
||||
return relationNewRequest -> {
|
||||
ImdgValidationContext<RelationNewRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(relationNewRequest);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
addImdg.accept(IMDGDistributedNames.Map_ClearingCategoryDictionary);
|
||||
addImdg.accept(IMDGDistributedNames.Map_WorkflowStatusDictionary);
|
||||
return new ValidatorImpl<>(context,
|
||||
IdPresentRule.instance("companyId",
|
||||
RelationNewRequest::getCompanyId,
|
||||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.CompanyNotFound),
|
||||
DictionaryPresentRule.instance("documentType",
|
||||
RelationNewRequest::getClearingMemberCategory,
|
||||
IMDGDistributedNames.Map_ClearingCategoryDictionary,
|
||||
ClearingCategoryDictionary.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.WrongFieldValue),
|
||||
DictionaryPresentRule.instance("serviceStatus",
|
||||
RelationNewRequest::getServiceStatus,
|
||||
IMDGDistributedNames.Map_WorkflowStatusDictionary,
|
||||
WorkflowStatusDictionary.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.WrongFieldValue)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean("relationUpdateRequestValidation")
|
||||
public Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator(
|
||||
Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation
|
||||
) {
|
||||
return relationUpdateRequest -> {
|
||||
ImdgValidationContext<RelationUpdateRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(relationUpdateRequest);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Relation);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
// addImdg.accept(IMDGDistributedNames.Map_ClearingCategoryDictionary);
|
||||
addImdg.accept(IMDGDistributedNames.Map_WorkflowStatusDictionary);
|
||||
return new ValidatorImpl<>(context,
|
||||
IdPresentRule.instance("id",
|
||||
RelationUpdateRequest::getId,
|
||||
IMDGDistributedNames.Map_Relation,
|
||||
Relation.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.RelationNotFound,
|
||||
relation -> {
|
||||
if (relation.getConsumerId() == null) return null;
|
||||
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
|
||||
Company company = companyImdg.getSingleObjectByID(relation.getConsumerId());
|
||||
if (company == null) {
|
||||
return CompanyErrors.CompanyNotFound;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}),
|
||||
// IdPresentRule.instance("companyId",
|
||||
// RelationUpdateRequest::getCompanyId,
|
||||
// IMDGDistributedNames.Map_Company,
|
||||
// Company.class,
|
||||
// CompanyErrors.RequiredFieldEmpty,
|
||||
// CompanyErrors.CompanyNotFound),
|
||||
// DictionaryPresentRule.instance("documentType",
|
||||
// RelationUpdateRequest::getClearingMemberCategory,
|
||||
// IMDGDistributedNames.Map_ClearingCategoryDictionary,
|
||||
// ClearingCategoryDictionary.class,
|
||||
// CompanyErrors.RequiredFieldEmpty,
|
||||
// CompanyErrors.WrongFieldValue),
|
||||
DictionaryPresentRule.instance("serviceStatus",
|
||||
RelationUpdateRequest::getServiceStatus,
|
||||
IMDGDistributedNames.Map_WorkflowStatusDictionary,
|
||||
WorkflowStatusDictionary.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.WrongFieldValue)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean("relationDeleteRequestValidation")
|
||||
public Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator(
|
||||
Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation
|
||||
) {
|
||||
return relationDeleteRequest -> {
|
||||
ImdgValidationContext<CommonDeleteRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(relationDeleteRequest);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Relation);
|
||||
return new ValidatorImpl<>(context,
|
||||
IdPresentRule.instance("id",
|
||||
CommonDeleteRequest::getId,
|
||||
IMDGDistributedNames.Map_Relation,
|
||||
Relation.class,
|
||||
CompanyErrors.RequiredFieldEmpty,
|
||||
CompanyErrors.RelationNotFound
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,15 @@ package ru.spcex.clearing.company.config.validation;
|
|||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.account.ClientCode;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.CompanySymbols;
|
||||
import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
|
||||
import ru.clearing.classes.statics.data.company.relation.Relation;
|
||||
import ru.clearing.classes.statics.data.profile.Contact;
|
||||
import ru.clearing.classes.statics.data.profile.ProfileDocument;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.clearing.platform.dictionary.*;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
|
|
@ -34,6 +38,7 @@ public class ValidationConfig {
|
|||
addImdg.accept(IMDGDistributedNames.Map_DocumentTypeDictionary, DocumentTypeDictionary.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_ContactTypeDictionary, ContactTypeDictionary.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Contact, Contact.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
|
||||
addImdg.accept(IMDGDistributedNames.Map_WorkflowStatusDictionary, WorkflowStatusDictionary.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
|
||||
|
|
@ -44,6 +49,10 @@ public class ValidationConfig {
|
|||
addImdg.accept(IMDGDistributedNames.Map_LegalKindDictionary, LegalKindDictionary.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_OrganizationTypeDictionary, OrganizationTypeDictionary.class);
|
||||
|
||||
addImdg.accept(IMDGDistributedNames.Map_ClientCode, ClientCode.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account, Account.class);
|
||||
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
|
||||
|
||||
return imdg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ public enum CompanyErrors implements IErrorEnumId {
|
|||
CompanyAlreadyHasLiabilities(3018L), // У компании %s присутствуют обязательства.
|
||||
CompanyWithCompanySymbolAlreadyExist(3019L), // Компания с %s = %s уже создана" (где первый %s - companySymbol, второй %s - companySymbolValue)
|
||||
EditCompanySymbols(3020L), // Тип реквизита компании %s не может быть изменен.
|
||||
EditContactType(3021L) // Тип контакта компании %s не может быть изменен.
|
||||
EditContactType(3021L), // Тип контакта компании %s не может быть изменен.
|
||||
TradingClearingRegistryNotFound(3022L), // ТКР с %s не найден
|
||||
AccountNotFound(3023L), // Счет %s не найден
|
||||
ClearingMemberCategoryOnMKRAlreadyExist(3024L), // Договорные отношения %s в секции МКР уже созданы.
|
||||
ClearingMemberCategoryOnFONDAlreadyExist(3025L), // Договорные отношения %s на фондовой секции уже созданы.
|
||||
RelationNotFound(3026L), // Запись о договорных отношениях не найдена
|
||||
;
|
||||
private final Long id;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,413 @@
|
|||
package ru.spcex.clearing.company.service;
|
||||
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.account.ClientCode;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.ActionType;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeUpdateRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.TradingClearingRegistryNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.TradingClearingRegistryUpdateRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.clearing.util.services.exchangers.BiDirectionQueueExchanger;
|
||||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
import ru.spcex.platform.enumeration.TradingClearingRegistryType;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
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.iml.hazelcast.adapter.ImdgIdGeneratorHazelcast;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.error.ClearingBaseException;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Service
|
||||
public class ClientCodeService extends QueueConsumer implements InitializingBean, DisposableBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Producer<String, Object> kafkaProducer;
|
||||
private final ImdgId idGenerator;
|
||||
private final Imdg<ClientCode> clientCodeMap;
|
||||
private final Imdg<Company> companyMap;
|
||||
private final Imdg<TradingClearingRegistry> tradingClearingRegistryMap;
|
||||
|
||||
|
||||
private final Function<ClientCodeNewRequest, IValidator> clientCodeNewRequestValidator;
|
||||
private final Function<ClientCodeUpdateRequest, IValidator> clientCodeUpdateRequestValidator;
|
||||
private final Function<CommonDeleteRequest, IValidator> clientCodeDeleteRequestValidator;
|
||||
private final ValidationHelper validationHelper;
|
||||
private final UserRoleVerification userRoleVerification;
|
||||
private final IMessageResolver messageResolver;
|
||||
|
||||
BiDirectionQueueExchanger<BaseRequest<TradingClearingRegistryNewRequest>> accountServiceExchanger;
|
||||
|
||||
@Autowired
|
||||
public ClientCodeService(Consumer<String, Object> kafkaQueue1, Consumer<String, Object> kafkaQueue2,
|
||||
Producer<String, Object> kafkaProducer,
|
||||
ImdgProvider imdgProvider,
|
||||
ValidationHelper validationHelper,
|
||||
IMessageResolver messageResolver,
|
||||
UserRoleVerification userRoleVerification,
|
||||
@Qualifier("clientCodeNewRequestValidator") Function<ClientCodeNewRequest, IValidator> clientCodeNewRequestValidator,
|
||||
@Qualifier("clientCodeUpdateRequestValidator") Function<ClientCodeUpdateRequest, IValidator> clientCodeUpdateRequestValidator,
|
||||
@Qualifier("clientCodeDeleteRequestValidator") Function<CommonDeleteRequest, IValidator> clientCodeDeleteRequestValidator) {
|
||||
super(kafkaQueue1, kafkaProducer);
|
||||
this.kafkaProducer = kafkaProducer;
|
||||
this.idGenerator = imdgProvider.getImdgIdGenerator();
|
||||
this.clientCodeMap = imdgProvider.getImdg(IMDGDistributedNames.Map_ClientCode, ClientCode.class);
|
||||
this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.tradingClearingRegistryMap = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
this.clientCodeNewRequestValidator = clientCodeNewRequestValidator;
|
||||
this.clientCodeUpdateRequestValidator = clientCodeUpdateRequestValidator;
|
||||
this.clientCodeDeleteRequestValidator = clientCodeDeleteRequestValidator;
|
||||
this.validationHelper = validationHelper;
|
||||
this.messageResolver = messageResolver;
|
||||
this.userRoleVerification = userRoleVerification;
|
||||
|
||||
this.accountServiceExchanger = new BiDirectionQueueExchanger<>(kafkaQueue2, kafkaProducer,
|
||||
Consts.DESTINATION_TRADING_CLEARING_REGISTRY_NEW,
|
||||
Consts.REQUEST_INFO_UPDATE, true, // REQUEST_INFO_UPDATE - стандартная очередь, для результатов всех реквестов. DESTINATION_TRADING_CLEARING_REGISTRY_REPLY,
|
||||
60000
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
callback(ClientCodeNewRequest.class)
|
||||
.setConsumer(this::clientCodeNew)
|
||||
.forDestination(Consts.DESTINATION_CLIENT_CODE_NEW, callbacks::put);
|
||||
callback(ClientCodeNewRequest.class)
|
||||
.setConsumer(this::clientCodeNewFromApiUmCompany)
|
||||
.forDestination(Consts.DESTINATION_CLIENT_CODE_NEW_UM_COMPANY, callbacks::put);
|
||||
|
||||
callback(ClientCodeUpdateRequest.class)
|
||||
.setConsumer(this::clientCodeUpdate)
|
||||
.forDestination(Consts.DESTINATION_CLIENT_CODE_UPDATE, callbacks::put);
|
||||
callback(CommonDeleteRequest.class)
|
||||
.setConsumer(this::clientCodeDelete)
|
||||
.forDestination(Consts.DESTINATION_CLIENT_CODE_DELETE, callbacks::put);
|
||||
init();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
accountServiceExchanger.close();
|
||||
}
|
||||
|
||||
protected RequestInfoUpdate clientCodeNew(BaseRequest<ClientCodeNewRequest> userRequest) {
|
||||
log.debug("ClientCodeNewRequest received {}", userRequest.getId());
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, clientCodeNewRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
ClientCodeNewRequest req = userRequest.getRequestPayload();
|
||||
|
||||
boolean doCreateTCR = checkNeedCreateTCR(req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
if (doCreateTCR) {
|
||||
try {
|
||||
createAndWaitTCR(userRequest.getId(), null,
|
||||
req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
} catch (ClearingBaseException e) {
|
||||
log.error("Can not wait creation of TCR. request id={};CompanyId={}, MoneyAccountId={}, DepoAccountId={}; {}",
|
||||
userRequest.getId(), req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId(),
|
||||
e.toString());
|
||||
return makeErrorResponse(userRequest, CompanyErrors.GeneralError, "Can not create TCR at this moment");
|
||||
}
|
||||
}
|
||||
|
||||
ClientCode newClientCode = buildClientCode(req);
|
||||
clientCodeMap.insert(newClientCode);
|
||||
log.debug("successfully processed, new clientCode id {}", newClientCode.getId());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected RequestInfoUpdate clientCodeNewFromApiUmCompany(BaseRequest<ClientCodeNewRequest> userRequest) {
|
||||
log.debug("ClientCodeNewRequest received {}", userRequest.getId());
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, clientCodeNewRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
|
||||
ClientCodeNewRequest req = userRequest.getRequestPayload();
|
||||
|
||||
boolean doCreateTCR = checkNeedCreateTCR(req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
if (doCreateTCR) {
|
||||
try {
|
||||
createAndWaitTCR(userRequest.getId(), null,
|
||||
req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
} catch (ClearingBaseException e) {
|
||||
log.error("Can not wait creation of TCR. request id={};CompanyId={}, MoneyAccountId={}, DepoAccountId={}; {}",
|
||||
userRequest.getId(), req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId(),
|
||||
e.toString());
|
||||
return makeErrorResponse(userRequest, CompanyErrors.GeneralError, "Can not create TCR at this moment");
|
||||
}
|
||||
}
|
||||
|
||||
ClientCode newClientCode = buildClientCode(req);
|
||||
clientCodeMap.insert(newClientCode);
|
||||
log.debug("successfully processed, new clientCode id {}", newClientCode.getId());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected RequestInfoUpdate clientCodeUpdate(BaseRequest<ClientCodeUpdateRequest> userRequest) {
|
||||
ClientCodeUpdateRequest req = userRequest.getRequestPayload();
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, clientCodeUpdateRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
|
||||
log.debug("ClientCodeUpdateRequest received, id={}", req.getId());
|
||||
ClientCode clientCode = clientCodeMap.getSingleObjectByID(req.getId());
|
||||
if (clientCode == null) {
|
||||
return makeErrorResponse(userRequest, CompanyErrors.RecordNotFound, req.getId());
|
||||
}
|
||||
|
||||
boolean doCreateTCR = checkNeedCreateTCR(req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
if (doCreateTCR) {
|
||||
try {
|
||||
createAndWaitTCR(userRequest.getId(), clientCode.getId(),
|
||||
req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
} catch (ClearingBaseException e) {
|
||||
log.error("Can not wait creation of TCR. request id={};CompanyId={}, MoneyAccountId={}, DepoAccountId={}; {}",
|
||||
userRequest.getId(), req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId(),
|
||||
e.toString());
|
||||
return makeErrorResponse(userRequest, CompanyErrors.GeneralError, "Can not create TCR at this moment");
|
||||
}
|
||||
}
|
||||
|
||||
updateClientCode(clientCode, req);
|
||||
|
||||
clientCodeMap.update(clientCode);
|
||||
log.debug("successfully processed update, id {}", clientCode.getId());
|
||||
return null;
|
||||
}
|
||||
|
||||
private RequestInfoUpdate makeErrorResponse(BaseRequest<?> req, CompanyErrors err, Object... arg) {
|
||||
String errMsg = messageResolver.resolve(new EnumMessage(err, arg));
|
||||
return new RequestInfoUpdate()
|
||||
.setId(req.getId())
|
||||
.setStatus(ru.spcex.clearing.platform.messaging.service.Status.Error)
|
||||
.setMessage(errMsg);
|
||||
|
||||
}
|
||||
|
||||
protected RequestInfoUpdate clientCodeDelete(BaseRequest<CommonDeleteRequest> userRequest) {
|
||||
log.debug("CommonDeleteRequest received id = {}", userRequest.getId());
|
||||
CommonDeleteRequest req = userRequest.getRequestPayload();
|
||||
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, clientCodeDeleteRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
ClientCode clientCode = clientCodeMap.getSingleObjectByID(req.getId());
|
||||
if (clientCode.getMoneyAccountId() != null) {
|
||||
log.debug("Delete clientCode.id = {}: send message to account-service", clientCode.getId());
|
||||
sendBlockTCR(clientCode.getTradingClearingRegistryId(), clientCode.getMoneyAccountId());
|
||||
}
|
||||
log.debug("Delete clientCode.id={}", clientCode.getId());
|
||||
clientCodeMap.delete(clientCode);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
TradingClearingRegistry selectTradingClearingRegistry(Long companyId, Long moneyAccountId, Long depoAccountId) {
|
||||
Map<String, Comparable<?>> query = new HashMap<>();
|
||||
query.put("companyId", companyId);
|
||||
query.put("moneyAccountId", moneyAccountId);
|
||||
query.put("tradingClearingRegistryType", TradingClearingRegistryType.Client_B.getKey());
|
||||
if (depoAccountId != null) {
|
||||
query.put("depoAaccountId", depoAccountId); // todo опечатка в поле класса, см. meta.xml!
|
||||
}
|
||||
TradingClearingRegistry result = tradingClearingRegistryMap.getSingleObjectByFieldValues(query);
|
||||
log.trace("TradingClearingRegistry by: {}; {}found", query, result == null ? "not " : "");
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean checkNeedCreateTCR(Long companyId, Long moneyAccountId, Long depoAccountId) {
|
||||
// moneyAccountId обязателен, depoAccountId опционален
|
||||
if (moneyAccountId == null) {
|
||||
return false;
|
||||
}
|
||||
TradingClearingRegistry result = selectTradingClearingRegistry(companyId, moneyAccountId, depoAccountId);
|
||||
if (result == null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void createAndWaitTCR(Long reqId, Long clientCode,
|
||||
Long companyId, Long moneyAccountId, Long depoAccountId) throws ClearingBaseException {
|
||||
log.debug("For request {}, clientCode={} need create TCR: companyId={}, moneyAccountId={}, depoAccountId={}",
|
||||
reqId, clientCode == null ? "new" : clientCode,
|
||||
companyId, moneyAccountId, depoAccountId);
|
||||
BaseRequest<TradingClearingRegistryNewRequest> request = new BaseRequest<>();
|
||||
request.setId(idGenerator.nextId());
|
||||
request.setActionType(ActionType.NEW);
|
||||
TradingClearingRegistryNewRequest requestPayload = new TradingClearingRegistryNewRequest();
|
||||
requestPayload.setCompanyId(companyId);
|
||||
requestPayload.setMoneyAccountId(moneyAccountId);
|
||||
requestPayload.setDepoAccountId(depoAccountId);
|
||||
// requestPayload.setStatus(WorkflowStatus.Active.getKey());
|
||||
requestPayload.setTradingClearingRegistryType(TradingClearingRegistryType.Client_B.getKey());
|
||||
request.setRequestPayload(requestPayload);
|
||||
try {
|
||||
Long reply = accountServiceExchanger.exchange(request);
|
||||
if (reply == null) {
|
||||
throw new ClearingBaseException(CompanyErrors.GeneralError, "Waiting account-service timeout");
|
||||
}
|
||||
// примечание: ошибка и сбой (непредвиденное завершение программы) не приведёт к необратимым последствиям,
|
||||
// т.к. пользователь сможет повторить запрос, а созданный на предыдущем запросе ТКР уже будет создан и найдётся.
|
||||
} catch (InterruptedException e) {
|
||||
throw new ClearingBaseException(CompanyErrors.GeneralError, "Waiting account-service timeout");
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendBlockTCR(Long tradingClearingRegistryId, Long moneyAccountId) {
|
||||
if (tradingClearingRegistryId == null) {
|
||||
throw new IllegalArgumentException("tradingClearingRegistryId was null");
|
||||
}
|
||||
BaseRequest<TradingClearingRegistryUpdateRequest> request = new BaseRequest<>();
|
||||
request.setId(idGenerator.nextId());
|
||||
request.setActionType(ActionType.UPDATE);
|
||||
TradingClearingRegistryUpdateRequest requestPayload = new TradingClearingRegistryUpdateRequest();
|
||||
requestPayload.setId(tradingClearingRegistryId);
|
||||
requestPayload.setStatus(WorkflowStatus.Blocked.getKey());
|
||||
request.setRequestPayload(requestPayload);
|
||||
|
||||
try {
|
||||
sendMessage(Consts.DESTINATION_TRADING_CLEARING_REGISTRY_UPDATE, request);
|
||||
} catch (Exception e) {
|
||||
log.error("Can not send block TCR message, {}", e.toString());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param queue Consts.*
|
||||
* @param message BaseRequest
|
||||
* @return
|
||||
*/
|
||||
private Long sendMessage(String queue, BaseRequest<?> message) {
|
||||
Long sentRequestId = message.getId();
|
||||
if (sentRequestId == null) {
|
||||
throw new IllegalArgumentException("Message " + message.getClass().getSimpleName() + " required id.");
|
||||
}
|
||||
log.debug("Send to \"{}\" message {} id={}", queue, message.getActionType(), sentRequestId);
|
||||
try {
|
||||
Future<RecordMetadata> send = kafkaProducer.send(new ProducerRecord<>(queue, message));
|
||||
send.get();
|
||||
return sentRequestId;
|
||||
} catch (InterruptedException e) {
|
||||
log.error("Interrupt when send message, {}", ExceptionUtils.getStackTrace(e));
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("Thread interrupted when send message to " + queue, e);
|
||||
} catch (ExecutionException e) {
|
||||
log.error("Error at send message, {} cause: {}", e.toString(), ExceptionUtils.getStackTrace(e.getCause()));
|
||||
throw new RuntimeException("Send message error", e.getCause());
|
||||
} catch (Exception e) {
|
||||
log.error("Unexpected exception when send message: {}", ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param req требуется заполнить tradingClearingRegistryId по tradingClearingRegistry.code
|
||||
* @return
|
||||
*/
|
||||
private ClientCode buildClientCode(ClientCodeNewRequest req) {
|
||||
ClientCode clientCode = new ClientCode();
|
||||
// clientCode.setId(idSequence.newId()); add in insert
|
||||
clientCode.setCreated(Instant.now());
|
||||
clientCode.setUpdated(clientCode.getCreated());
|
||||
|
||||
clientCode.setCompanyId(req.getCompanyId());
|
||||
clientCode.setCode(req.getCode());
|
||||
|
||||
if (req.getMoneyAccountId() != null) {
|
||||
TradingClearingRegistry tradingClearingRegistry = selectTradingClearingRegistry(req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
if (tradingClearingRegistry == null) {
|
||||
log.warn("TCR not found: CompanyId {}, MoneyAccountId {}, DepoAccountId {}",
|
||||
req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
} else {
|
||||
clientCode.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
}
|
||||
}
|
||||
|
||||
clientCode.setMoneyAccountId(req.getMoneyAccountId());
|
||||
clientCode.setDepoAccountId(req.getDepoAccountId());
|
||||
clientCode.setStatus(req.getStatus());
|
||||
|
||||
return clientCode;
|
||||
}
|
||||
|
||||
private void updateClientCode(ClientCode clientCode, ClientCodeUpdateRequest req) {
|
||||
assert clientCode.getId() != null && clientCode.getId().equals(req.getId());
|
||||
|
||||
clientCode.setCompanyId(req.getCompanyId());
|
||||
clientCode.setCode(req.getCode());
|
||||
|
||||
if (req.getMoneyAccountId() != null) {
|
||||
TradingClearingRegistry tradingClearingRegistry = selectTradingClearingRegistry(req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
if (tradingClearingRegistry == null) {
|
||||
log.warn("TCR not found: CompanyId {}, MoneyAccountId {}, DepoAccountId {}",
|
||||
req.getCompanyId(), req.getMoneyAccountId(), req.getDepoAccountId());
|
||||
} else {
|
||||
clientCode.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
}
|
||||
}
|
||||
|
||||
clientCode.setTradingClearingRegistryId(req.getTradingClearingRegistryId());
|
||||
clientCode.setMoneyAccountId(req.getMoneyAccountId());
|
||||
clientCode.setDepoAccountId(req.getDepoAccountId());
|
||||
clientCode.setStatus(req.getStatus());
|
||||
|
||||
clientCode.setUpdated(Instant.now());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
|
|||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.profile.CompanyInfo;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.company.util.RequestHelper;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
|
|
@ -22,14 +22,18 @@ import ru.spcex.clearing.util.security.UserRoleVerification;
|
|||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.ImdgTransaction;
|
||||
import ru.spcex.platform.utils.error.ValidationException;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Service
|
||||
public class CompanyInfoService extends QueueConsumer implements InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final Imdg<Company> companyMap;
|
||||
protected final CompanyService companyService;
|
||||
private final RequestHelper requestHelper;
|
||||
|
|
@ -46,6 +50,7 @@ public class CompanyInfoService extends QueueConsumer implements InitializingBea
|
|||
Function<CompanyInfoUpdateRequest, IValidator> companyInfoUpdateRequestValidator) {
|
||||
super(kafkaQueue, kafkaProducer);
|
||||
this.companyService = companyService;
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.validationHelper = validationHelper;
|
||||
this.userRoleVerification = userRoleVerification;
|
||||
|
|
@ -56,16 +61,16 @@ public class CompanyInfoService extends QueueConsumer implements InitializingBea
|
|||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
callback(CompanyInfoUpdateRequest.class)
|
||||
.setFunction(this::companyInfoUpdate)
|
||||
.setFunction(request -> requestHelper.requestFunction(this::companyInfoUpdate, request))
|
||||
.forDestination(Consts.DESTINATION_COMPANY_INFO_UPDATE, callbacks::put);
|
||||
callback(CompanyInfoUpdateRequest.class)
|
||||
.setFunction(this::companyInfoUpdate)
|
||||
.setFunction(request -> requestHelper.requestFunction(this::companyInfoUpdate, request))
|
||||
.forDestination(Consts.DESTINATION_COMPANY_INFO_NEW, callbacks::put); // логика заполнения одинакова с companyInfoUpdate
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
public RequestInfoUpdate companyInfoUpdate(BaseRequest<CompanyInfoUpdateRequest> companyInfoReq) {
|
||||
public RequestInfoUpdate companyInfoUpdate(BaseRequest<CompanyInfoUpdateRequest> companyInfoReq) throws ValidationException {
|
||||
CompanyInfoUpdateRequest req = companyInfoReq.getRequestPayload();
|
||||
log.debug("{} received", req.getClass().getSimpleName());
|
||||
{ // Валидация, ValidationException
|
||||
|
|
@ -81,6 +86,7 @@ public class CompanyInfoService extends QueueConsumer implements InitializingBea
|
|||
log.trace("Company {} not found", req.getId());
|
||||
return requestHelper.makeErrorResponse(companyInfoReq, CompanyErrors.CompanyNotFound, companyInfoReq.getId());
|
||||
}
|
||||
company.setUpdated(Instant.now());
|
||||
CompanyInfo companyInfo = company.getProfile();
|
||||
|
||||
companyInfo.setCorporationSoleType(req.getCorporationSoleType());
|
||||
|
|
@ -93,8 +99,39 @@ public class CompanyInfoService extends QueueConsumer implements InitializingBea
|
|||
companyInfo.setShortNameEng(req.getShortNameEng());
|
||||
companyInfo.setFullNameEng(req.getFullNameEng());
|
||||
|
||||
company.setUpdated(Instant.now());
|
||||
company.setShortName(req.getShortName());
|
||||
company.setFullName(req.getFullName());
|
||||
boolean simpleUpdate = true;
|
||||
if (req.getWorkflowStatus() != null) {
|
||||
String prevStatus = company.getWorkflowStatus();
|
||||
company.setWorkflowStatus(req.getWorkflowStatus());
|
||||
if (!Objects.equals(prevStatus, company.getWorkflowStatus())) {
|
||||
simpleUpdate = false;
|
||||
ImdgTransaction transaction = imdgProvider.newTransaction();
|
||||
transaction.beginTransaction();
|
||||
boolean txOk = false;
|
||||
try {
|
||||
companyService.relationService.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus());
|
||||
Imdg<Company> txCompanyMap = transaction.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
txCompanyMap.update(company);
|
||||
log.trace("Company {} updated", company.getId());
|
||||
txOk = true;
|
||||
} finally {
|
||||
if (txOk)
|
||||
transaction.commitTransaction();
|
||||
else
|
||||
transaction.rollbackTransaction();
|
||||
}
|
||||
} else {
|
||||
log.trace("Status was not changed");
|
||||
}
|
||||
} else {
|
||||
log.trace("Null new WorkflowStatus");
|
||||
}
|
||||
if (simpleUpdate) {
|
||||
companyMap.update(company);
|
||||
log.trace("Company {} updated", company.getId());
|
||||
}
|
||||
log.debug("successfully CompanyInfo processed, id {}", companyInfo.getId());
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.company.CompanyRoleSet;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.company.util.RequestHelper;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
|
|||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.CompanySymbols;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.company.util.RequestHelper;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
|
|
@ -29,13 +29,11 @@ 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.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.error.ClearingBaseException;
|
||||
import ru.spcex.platform.utils.error.ValidationException;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
|
@ -56,7 +54,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
|
||||
protected CompanySymbolService companySymbolService;
|
||||
protected AccountNotificationHelper accountNotification;
|
||||
protected RelationHelper relationHelper;
|
||||
protected RelationService relationService;
|
||||
|
||||
@Autowired
|
||||
public CompanyService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
|
||||
|
|
@ -73,7 +71,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
|
||||
CompanySymbolService companySymbolService,
|
||||
AccountNotificationHelper accountNotification,
|
||||
RelationHelper relationHelper
|
||||
RelationService relationService
|
||||
) {
|
||||
super(kafkaQueue, kafkaProducer);
|
||||
this.imdgProvider = imdgProvider;
|
||||
|
|
@ -89,7 +87,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
this.companySymbolService = companySymbolService;
|
||||
companySymbolService.setCompanyService(this);
|
||||
this.accountNotification = accountNotification;
|
||||
this.relationHelper = relationHelper;
|
||||
this.relationService = relationService;
|
||||
|
||||
companyIMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
}
|
||||
|
|
@ -145,9 +143,9 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
companyMap.insert(company);
|
||||
log.debug("company-new request processed, BaseRequest.id = {}, company.id={}",
|
||||
companyNewRequestBaseRequest.getId(), company.getId());
|
||||
relationHelper.createNewRelation(transaction, company);
|
||||
relationService.createNewRelation(transaction, company);
|
||||
if (!(WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()))) { // Block
|
||||
relationHelper.onChangeWorkflowStatus(transaction, company, null, company.getWorkflowStatus());
|
||||
relationService.onChangeWorkflowStatus(transaction, company, null, company.getWorkflowStatus());
|
||||
}
|
||||
txOk = true;
|
||||
} finally {
|
||||
|
|
@ -180,10 +178,10 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
log.trace("Company {} not found", updateRequest.getId());
|
||||
return requestHelper.makeErrorResponse(companyUpdateRequestBaseRequest, CompanyErrors.CompanyNotFound, updateRequest.getId());
|
||||
}
|
||||
if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
|
||||
log.trace("Company {} not active: {}", company.getId(), company.getWorkflowStatus());
|
||||
return requestHelper.makeErrorResponse(companyUpdateRequestBaseRequest, CompanyErrors.CompanyDisabled, updateRequest.getId());
|
||||
}
|
||||
// if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
|
||||
// log.trace("Company {} not active: {}", company.getId(), company.getWorkflowStatus());
|
||||
// return requestHelper.makeErrorResponse(companyUpdateRequestBaseRequest, CompanyErrors.CompanyDisabled, updateRequest.getId());
|
||||
// }
|
||||
|
||||
company.setUpdated(Instant.now());
|
||||
company.setShortName(updateRequest.getShortName());
|
||||
|
|
@ -199,7 +197,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
if (updateRequest.getWorkflowStatus() != null) {
|
||||
company.setWorkflowStatus(updateRequest.getWorkflowStatus());
|
||||
if (!Objects.equals(prevStatus, company.getWorkflowStatus())) {
|
||||
relationHelper.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus());
|
||||
relationService.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus());
|
||||
} else {
|
||||
log.trace("Status was not changed");
|
||||
}
|
||||
|
|
@ -286,7 +284,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
String prevStatus = company.getWorkflowStatus();
|
||||
company.setWorkflowStatus(WorkflowStatus.Blocked.getKey());
|
||||
|
||||
relationHelper.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus());
|
||||
relationService.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus());
|
||||
log.debug("Update company.id={}", company.getId());
|
||||
companyMap.update(company);
|
||||
|
||||
|
|
@ -339,7 +337,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
|
|||
|
||||
company.setWorkflowStatus(WorkflowStatus.Blocked.getKey());
|
||||
|
||||
relationHelper.onChangeWorkflowStatusOnlyRelationChange(transaction, company, company.getWorkflowStatus());
|
||||
relationService.onChangeWorkflowStatusOnlyRelationChange(transaction, company, company.getWorkflowStatus());
|
||||
log.debug("Update company.id={}", company.getId());
|
||||
companyMap.update(company);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.company.CompanySymbols;
|
||||
import ru.spcex.clearing.company.util.RequestHelper;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import org.springframework.stereotype.Service;
|
|||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.profile.ProfileDocument;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.company.util.RequestHelper;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
|
|
@ -21,7 +21,6 @@ import ru.spcex.clearing.platform.messaging.domain.cud.company.ProfileDocumentNe
|
|||
import ru.spcex.clearing.platform.messaging.domain.cud.company.ProfileDocumentUpdateRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
import ru.spcex.platform.enumeration.DocumentTypes;
|
||||
|
|
@ -174,8 +173,10 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
|
|||
ProfileDocument profileDocument = profileDocumentMap.getSingleObjectByID(profileDocumentUpdateRequest.getId());
|
||||
|
||||
String prevDocType = profileDocument.getDocumentType();
|
||||
if (profileDocumentUpdateRequest.getCompanyId() != null)
|
||||
profileDocument.setCompanyId(profileDocumentUpdateRequest.getCompanyId());
|
||||
if (profileDocumentUpdateRequest.getCompanyId() != null && !profileDocumentUpdateRequest.getCompanyId().equals(profileDocument.getCompanyId())) {
|
||||
log.warn("profileDocumentUpdateRequest[{}] CompanyId {} not match", profileDocumentUpdateRequest.getId(), profileDocumentUpdateRequest.getCompanyId());
|
||||
return requestHelper.makeErrorResponse(profileDocumentUpdateRequestBaseRequest, CompanyErrors.WrongFieldValue, "companyId");
|
||||
}
|
||||
|
||||
if (profileDocumentUpdateRequest.getDocumentType() != null)
|
||||
profileDocument.setDocumentType(profileDocumentUpdateRequest.getDocumentType());
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
package ru.spcex.clearing.company.service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.relation.Relation;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.ServiceProduct;
|
||||
import ru.spcex.platform.enumeration.ServiceStatus;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgTransaction;
|
||||
import ru.spcex.platform.utils.error.ValidationException;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class RelationHelper {
|
||||
protected static final Long SPVB_ID = 1L; // СПВБ
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected AccountNotificationHelper accountNotification;
|
||||
|
||||
@Autowired
|
||||
public RelationHelper(AccountNotificationHelper accountNotification) {
|
||||
this.accountNotification = accountNotification;
|
||||
}
|
||||
|
||||
protected void createNewRelation(ImdgTransaction transaction, Company company) {
|
||||
Relation relation = new Relation();
|
||||
// relation.setId(idSequence.nextId());
|
||||
relation.setCreated(Instant.now());
|
||||
relation.setUpdated(relation.getCreated());
|
||||
|
||||
relation.setConsumerId(company.getId());
|
||||
relation.setSupplierId(SPVB_ID); // 1 СПВБ
|
||||
relation.setServiceStatus(WorkflowStatus.Active.getKey());
|
||||
relation.setService(ru.spcex.platform.enumeration.Service.MKR.getKey()); // MKR
|
||||
relation.setServiceProduct(ServiceProduct.ZERO.getKey());
|
||||
log.debug("New Relation[{}] created.", relation.getId());
|
||||
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
relationMap.insert(relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param company
|
||||
* @param oldStatus
|
||||
* @param newStatus WorkflowStatus.Active - при возобналвении; WorkflowStatus.Blocked - при блокировки/расторжении
|
||||
*/
|
||||
public void onChangeWorkflowStatus(ImdgTransaction transaction, Company company, String oldStatus, String newStatus) throws ValidationException {
|
||||
log.debug("Company id={} status changed from {} to {}",
|
||||
company.getId(), oldStatus, company.getWorkflowStatus());
|
||||
onChangeWorkflowStatusOnlyRelationChange(transaction, company, newStatus);
|
||||
|
||||
if (WorkflowStatus.Blocked.equalsByKey(newStatus)) {
|
||||
// IV - сообщения на добавления документа расторжения договора
|
||||
CompanyErrors hasError = accountNotification.accountTerminationNotification(company.getId());
|
||||
if (hasError != null) {
|
||||
log.warn("Can not block company, cause error {}", hasError);
|
||||
throw new ValidationException(hasError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onChangeWorkflowStatusOnlyRelationChange(ImdgTransaction transaction, Company company, String newStatus) throws ValidationException {
|
||||
assert Objects.equals(newStatus, company.getWorkflowStatus());
|
||||
String query = String.format("consumerId=%s", company.getId());
|
||||
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
Collection<Relation> relations = relationMap.getCollectionObjectsBySQL(query);
|
||||
log.trace("Selected {} Relation by query: {}", relations.size(), query);
|
||||
Instant now = Instant.now();
|
||||
for (Relation relation : relations) {
|
||||
boolean modified = false;
|
||||
if (WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
|
||||
if (!ServiceStatus.Reopened.equalsByKey(relation.getServiceStatus())) {
|
||||
relation.setServiceStatus(ServiceStatus.Reopened.getKey());
|
||||
modified = true;
|
||||
}
|
||||
} else if (WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus())) {
|
||||
if (!ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) {
|
||||
relation.setServiceStatus(ServiceStatus.Closed.getKey());
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
relation.setUpdated(now);
|
||||
log.debug("Relation id={} updated", relation.getId());
|
||||
relationMap.update(relation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
package ru.spcex.clearing.company.service;
|
||||
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.relation.Relation;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.util.services.RequestHelper;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.*;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.clearing.validation.common.ValidationHelper;
|
||||
import ru.spcex.platform.enumeration.ClearingCategory;
|
||||
import ru.spcex.platform.enumeration.ServiceProduct;
|
||||
import ru.spcex.platform.enumeration.ServiceStatus;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
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.utils.error.ValidationException;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Service
|
||||
public class RelationService extends QueueConsumer implements InitializingBean {
|
||||
protected static final Long SPVB_ID = 1L; // СПВБ
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected ImdgProvider imdgProvider;
|
||||
protected ImdgId idSequence;
|
||||
protected Imdg<Relation> relationMap;
|
||||
protected Imdg<Company> companyMap;
|
||||
protected AccountNotificationHelper accountNotification;
|
||||
protected UserRoleVerification userRoleVerification;
|
||||
protected RequestHelper requestHelper;
|
||||
|
||||
protected ValidationHelper validationHelper;
|
||||
private Function<RelationNewRequest, IValidator> relationNewRequestValidator;
|
||||
private Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator;
|
||||
private Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator;
|
||||
|
||||
@Autowired
|
||||
public RelationService(Consumer<String, Object> kafkaQueue,
|
||||
Producer<String, Object> kafkaProducer,
|
||||
ImdgProvider imdgProvider,
|
||||
RequestHelper requestHelper,
|
||||
|
||||
UserRoleVerification userRoleVerification,
|
||||
ValidationHelper validationHelper,
|
||||
@Qualifier("relationNewRequestValidation") Function<RelationNewRequest, IValidator> relationNewRequestValidator,
|
||||
@Qualifier("relationUpdateRequestValidation") Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator,
|
||||
@Qualifier("relationDeleteRequestValidation") Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator,
|
||||
|
||||
AccountNotificationHelper accountNotification) {
|
||||
super(kafkaQueue, kafkaProducer);
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.idSequence = imdgProvider.getImdgIdGenerator();
|
||||
this.accountNotification = accountNotification;
|
||||
this.userRoleVerification = userRoleVerification;
|
||||
|
||||
this.validationHelper = validationHelper;
|
||||
this.relationNewRequestValidator = relationNewRequestValidator;
|
||||
this.relationUpdateRequestValidator = relationUpdateRequestValidator;
|
||||
this.relationDeleteRequestValidator = relationDeleteRequestValidator;
|
||||
|
||||
relationMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.requestHelper = requestHelper.setLogger(log);
|
||||
}
|
||||
|
||||
// --- external API ---
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
// this.profileDocumentMap = imdgProvider.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class);
|
||||
// this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
|
||||
callback(RelationNewRequest.class)
|
||||
.setFunction(this::relationNew)
|
||||
.forDestination(Consts.DESTINATION_RELATION_NEW, callbacks::put);
|
||||
callback(RelationUpdateRequest.class)
|
||||
.setFunction(this::relationUpdate)
|
||||
.forDestination(Consts.DESTINATION_RELATION_UPDATE, callbacks::put);
|
||||
callback(CommonDeleteRequest.class)
|
||||
.setFunction(this::relationDelete)
|
||||
.forDestination(Consts.DESTINATION_RELATION_DELETE, callbacks::put);
|
||||
init();
|
||||
}
|
||||
|
||||
private synchronized RequestInfoUpdate relationNew(BaseRequest<RelationNewRequest> relationNewBaseRequest) {
|
||||
RelationNewRequest req = relationNewBaseRequest.getRequestPayload();
|
||||
log.debug("relation-new request received, BaseRequest.id = {}", relationNewBaseRequest.getId());
|
||||
{ // Валидация
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(relationNewBaseRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(relationNewBaseRequest, relationNewRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
}
|
||||
|
||||
|
||||
Company company = companyMap.getSingleObjectByID(req.getCompanyId());
|
||||
|
||||
Relation existRelation = searchRelation(req.getClearingMemberCategory(), req.getCompanyId());
|
||||
if (existRelation != null && !WorkflowStatus.Blocked.equalsByKey(existRelation.getServiceStatus())) {
|
||||
CompanyErrors errorType;
|
||||
if (ru.spcex.platform.enumeration.Service.MKR.equalsByKey(existRelation.getService())) {
|
||||
errorType = CompanyErrors.ClearingMemberCategoryOnMKRAlreadyExist;
|
||||
} else if (ru.spcex.platform.enumeration.Service.FOND.equalsByKey(existRelation.getService())) {
|
||||
errorType = CompanyErrors.ClearingMemberCategoryOnFONDAlreadyExist;
|
||||
} else {
|
||||
log.warn("Unknown relation[{}] service={}", existRelation.getId(), existRelation.getService());
|
||||
errorType = CompanyErrors.GeneralError;
|
||||
}
|
||||
return requestHelper.makeErrorResponse(relationNewBaseRequest, errorType);
|
||||
}
|
||||
|
||||
Relation relation;
|
||||
if (existRelation == null) {
|
||||
relation = new Relation();
|
||||
relation.setId(idSequence.nextId());
|
||||
relation.setCreated(Instant.now());
|
||||
relation.setUpdated(relation.getCreated());
|
||||
} else {
|
||||
log.info("Found exist relation id={}, it will be update.", existRelation.getId());
|
||||
relation = existRelation;
|
||||
relation.setUpdated(Instant.now());
|
||||
}
|
||||
|
||||
relation.setConsumerId(req.getCompanyId());
|
||||
relation.setSupplierId(SPVB_ID); // 1 СПВБ
|
||||
if (req.getServiceStatus() != null) {
|
||||
relation.setServiceStatus(req.getServiceStatus());
|
||||
} else {
|
||||
if (existRelation != null) {
|
||||
relation.setServiceStatus(ServiceStatus.Reopened.getKey());
|
||||
log.debug("Request has no status. Set status by resume: {}", relation.getServiceStatus());
|
||||
} else {
|
||||
String toStatus = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Active.getKey() :
|
||||
WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Closed.getKey() :
|
||||
null;
|
||||
log.debug("Request has no status. Set status by company[{}].status={}. Relation[{}].serviceSStatus={}",
|
||||
company.getId(), company.getWorkflowStatus(), toStatus);
|
||||
relation.setServiceStatus(toStatus);
|
||||
}
|
||||
}
|
||||
relation.setService(ru.spcex.platform.enumeration.Service.MKR.getKey()); // MKR
|
||||
relation.setServiceProduct(ServiceProduct.ZERO.getKey());
|
||||
relation.setComment(req.getComment());
|
||||
|
||||
relationMap.insert(relation);
|
||||
log.debug("New Relation[{}] created.", relation.getId());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Relation searchRelation(String clearingMemberCategory, Long consumerId) {
|
||||
String svc;
|
||||
if (ClearingCategory.B.equalsByKey(clearingMemberCategory)
|
||||
|| ClearingCategory.I.equalsByKey(clearingMemberCategory)
|
||||
|| ClearingCategory.V.equalsByKey(clearingMemberCategory)
|
||||
) {
|
||||
svc = ru.spcex.platform.enumeration.Service.MKR.getKey();
|
||||
} else if (ClearingCategory.C.equalsByKey(clearingMemberCategory)
|
||||
|| ClearingCategory.F.equalsByKey(clearingMemberCategory)
|
||||
) {
|
||||
svc = ru.spcex.platform.enumeration.Service.FOND.getKey();
|
||||
} else {
|
||||
log.warn("Unexpected relation Relation={}", clearingMemberCategory);
|
||||
return null;
|
||||
}
|
||||
Relation existRelation = relationMap.getSingleObjectByFieldValues(Map.of(
|
||||
"consumerId", consumerId,
|
||||
"service", svc
|
||||
));
|
||||
return existRelation;
|
||||
}
|
||||
|
||||
private synchronized RequestInfoUpdate relationUpdate(BaseRequest<RelationUpdateRequest> relationUpdateBaseRequest) {
|
||||
RelationUpdateRequest req = relationUpdateBaseRequest.getRequestPayload();
|
||||
log.debug("relation-update request received, BaseRequest.id = {}", relationUpdateBaseRequest.getId());
|
||||
{ // Валидация
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(relationUpdateBaseRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(relationUpdateBaseRequest, relationUpdateRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
}
|
||||
|
||||
|
||||
Relation relation = relationMap.getSingleObjectByID(req.getId());
|
||||
relation.setUpdated(relation.getCreated());
|
||||
|
||||
if (req.getServiceStatus() != null) {
|
||||
log.debug("To relation {} set serivceStatus=\"{}\" by user request.", relation.getId(), req.getServiceStatus());
|
||||
relation.setServiceStatus(req.getServiceStatus());
|
||||
} else {
|
||||
if (relation.getConsumerId() == null) {
|
||||
log.warn("Relation[{}]. consumerId was null", relation.getId());
|
||||
}
|
||||
Company company = companyMap.getSingleObjectByID(relation.getConsumerId());
|
||||
String toStatus = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Active.getKey() :
|
||||
WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Closed.getKey() :
|
||||
null;
|
||||
if (ServiceStatus.Active.equalsByKey(toStatus) && ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) {
|
||||
relation.setServiceStatus(ServiceStatus.Reopened.getKey());
|
||||
log.debug("Set status by resume: {}", relation.getServiceStatus());
|
||||
} else {
|
||||
relation.setServiceStatus(toStatus);
|
||||
log.debug("Request has no status. Set status by company[{}].status={}. Relation[{}].serviceSStatus={}",
|
||||
company.getId(), company.getWorkflowStatus(), toStatus, relation.getServiceStatus());
|
||||
}
|
||||
}
|
||||
|
||||
relation.setComment(req.getComment());
|
||||
|
||||
relationMap.insert(relation);
|
||||
log.debug("Update Relation[{}] created.", relation.getId());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private synchronized RequestInfoUpdate relationDelete(BaseRequest<CommonDeleteRequest> relationDeleteBaseRequest) {
|
||||
CommonDeleteRequest req = relationDeleteBaseRequest.getRequestPayload();
|
||||
log.debug("relation-delete request received, BaseRequest.id = {}", relationDeleteBaseRequest.getId());
|
||||
{ // Валидация
|
||||
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(relationDeleteBaseRequest);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
|
||||
requestInfoUpdate = validationHelper.validateTillFirstError(relationDeleteBaseRequest, relationDeleteRequestValidator);
|
||||
if (requestInfoUpdate != null) return requestInfoUpdate;
|
||||
}
|
||||
|
||||
|
||||
Relation relation = relationMap.getSingleObjectByID(req.getId());
|
||||
if (WorkflowStatus.Blocked.equalsByKey(relation.getServiceStatus())) {
|
||||
log.warn("Relation {} already blocked.", relation.getId());
|
||||
} else {
|
||||
relation.setUpdated(relation.getCreated());
|
||||
relation.setServiceStatus(WorkflowStatus.Blocked.getKey());
|
||||
|
||||
relationMap.insert(relation);
|
||||
log.debug("Relation[{}] block.", relation.getId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// --- internal API ---
|
||||
|
||||
protected void createNewRelation(ImdgTransaction transaction, Company company) {
|
||||
Relation relation = new Relation();
|
||||
// relation.setId(idSequence.nextId());
|
||||
relation.setCreated(Instant.now());
|
||||
relation.setUpdated(relation.getCreated());
|
||||
|
||||
relation.setConsumerId(company.getId());
|
||||
relation.setSupplierId(SPVB_ID); // 1 СПВБ
|
||||
relation.setServiceStatus(WorkflowStatus.Active.getKey());
|
||||
relation.setService(ru.spcex.platform.enumeration.Service.MKR.getKey()); // MKR
|
||||
relation.setServiceProduct(ServiceProduct.ZERO.getKey());
|
||||
log.debug("New Relation[{}] created.", relation.getId());
|
||||
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
relationMap.insert(relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param company
|
||||
* @param oldStatus
|
||||
* @param newStatus WorkflowStatus.Active - при возобналвении; WorkflowStatus.Blocked - при блокировки/расторжении
|
||||
*/
|
||||
public void onChangeWorkflowStatus(ImdgTransaction transaction, Company company, String oldStatus, String newStatus) throws ValidationException {
|
||||
log.debug("Company id={} status changed from {} to {}",
|
||||
company.getId(), oldStatus, company.getWorkflowStatus());
|
||||
onChangeWorkflowStatusOnlyRelationChange(transaction, company, newStatus);
|
||||
|
||||
if (WorkflowStatus.Blocked.equalsByKey(newStatus)) {
|
||||
// IV - сообщения на добавления документа расторжения договора
|
||||
CompanyErrors hasError = accountNotification.accountTerminationNotification(company.getId());
|
||||
if (hasError != null) {
|
||||
log.warn("Can not block company, cause error {}", hasError);
|
||||
throw new ValidationException(hasError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void onChangeWorkflowStatusOnlyRelationChange(ImdgTransaction transaction, Company company, String newStatus) throws ValidationException {
|
||||
assert Objects.equals(newStatus, company.getWorkflowStatus());
|
||||
String query = String.format("consumerId=%s", company.getId());
|
||||
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
Collection<Relation> relations = relationMap.getCollectionObjectsBySQL(query);
|
||||
log.trace("Selected {} Relation by query: {}", relations.size(), query);
|
||||
Instant now = Instant.now();
|
||||
for (Relation relation : relations) {
|
||||
boolean modified = false;
|
||||
if (WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
|
||||
if (!ServiceStatus.Reopened.equalsByKey(relation.getServiceStatus())) {
|
||||
relation.setServiceStatus(ServiceStatus.Reopened.getKey());
|
||||
modified = true;
|
||||
}
|
||||
} else if (WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus())) {
|
||||
if (!ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) {
|
||||
relation.setServiceStatus(ServiceStatus.Closed.getKey());
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
relation.setUpdated(now);
|
||||
log.debug("Relation id={} updated", relation.getId());
|
||||
relationMap.update(relation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,367 @@
|
|||
package ru.spcex.clearing.company.service;
|
||||
|
||||
import org.apache.kafka.clients.consumer.MockConsumer;
|
||||
import org.apache.kafka.clients.producer.MockProducer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.account.ClientCode;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.profile.CompanyInfo;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.clearing.platform.dictionary.*;
|
||||
import ru.spcex.clearing.company.config.BeanConfiguration;
|
||||
import ru.spcex.clearing.company.config.validation.ClientCodeValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.ValidationConfig;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeUpdateRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.test.MatcherFactory;
|
||||
import ru.spcex.clearing.test.TestUtils;
|
||||
import ru.spcex.clearing.test.config.ImdgTestConfig;
|
||||
import ru.spcex.clearing.test.config.KafkaTestConfig;
|
||||
import ru.spcex.platform.enumeration.TradingClearingRegistryType;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator;
|
||||
import static ru.spcex.clearing.test.TestUtils.*;
|
||||
import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProviderAndAddAdminWithDefaultId;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {
|
||||
ClientCodeService.class,
|
||||
ClientCodeValidationConfig.class,
|
||||
|
||||
ValidationConfig.class,
|
||||
BeanConfiguration.class,
|
||||
|
||||
KafkaTestConfig.class,
|
||||
ImdgTestConfig.class})
|
||||
class ClientCodeServiceTest {
|
||||
|
||||
private static final int PARTITION = 0;
|
||||
private static final Long ID = 4L;
|
||||
public static final MatcherFactory.Matcher<ClientCode> CLIENT_CODE_MATCHER = usingIgnoringFieldsComparator("created","updated");
|
||||
|
||||
private static final Long TCR_ID = 41L;
|
||||
private static final Long COMPANY_ID = 42L;
|
||||
|
||||
@Autowired
|
||||
ClientCodeService clientCodeService;
|
||||
@Autowired
|
||||
@Qualifier("hazelcastServiceTest")
|
||||
private ImdgProvider hazelcastServiceTest;
|
||||
@Captor
|
||||
private ArgumentCaptor<ProducerRecord> producerRecord;
|
||||
@SpyBean
|
||||
private MockProducer<String, Object> mockProducer;
|
||||
|
||||
private Imdg<ClientCode> clientCodeImdg;
|
||||
|
||||
|
||||
// ****************************-*******************
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
waitAvailableImdgProviderAndAddAdminWithDefaultId();
|
||||
clientCodeImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_ClientCode, ClientCode.class);
|
||||
|
||||
// Словари для теста, применяются в ValidationConfig
|
||||
putToDictionary(IMDGDistributedNames.Map_WorkflowStatusDictionary, new WorkflowStatusDictionary(), "ACTV");
|
||||
putToDictionary(IMDGDistributedNames.Map_CompanySymbolDictionary, new CompanySymbolDictionary(), "CLRC");
|
||||
putToDictionary(IMDGDistributedNames.Map_CorporationSoleTypeDictionary, new CorporationSoleTypeDictionary(), "GDIR");
|
||||
putToDictionary(IMDGDistributedNames.Map_CountryCodeDictionary, new CountryCodeDictionary(), "RUS");
|
||||
putToDictionary(IMDGDistributedNames.Map_AllowedDictionary, new AllowedDictionary(), "ALWD");
|
||||
putToDictionary(IMDGDistributedNames.Map_LegalKindDictionary, new LegalKindDictionary(), "JURD");
|
||||
putToDictionary(IMDGDistributedNames.Map_OrganizationTypeDictionary, new OrganizationTypeDictionary(), "NCRD");
|
||||
|
||||
|
||||
Imdg<Company> companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
Company company1 = new Company();
|
||||
company1.setId(COMPANY_ID);
|
||||
company1.setWorkflowStatus(WorkflowStatus.Active.getKey());
|
||||
company1.setFullName("Company prime");
|
||||
company1.setShortName("Seizwell");
|
||||
company1.setProfile(new CompanyInfo());
|
||||
company1.getProfile().setCompanyId(COMPANY_ID);
|
||||
company1.getProfile().setCountryCode("TLDI");
|
||||
company1.getProfile().setDescription("Big profit from TLD Company Prime.");
|
||||
company1.getProfile().setLegalKind("TLDI");
|
||||
company1.getProfile().setResidence("TLDI");
|
||||
companyImdg.insert(company1);
|
||||
|
||||
Imdg<TradingClearingRegistry> tcrImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
TradingClearingRegistry registry1 = new TradingClearingRegistry();
|
||||
registry1.setId(TCR_ID);
|
||||
registry1.setCompanyId(COMPANY_ID);
|
||||
registry1.setCode("code-120-101");
|
||||
registry1.setMoneyAccountId(131L);
|
||||
registry1.setDepoAaccountId(132L);
|
||||
registry1.setTradingClearingRegistryType(TradingClearingRegistryType.Client_B.getKey());
|
||||
registry1.setStatus(WorkflowStatus.Active.getKey());
|
||||
tcrImdg.insert(registry1);
|
||||
|
||||
Imdg<Account> accounts = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Account, Account.class);
|
||||
Account moneyAccount=new Account();
|
||||
moneyAccount.setId(131L);
|
||||
moneyAccount.setAccount("AAAA-4444");
|
||||
moneyAccount.setStatus("ACTV");
|
||||
moneyAccount.setCompanyId(COMPANY_ID); // для валидации принадлежности счёта
|
||||
accounts.insert(moneyAccount);
|
||||
Account depoAccount=new Account();
|
||||
depoAccount.setId(132L);
|
||||
depoAccount.setAccount("AAAB-44654");
|
||||
depoAccount.setStatus("ACTV");
|
||||
depoAccount.setCompanyId(COMPANY_ID); // для валидации принадлежности счёта
|
||||
accounts.insert(depoAccount);
|
||||
|
||||
TestUtils.FutureRecordMetadata future = spy(TestUtils.FutureRecordMetadata.class);
|
||||
doReturn(future).when(mockProducer).send(producerRecord.capture());
|
||||
}
|
||||
|
||||
private <D extends AbstractDictionary> void putToDictionary(String mapName, D object, String code) {
|
||||
Imdg<D> dMap = (Imdg) hazelcastServiceTest.getImdg(mapName, object.getClass());
|
||||
object.setId(2L);
|
||||
object.setCode(code);
|
||||
object.setName("name of " + code);
|
||||
dMap.insert(object);
|
||||
}
|
||||
|
||||
@Test
|
||||
void selectTradingClearingRegistry() {
|
||||
TradingClearingRegistry tcr = clientCodeService.selectTradingClearingRegistry(COMPANY_ID, 131L, 132L);
|
||||
assertNotNull(tcr);
|
||||
assertEquals(41L, tcr.getId());
|
||||
|
||||
tcr = clientCodeService.selectTradingClearingRegistry(COMPANY_ID, 131L, null);
|
||||
assertNotNull(tcr);
|
||||
assertEquals(41L, tcr.getId());
|
||||
|
||||
assertNull(clientCodeService.selectTradingClearingRegistry(0L, 131L, 132L));
|
||||
assertNull(clientCodeService.selectTradingClearingRegistry(COMPANY_ID, 0L, 132L));
|
||||
assertNull(clientCodeService.selectTradingClearingRegistry(COMPANY_ID, 131L, 0L));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link ClientCodeService#clientCodeUpdate(BaseRequest)}<br>
|
||||
* Тест проверяет создание {@link ClientCode} в IMDG при передаче из Apache Kafka (очередь 1).<br>
|
||||
* Входной запрос {@link ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest}:<br>
|
||||
**/
|
||||
@Test
|
||||
void clientCodeNew1() {
|
||||
//ARRANGE
|
||||
final String ccCode = "Lucky planet";
|
||||
ClientCodeNewRequest clientCodeNewRequest = new ClientCodeNewRequest();
|
||||
clientCodeNewRequest.setCompanyId(COMPANY_ID);
|
||||
clientCodeNewRequest.setCode(ccCode);
|
||||
clientCodeNewRequest.setTradingClearingRegistryId(TCR_ID);
|
||||
clientCodeNewRequest.setDepoAccountId(null);
|
||||
clientCodeNewRequest.setMoneyAccountId(null);
|
||||
clientCodeNewRequest.setStatus("ACTV");
|
||||
|
||||
ClientCode predictableClientCode = new ClientCode();
|
||||
predictableClientCode.setCode(ccCode);
|
||||
predictableClientCode.setStatus("ACTV");
|
||||
predictableClientCode.setCompanyId(COMPANY_ID);
|
||||
// predictableClientCode.setMoneyAccountId(131L);
|
||||
// predictableClientCode.setDepoAccountId(132L);
|
||||
// predictableClientCode.setTradingClearingRegistryId(TCR_ID);
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForNew(clientCodeNewRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) clientCodeService.getConsumer(), Consts.DESTINATION_CLIENT_CODE_NEW, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
ClientCode resultNew = clientCodeImdg.getSingleObjectBySQL(String.format("code = '%s'", ccCode));
|
||||
predictableClientCode.setId(resultNew.getId());
|
||||
CLIENT_CODE_MATCHER.assertMatch(resultNew, predictableClientCode);
|
||||
assertNotNull(resultNew.getCreated());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ClientCodeService#clientCodeUpdate(BaseRequest)}<br>
|
||||
* Тест проверяет создание {@link ClientCode} в IMDG при передаче из Apache Kafka (очередь 2).<br>
|
||||
* Входной запрос {@link ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest}:<br>
|
||||
**/
|
||||
@Test
|
||||
void clientCodeNew2() {
|
||||
//ARRANGE
|
||||
final String ccCode = "Lucky planet";
|
||||
ClientCodeNewRequest clientCodeNewRequest = new ClientCodeNewRequest();
|
||||
clientCodeNewRequest.setCompanyId(COMPANY_ID);
|
||||
clientCodeNewRequest.setCode(ccCode);
|
||||
clientCodeNewRequest.setTradingClearingRegistryId(TCR_ID);
|
||||
clientCodeNewRequest.setDepoAccountId(null);
|
||||
clientCodeNewRequest.setMoneyAccountId(null);
|
||||
clientCodeNewRequest.setStatus("ACTV");
|
||||
|
||||
ClientCode predictableClientCode = new ClientCode();
|
||||
predictableClientCode.setCode(ccCode);
|
||||
predictableClientCode.setStatus("ACTV");
|
||||
predictableClientCode.setCompanyId(COMPANY_ID);
|
||||
// predictableClientCode.setMoneyAccountId(131L);
|
||||
// predictableClientCode.setDepoAccountId(132L);
|
||||
// predictableClientCode.setTradingClearingRegistryId(TCR_ID);
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForNew(clientCodeNewRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) clientCodeService.getConsumer(), Consts.DESTINATION_CLIENT_CODE_NEW_UM_COMPANY, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
ClientCode resultNew = clientCodeImdg.getSingleObjectBySQL(String.format("code = '%s'", ccCode));
|
||||
predictableClientCode.setId(resultNew.getId());
|
||||
CLIENT_CODE_MATCHER.assertMatch(resultNew, predictableClientCode);
|
||||
assertNotNull(resultNew.getCreated());
|
||||
}
|
||||
|
||||
//todo добавить тест NEW заполненными MoneyAccountId(131L), DepoAccountId(132L); - от этого направляется дополнительное сообщение в очередь и используется ожидание ответа.
|
||||
|
||||
/**
|
||||
* {@link ClientCodeService#clientCodeUpdate(BaseRequest)}<br>
|
||||
* Тест проверяет обновление сущности {@link ClientCode} в IMDG при передаче из Apache Kafka.<br>
|
||||
* Входной запрос {@link ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeUpdateRequest}:<br>
|
||||
**/
|
||||
@Test
|
||||
void clientCodeUpdate() {
|
||||
//ARRANGE
|
||||
ClientCode existsClientCode = new ClientCode();
|
||||
existsClientCode.setId(ID);
|
||||
existsClientCode.setCompanyId(COMPANY_ID);
|
||||
existsClientCode.setCode("0000");
|
||||
existsClientCode.setTradingClearingRegistryId(TCR_ID);
|
||||
existsClientCode.setMoneyAccountId(131L);
|
||||
existsClientCode.setDepoAccountId(132L);
|
||||
existsClientCode.setStatus("ACTV");
|
||||
clientCodeImdg.insert(existsClientCode);
|
||||
|
||||
ClientCodeUpdateRequest clientCodeUpdateRequest = new ClientCodeUpdateRequest();
|
||||
clientCodeUpdateRequest.setId(ID);
|
||||
clientCodeUpdateRequest.setCompanyId(COMPANY_ID);
|
||||
clientCodeUpdateRequest.setCode("1111");
|
||||
clientCodeUpdateRequest.setTradingClearingRegistryId(TCR_ID);
|
||||
clientCodeUpdateRequest.setMoneyAccountId(131L);
|
||||
clientCodeUpdateRequest.setDepoAccountId(132L);
|
||||
clientCodeUpdateRequest.setStatus("ACTV");
|
||||
|
||||
ClientCode predictableClientCode = new ClientCode();
|
||||
predictableClientCode.setId(ID);
|
||||
predictableClientCode.setCompanyId(COMPANY_ID);
|
||||
predictableClientCode.setCode("1111");
|
||||
predictableClientCode.setTradingClearingRegistryId(TCR_ID);
|
||||
predictableClientCode.setMoneyAccountId(131L);
|
||||
predictableClientCode.setDepoAccountId(132L);
|
||||
predictableClientCode.setStatus("ACTV");
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForUpdate(clientCodeUpdateRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) clientCodeService.getConsumer(), Consts.DESTINATION_CLIENT_CODE_UPDATE, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
|
||||
ClientCode resultUpdating = clientCodeImdg.getSingleObjectByID(ID);
|
||||
CLIENT_CODE_MATCHER.assertMatch(resultUpdating, predictableClientCode);
|
||||
assertNotNull(resultUpdating.getUpdated());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link ClientCodeService#clientCodeUpdate(BaseRequest)}<br>
|
||||
* Тест проверяет удаление {@link ClientCode} из IMDG при передаче из Apache Kafka.<br>
|
||||
* Входной запрос {@link ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest}:<br>
|
||||
**/
|
||||
@Test
|
||||
void clientCodeDelete1() {
|
||||
//ARRANGE
|
||||
ClientCode existsClientCode = new ClientCode();
|
||||
existsClientCode.setId(ID);
|
||||
existsClientCode.setCompanyId(COMPANY_ID);
|
||||
existsClientCode.setCode("0000");
|
||||
// Если следующие поля заполнить, то дополнительно отправит сообщение в trading-clearing-registry-update:
|
||||
existsClientCode.setTradingClearingRegistryId(null);
|
||||
existsClientCode.setMoneyAccountId(null);
|
||||
existsClientCode.setDepoAccountId(null);
|
||||
existsClientCode.setStatus("ACTV");
|
||||
|
||||
clientCodeImdg.insert(existsClientCode);
|
||||
|
||||
CommonDeleteRequest clientCodeDeleteRequest = new CommonDeleteRequest();
|
||||
clientCodeDeleteRequest.setId(ID);
|
||||
|
||||
Assertions.assertNotNull(clientCodeImdg.getSingleObjectByID(ID)); // verify test data
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForUpdate(clientCodeDeleteRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) clientCodeService.getConsumer(), Consts.DESTINATION_CLIENT_CODE_DELETE, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
ClientCode resultUpdate = clientCodeImdg.getSingleObjectByID(ID);
|
||||
Assertions.assertNull(resultUpdate);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * {@link ClientCodeService#clientCodeUpdate(BaseRequest)}<br>
|
||||
// * Тест проверяет удаление {@link ClientCode} из IMDG при передаче из Apache Kafka.<br>
|
||||
// * У ClientCode заполнены MoneyAccountId, DepoAccountId - по этому при удалении должно направиться дополнительное сообщение в очередь DESTINATION_TRADING_CLEARING_REGISTRY_UPDATE<br>
|
||||
// * Входной запрос {@link ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest}:<br>
|
||||
// **/
|
||||
// @Test
|
||||
// void clientCodeDelete2() {
|
||||
// //ARRANGE
|
||||
// ClientCode existsClientCode = new ClientCode();
|
||||
// existsClientCode.setId(ID);
|
||||
// existsClientCode.setCompanyId(COMPANY_ID);
|
||||
// existsClientCode.setCode("0000");
|
||||
// // Если следующие поля заполнить, то дополнительно отправит сообщение в trading-clearing-registry-update:
|
||||
// existsClientCode.setTradingClearingRegistryId(TCR_ID);
|
||||
// existsClientCode.setMoneyAccountId(131L);
|
||||
// existsClientCode.setDepoAccountId(132L);
|
||||
// existsClientCode.setStatus("ACTV");
|
||||
//
|
||||
// clientCodeImdg.insert(existsClientCode);
|
||||
//
|
||||
// CommonDeleteRequest clientCodeDeleteRequest = new CommonDeleteRequest();
|
||||
// clientCodeDeleteRequest.setId(ID);
|
||||
//
|
||||
// Assertions.assertNotNull(clientCodeImdg.getSingleObjectByID(ID)); // verify test data
|
||||
//
|
||||
// //ACT
|
||||
// String jsonString = getJsonStringForUpdate(clientCodeDeleteRequest, ID);
|
||||
//
|
||||
// addRecordToKafka((MockConsumer) clientCodeService.getConsumer(), Consts.DESTINATION_CLIENT_CODE_DELETE, PARTITION, 0, jsonString);
|
||||
//
|
||||
// //ASSERT
|
||||
//
|
||||
// waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
// ClientCode resultUpdate = clientCodeImdg.getSingleObjectByID(ID);
|
||||
// Assertions.assertNull(resultUpdate);
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import ru.clearing.platform.dictionary.*;
|
|||
import ru.spcex.clearing.company.config.BeanConfiguration;
|
||||
import ru.spcex.clearing.company.config.validation.CompanySymbolValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.CompanyValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.RelationValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.ValidationConfig;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
|
|
@ -50,7 +51,8 @@ import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProv
|
|||
ValidationConfig.class,
|
||||
CompanySymbolService.class,
|
||||
AccountNotificationHelper.class,
|
||||
RelationHelper.class,
|
||||
RelationService.class,
|
||||
RelationValidationConfig.class,
|
||||
BeanConfiguration.class,
|
||||
|
||||
KafkaTestConfig.class,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import ru.clearing.platform.dictionary.WorkflowStatusDictionary;
|
|||
import ru.spcex.clearing.company.config.BeanConfiguration;
|
||||
import ru.spcex.clearing.company.config.validation.CompanySymbolValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.CompanyValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.RelationValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.ValidationConfig;
|
||||
import ru.spcex.clearing.company.error.CompanyErrors;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
|
|
@ -54,7 +55,7 @@ import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProv
|
|||
ValidationConfig.class,
|
||||
CompanySymbolService.class,
|
||||
AccountNotificationHelper.class,
|
||||
RelationHelper.class,
|
||||
RelationService.class, RelationValidationConfig.class,
|
||||
|
||||
CompanySymbolService.class,
|
||||
CompanySymbolValidationConfig.class,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.CompanySymbols;
|
||||
import ru.clearing.platform.dictionary.CompanySymbolDictionary;
|
||||
import ru.spcex.clearing.company.config.BeanConfiguration;
|
||||
import ru.spcex.clearing.company.config.validation.CompanySymbolValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.CompanyValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.RelationValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.ValidationConfig;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
|
|
@ -49,7 +51,7 @@ import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProv
|
|||
CompanyService.class,
|
||||
CompanyValidationConfig.class,
|
||||
AccountNotificationHelper.class,
|
||||
RelationHelper.class,
|
||||
RelationService.class, RelationValidationConfig.class,
|
||||
|
||||
KafkaTestConfig.class,
|
||||
ImdgTestConfig.class})
|
||||
|
|
@ -92,6 +94,14 @@ class CompanySymbolServiceTest {
|
|||
cioSymbol.setName(CompanySymbol.CIO.getKey());
|
||||
companySymbolDictionaryImdg.insert(cioSymbol);
|
||||
}
|
||||
Imdg<Company> companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
{
|
||||
Company company = new Company();
|
||||
company.setId(ID);
|
||||
company.setShortName("TST");
|
||||
company.setWorkflowStatus("ACTV");
|
||||
companyImdg.insert(company);
|
||||
}
|
||||
|
||||
|
||||
TestUtils.FutureRecordMetadata future = spy(TestUtils.FutureRecordMetadata.class);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,214 @@
|
|||
package ru.spcex.clearing.company.service;
|
||||
|
||||
import org.apache.kafka.clients.consumer.MockConsumer;
|
||||
import org.apache.kafka.clients.producer.MockProducer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.relation.Relation;
|
||||
import ru.clearing.platform.dictionary.ClearingCategoryDictionary;
|
||||
import ru.clearing.platform.dictionary.WorkflowStatusDictionary;
|
||||
import ru.spcex.clearing.company.config.BeanConfiguration;
|
||||
import ru.spcex.clearing.company.config.validation.RelationValidationConfig;
|
||||
import ru.spcex.clearing.company.config.validation.ValidationConfig;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.RelationNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.company.RelationUpdateRequest;
|
||||
import ru.spcex.clearing.test.MatcherFactory;
|
||||
import ru.spcex.clearing.test.TestUtils;
|
||||
import ru.spcex.clearing.test.config.ImdgTestConfig;
|
||||
import ru.spcex.clearing.test.config.KafkaTestConfig;
|
||||
import ru.spcex.platform.enumeration.ClearingCategory;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator;
|
||||
import static ru.spcex.clearing.test.TestUtils.*;
|
||||
import static ru.spcex.clearing.test.config.ImdgTestConfig.currentID;
|
||||
import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProviderAndAddAdminWithDefaultId;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {
|
||||
BeanConfiguration.class,
|
||||
ValidationConfig.class,
|
||||
RelationService.class,
|
||||
AccountNotificationHelper.class,
|
||||
RelationValidationConfig.class,
|
||||
KafkaTestConfig.class,
|
||||
ImdgTestConfig.class})
|
||||
class RelationServiceTest {
|
||||
|
||||
public static final MatcherFactory.Matcher<Relation> RELATION_MATCHER = usingIgnoringFieldsComparator("created", "updated");
|
||||
private static final int PARTITION = 0;
|
||||
|
||||
private static final Long ID = currentID.getAndIncrement();
|
||||
@Autowired
|
||||
RelationService relationService;
|
||||
@Autowired
|
||||
@Qualifier("hazelcastServiceTest")
|
||||
private ImdgProvider hazelcastServiceTest;
|
||||
private Imdg<Relation> relationMap;
|
||||
private Imdg<Company> companyMap;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<ProducerRecord> producerRecord;
|
||||
@SpyBean
|
||||
private MockProducer<String, Object> mockProducer;
|
||||
|
||||
private long COMPANY_ID;
|
||||
|
||||
private final long RELATION_ID = ID;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
waitAvailableImdgProviderAndAddAdminWithDefaultId();
|
||||
this.relationMap = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||
this.companyMap = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
|
||||
Company testCompany = new Company();
|
||||
testCompany.setWorkflowStatus(WorkflowStatus.Active.getKey());
|
||||
COMPANY_ID = companyMap.insert(testCompany);
|
||||
|
||||
Imdg<WorkflowStatusDictionary> workflowStatusDictionaryImdg = hazelcastServiceTest.getImdg(
|
||||
IMDGDistributedNames.Map_WorkflowStatusDictionary,
|
||||
WorkflowStatusDictionary.class
|
||||
);
|
||||
WorkflowStatusDictionary workflowStatusDictionary = new WorkflowStatusDictionary();
|
||||
workflowStatusDictionary.setId(1L);
|
||||
workflowStatusDictionary.setCode(WorkflowStatus.Active.getKey());
|
||||
workflowStatusDictionary.setName("active");
|
||||
workflowStatusDictionaryImdg.insert(workflowStatusDictionary);
|
||||
workflowStatusDictionary = new WorkflowStatusDictionary();
|
||||
workflowStatusDictionary.setId(2L);
|
||||
workflowStatusDictionary.setCode(WorkflowStatus.Blocked.getKey());
|
||||
workflowStatusDictionary.setName("not active");
|
||||
workflowStatusDictionaryImdg.insert(workflowStatusDictionary);
|
||||
|
||||
Imdg<ClearingCategoryDictionary> clearingCategoryDictionaryImdg = hazelcastServiceTest.getImdg(
|
||||
IMDGDistributedNames.Map_ClearingCategoryDictionary,
|
||||
ClearingCategoryDictionary.class
|
||||
);
|
||||
ClearingCategoryDictionary clearingCategoryDictionary = new ClearingCategoryDictionary();
|
||||
clearingCategoryDictionary.setId(1L);
|
||||
clearingCategoryDictionary.setCode(ClearingCategory.I.getKey());
|
||||
clearingCategoryDictionary.setName("I");
|
||||
clearingCategoryDictionaryImdg.insert(clearingCategoryDictionary);
|
||||
|
||||
TestUtils.FutureRecordMetadata future = spy(TestUtils.FutureRecordMetadata.class);
|
||||
doReturn(future).when(mockProducer).send(producerRecord.capture());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void newRelation() {
|
||||
//ARRANGE
|
||||
RelationNewRequest relationNewRequest = new RelationNewRequest();
|
||||
relationNewRequest.setCompanyId(COMPANY_ID);
|
||||
relationNewRequest.setServiceStatus("ACTV");
|
||||
relationNewRequest.setClearingMemberCategory("I");
|
||||
relationNewRequest.setComment(null);
|
||||
|
||||
Relation predictableRelation = new Relation();
|
||||
predictableRelation.setId(RELATION_ID);
|
||||
predictableRelation.setConsumerId(relationNewRequest.companyId);
|
||||
predictableRelation.setService("MKR");
|
||||
predictableRelation.setServiceProduct("ZERO");
|
||||
predictableRelation.setSupplierId(1L);
|
||||
predictableRelation.setServiceStatus("ACTV");
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForNew(relationNewRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) relationService.getConsumer(), Consts.DESTINATION_RELATION_NEW, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
Relation resultNew = relationMap.getSingleObjectBySQL("serviceStatus=ACTV"); // String.format("supplierId = %d", COMPANY_ID));
|
||||
predictableRelation.setId(resultNew.getId());
|
||||
RELATION_MATCHER.assertMatch(resultNew, predictableRelation);
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateRelation() {
|
||||
//ARRANGE
|
||||
Relation existsRelation = new Relation();
|
||||
existsRelation.setId(ID);
|
||||
existsRelation.setConsumerId(COMPANY_ID);
|
||||
existsRelation.setSupplierId(1L);
|
||||
existsRelation.setComment("Test ONE");
|
||||
existsRelation.setServiceStatus("ACTV");
|
||||
existsRelation.setServiceProduct("PROD");
|
||||
existsRelation.setService("MKR");
|
||||
relationMap.insert(existsRelation);
|
||||
|
||||
Relation predictableRelation = new Relation();
|
||||
predictableRelation.setId(ID);
|
||||
predictableRelation.setConsumerId(COMPANY_ID);
|
||||
predictableRelation.setSupplierId(1L);
|
||||
predictableRelation.setComment("Another Me - ONE");
|
||||
predictableRelation.setServiceStatus("ACTV");
|
||||
predictableRelation.setServiceProduct("PROD");
|
||||
predictableRelation.setService("MKR");
|
||||
|
||||
RelationUpdateRequest relationUpdateRequest = new RelationUpdateRequest();
|
||||
relationUpdateRequest.setId(RELATION_ID);
|
||||
relationUpdateRequest.setComment("Another Me - ONE");
|
||||
relationUpdateRequest.setServiceStatus("ACTV");
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForUpdate(relationUpdateRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) relationService.getConsumer(), Consts.DESTINATION_RELATION_UPDATE, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
Relation resultUpdate = relationMap.getSingleObjectBySQL(String.format("id = %d", RELATION_ID));
|
||||
// predictableProfileDocument.setId(resultUpdate.getId());
|
||||
RELATION_MATCHER.assertMatch(resultUpdate, predictableRelation);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void deleteProfileDocument() {
|
||||
//ARRANGE
|
||||
Relation existsRelation = new Relation();
|
||||
existsRelation.setId(ID);
|
||||
existsRelation.setConsumerId(COMPANY_ID);
|
||||
existsRelation.setSupplierId(1L);
|
||||
existsRelation.setComment("Test ONE");
|
||||
existsRelation.setServiceStatus("ACTV");
|
||||
existsRelation.setServiceProduct("PROD");
|
||||
existsRelation.setService("MKR");
|
||||
relationMap.insert(existsRelation);
|
||||
|
||||
CommonDeleteRequest profileDocumentDeleteRequest = new CommonDeleteRequest();
|
||||
profileDocumentDeleteRequest.setId(RELATION_ID);
|
||||
|
||||
//ACT
|
||||
String jsonString = getJsonStringForUpdate(profileDocumentDeleteRequest, ID);
|
||||
|
||||
addRecordToKafka((MockConsumer) relationService.getConsumer(), Consts.DESTINATION_RELATION_DELETE, PARTITION, 0, jsonString);
|
||||
|
||||
//ASSERT
|
||||
waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord);
|
||||
Relation resultUpdate = relationMap.getSingleObjectByID(RELATION_ID);
|
||||
// Assertions.assertNull(resultUpdate);
|
||||
assertEquals(WorkflowStatus.Blocked.getKey(), resultUpdate.getServiceStatus());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
-- DB version: 3.5.0.20
|
||||
-- DB version: 3.5.0.21
|
||||
-- DATA version: 3.5.0.4
|
||||
/* Dictionaries */
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (17, 'RG
|
|||
|
||||
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (18, 'UUID', 'Идентификатор во внешней системе', 'Внешний идентификатор') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;
|
||||
|
||||
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (19, 'RDPZ', 'Требуется получение документа о подтверждении открытия депозитного счета', 'Подтверждение депозитного счета') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;
|
||||
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (19, 'LICM', 'Лицензия на управление инвестиционными фондами, паевыми инвестиционными фондами, негосударственными пенсионными фондами', 'Лицензия на управление фондами') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;
|
||||
|
||||
INSERT INTO COMPANY_ROLE_DICTIONARY(ID, CODE, NAME) values (1, 'RPRT', 'Отчетная организация') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
|
|
@ -414,9 +414,9 @@ INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (36, 'SPRC', 'Запуск п
|
|||
|
||||
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (37, 'SPOC', 'Запуск постклиринга') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (38, 'LIMM', 'Выгрузка в торговую систему остатков секции МКР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (38, 'LIMM', 'Выгрузка в торговую систему остатков по деньгам') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (39, 'LIMF', 'Выгрузка в торговую систему остатков Фондовой секции') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (39, 'LIMS', 'Выгрузка в торговую систему остатков по бумагам') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (40, 'LIQU', 'Ликвидационная сессия по обязательтсвам участника') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import ru.spcex.platform.imdg.api.ImdgProvider;
|
|||
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
|
||||
|
||||
@Configuration
|
||||
public class SchedulerServiceImdgConfig {
|
||||
public class ImdgConfig {
|
||||
private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) {
|
||||
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
|
||||
if (maxPoolSz > 2) {
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package ru.spcex.clearing.scheduler.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
@Configuration
|
||||
public class SchedulerServiceConfig {
|
||||
@Bean(name = "taskScheduler")
|
||||
public TaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
threadPoolTaskScheduler.setPoolSize(5);
|
||||
threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
|
||||
return threadPoolTaskScheduler;
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ public class ClearingCalendarValidationConfig {
|
|||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
ValidationError.CompanyNotFound,
|
||||
false,
|
||||
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : ValidationError.CompanyNotActive),
|
||||
DictionaryPresentRule.instance("dayStatus",
|
||||
ClearingCalendarNewRequest::getDayStatus,
|
||||
|
|
@ -74,6 +75,7 @@ public class ClearingCalendarValidationConfig {
|
|||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
ValidationError.CompanyNotFound,
|
||||
false,
|
||||
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : ValidationError.CompanyNotActive),
|
||||
DictionaryPresentRule.instance("dayStatus",
|
||||
ClearingCalendarUpdateRequest::getDayStatus,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ public class PlannerTemplateValidationConfig {
|
|||
IMDGDistributedNames.Map_TaskDictionary,
|
||||
TaskDictionary.class),
|
||||
TimeNotBeforeRule.instance("taskTime",
|
||||
PlannerTemplateNewRequest::getTaskTime),
|
||||
PlannerTemplateNewRequest::getTaskTime,
|
||||
true,
|
||||
false),
|
||||
DictionaryPresentRule.instance("taskStatus",
|
||||
PlannerTemplateNewRequest::getTaskStatus,
|
||||
IMDGDistributedNames.Map_TaskStatusDictionary,
|
||||
|
|
@ -55,12 +57,14 @@ public class PlannerTemplateValidationConfig {
|
|||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
ValidationError.CompanyNotFound,
|
||||
false,
|
||||
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : ValidationError.CompanyNotActive),
|
||||
IdPresentRule.instance("securityId",
|
||||
PlannerTemplateNewRequest::getSecurityId,
|
||||
IMDGDistributedNames.Map_Security,
|
||||
Security.class,
|
||||
ValidationError.SecurityNotFound,
|
||||
false,
|
||||
security -> WorkflowStatus.Active.equalsByKey(security.getWorkflowStatus()) ? null : ValidationError.SecurityNotActive)
|
||||
);
|
||||
};
|
||||
|
|
@ -90,6 +94,7 @@ public class PlannerTemplateValidationConfig {
|
|||
false),
|
||||
TimeNotBeforeRule.instance("taskTime",
|
||||
PlannerTemplateUpdateRequest::getTaskTime,
|
||||
false,
|
||||
false),
|
||||
DictionaryPresentRule.instance("taskStatus",
|
||||
PlannerTemplateUpdateRequest::getTaskStatus,
|
||||
|
|
|
|||
|
|
@ -62,12 +62,14 @@ public class PlannerValidationConfig {
|
|||
IMDGDistributedNames.Map_Company,
|
||||
Company.class,
|
||||
ValidationError.CompanyNotFound,
|
||||
false,
|
||||
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : ValidationError.CompanyNotActive),
|
||||
IdPresentRule.instance("securityId",
|
||||
PlannerNewRequest::getSecurityId,
|
||||
IMDGDistributedNames.Map_Security,
|
||||
Security.class,
|
||||
ValidationError.SecurityNotFound,
|
||||
false,
|
||||
security -> WorkflowStatus.Active.equalsByKey(security.getWorkflowStatus()) ? null : ValidationError.SecurityNotActive)
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class TaskManager implements InitializingBean, AutoCloseable {
|
|||
private final ExecutorService outputExecutor;
|
||||
|
||||
@Autowired
|
||||
TaskManager(TaskScheduler taskScheduler,
|
||||
TaskManager(@Qualifier("taskScheduler") TaskScheduler taskScheduler,
|
||||
ImdgProvider imdgProvider,
|
||||
LauncherSender launcherSender,
|
||||
@Qualifier("plannerQueue") BlockingQueue<Map.Entry<Process, PlannerAllToday>> plannerQueue) {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,6 @@ public record EnumPresentRule<R, E extends IEnumKey>(String fieldName,
|
|||
for (E enumValue : enumValues) {
|
||||
if (enumValue.getKey().equals(enumCode)) return empty();
|
||||
}
|
||||
return of(ValidationError.WrongEnumValue, fieldName);
|
||||
return of(ValidationError.WrongDictionaryValue, fieldName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import ru.clearing.platform.dictionary.TaskStatusDictionary;
|
|||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.scheduler.config.ErrorResolverConfig;
|
||||
import ru.spcex.clearing.scheduler.config.PlannerQueueConfig;
|
||||
import ru.spcex.clearing.scheduler.config.SchedulerTestConfig;
|
||||
import ru.spcex.clearing.scheduler.config.SchedulerServiceConfig;
|
||||
import ru.spcex.clearing.scheduler.config.validation.ClearingCalendarValidationConfig;
|
||||
import ru.spcex.clearing.scheduler.config.validation.PlannerTemplateValidationConfig;
|
||||
import ru.spcex.clearing.scheduler.config.validation.PlannerValidationConfig;
|
||||
|
|
@ -60,7 +60,7 @@ import static ru.spcex.platform.enumeration.Market.mkrs;
|
|||
LauncherService.class,
|
||||
ErrorResolverConfig.class,
|
||||
PlannerQueueConfig.class,
|
||||
SchedulerTestConfig.class,
|
||||
SchedulerServiceConfig.class,
|
||||
ImdgTestConfig.class,
|
||||
KafkaTestConfig.class})
|
||||
public abstract class AbstractServiceTest {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class EnumPresentRuleTest extends AbstractServiceTest {
|
|||
setter.accept(record, "BAD_VALUE");
|
||||
enumMessages = strictValidator.validateAll();
|
||||
assertEquals(1, enumMessages.size());
|
||||
assertEquals(ValidationError.WrongEnumValue, enumMessages.iterator().next().getSubject());
|
||||
assertEquals(ValidationError.WrongDictionaryValue, enumMessages.iterator().next().getSubject());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -72,18 +72,22 @@ public interface Consts {
|
|||
@Deprecated
|
||||
String ACCOUNT_NEW_SDF01 = "account-new-sdf01";
|
||||
|
||||
String DESTINATION_RELATION_NEW = "relation-new";
|
||||
String DESTINATION_RELATION_UPDATE = "relation-update";
|
||||
String DESTINATION_RELATION_DELETE = "relation-delete";
|
||||
String DESTINATION_PROFILE_DOCUMENT_NEW = "profile-document-new";
|
||||
String DESTINATION_PROFILE_DOCUMENT_UPDATE = "profile-document-update";
|
||||
String DESTINATION_PROFILE_DOCUMENT_DELETE = "profile-document-delete";
|
||||
|
||||
String DESTINATION_CLIENT_CODE_NEW = "client-code-new";
|
||||
String DESTINATION_CLIENT_CODE_NEW_UM_COMPANY = "client-code-new-from-api-um-company";
|
||||
String DESTINATION_CLIENT_CODE_UPDATE = "client-code-update";
|
||||
String DESTINATION_CLIENT_CODE_DELETE = "client-code-delete";
|
||||
|
||||
String DESTINATION_TRADING_CLEARING_REGISTRY_NEW = "trading-clearing-registry-new";
|
||||
String DESTINATION_TRADING_CLEARING_REGISTRY_UPDATE = "trading-clearing-registry-update";
|
||||
String DESTINATION_TRADING_CLEARING_REGISTRY_DELETE = "trading-clearing-registry-delete";
|
||||
// String DESTINATION_TRADING_CLEARING_REGISTRY_REPLY = "trading-clearing-registry";
|
||||
|
||||
String DESTINATION_SDF08_NEW = "s-df-08-new";
|
||||
String DESTINATION_SDF02_NEW = "s-df-02-new";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package ru.spcex.clearing.platform.messaging.domain.cud.company;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class RelationNewRequest {
|
||||
@JsonProperty
|
||||
public Long companyId;
|
||||
@JsonProperty
|
||||
private String serviceStatus;
|
||||
@JsonProperty
|
||||
private String clearingMemberCategory;
|
||||
@JsonProperty
|
||||
private String comment;
|
||||
|
||||
public Long getCompanyId() {
|
||||
return companyId;
|
||||
}
|
||||
|
||||
public void setCompanyId(Long companyId) {
|
||||
this.companyId = companyId;
|
||||
}
|
||||
|
||||
public String getServiceStatus() {
|
||||
return serviceStatus;
|
||||
}
|
||||
|
||||
public void setServiceStatus(String serviceStatus) {
|
||||
this.serviceStatus = serviceStatus;
|
||||
}
|
||||
|
||||
public String getClearingMemberCategory() {
|
||||
return clearingMemberCategory;
|
||||
}
|
||||
|
||||
public void setClearingMemberCategory(String clearingMemberCategory) {
|
||||
this.clearingMemberCategory = clearingMemberCategory;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,8 @@ public class TradingClearingRegistryNewRequest {
|
|||
private Long depoAccountId;
|
||||
@JsonProperty
|
||||
private String status;
|
||||
@JsonProperty
|
||||
private String tradingClearingRegistryType;
|
||||
|
||||
public Long getCompanyId() {
|
||||
return companyId;
|
||||
|
|
@ -50,6 +52,14 @@ public class TradingClearingRegistryNewRequest {
|
|||
return status;
|
||||
}
|
||||
|
||||
public String getTradingClearingRegistryType() {
|
||||
return tradingClearingRegistryType;
|
||||
}
|
||||
|
||||
public void setTradingClearingRegistryType(String tradingClearingRegistryType) {
|
||||
this.tradingClearingRegistryType = tradingClearingRegistryType;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
package ru.spcex.clearing.platform.messaging.domain.cud.utilities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class STradesImportedRequest {
|
||||
@JsonProperty
|
||||
private Long tradeNum;
|
||||
|
||||
public Long getTradeNum() {
|
||||
return tradeNum;
|
||||
}
|
||||
|
||||
public void setTradeNum(Long tradeNum) {
|
||||
this.tradeNum = tradeNum;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ public class QueueConsumer implements AutoCloseable {
|
|||
public void init() {
|
||||
inputExecutor.submit(() -> {
|
||||
try {
|
||||
log.debug("Using kafka consumer {} for subscribe on \"{}\"", consumer, callbacks.keySet());
|
||||
if (supportStartOffsetTimeWindow) {
|
||||
consumer.subscribe(callbacks.keySet(), new OffsetChanger(consumer, callbacks.keySet()));
|
||||
} else {
|
||||
|
|
@ -82,9 +83,11 @@ public class QueueConsumer implements AutoCloseable {
|
|||
Object o = null;
|
||||
int lastErrors = 0;
|
||||
while (!closed.get()) {
|
||||
String lastTopic = null;
|
||||
try {
|
||||
ConsumerRecords<String, Object> records = consumer.poll(Duration.of(10, ChronoUnit.SECONDS));
|
||||
for (ConsumerRecord<String, Object> next : records) {
|
||||
lastTopic = next.topic();
|
||||
ConsumerSpecificClass<?> callback = callbacks.get(next.topic());
|
||||
Class<?> clazz = callback.getClazz();
|
||||
JavaType payloadType = json.getTypeFactory().constructParametricType(BaseRequest.class, clazz);
|
||||
|
|
@ -98,7 +101,8 @@ public class QueueConsumer implements AutoCloseable {
|
|||
}
|
||||
lastErrors = 0;
|
||||
} catch (Throwable e) {
|
||||
log.error(ExceptionUtils.getStackTrace(e));
|
||||
log.error("Listener {} last topic \"{}\", error: {}",
|
||||
QueueConsumer.this.getClass().getName(), lastTopic, ExceptionUtils.getStackTrace(e));
|
||||
if (producer != null && o != null) {
|
||||
sendErrorResponse((BaseRequest<?>) o);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue