Merge branch 'dev' into cls-301

This commit is contained in:
akulikov 2023-05-26 10:16:01 +03:00
commit 94ed38e0de
73 changed files with 2039 additions and 550 deletions

View file

@ -30,18 +30,6 @@ public class AccountNewAction implements IAction<AccountNewRequest> {
@JsonProperty @JsonProperty
private String accountType; private String accountType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.companyId == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "companyId"));
if (!StringUtils.hasLength(this.account))
errors.add(new EnumMessage(BackEndError.ValidationError, "account"));
if (!StringUtils.hasLength(this.accountType))
errors.add(new EnumMessage(BackEndError.ValidationError, "accountType"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public AccountNewRequest toRequest() { public AccountNewRequest toRequest() {
var req = new AccountNewRequest(); var req = new AccountNewRequest();

View file

@ -32,16 +32,6 @@ public class AccountUpdateAction implements IAction<AccountUpdateRequest> {
@JsonProperty @JsonProperty
private String accountType; private String accountType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.id == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "id"));
if (!StringUtils.hasLength(this.accountType))
errors.add(new EnumMessage(BackEndError.ValidationError, "accountType"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public AccountUpdateRequest toRequest() { public AccountUpdateRequest toRequest() {
var req = new AccountUpdateRequest(); var req = new AccountUpdateRequest();

View file

@ -51,31 +51,18 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
@Override @Override
public Collection<EnumMessage> validate() { public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>(); List<EnumMessage> errors = new ArrayList<>();
if (!StringUtils.hasLength(this.bankIdentificationCode))
errors.add(new EnumMessage(BackEndError.ValidationError, "bankIdentificationCode"));
if (!StringUtils.hasLength(this.bankName))
errors.add(new EnumMessage(BackEndError.ValidationError, "bankIdentificationCode"));
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(correspondentAccount)) { if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(correspondentAccount)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccount")); errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccount"));
} }
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(correspondentAccountName)) { if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(correspondentAccountName)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccountName")); errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccountName"));
} }
if (!StringUtils.hasLength(currency)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "currency"));
}
if (!StringUtils.hasLength(destination)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "destination"));
}
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(taxpayerIdentificationNumber)) { if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(taxpayerIdentificationNumber)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "taxpayerIdentificationNumber")); errors.add(new EnumMessage(BackEndError.ValidationError, "taxpayerIdentificationNumber"));
} }
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(taxRegistrationReasonCode)) { if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(taxRegistrationReasonCode)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "taxRegistrationReasonCode")); errors.add(new EnumMessage(BackEndError.ValidationError, "taxRegistrationReasonCode"));
} }
if (TextUtil.isEmpty(account)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "account"));
}
return errors.isEmpty() ? Collections.emptyList() : errors; return errors.isEmpty() ? Collections.emptyList() : errors;
} }
@ -172,4 +159,12 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
public void setAccount(String account) { public void setAccount(String account) {
this.account = account; this.account = account;
} }
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
} }

View file

@ -42,11 +42,6 @@ public class BankAccountUpdateAction implements IAction<BankAccountUpdateRequest
@ApiModelProperty(value = "Номер счета", example = "11111222223333344444") @ApiModelProperty(value = "Номер счета", example = "11111222223333344444")
private String account; private String account;
@Override
public Collection<EnumMessage> validate() {
return Collections.emptyList();
}
@Override @Override
public BankAccountUpdateRequest toRequest() { public BankAccountUpdateRequest toRequest() {
var req = new BankAccountUpdateRequest(); var req = new BankAccountUpdateRequest();

View file

@ -35,16 +35,6 @@ public class ClientCodeNewAction implements IAction<ClientCodeNewRequest> {
@JsonProperty @JsonProperty
private String status; private String status;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.companyId == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "companyId"));
if (!StringUtils.hasLength(this.code))
errors.add(new EnumMessage(BackEndError.ValidationError, "code"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public ClientCodeNewRequest toRequest() { public ClientCodeNewRequest toRequest() {
var req = new ClientCodeNewRequest(); var req = new ClientCodeNewRequest();

View file

@ -36,13 +36,6 @@ public class ClientCodeUpdateAction implements IAction<ClientCodeUpdateRequest>
@JsonProperty @JsonProperty
private String status; private String status;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.id == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "id"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public ClientCodeUpdateRequest toRequest() { public ClientCodeUpdateRequest toRequest() {

View file

@ -4,9 +4,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolNewRequest;
public class CompanySymbolNewAction implements IAction<CompanySymbolUpdateRequest> { public class CompanySymbolNewAction implements IAction<CompanySymbolNewRequest> {
@ApiModelProperty(value = "Идентификатор Компании", example = "1234") @ApiModelProperty(value = "Идентификатор Компании", example = "1234")
@JsonProperty @JsonProperty
private Long companyId; private Long companyId;
@ -18,8 +18,8 @@ public class CompanySymbolNewAction implements IAction<CompanySymbolUpdateReques
private String companySymbolValue; private String companySymbolValue;
@Override @Override
public CompanySymbolUpdateRequest toRequest() { public CompanySymbolNewRequest toRequest() {
CompanySymbolUpdateRequest request = new CompanySymbolUpdateRequest(); CompanySymbolNewRequest request = new CompanySymbolNewRequest();
request.setCompanyId(this.companyId); request.setCompanyId(this.companyId);
request.setCompanySymbol(this.companySymbol); request.setCompanySymbol(this.companySymbol);
request.setCompanySymbolValue(this.companySymbolValue); request.setCompanySymbolValue(this.companySymbolValue);

View file

@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingNewRequest;
import java.math.BigDecimal; import java.math.BigDecimal;

View file

@ -36,16 +36,6 @@ public class PIClearingOutbondActionNew implements IAction<PIClearingOutbondActi
public Long debitLeg_accountId; public Long debitLeg_accountId;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.senderId == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "senderId"));
if (this.addresseeId == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "addresseeId"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public PIClearingOutbondActionNewRequest toRequest() { public PIClearingOutbondActionNewRequest toRequest() {
var req = new PIClearingOutbondActionNewRequest(); var req = new PIClearingOutbondActionNewRequest();

View file

@ -37,17 +37,6 @@ public class RSplitDepositActionNew implements IAction<RegistrySplitDepositActio
@JsonProperty @JsonProperty
public String contract; public String contract;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (StringUtils.isEmpty(this.contract))
errors.add(new EnumMessage(BackEndError.ValidationError, "contract"));
if (this.refundDate == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "refundDate"));
if (this.outboundAmount == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "outboundAmount"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public RegistrySplitDepositActionRequest toRequest() { public RegistrySplitDepositActionRequest toRequest() {

View file

@ -27,15 +27,6 @@ public class TradingClearingRegistryNewAction implements IAction<TradingClearing
@JsonProperty @JsonProperty
private String status; private String status;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.companyId == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "companyId"));
if (this.moneyAccountId == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "moneyAccountId"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public TradingClearingRegistryNewRequest toRequest() { public TradingClearingRegistryNewRequest toRequest() {

View file

@ -35,15 +35,6 @@ public class TradingClearingRegistryUpdateAction implements IAction<TradingClear
@JsonProperty @JsonProperty
private String status; private String status;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.id == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "id"));
if (StringUtils.isEmpty(this.status))
errors.add(new EnumMessage(BackEndError.ValidationError, "status"));
return errors.isEmpty() ? Collections.emptyList() : errors;
}
@Override @Override
public TradingClearingRegistryUpdateRequest toRequest() { public TradingClearingRegistryUpdateRequest toRequest() {

View file

@ -46,18 +46,6 @@ public class ClearingCalendarNewAction implements IAction<ClearingCalendarNewReq
return ActionType.NEW; return ActionType.NEW;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (clearingDate == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"clearingDate"));
}
if (TextUtil.isEmpty(dayStatus)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskStatus"));
}
return errors;
}
public LocalDate getClearingDate() { public LocalDate getClearingDate() {
return clearingDate; return clearingDate;
} }

View file

@ -52,21 +52,6 @@ public class ClearingCalendarUpdateAction implements IAction<ClearingCalendarUpd
return ActionType.UPDATE; return ActionType.UPDATE;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (id == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"id"));
}
if (clearingDate == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"clearingDate"));
}
if (TextUtil.isEmpty(dayStatus)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskStatus"));
}
return errors;
}
@Override @Override
public Long getId() { public Long getId() {
return id; return id;

View file

@ -78,23 +78,6 @@ public class PlannerNewAction implements IAction<PlannerNewRequest> {
return ActionType.NEW; return ActionType.NEW;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (TextUtil.isEmpty(task)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"task"));
}
if (taskTime == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskTime"));
}
if (clearingDate == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"clearingDate"));
}
if (TextUtil.isEmpty(taskStatus)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskStatus"));
}
return errors;
}
public String getTask() { public String getTask() {
return task; return task;

View file

@ -62,20 +62,6 @@ public class PlannerTemplateNewAction implements IAction<PlannerTemplateNewReque
return ActionType.NEW; return ActionType.NEW;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (TextUtil.isEmpty(task)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"task"));
}
if (taskTime == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskTime"));
}
if (TextUtil.isEmpty(taskStatus)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskStatus"));
}
return errors;
}
public String getTask() { public String getTask() {
return task; return task;

View file

@ -67,23 +67,6 @@ public class PlannerTemplateUpdateAction implements IAction<PlannerTemplateUpdat
return ActionType.UPDATE; return ActionType.UPDATE;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (id == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"id"));
}
if (TextUtil.isEmpty(task)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"task"));
}
if (taskTime == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskTime"));
}
if (TextUtil.isEmpty(taskStatus)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskStatus"));
}
return errors;
}
@Override @Override
public Long getId() { public Long getId() {

View file

@ -84,27 +84,6 @@ public class PlannerUpdateAction implements IAction<PlannerUpdateRequest>, WithI
return ActionType.UPDATE; return ActionType.UPDATE;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (id == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"id"));
}
if (TextUtil.isEmpty(task)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"task"));
}
if (taskTime == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskTime"));
}
if (clearingDate == null) {
errors.add(new EnumMessage(BackEndError.ValidationError,"clearingDate"));
}
if (TextUtil.isEmpty(taskStatus)) {
errors.add(new EnumMessage(BackEndError.ValidationError,"taskStatus"));
}
return errors;
}
@Override @Override
public Long getId() { public Long getId() {
return id; return id;

View file

@ -51,20 +51,6 @@ public class EquitySecurityNewAction implements IAction<EquitySecurityNewRequest
@JsonProperty @JsonProperty
public String instrumentType; public String instrumentType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (TextUtil.isEmpty(shortName))
errors.add(new EnumMessage(BackEndError.ValidationError, "shortName"));
if (TextUtil.isEmpty(securitySymbol))
errors.add(new EnumMessage(BackEndError.ValidationError, "securitySymbol"));
if (lotSize == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "lotSize"));
if (TextUtil.isEmpty(instrumentType))
errors.add(new EnumMessage(BackEndError.ValidationError, "instrumentType"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@Override @Override
public EquitySecurityNewRequest toRequest() { public EquitySecurityNewRequest toRequest() {
var req = new EquitySecurityNewRequest(); var req = new EquitySecurityNewRequest();

View file

@ -53,13 +53,6 @@ public class EquitySecurityUpdateAction implements IAction<EquitySecurityUpdateR
@JsonProperty @JsonProperty
public String instrumentType; public String instrumentType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (id == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "id"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@Override @Override
public EquitySecurityUpdateRequest toRequest() { public EquitySecurityUpdateRequest toRequest() {

View file

@ -73,19 +73,6 @@ public class FixedIncomeSecurityNewAction implements IAction<FixedIncomeSecurity
@JsonProperty @JsonProperty
public String instrumentType; public String instrumentType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (TextUtil.isEmpty(securitySymbol))
errors.add(new EnumMessage(BackEndError.ValidationError, "securitySymbol"));
if (TextUtil.isEmpty(shortName))
errors.add(new EnumMessage(BackEndError.ValidationError, "shortName"));
if (lotSize == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "lotSize"));
if (TextUtil.isEmpty(instrumentType))
errors.add(new EnumMessage(BackEndError.ValidationError, "instrumentType"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@Override @Override
public FixedIncomeSecurityNewRequest toRequest() { public FixedIncomeSecurityNewRequest toRequest() {

View file

@ -75,14 +75,6 @@ public class FixedIncomeSecurityUpdateAction implements IAction<FixedIncomeSecur
@JsonProperty @JsonProperty
public String instrumentType; public String instrumentType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (id == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "id"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@Override @Override
public FixedIncomeSecurityUpdateRequest toRequest() { public FixedIncomeSecurityUpdateRequest toRequest() {
var req = new FixedIncomeSecurityUpdateRequest(); var req = new FixedIncomeSecurityUpdateRequest();

View file

@ -74,29 +74,6 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
@JsonProperty @JsonProperty
public String instrumentType; public String instrumentType;
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (TextUtil.isEmpty(securitySymbol))
errors.add(new EnumMessage(BackEndError.ValidationError, "securitySymbol"));
if (TextUtil.isEmpty(shortName))
errors.add(new EnumMessage(BackEndError.ValidationError, "shortName"));
if (this.lotSize == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "lotSize"));
if (this.nominalValue == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "nominalValue"));
if (TextUtil.isEmpty(nominalCurrency))
errors.add(new EnumMessage(BackEndError.ValidationError, "nominalCurrency"));
if (this.startDate == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "startDate"));
if (this.endDate == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "endDate"));
if (this.termType == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "termType"));
if (TextUtil.isEmpty(instrumentType))
errors.add(new EnumMessage(BackEndError.ValidationError, "instrumentType"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@Override @Override
public MoneyMarketSecurityNewRequest toRequest() { public MoneyMarketSecurityNewRequest toRequest() {

View file

@ -99,14 +99,6 @@ public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecur
return req; return req;
} }
@Override
public Collection<EnumMessage> validate() {
List<EnumMessage> errors = new ArrayList<>();
if (this.id == null)
errors.add(new EnumMessage(BackEndError.ValidationError, "id"));
return errors.size() > 0 ? errors : Collections.emptyList();
}
@ApiModelProperty(hidden = true) @ApiModelProperty(hidden = true)
@Override @Override
public ActionType getActionType() { public ActionType getActionType() {

View file

@ -82,7 +82,9 @@ public class MetaServer extends MetaBase {
log.warn("META SERVER >>> {}", e.getLocalizedMessage()); log.warn("META SERVER >>> {}", e.getLocalizedMessage());
continue; continue;
} }
actionObjectsExtracted.put(actionElement.getDestination(), oe); String actionDestination = // обычно бывают =null о этому эффективнее по имени класса а не по: objectElement.getSubscription().destination + "/"+ actionElement.getDestination();
oe.getClassName();
actionObjectsExtracted.put(actionDestination, oe);
} }
} }
} catch (Throwable e) { } catch (Throwable e) {

View file

@ -17,6 +17,7 @@ import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.backendapi.errors.NotFound404Exception; import ru.spcex.clearing.backendapi.errors.NotFound404Exception;
import ru.spcex.clearing.backendapi.security.KeycloakUtils; import ru.spcex.clearing.backendapi.security.KeycloakUtils;
import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IOperator;
import ru.spcex.clearing.backendapi.service.validation.ActionMetaValidation;
import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider; import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
@ -39,13 +40,16 @@ public class OperatorImpl implements IOperator {
private final Producer<String, Object> kafka; private final Producer<String, Object> kafka;
private final ImdgId idGenerator; private final ImdgId idGenerator;
private final ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private final ActionMetaValidation actionMetaValidation;
private final ActionValidationProvider validation; private final ActionValidationProvider validation;
private final Imdg<User> userImdg; private final Imdg<User> userImdg;
public OperatorImpl(Producer<String, Object> kafka, ImdgProvider imdgProvider, ActionValidationProvider validation) { public OperatorImpl(Producer<String, Object> kafka, ImdgProvider imdgProvider,
ActionMetaValidation actionMetaValidation, ActionValidationProvider validation) {
this.kafka = kafka; this.kafka = kafka;
this.idGenerator = imdgProvider.getImdgIdGenerator(); this.idGenerator = imdgProvider.getImdgIdGenerator();
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.actionMetaValidation = actionMetaValidation;
this.validation = validation; this.validation = validation;
this.userImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class); this.userImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class);
} }
@ -112,6 +116,18 @@ public class OperatorImpl implements IOperator {
if (validationErrors.size() > 0) { if (validationErrors.size() > 0) {
throw new ActionValidationException(validationErrors); throw new ActionValidationException(validationErrors);
} }
// Валидация по мете (рекомендуется использовать её,а не iAction.validate();
IValidator metaValidator = actionMetaValidation.getValidator(destination, iAction);
if (metaValidator != null) {
metaValidator.tillFirstError().ifPresent(enumMessage -> {
if (enumMessage.getSubject().equalsById(BackEndError.ResourceNotFound.getId())) {
throw new NotFound404Exception(enumMessage);
} else {
throw new ActionValidationException(enumMessage);
}
});
}
//валидация требующая IMDG поиска других сущностей и т.д. //валидация требующая IMDG поиска других сущностей и т.д.
IValidator validator = validation.getValidator(destination, iAction); IValidator validator = validation.getValidator(destination, iAction);
if (validator != null) { if (validator != null) {

View file

@ -0,0 +1,142 @@
package ru.spcex.clearing.backendapi.service.validation;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityUpdateAction;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.backendapi.meta.FieldExtracted;
import ru.spcex.clearing.backendapi.meta.MetaServer;
import ru.spcex.clearing.backendapi.meta.ObjectExtracted;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import ru.spcex.platform.utils.validation.IValidator;
import ru.spcex.platform.utils.validation.ValidatorImpl;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
/**
* Проверка обязательности полей для IAction по мете
*/
@Component
public class ActionMetaValidation implements InitializingBean {
protected static final Logger log = LoggerFactory.getLogger(ActionMetaValidation.class);
protected final Map<String, Function<Object, IValidator>> validators;
protected final MetaServer meta;
@Autowired
public ActionMetaValidation(MetaServer meta) {
this.validators = new HashMap<>();
this.meta = meta;
}
@Override
public void afterPropertiesSet() {
for (Map.Entry<String, ObjectExtracted> entry : meta.getActionObjectsExtracted().entrySet()) {
if (StringUtils.isEmpty(entry.getKey())) continue;
Function<Object, IValidator> validator = validatorConstructor(entry.getValue());
if (validator == null) continue;
validators.put(entry.getKey(), validator);
}
log.debug("Init {} IAction validator for: {}", validators.size(), validators.keySet());
}
@SuppressWarnings("unchecked")
public IValidator getValidator(String destination, Object action) {
if (action == null)
return null;
//if (destination == null) destination = action.getClass().getName();
String actionDestination = action.getClass().getName(); // см. реализацию в MetaServer String actionDestination =...
Function<Object, IValidator> constructor = (Function<Object, IValidator>) validators.get(actionDestination);
if (constructor != null)
return constructor.apply(action);
return null;
}
private <T extends Object> Function<T, IValidator> validatorConstructor(ObjectExtracted metaAction) {
if (!metaAction.getFields().stream().anyMatch(field -> field.getField().isRequired())) {
log.debug("Action {}: no any required fields. Do not need validator.", metaAction.getClassName());
// нет обязательных полей для валидации
return null;
}
// Тестирование getter
{
Object object;
try {
object = metaAction.getClazz().getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException("Error self-test validator on class " + metaAction.getClazz(), e);
}
for (FieldExtracted field : metaAction.getFields()) {
try {
if (field.getField().isRequired() != null && field.getField().isRequired()) {
Object value = field.extractValue(object);
}
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
log.warn("Error self-test validator on class {} and field {}: {}",
metaAction.getClazz(), field.getMemberName(), ExceptionUtils.getStackTrace(e));
}
}
}
final MetaValidatorRule metaValidatorRule = new MetaValidatorRule(metaAction);
return iAcc -> {
ImdgValidationContext<T> ctx = new ImdgValidationContext<>();
ctx.setValidatedObject(iAcc);
ValidatorImpl<ImdgValidationContext<T>> iValidator = new ValidatorImpl(ctx);
iValidator.addRule(metaValidatorRule);
// в дальнейшем можно улучшить и разделить валидатор по полям
return iValidator;
};
}
static class MetaValidatorRule implements IValidationRule<ImdgValidationContext<IAction>> {
public final ObjectExtracted metaAction;
public MetaValidatorRule(ObjectExtracted metaAction) {
this.metaAction = metaAction;
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<IAction> context) {
IAction object = context.getValidatedObject();
for (FieldExtracted field : metaAction.getFields()) {
try {
if (field.getField().isRequired() != null && field.getField().isRequired()) {
Object value = field.extractValue(object);
if (value == null)
return of(BackEndError.ValidationError, field.getMemberName());
// if (value instanceof String && ((String)value).isEmpty()) // пустое поле, но не null
// return of(BackEndError.ValidationError, field.getMemberName());
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
if (object instanceof MoneyMarketSecurityUpdateAction) {
//todo в мете для moneyMarketSecurity / actions / put / для поля lotSize field="securityId" исключение - там надо оставить field, требуется для frontend
if (((MoneyMarketSecurityUpdateAction) object).getLotSize() == null)
return of(BackEndError.ValidationError, "LotSize");
} else {
log.warn("Error apply meta-validator {} for {} : {}",
metaAction, object, e.toString());
}
}
}
return empty();
}
@Override
public String ruleName() {
return getClass().getSimpleName() + " of " + metaAction.getClassName();
}
}
}

View file

@ -2501,6 +2501,8 @@
"confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityNewAction",
"fields": [ "fields": [
{"code": "instrumentType", {"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2578,6 +2580,8 @@
"confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true
@ -2770,6 +2774,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType", "confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityNewAction",
"fields": [ "fields": [
{"code": "instrumentType", {"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2823,6 +2829,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType", "confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true
@ -2981,6 +2989,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityNewAction",
"fields": [ "fields": [
{"code": "instrumentType", {"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -3054,6 +3064,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3131,6 +3143,8 @@
"confirmation": "securitySymbol,shortName", "confirmation": "securitySymbol,shortName",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3505,6 +3519,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status", "confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeNewAction",
"fields": [ "fields": [
{"code": "companyId", {"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false "type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false
@ -3538,6 +3554,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status", "confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3648,6 +3666,8 @@
"confirmation": "companyId,moneyAccountId,depoAccountId,status", "confirmation": "companyId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryNewAction",
"fields": [ "fields": [
{"code": "companyId", {"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true "type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -3673,6 +3693,8 @@
"confirmation": "companyId,code,moneyAccountId,depoAccountId,status", "confirmation": "companyId,code,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3925,6 +3947,8 @@
"confirmation": "contract,outboundAmount,refundDate", "confirmation": "contract,outboundAmount,refundDate",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.RSplitDepositActionNew",
"fields": [ "fields": [
{"code": "contract", {"code": "contract",
"type": 2,"length": 255,"name": "Договор","shortname": "Договор","required": true "type": 2,"length": 255,"name": "Договор","shortname": "Договор","required": true
@ -4006,6 +4030,8 @@
"confirmation": "companyId,account,status", "confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountNewAction",
"fields": [ "fields": [
{"code": "companyId", {"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true "type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -4031,6 +4057,8 @@
"confirmation": "companyId,account,status", "confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
@ -4060,6 +4088,8 @@
"confirmation": "companyId,account", "confirmation": "companyId,account",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
@ -4226,6 +4256,8 @@
"confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination", "confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction",
"fields": [ "fields": [
{"code": "currency", {"code": "currency",
"type": 12,"name": "Код валюты","shortname": "Валюта","required": true,"link": "currencyCode","linkCode": "code" "type": 12,"name": "Код валюты","shortname": "Валюта","required": true,"link": "currencyCode","linkCode": "code"
@ -4275,6 +4307,8 @@
"confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination", "confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "bankAccount","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "bankAccount","linkCode": "id","required": true
@ -4489,6 +4523,8 @@
"name": "Новый шаблон расписания операционного дня", "name": "Новый шаблон расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateNewAction",
"fields": [ "fields": [
{"code": "task", {"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true "type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4524,6 +4560,8 @@
"name": "Изменение шаблона расписания операционного дня", "name": "Изменение шаблона расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "plannerTemplate","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "plannerTemplate","linkCode": "id","required": true
@ -4614,6 +4652,8 @@
"name": "Добавление записи в календарь", "name": "Добавление записи в календарь",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarNewAction",
"fields": [ "fields": [
{"code": "clearingDate", {"code": "clearingDate",
"type": 6,"name": "Дата","shortname": "Дата","required": true "type": 6,"name": "Дата","shortname": "Дата","required": true
@ -4633,6 +4673,8 @@
"name": "Изменение записи в календаре", "name": "Изменение записи в календаре",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clearingCalendar","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clearingCalendar","linkCode": "id","required": true
@ -4731,6 +4773,8 @@
"name": "Новое расписание", "name": "Новое расписание",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerNewAction",
"fields": [ "fields": [
{"code": "task", {"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true "type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4770,6 +4814,8 @@
"name": "Изменение расписания", "name": "Изменение расписания",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "planner","required": true,"linkCode": "id" "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "planner","required": true,"linkCode": "id"
@ -6666,6 +6712,8 @@
"destination": "payment-instructions/clearing-outbound", "destination": "payment-instructions/clearing-outbound",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.payment.PIClearingOutbondActionNew",
"fields": [ "fields": [
{"code": "senderId", {"code": "senderId",
"type": 1,"name": "Участник отправитель","shortname": "Отправитель","link": "company","required": true "type": 1,"name": "Участник отправитель","shortname": "Отправитель","link": "company","required": true

View file

@ -578,7 +578,7 @@
<workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="workflowStatus" extends="security"/> <workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="workflowStatus" extends="security"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление инструмента Денежного рынка" confirmation="securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency"> <post name="Добавление инструмента Денежного рынка" confirmation="securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityNewAction">
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/> <instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" required="true"/> <securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" required="true"/>
<shortName type="2" length="255" name="Краткое наименование инструмента" shortname="Краткое наименование" required="true"/> <shortName type="2" length="255" name="Краткое наименование инструмента" shortname="Краткое наименование" required="true"/>
@ -597,7 +597,7 @@
<isin type="2" length="50" name="Наименование инструмента ISIN" shortname="ISIN"/> <isin type="2" length="50" name="Наименование инструмента ISIN" shortname="ISIN"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/> <workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</post> </post>
<put name="Изменение инструмента Денежного рынка" confirmation="securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency"> <put name="Изменение инструмента Денежного рынка" confirmation="securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="moneyMarketSecurity" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="moneyMarketSecurity" linkCode="id" required="true"/>
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/> <instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/> <securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/>
@ -643,7 +643,7 @@
<workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="workflowStatus" extends="security"/> <workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="workflowStatus" extends="security"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление акции" confirmation="securitySymbol,shortName,fullName,isin,shareType"> <post name="Добавление акции" confirmation="securitySymbol,shortName,fullName,isin,shareType" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityNewAction">
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/> <instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" required="true"/> <securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" required="true"/>
<shortName type="2" length="255" name="Краткое наименование инструмента" shortname="Краткое наименование" required="true"/> <shortName type="2" length="255" name="Краткое наименование инструмента" shortname="Краткое наименование" required="true"/>
@ -656,7 +656,7 @@
<fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/> <fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/> <workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</post> </post>
<put name="Изменение акции" confirmation="securitySymbol,shortName,fullName,isin,shareType"> <put name="Изменение акции" confirmation="securitySymbol,shortName,fullName,isin,shareType" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="equitySecurity" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="equitySecurity" linkCode="id" required="true"/>
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/> <instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/> <securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/>
@ -695,7 +695,7 @@
<workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="workflowStatus" extends="security"/> <workflowStatus type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="workflowStatus" extends="security"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление облигации" confirmation="securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency"> <post name="Добавление облигации" confirmation="securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityNewAction">
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/> <instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" required="true"/> <securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" required="true"/>
<shortName type="2" length="255" name="Краткое наименование инструмента" shortname="Краткое наименование" required="true"/> <shortName type="2" length="255" name="Краткое наименование инструмента" shortname="Краткое наименование" required="true"/>
@ -713,7 +713,7 @@
<fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/> <fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/> <workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</post> </post>
<put name="Изменение облигации" confirmation="securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency"> <put name="Изменение облигации" confirmation="securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="fixedIncomeSecurity" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="fixedIncomeSecurity" linkCode="id" required="true"/>
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/> <instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/> <securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/>
@ -732,7 +732,7 @@
<fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/> <fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/> <workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</put> </put>
<delete name="Блокировка облигации" confirmation="securitySymbol,shortName"> <delete name="Блокировка облигации" confirmation="securitySymbol,shortName" class="ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="fixedIncomeSecurity" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="fixedIncomeSecurity" linkCode="id" required="true"/>
</delete> </delete>
</actions> </actions>
@ -818,7 +818,7 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление кода клиента" confirmation="companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status"> <post name="Добавление кода клиента" confirmation="companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status" class="ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeNewAction">
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" required="true" enabled="false"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" required="true" enabled="false"/>
<code type="2" length="255" name="Код клиента" shortname="Код клиента" required="true"/> <code type="2" length="255" name="Код клиента" shortname="Код клиента" required="true"/>
<tradingClearingRegistryId type="1" name="Торгово-клиринговый регистр" shortname="ТКР" link="tradingClearingRegistry" linkCode="code"/> <tradingClearingRegistryId type="1" name="Торгово-клиринговый регистр" shortname="ТКР" link="tradingClearingRegistry" linkCode="code"/>
@ -826,7 +826,7 @@
<depoAccountId type="1" name="Номер депозитарного счета" shortname="Депозитарный счет" link="account" linkCode="account"/> <depoAccountId type="1" name="Номер депозитарного счета" shortname="Депозитарный счет" link="account" linkCode="account"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/> <status type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</post> </post>
<put name="Изменение кода клиента" confirmation="companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status"> <put name="Изменение кода клиента" confirmation="companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status" class="ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="clientCode" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="clientCode" linkCode="id" required="true"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/>
<code type="2" length="255" name="Код клиента" shortname="Код клиента"/> <code type="2" length="255" name="Код клиента" shortname="Код клиента"/>
@ -853,13 +853,13 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<actions> <actions>
<post name="Добавление ТКР" confirmation="companyId,moneyAccountId,depoAccountId,status"> <post name="Добавление ТКР" confirmation="companyId,moneyAccountId,depoAccountId,status" class="ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryNewAction">
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" required="true"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" required="true"/>
<moneyAccountId type="1" name="Номер денежного счета" shortname="Денежный счет" link="account" linkCode="account" required="true"/> <moneyAccountId type="1" name="Номер денежного счета" shortname="Денежный счет" link="account" linkCode="account" required="true"/>
<depoAccountId type="1" name="Номер депозитарного счета" shortname="Депозитарный счет" link="account" linkCode="account"/> <depoAccountId type="1" name="Номер депозитарного счета" shortname="Депозитарный счет" link="account" linkCode="account"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/> <status type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</post> </post>
<put name="Изменение ТКР" confirmation="companyId,code,moneyAccountId,depoAccountId,status"> <put name="Изменение ТКР" confirmation="companyId,code,moneyAccountId,depoAccountId,status" class="ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="clientCode" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="clientCode" linkCode="id" required="true"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/>
<code type="2" length="255" name="Код торгово-клирингового регистра" shortname="ТКР" enabled="false"/> <code type="2" length="255" name="Код торгово-клирингового регистра" shortname="ТКР" enabled="false"/>
@ -921,7 +921,7 @@
<createdAt field="created" type="4" name="Дата и время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/> <createdAt field="created" type="4" name="Дата и время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" name="Дата и время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/> <updatedAt field="updated" type="4" name="Дата и время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<actions> <actions>
<post name="Досрочное изъятие части денежных средств по депозиту МКР" destination="registries/splitDeposit" confirmation="contract,outboundAmount,refundDate"> <post name="Досрочное изъятие части денежных средств по депозиту МКР" destination="registries/splitDeposit" confirmation="contract,outboundAmount,refundDate" class="ru.spcex.clearing.backendapi.controller.request.cud.registry.RSplitDepositActionNew">
<contract type="2" length="255" name="Договор" shortname="Договор" required="true"/> <contract type="2" length="255" name="Договор" shortname="Договор" required="true"/>
<outboundAmount type="10" name="Сумма изъятия" shortname="Сумма" required="true"/> <outboundAmount type="10" name="Сумма изъятия" shortname="Сумма" required="true"/>
<refundDate type="6" name="Дата возврата" shortname="Дата" required="true"/> <refundDate type="6" name="Дата возврата" shortname="Дата" required="true"/>
@ -941,20 +941,20 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление корреспондентского счета" confirmation="companyId,account,status"> <post name="Добавление корреспондентского счета" confirmation="companyId,account,status" class="ru.spcex.clearing.backendapi.controller.request.cud.account.AccountNewAction">
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" required="true"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" required="true"/>
<account type="2" length="50" name="Номер счета" shortname="Счет" required="true"/> <account type="2" length="50" name="Номер счета" shortname="Счет" required="true"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/> <status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/>
<accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/> <accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/>
</post> </post>
<put name="Изменение корреспондентского счета" confirmation="companyId,account,status"> <put name="Изменение корреспондентского счета" confirmation="companyId,account,status" class="ru.spcex.clearing.backendapi.controller.request.cud.account.AccountUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="account" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="account" linkCode="id" required="true"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/>
<account type="2" length="50" name="Номер счета" shortname="Счет" enabled="false"/> <account type="2" length="50" name="Номер счета" shortname="Счет" enabled="false"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/> <status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/>
<accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/> <accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/>
</put> </put>
<delete name="Блокировка корреспондентского счета" confirmation="companyId,account"> <delete name="Блокировка корреспондентского счета" confirmation="companyId,account" class="ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="account" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="account" linkCode="id" required="true"/>
</delete> </delete>
</actions> </actions>
@ -995,7 +995,7 @@
<status type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="serviceStatus" extends="account"/> <status type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" link="serviceStatus" extends="account"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление счета вывода средств из ПРЦ" confirmation="currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination"> <post name="Добавление счета вывода средств из ПРЦ" confirmation="currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination" class="ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction">
<currency type="12" name="Код валюты" shortname="Валюта" required="true" link="currencyCode" linkCode="code"/> <currency type="12" name="Код валюты" shortname="Валюта" required="true" link="currencyCode" linkCode="code"/>
<bankIdentificationCode type="2" length="255" name="Банковский идентификационный код (БИК)" shortname="БИК" required="true"/> <bankIdentificationCode type="2" length="255" name="Банковский идентификационный код (БИК)" shortname="БИК" required="true"/>
<bankName type="2" length="255" name="Наименование банка" shortname="Наименование" required="true"/> <bankName type="2" length="255" name="Наименование банка" shortname="Наименование" required="true"/>
@ -1007,7 +1007,7 @@
<destination type="2" length="255" name="Назначение платежа" shortname="Назначение платежа" visible="false"/> <destination type="2" length="255" name="Назначение платежа" shortname="Назначение платежа" visible="false"/>
<companyId type="1" name="Компания" shortname="Компания" link="company" linkCode="shortName" required="true"/> <companyId type="1" name="Компания" shortname="Компания" link="company" linkCode="shortName" required="true"/>
</post> </post>
<put name="Изменение счета вывода средств из ПРЦ" confirmation="currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination"> <put name="Изменение счета вывода средств из ПРЦ" confirmation="currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination" class="ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="bankAccount" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="bankAccount" linkCode="id" required="true"/>
<currency type="12" name="Код валюты" shortname="Валюта" link="currencyCode" linkCode="code"/> <currency type="12" name="Код валюты" shortname="Валюта" link="currencyCode" linkCode="code"/>
<bankIdentificationCode type="2" length="255" name="Банковский идентификационный код (БИК)" shortname="БИК"/> <bankIdentificationCode type="2" length="255" name="Банковский идентификационный код (БИК)" shortname="БИК"/>
@ -1055,7 +1055,7 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Новый шаблон расписания операционного дня"> <post name="Новый шаблон расписания операционного дня" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateNewAction">
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/> <task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/> <taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/>
<section type="12" name="Секция" shortname="Секция" link="section" linkCode="name" linkKeyCode="code"/> <section type="12" name="Секция" shortname="Секция" link="section" linkCode="name" linkKeyCode="code"/>
@ -1064,7 +1064,7 @@
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/>
<securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName"/> <securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName"/>
</post> </post>
<put name="Изменение шаблона расписания операционного дня"> <put name="Изменение шаблона расписания операционного дня" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="plannerTemplate" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="plannerTemplate" linkCode="id" required="true"/>
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/> <task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/> <taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/>
@ -1087,12 +1087,12 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Добавление записи в календарь"> <post name="Добавление записи в календарь" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarNewAction">
<clearingDate type="6" name="Дата" shortname="Дата" required="true"/> <clearingDate type="6" name="Дата" shortname="Дата" required="true"/>
<dayStatus type="12" name="Статус" shortname="Статус" link="dayStatus" required="true"/> <dayStatus type="12" name="Статус" shortname="Статус" link="dayStatus" required="true"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/>
</post> </post>
<put name="Изменение записи в календаре"> <put name="Изменение записи в календаре" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="clearingCalendar" linkCode="id" required="true"/> <id type="1" name="Идентификатор записи" shortname="ID" link="clearingCalendar" linkCode="id" required="true"/>
<clearingDate type="6" name="Дата" shortname="Дата" required="true"/> <clearingDate type="6" name="Дата" shortname="Дата" required="true"/>
<dayStatus type="12" name="Статус" shortname="Статус" link="dayStatus" required="true"/> <dayStatus type="12" name="Статус" shortname="Статус" link="dayStatus" required="true"/>
@ -1117,7 +1117,7 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions> <actions>
<post name="Новое расписание"> <post name="Новое расписание" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerNewAction">
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/> <task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<clearingDate type="6" name="Дата задачи" shortname="Дата задачи" required="true"/> <clearingDate type="6" name="Дата задачи" shortname="Дата задачи" required="true"/>
<taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/> <taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/>
@ -1127,7 +1127,7 @@
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/> <companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/>
<securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName"/> <securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName"/>
</post> </post>
<put name="Изменение расписания"> <put name="Изменение расписания" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="planner" required="true" linkCode="id"/> <id type="1" name="Идентификатор записи" shortname="ID" link="planner" required="true" linkCode="id"/>
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/> <task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<clearingDate type="6" name="Дата задачи" shortname="Дата задачи" required="true"/> <clearingDate type="6" name="Дата задачи" shortname="Дата задачи" required="true"/>
@ -1554,7 +1554,7 @@
<clearingDate type="6" name="Дата расчета" shortname="Дата расчета" searchable="true" sortable="true" ignore="true"/> <clearingDate type="6" name="Дата расчета" shortname="Дата расчета" searchable="true" sortable="true" ignore="true"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/> <sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
<actions> <actions>
<post name="Вывод денежных средств c регистра инициатора" destination="payment-instructions/clearing-outbound"> <post name="Вывод денежных средств c регистра инициатора" destination="payment-instructions/clearing-outbound" class="ru.spcex.clearing.backendapi.controller.request.cud.payment.PIClearingOutbondActionNew">
<senderId type="1" name="Участник отправитель" shortname="Отправитель" link="company" required="true"/> <senderId type="1" name="Участник отправитель" shortname="Отправитель" link="company" required="true"/>
<addresseeId type="1" name="Участник получатель" shortname="Получатель" link="company" required="true"/> <addresseeId type="1" name="Участник получатель" shortname="Получатель" link="company" required="true"/>
<paymentPurpose type="2" length="255" name="Назначение платежа" shortname="Назначение" searchable="true" sortable="true" visible="true"/> <paymentPurpose type="2" length="255" name="Назначение платежа" shortname="Назначение" searchable="true" sortable="true" visible="true"/>

View file

@ -5,7 +5,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import ru.spcex.clearing.backendapi.meta.MetaServer;
import ru.spcex.clearing.backendapi.service.impl.OperatorImpl; import ru.spcex.clearing.backendapi.service.impl.OperatorImpl;
import ru.spcex.clearing.backendapi.service.validation.ActionMetaValidation;
import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider; import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
@ -18,8 +20,9 @@ public class IOperatorTest {
@Autowired @Autowired
@Bean("iOperatorTest") @Bean("iOperatorTest")
public OperatorImpl createIOperator(Producer<String, Object> kafka, ActionValidationProvider validationProvider) { public OperatorImpl createIOperator(Producer<String, Object> kafka,
return new OperatorImpl(kafka, hazelcastServiceTest, validationProvider); ActionMetaValidation actionMetaValidation, ActionValidationProvider validationProvider) {
return new OperatorImpl(kafka, hazelcastServiceTest, actionMetaValidation, validationProvider);
} }
@Bean @Bean
@ -27,4 +30,10 @@ public class IOperatorTest {
return new ActionValidationProvider(hazelcastServiceTest); return new ActionValidationProvider(hazelcastServiceTest);
} }
@Bean
public ActionMetaValidation actionMetaValidation(MetaServer metaServer) {
return new ActionMetaValidation(metaServer);
}
} }

View file

@ -0,0 +1,94 @@
package ru.spcex.clearing.backendapi.service.validation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.backendapi.controller.request.cud.company.ListingNewAction;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.meta.GetResponseFactoryTestConfiguration;
import ru.spcex.clearing.backendapi.meta.MetaServer;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.validation.IValidator;
import java.util.ArrayList;
import java.util.Collection;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = GetResponseFactoryTestConfiguration.class)
class ActionMetaValidationTest {
@Autowired @Qualifier("metaJsonTest")
protected MetaServer meta;
@Test
void getValidator() {
ActionMetaValidation metaValidator = new ActionMetaValidation(meta);
metaValidator.afterPropertiesSet();
{
IAction<?> action = new ListingNewAction();
assertTrue(action.validate().isEmpty());
IValidator v = metaValidator.getValidator(null, action);
assertNull(v, "Пока не прописан в мете");
}
{
IAction<?> action = new CommonDeleteAction();
assertFalse(action.validate().isEmpty()); // стандартный валидатор - требуется id
IValidator v = metaValidator.getValidator(null, action);
Collection<EnumMessage> vResult = v.validateAll();
assertEquals("[EnumMessage{subject=ValidationError, args: [id]}]", vResult.toString());
}
{
CommonDeleteAction action = new CommonDeleteAction();
action.setId(123L);
assertTrue(action.validate().isEmpty()); // стандартный валидатор - требуется id
IValidator v = metaValidator.getValidator(null, action);
Collection<EnumMessage> vResult = v.validateAll();
assertEquals("[]", vResult.toString());
}
}
@Test
void testForBankAccountNewAction() {
ActionMetaValidation metaValidator = new ActionMetaValidation(meta);
metaValidator.afterPropertiesSet();
{
BankAccountNewAction action = new BankAccountNewAction();
assertTrue(action.validate().isEmpty());
IValidator v = metaValidator.getValidator(null, action);
assertNotNull(v);
Collection<EnumMessage> vResult = v.validateAll();
assertEquals("[EnumMessage{subject=ValidationError, args: [currency]}]", vResult.toString());
}
{
BankAccountNewAction action = new BankAccountNewAction();
action.setBankIdentificationCode("Hello world");
action.setBankName("Hello world");
action.setCorrespondentAccount("Hello world");
action.setCorrespondentAccountName("Hello world");
action.setCurrency("Hello world");
action.setDestination("Hello world");
action.setTaxpayerIdentificationNumber("Hello world");
action.setTaxRegistrationReasonCode("Hello world");
action.setAccount("Hello world");
action.setCompanyId(123L);
IValidator v = metaValidator.getValidator(null, action);
assertNotNull(v);
Collection<EnumMessage> vResult = v.validateAll();
assertEquals("[]", vResult.toString());
}
}
}

View file

@ -2501,6 +2501,8 @@
"confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityNewAction",
"fields": [ "fields": [
{"code": "instrumentType", {"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2578,6 +2580,8 @@
"confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true
@ -2770,6 +2774,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType", "confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityNewAction",
"fields": [ "fields": [
{"code": "instrumentType", {"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2823,6 +2829,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType", "confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true
@ -2981,6 +2989,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityNewAction",
"fields": [ "fields": [
{"code": "instrumentType", {"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -3054,6 +3064,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3131,6 +3143,8 @@
"confirmation": "securitySymbol,shortName", "confirmation": "securitySymbol,shortName",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3505,6 +3519,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status", "confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeNewAction",
"fields": [ "fields": [
{"code": "companyId", {"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false "type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false
@ -3538,6 +3554,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status", "confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3648,6 +3666,8 @@
"confirmation": "companyId,moneyAccountId,depoAccountId,status", "confirmation": "companyId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryNewAction",
"fields": [ "fields": [
{"code": "companyId", {"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true "type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -3673,6 +3693,8 @@
"confirmation": "companyId,code,moneyAccountId,depoAccountId,status", "confirmation": "companyId,code,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3925,6 +3947,8 @@
"confirmation": "contract,outboundAmount,refundDate", "confirmation": "contract,outboundAmount,refundDate",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.RSplitDepositActionNew",
"fields": [ "fields": [
{"code": "contract", {"code": "contract",
"type": 2,"length": 255,"name": "Договор","shortname": "Договор","required": true "type": 2,"length": 255,"name": "Договор","shortname": "Договор","required": true
@ -4006,6 +4030,8 @@
"confirmation": "companyId,account,status", "confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountNewAction",
"fields": [ "fields": [
{"code": "companyId", {"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true "type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -4031,6 +4057,8 @@
"confirmation": "companyId,account,status", "confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
@ -4060,6 +4088,8 @@
"confirmation": "companyId,account", "confirmation": "companyId,account",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
@ -4226,6 +4256,8 @@
"confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination", "confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction",
"fields": [ "fields": [
{"code": "currency", {"code": "currency",
"type": 12,"name": "Код валюты","shortname": "Валюта","required": true,"link": "currencyCode","linkCode": "code" "type": 12,"name": "Код валюты","shortname": "Валюта","required": true,"link": "currencyCode","linkCode": "code"
@ -4275,6 +4307,8 @@
"confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination", "confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "bankAccount","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "bankAccount","linkCode": "id","required": true
@ -4489,6 +4523,8 @@
"name": "Новый шаблон расписания операционного дня", "name": "Новый шаблон расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateNewAction",
"fields": [ "fields": [
{"code": "task", {"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true "type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4524,6 +4560,8 @@
"name": "Изменение шаблона расписания операционного дня", "name": "Изменение шаблона расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "plannerTemplate","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "plannerTemplate","linkCode": "id","required": true
@ -4614,6 +4652,8 @@
"name": "Добавление записи в календарь", "name": "Добавление записи в календарь",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarNewAction",
"fields": [ "fields": [
{"code": "clearingDate", {"code": "clearingDate",
"type": 6,"name": "Дата","shortname": "Дата","required": true "type": 6,"name": "Дата","shortname": "Дата","required": true
@ -4633,6 +4673,8 @@
"name": "Изменение записи в календаре", "name": "Изменение записи в календаре",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clearingCalendar","linkCode": "id","required": true "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clearingCalendar","linkCode": "id","required": true
@ -4731,6 +4773,8 @@
"name": "Новое расписание", "name": "Новое расписание",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerNewAction",
"fields": [ "fields": [
{"code": "task", {"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true "type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4770,6 +4814,8 @@
"name": "Изменение расписания", "name": "Изменение расписания",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerUpdateAction",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "planner","required": true,"linkCode": "id" "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "planner","required": true,"linkCode": "id"
@ -6666,6 +6712,8 @@
"destination": "payment-instructions/clearing-outbound", "destination": "payment-instructions/clearing-outbound",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.payment.PIClearingOutbondActionNew",
"fields": [ "fields": [
{"code": "senderId", {"code": "senderId",
"type": 1,"name": "Участник отправитель","shortname": "Отправитель","link": "company","required": true "type": 1,"name": "Участник отправитель","shortname": "Отправитель","link": "company","required": true

View file

@ -2,10 +2,8 @@ package ru.clearing.classes.statics.data.registry;
import ru.clearing.classes.ConstSerializable; import ru.clearing.classes.ConstSerializable;
import ru.clearing.classes.objects.BusinessObject; import ru.clearing.classes.objects.BusinessObject;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
/** /**
@ -414,9 +412,9 @@ public class Registry extends BusinessObject implements Cloneable {
} }
@Override @Override
public Object clone() { public Registry clone() {
try { try {
return super.clone(); return (Registry) super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
throw new RuntimeException("never", e); // it is Cloneable throw new RuntimeException("never", e); // it is Cloneable
} }

View file

@ -2,9 +2,8 @@ package ru.spcex.clearing.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import ru.spcex.clearing.service.executors.AbstractExecutor; import ru.spcex.clearing.service.executors.*;
import ru.spcex.clearing.service.executors.Sdf01Executor; import ru.spcex.clearing.service.executors.SdfLegacyExecutor;
import ru.spcex.clearing.service.executors.Sdf57Executor;
import ru.spcex.platform.enumeration.SdfTable; import ru.spcex.platform.enumeration.SdfTable;
import java.util.HashMap; import java.util.HashMap;
@ -14,11 +13,15 @@ import java.util.Map;
public class SdfExecutorsConfig { public class SdfExecutorsConfig {
@Bean("sdfExecutors") @Bean("sdfExecutors")
public Map<SdfTable, AbstractExecutor<?>> executorsMap(Sdf01Executor sdf01Executor, public Map<SdfTable, AbstractExecutor<?>> executorsMap(SdfLegacyExecutor sdf01Executor,
Sdf57Executor sdf57Executor) { Sdf57Executor sdf57Executor,
Sdf04Executor sdf04Executor,
Sdf13Executor sdf13Executor) {
Map<SdfTable, AbstractExecutor<?>> executors = new HashMap<>(); Map<SdfTable, AbstractExecutor<?>> executors = new HashMap<>();
executors.put(SdfTable.SDF_01, sdf01Executor); executors.put(SdfTable.SDF_01, sdf01Executor);
executors.put(SdfTable.SDF_57, sdf57Executor); executors.put(SdfTable.SDF_57, sdf57Executor);
executors.put(SdfTable.SDF_04, sdf04Executor);
executors.put(SdfTable.SDF_13, sdf13Executor);
return executors; return executors;
} }
} }

View file

@ -140,4 +140,22 @@ public class ValidationConfig {
); );
}; };
} }
@Bean("sdf01ValidatorNew")
public Function<SDf01, IValidator> sdf01ValidatorNew() {
return sDf01 -> {
ImdgValidationContext<SDf01> context = new ImdgValidationContext<>();
context.setValidatedObject(sDf01);
Consumer<String> addImdg = (s) -> context.addImdg(s, getImdg(s));
addImdg.accept(IMDGDistributedNames.Map_Account);
addImdg.accept(IMDGDistributedNames.Map_Company);
return new ValidatorImpl<>(context,
Sdf01NewValidationRule.CompanyPresent,
Sdf01NewValidationRule.AccountType,
Sdf01NewValidationRule.AccountPresent,
Sdf01NewValidationRule.CurrencyCode,
Sdf01NewValidationRule.DatIsCurrentDt
);
};
}
} }

View file

@ -19,6 +19,11 @@ public enum ClearingError implements IErrorEnumId {
ClearingUnavailableForCompany(5421L), ClearingUnavailableForCompany(5421L),
InsecurityObligation(5422L), InsecurityObligation(5422L),
NewDealsNotFound(5423L), NewDealsNotFound(5423L),
//ошибки "перенесенные" из balance-service
CompanyNotFoundB(5211L),
CurrencyNotFound(5213L),
OperationCanBeRunForTodayOnly(5214L),
AccountWrongType(5216L),
; ;
private final Long id; private final Long id;

View file

@ -5,6 +5,7 @@ import ru.spcex.platform.utils.enumeration.IErrorEnumId;
public enum ClearingErrorInternal implements IErrorEnumId { public enum ClearingErrorInternal implements IErrorEnumId {
ClearingNotAllowed(1L), ClearingNotAllowed(1L),
AccountNotActive(5415L), AccountNotActive(5415L),
AccountNotPresent(3L),
CompanyNotActive(5411L), CompanyNotActive(5411L),
FinancialObligationNotSatisfied(4L), FinancialObligationNotSatisfied(4L),
SessionGeneralError(2L); SessionGeneralError(2L);

View file

@ -62,8 +62,11 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
.setConsumer(primaryAuctionBnSession::runSession) .setConsumer(primaryAuctionBnSession::runSession)
.forDestination(Task.startOfClearing.topic(), callbacks::put); .forDestination(Task.startOfClearing.topic(), callbacks::put);
callback(Object.class) callback(Object.class)
.setConsumer(primaryAuctionBnSession::continueSession) .setConsumer(primaryAuctionBnSession::continueSessionFirstPart)
.forDestination(Consts.SDF57_PROCESS, callbacks::put); .forDestination(Consts.CONTINUE_SESSION_BN_FIRST_PART, callbacks::put);
callback(Object.class)
.setConsumer(primaryAuctionBnSession::continueSessionSecondPart)
.forDestination(Consts.CONTINUE_SESSION_BN_SECOND_PART, callbacks::put);
callback(Object.class) callback(Object.class)
.setConsumer(event -> clearingService.executeSTrade()) .setConsumer(event -> clearingService.executeSTrade())

View file

@ -8,14 +8,16 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.sdf.SDf01;
import ru.clearing.classes.statics.data.sdf.SDf04;
import ru.clearing.classes.statics.data.sdf.SDf13;
import ru.clearing.classes.statics.data.sdf.SDf57; import ru.clearing.classes.statics.data.sdf.SDf57;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdf01Request; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdf01Request;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.ContinueSessionBnRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.executors.AbstractExecutor; import ru.spcex.clearing.service.executors.AbstractExecutor;
@ -24,11 +26,9 @@ import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.SdfTable; import ru.spcex.platform.enumeration.SdfTable;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.collection.Pair;
import java.util.Collection; import java.util.*;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -40,6 +40,11 @@ public class StatementService extends QueueConsumer implements InitializingBean
private final Map<SdfTable, Imdg<? extends SpcexObjectBase>> sdfImdgs; private final Map<SdfTable, Imdg<? extends SpcexObjectBase>> sdfImdgs;
private final Map<SdfTable, AbstractExecutor<?>> executorsMap; private final Map<SdfTable, AbstractExecutor<?>> executorsMap;
/**
* Пары sdf запросов пришедшие с модуля dbf-import
*/
private final Map<Long, Pair<StatementRequest, StatementRequest>> pairOfSdfRequest = new HashMap<>();
@Autowired @Autowired
public StatementService(Consumer<String, Object> kafkaQueue, public StatementService(Consumer<String, Object> kafkaQueue,
ImdgProvider imdgProvider, ImdgProvider imdgProvider,
@ -52,6 +57,8 @@ public class StatementService extends QueueConsumer implements InitializingBean
this.executorsMap = executorsMap; this.executorsMap = executorsMap;
this.sdfImdgs.put(SdfTable.SDF_01, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); this.sdfImdgs.put(SdfTable.SDF_01, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class));
this.sdfImdgs.put(SdfTable.SDF_57, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf57, SDf57.class)); this.sdfImdgs.put(SdfTable.SDF_57, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf57, SDf57.class));
this.sdfImdgs.put(SdfTable.SDF_04, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf04, SDf04.class));
this.sdfImdgs.put(SdfTable.SDF_13, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf13, SDf13.class));
} }
@Override @Override
@ -64,31 +71,145 @@ public class StatementService extends QueueConsumer implements InitializingBean
private void process(BaseRequest<StatementRequest> systemRequest) { private void process(BaseRequest<StatementRequest> systemRequest) {
StatementRequest statementRequest = systemRequest.getRequestPayload(); StatementRequest statementRequest = systemRequest.getRequestPayload();
Collection<? extends SpcexObjectBase> sdfGroup;
SdfTable table = statementRequest.getTable(); SdfTable table = statementRequest.getTable();
Imdg<? extends SpcexObjectBase> sdfImdg = sdfImdgs.get(table);
Optional<Long> completePairKey = saveRequest(statementRequest);
if (completePairKey.isPresent()) {
if (List.of(SdfTable.SDF_01, SdfTable.SDF_57).contains(table)) {
{
//всегда сначала обработаем sdf57
Long key = completePairKey.get();
Pair<StatementRequest, StatementRequest> pair = pairOfSdfRequest.get(key);
processSdf57(pair.getSecond());
//затем sdf01
processSdf01(pair.getFirst());
//теперь можем продолжить сессию с шага 1
ContinueSessionBnRequest continueSessionBn = new ContinueSessionBnRequest();
kafkaSender.sendRequestToQueue(Consts.CONTINUE_SESSION_BN_FIRST_PART, continueSessionBn);
pairOfSdfRequest.remove(key);
}
} else if (List.of(SdfTable.SDF_08, SdfTable.SDF_13).contains(table)) {
//not implemented part; it's actually stage number 8 from any session
{
//всегда сначала обработаем sdf04
Long key = completePairKey.get();
Pair<StatementRequest, StatementRequest> pair = pairOfSdfRequest.get(key);
processSdf04(pair.getFirst());
//затем sdf01
processSdf13(pair.getSecond());
//теперь можем продолжить сессию с шага 1
ContinueSessionBnRequest continueSessionBn = new ContinueSessionBnRequest();
kafkaSender.sendRequestToQueue(Consts.CONTINUE_SESSION_BN_SECOND_PART, continueSessionBn);
pairOfSdfRequest.remove(key);
}
}
}
}
private void processSdf57(StatementRequest statementRequest) {
Imdg<SDf57> sdfImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf57, SDf57.class);
Collection<? extends SpcexObjectBase> sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of(
"generationId", statementRequest.getGroupId()));
AbstractExecutor service = executorsMap.get(SdfTable.SDF_57);
service.execute(sdfGroup, statementRequest);
}
private void processSdf04(StatementRequest statementRequest) {
Imdg<SDf04> sdfImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf04, SDf04.class);
Collection<? extends SpcexObjectBase> sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of(
"generationId", statementRequest.getGroupId()));
AbstractExecutor service = executorsMap.get(SdfTable.SDF_04);
service.execute(sdfGroup, statementRequest);
}
private void processSdf13(StatementRequest statementRequest) {
Imdg<SDf13> sdfImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf13, SDf13.class);
Collection<? extends SpcexObjectBase> sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of(
"generationId", statementRequest.getGroupId()));
AbstractExecutor service = executorsMap.get(SdfTable.SDF_13);
service.execute(sdfGroup, statementRequest);
}
private void processSdf01(StatementRequest statementRequest) {
Imdg<SDf01> sdfImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class);
Collection<? extends SpcexObjectBase> sdfGroup;
if (statementRequest.getAccountCreationResults().size() == 0) { if (statementRequest.getAccountCreationResults().size() == 0) {
sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of("generationId", statementRequest.getGroupId())); sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of(
"generationId", statementRequest.getGroupId()));
} else { } else {
//todo могут ли тут реквесты бегать по кругу, если да, то у нас проблемы
sdfGroup = statementRequest.getAccountCreationResults() sdfGroup = statementRequest.getAccountCreationResults()
.stream() .stream()
.filter(part -> part.getErrorCode() == null) //fixme эти случае должны попадать в ошибочный sdf02 .filter(part -> part.getErrorCode() == null) //fixme эти случае должны попадать в ошибочный sdf02
.map(part -> sdfImdg.getSingleObjectByID(part.getSdfId())) .map(part -> sdfImdg.getSingleObjectByID(part.getSdfId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
AbstractExecutor service = executorsMap.get(SdfTable.SDF_01);
AbstractExecutor service = executorsMap.get(table);
Result res = service.execute(sdfGroup, statementRequest); Result res = service.execute(sdfGroup, statementRequest);
if (res.getAccountRequests().size() != 0) { if (res.getAccountRequests().size() != 0) {
kafkaSender.sendRequestToQueue(Consts.ACCOUNT_NEW_SDF01, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests())); kafkaSender.sendRequestToQueue(Consts.ACCOUNT_NEW_SDF01, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests()));
} else if (service.isNeedToSendCommandToExport()) { } else if (service.isNeedToSendCommand()) {
ExportToFileRequest exportRequest = new ExportToFileRequest(); service.sendCommand(kafkaSender, res);
exportRequest.setSdfGroupId(res.getGenerationId());
exportRequest.setNameOfTable(service.exportTableName());
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest);
} }
} }
private Optional<Long> saveRequest(StatementRequest statementRequest) {
SdfTable sdfTable = statementRequest.getTable();
if (pairOfSdfRequest.isEmpty()) {
Long id = imdgProvider.getImdgIdGenerator().nextId();
pairOfSdfRequest.put(id, getPairByTableName(sdfTable, statementRequest));
} else {
//найдем первую неполноценную пару
Optional<Long> uncompletedPairId = findUncompletedPairByTableName(sdfTable);
if (uncompletedPairId.isPresent()) {
Long key = uncompletedPairId.get();
Pair<StatementRequest, StatementRequest> completed = pairOfSdfRequest.get(key);
if (completed.getFirst() == null) {
completed.setFirst(statementRequest);
} else {
completed.setSecond(statementRequest);
}
pairOfSdfRequest.put(key, completed);
//укомплектованная пара
return Optional.of(key);
} else {
//если таких нет, то просто создаем новую с одной частью
Long id = imdgProvider.getImdgIdGenerator().nextId();
;
pairOfSdfRequest.put(id, getPairByTableName(sdfTable, statementRequest));
}
}
return Optional.empty();
}
private Pair<StatementRequest, StatementRequest> getPairByTableName(SdfTable sdfTable, StatementRequest statementRequest) {
Pair<StatementRequest, StatementRequest> pair = null;
switch (sdfTable) {
case SDF_01 -> pair = new Pair<>(statementRequest, null);
case SDF_57 -> pair = new Pair<>(null, statementRequest);
case SDF_04 -> pair = new Pair<>(statementRequest, null);
case SDF_13 -> pair = new Pair<>(null, statementRequest);
}
return pair;
}
private Optional<Long> findUncompletedPairByTableName(SdfTable sdfTable) {
Optional<Long> uncompletedPair = Optional.empty();
switch (sdfTable) {
case SDF_01 ->
uncompletedPair = pairOfSdfRequest.entrySet().stream().filter(entry -> entry.getValue().getFirst() != null && entry.getValue().getSecond() == null).findFirst().map(Map.Entry::getKey);
case SDF_57 ->
uncompletedPair = pairOfSdfRequest.entrySet().stream().filter(entry -> entry.getValue().getFirst() == null && entry.getValue().getSecond() != null).findFirst().map(Map.Entry::getKey);
case SDF_04 ->
uncompletedPair = pairOfSdfRequest.entrySet().stream().filter(entry -> entry.getValue().getFirst() != null && entry.getValue().getSecond() == null).findFirst().map(Map.Entry::getKey);
case SDF_13 ->
uncompletedPair = pairOfSdfRequest.entrySet().stream().filter(entry -> entry.getValue().getFirst() == null && entry.getValue().getSecond() != null).findFirst().map(Map.Entry::getKey);
}
return uncompletedPair;
}
private AccountSdf01Request createAccountsRequest(Long sdf01GroupingId, List<AccountSdfRequestPart> accountRequests) { private AccountSdf01Request createAccountsRequest(Long sdf01GroupingId, List<AccountSdfRequestPart> accountRequests) {
AccountSdf01Request r = new AccountSdf01Request(); AccountSdf01Request r = new AccountSdf01Request();
r.setGroupingSdf01Id(sdf01GroupingId); r.setGroupingSdf01Id(sdf01GroupingId);

View file

@ -0,0 +1,74 @@
package ru.spcex.clearing.service.builder;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.util.Map;
public class PaymentInstructionBuilder {
private Registry registry;
private ImdgProvider imdgProvider;
public static PaymentInstructionBuilder builder(ImdgProvider imdgProvider, Registry registry) {
return new PaymentInstructionBuilder(imdgProvider, registry);
}
private PaymentInstructionBuilder(ImdgProvider imdgProvider, Registry registry) {
this.imdgProvider = imdgProvider;
this.registry = registry;
}
public PaymentInstruction build() {
PaymentInstruction paymentInstruction = new PaymentInstruction();
paymentInstruction.setSenderId(registry.getCompanyId());
paymentInstruction.setAddresseeId(registry.getCounterPartyId());
Imdg<CompanySymbols> companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
CompanySymbols companySymbols = companySymbolsImdg.getSingleObjectByFieldValues(Map.of(
"companyId", registry.getCompanyId(),
"companySymbol", CompanySymbol.BIC.getKey())
);
CompanySymbols counterCompanySymbols = companySymbolsImdg.getSingleObjectByFieldValues(Map.of(
"companyId", registry.getCounterPartyId(),
"companySymbol", CompanySymbol.BIC.getKey())
);
if (companySymbols != null) {
paymentInstruction.setPayeeBic(companySymbols.getCompanySymbolValue());
}
if (counterCompanySymbols != null) {
paymentInstruction.setAdresseeBic(counterCompanySymbols.getCompanySymbolValue());
}
Imdg<Company> companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
Company company = companyImdg.getSingleObjectByFieldValues(Map.of("companyId", registry.getCompanyId()));
if (company != null) {
paymentInstruction.setPayeeBankName(company.getShortName());
paymentInstruction.setAddresseeBankName(company.getShortName());
}
paymentInstruction.setSettlementDate(registry.getSettlementDate());
paymentInstruction.setCreditLeg_amount(registry.getBalance());
paymentInstruction.setDebitLeg_amount(registry.getBalance());
paymentInstruction.setCreditLeg_accountId(registry.getAccountId());
Imdg<Account> accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
Account account = accountImdg.getSingleObjectByID(registry.getAccountId());
if (account != null) {
paymentInstruction.setCreditLeg_account(account.getAccount());
}
paymentInstruction.setDebitLeg_accountId(registry.getAccountId());
// Account account = accountImdg.getSingleObjectByID(registry.get());
// paymentInstruction.setDebitLeg_account();
return paymentInstruction;
}
}

View file

@ -1,6 +1,7 @@
package ru.spcex.clearing.service.executors; package ru.spcex.clearing.service.executors;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.model.Result; import ru.spcex.clearing.service.model.Result;
import java.util.Collection; import java.util.Collection;
@ -8,5 +9,6 @@ import java.util.Collection;
public abstract class AbstractExecutor<T> { public abstract class AbstractExecutor<T> {
public abstract Result execute(Collection<T> sdf, StatementRequest statementRequest); public abstract Result execute(Collection<T> sdf, StatementRequest statementRequest);
public abstract String exportTableName(); public abstract String exportTableName();
public abstract boolean isNeedToSendCommandToExport(); public abstract boolean isNeedToSendCommand();
public abstract void sendCommand(KafkaSender kafkaSender, Result result);
} }

View file

@ -2,73 +2,107 @@ package ru.spcex.clearing.service.executors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.account.AccountBalance; import ru.clearing.classes.statics.data.account.ClearingAccount;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.misc.Currency;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.sdf.SDf01;
import ru.clearing.classes.statics.data.sdf.SDf02; import ru.clearing.classes.statics.data.sdf.SDf02;
import ru.clearing.classes.statics.data.security.Security;
import ru.clearing.classes.statics.data.statement.Statement; import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.error.ClearingErrorInternal;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.ContinueSessionBnRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.LoggingService; import ru.spcex.clearing.service.LoggingService;
import ru.spcex.clearing.service.model.Result; import ru.spcex.clearing.service.model.Result;
import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.clearing.session.stage.util.RegistryUtil;
import ru.spcex.platform.enumeration.*; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.number.BigDecimalUtil;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@Service @Service
public class Sdf01Executor extends AbstractExecutor<SDf01> { public class Sdf01Executor extends AbstractExecutor<SDf01> {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final static DateTimeFormatter datFormatter = DateTimeFormatter.ofPattern("dd.MM.yy");
private final Imdg<Statement> statementImdg; private final Imdg<Statement> statementImdg;
private final Imdg<Registry> registryImdg;
private final Function<SDf01, IValidator> sDf01Validator; private final Function<SDf01, IValidator> sDf01Validator;
private final LoggingService errorLogger;
private final Imdg<SDf02> sdf02Imdg;
private final ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private final IMessageResolver errorResolver; private final Imdg<ClearingAccount> clearingAccountImdg;
private final Imdg<AccountBalance> accountBalanceImdg; private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
private final Imdg<Security> securityImdg;
private final Imdg<Currency> currencyImdg;
private final Imdg<SDf02> sdf02Imdg;
private final IMessageResolver messageResolver;
public Sdf01Executor(Function<SDf01, IValidator> sDf01Validator, public Sdf01Executor(@Qualifier("sdf01ValidatorNew") Function<SDf01, IValidator> sDf01Validator,
LoggingService errorLogger, LoggingService errorLogger,
ImdgProvider imdgProvider, ImdgProvider imdgProvider,
IMessageResolver errorResolver) { IMessageResolver errorResolver, IMessageResolver messageResolver) {
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class);
; this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
this.sDf01Validator = sDf01Validator; this.sDf01Validator = sDf01Validator;
this.errorLogger = errorLogger;
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.errorResolver = errorResolver; this.messageResolver = messageResolver;
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
} }
//todo доделать контроль sdf01 и sdf57
@Override @Override
public String exportTableName() { public String exportTableName() {
return "DF-02"; return null;
} }
@Override @Override
public boolean isNeedToSendCommandToExport() { public boolean isNeedToSendCommand() {
return true; return true;
} }
@Override
public void sendCommand(KafkaSender kafkaSender, Result result) {
ContinueSessionBnRequest continueSessionBn = new ContinueSessionBnRequest();
continueSessionBn.setGenerationId(result.getGenerationId());
kafkaSender.sendRequestToQueue(Consts.CONTINUE_SESSION_BN_FIRST_PART, continueSessionBn);
ExportToFileRequest exportRequest = new ExportToFileRequest();
exportRequest.setSdfGroupId(result.getGenerationId());
exportRequest.setNameOfTable(exportTableName());
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest);
}
public Result execute(Collection<SDf01> sdf, StatementRequest statementRequest) { public Result execute(Collection<SDf01> sdf, StatementRequest statementRequest) {
Result result = new Result(); Result result = new Result();
Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId(); Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId();
@ -76,76 +110,85 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
for (SDf01 sdf01 : sdf) { for (SDf01 sdf01 : sdf) {
IValidator validator = sDf01Validator.apply(sdf01); IValidator validator = sDf01Validator.apply(sdf01);
Optional<EnumMessage> error = validator.tillFirstError(); Optional<EnumMessage> error = validator.tillFirstError();
Company company = validator.getStored(ValidationStored.Company); Company company = validator.getStored(ValidationStored.Sdf01Company);
Account account = validator.getStored(ValidationStored.Sdf01Account);
if (statementRequest.getAccountCreationResults().size() == 0 if (statementRequest.getAccountCreationResults().size() == 0
&& ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { && ClearingErrorInternal.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
//на данном шаге company существует -> getId ok //на данном шаге company существует -> getId ok
//формируем пакетный запрос на добавление account //формируем пакетный запрос на добавление account
//ответ придет в этот же метод, process //ответ придет в этот же метод, process
result.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId())); result.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId()));
log.info("account {} for sdf01.id={} not found - send request for creation", sdf01.getAccount(), sdf01.getId()); log.info("account {} for sdf01.id={} not found - send request for creation", sdf01.getAccount(), sdf01.getId());
continue; continue;
} else if (ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { } else if (ClearingErrorInternal.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
log.error("fatal error: resumed processing after generating accounts, but no account found for sdf01.id={}", sdf01.getId()); log.error("fatal error: resumed processing after generating accounts, but no account found for sdf01.id={}", sdf01.getId());
} }
if (error.isPresent()) { if (error.isPresent()) {
errorLogger.logError("sdf01.id={}", error.get(), sdf01.getId()); log.error("sdf01.id={} error: {}", sdf01.getId(), messageResolver.resolve(error.get()));
//fixme инициировать = команда для другого сервиса? sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup));
sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup)); sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup));
continue; continue;
} }
Statement statement = statementImdg.getSingleObjectByFieldValues(Map.of("account", sdf01.getAccount()));
if (statement == null) { Statement stmt = createSdf01Statement(sdf01, company, account);
statement = createFlow(sdf01,
company, SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup); //fixme тоже мб убрать
validator.getStored(ValidationStored.Account));
} else {
updateFlow(statement, sdf01,
validator.getStored(ValidationStored.Account));
}
SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup);
sdf02Imdg.insert(sdf02New); sdf02Imdg.insert(sdf02New);
statement.setOutSDfId(sdf02New.getId()); stmt.setOutSDfId(sdf02New.getId());
// AccountResult accountResult = accountBalanceService.createAccountBalance(statement.getAddresseeId(), statement.getAccountId(), statement.getAmount(), statementImdg.update(stmt);
// null/*statement.getCashMovementCurrencyCode()*/);
// if (accountResult.getError() != null) { Optional<EnumMessage> err = validateActiveness(company, account);
// statement.setErrorCodeId(accountResult.getError().getSubject().getId()); if (err.isEmpty()) {
// todo statement.setErrorText(errorResolver.resolve(accountResult.getError())); Consumer<Registry> update = rgs -> {
// } else { updateReg(stmt, rgs);
// accountBalanceImdg.insert(accountResult.getAccount()); //insert == update? registryImdg.update(rgs);
// statement.setOperationStatus(OperationStatus.Executed.getKey()); };
// } Consumer<RegistryDesignation> create = (dsgn) -> {
statementImdg.update(statement); Registry registry = createRegistryByStatement(stmt, company, account, dsgn);
Registry registryF = registry.clone();
registryF.setRegistryUnit(RegistryUnit.F.getKey());
registryF.setRegistryCode(RegistryUtil.clearingCode(registryF));
registryF.setId(imdgProvider.getImdgIdGenerator().nextId());
Registry registryB = registry.clone();
registryB.setRegistryUnit(RegistryUnit.B.getKey());
registryB.setRegistryCode(RegistryUtil.clearingCode(registryB));
registryB.setId(imdgProvider.getImdgIdGenerator().nextId());
registryImdg.insert(registry);
registryImdg.insert(registryF);
registryImdg.insert(registryB);
};
findReg(stmt, RegistryInstrumentType.M).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A));
findReg(stmt, RegistryInstrumentType.S).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.D));
stmt.setOperationStatus(OperationStatus.Executed.getKey());
} else {
stmt.setErrorCodeId(err.get().getSubject().getId()); // fixme ErrorText insert
stmt.setOperationStatus(OperationStatus.Rejected.getKey());
statementImdg.update(stmt);
}
} }
return result; return result;
} }
private Statement createFlow(SDf01 sdf01, Company company, Account account) { private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy");
Statement statement = new Statement(); private Statement createSdf01Statement(SDf01 sdf01, Company company, Account account) {
statement.setAddresseeId(company.getId()); Statement stmt = new Statement();
statement.setSenderId(Sender.Prc.getId()); stmt.setAddresseeId(company.getId());
statement.setCreated(Instant.now()); stmt.setAddresseeId(company.getId());
statement.setClearingDate(LocalDate.now()); stmt.setSenderId(Sender.Prc.getId());
statement.setStatementType(StatementType.full.getKey()); stmt.setStatementType(StatementType.full.getKey());
statement.setAccountId(account.getId()); stmt.setAccountId(account.getId());
statement.setAccount(sdf01.getAccount()); stmt.setAccount(account.getAccount());
statement.setInOutDirection(InOutDirection.in.getKey()); stmt.setInOutDirection(InOutDirection.in.getKey());
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter)); stmt.setSettlementDate(LocalDate.parse(sdf01.getDat(), formatter));
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder())); if (sdf01.getRemainder() != null) {
statement.setOperationStatus(OperationStatus.Pending.getKey()); stmt.setAmount(new BigDecimal(sdf01.getRemainder()));
statement.setInSDfId(sdf01.getId()); }
statement.setInOutSDfType(InOutSDfType.type1.getKey()); stmt.setOperationStatus(OperationStatus.Pending.getKey());
statementImdg.insert(statement); stmt.setInSDfId(sdf01.getId());
return statement; stmt.setInOutSDfType(InOutSDfType.type1.getKey());
} stmt.setCreated(Instant.now());
return stmt;
private void updateFlow(Statement statement, SDf01 sdf01, Account account) {
statement.setUpdated(Instant.now());
statement.setAccountId(account.getId());
statement.setAccount(sdf01.getAccount());
statement.setInOutDirection(InOutDirection.in.getKey());
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
statementImdg.update(statement);
} }
private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) { private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) {
@ -157,7 +200,6 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
return req; return req;
} }
private SDf02 createErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) { private SDf02 createErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) {
SDf02 sDf02 = new SDf02(); SDf02 sDf02 = new SDf02();
sDf02.setCurr_code(sdf01.getCurr_code()); sDf02.setCurr_code(sdf01.getCurr_code());
@ -200,4 +242,100 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
sDf02.setResult("OK!"); sDf02.setResult("OK!");
return sDf02; return sDf02;
} }
private Optional<EnumMessage> validateActiveness(Company company, Account account) {
if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
return Optional.of(new EnumMessage(ClearingError.CompanyNotActive, company.getId()));
}
if (!WorkflowStatus.Active.equalsByKey(account.getStatus())) {
return Optional.of(new EnumMessage(ClearingError.AccountNotActive, account.getId()));
}
return Optional.empty();
}
private Registry createRegistryByStatement(Statement statement, Company company, Account account, RegistryDesignation designation) {
Registry rgs = new Registry();
rgs.setCompanyId(statement.getAddresseeId());
rgs.setTradingCode(company.getTradingCode());
rgs.setClearingCode(company.getClearingCode());
rgs.setShortName(company.getShortName());
rgs.setFullName(company.getFullName());
rgs.setAccountId(account.getId());
rgs.setAccountType(account.getAccountType());
rgs.setAccount(account.getAccount());
rgs.setRegistryDesignation(designation.getKey());
rgs.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
ClearingAccount accountForStatement = clearingAccountImdg.getSingleObjectByID(statement.getAccountId());
if (accountForStatement != null) {
rgs.setRegistryCapacity(accountForStatement.getClearingAccountType());
}
rgs.setRegistryUnit(RegistryUnit.T.getKey());
rgs.setRegistryCode(RegistryUtil.clearingCode(rgs));
Collection<TradingClearingRegistry> tcrsByAccount = tradingClearingRegistryImdg.getCollectionObjectsByFieldValues(Map.of(
"moneyAccountId", statement.getAccountId()
));
if (!tcrsByAccount.isEmpty()) {
TradingClearingRegistry tcr = tcrsByAccount.iterator().next();
rgs.setTradingClearingRegistryId(tcr.getId());
rgs.setTradingClearingRegistry(tcr.getCode());
}
rgs.setRegistryStatus(RegistryStatus.PROC.getKey());
rgs.setSecurityId(statement.getSecurityId());
if (statement.getSecurityId() != null) {
Security security = securityImdg.getSingleObjectByID(statement.getSecurityId());
if (security != null) {
rgs.setSecuritySymbol(security.getSecuritySymbol());
}
}
InOutDirection inOutDirection = IEnumKey.getEnumByKey(InOutDirection.class, statement.getInOutDirection());
//считаю balance при создании нулевым и исхожу из этого
//При добавлении (на базе изменения statement по sDf57):
//Если значение statement.inOutDirection=IN, то:
//= текущее значение registry.balance + statement.amount
//
//Если значение statement.inOutDirection=OUT, то:
//= текущее значение registry.balance - statement.amount
switch (inOutDirection) {
case in -> rgs.setBalance(statement.getAmount());
case out -> rgs.setBalance(statement.getAmount().negate());
}
rgs.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme ! смотри описание и ссылка на начало html'ки
//fixme !rgs.setSettlementCode();
rgs.setTradingDate(statement.getSettlementDate()); //fixme ! today ?
rgs.setClearingDate(LocalDate.now());
//fixme rgs.setRefundDate();
//fixme rgs.setValueDate();
rgs.setContract(statement.getContract());
//создается на базе stmt, companyCred, accountDeb
rgs.setCounterPartyId(statement.getAddresseeId());
rgs.setCreated(Instant.now());
return rgs;
}
private void updateReg(Statement s, Registry r) {
InOutDirection direction = IEnumKey.getEnumByKey(InOutDirection.class, s.getInOutDirection());
switch (direction) {
case in -> r.setBalance(r.getBalance().add(s.getAmount()));
case out -> r.setBalance(r.getBalance().subtract(s.getAmount()));
}
r.setUpdated(Instant.now());
}
private Optional<Registry> findReg(Statement s, RegistryInstrumentType registryInstrumentType) {
RegistryTradingParams p = new RegistryTradingParams(
RegistryDesignation.A, registryInstrumentType, RegistryCapacity.A, RegistryUnit.T
);
String sql = RegistryCodeSqlBuilder.getInstance(p).build();
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
ImdgPredicate rgstrPredicate = pb.and(pb.sql(sql),
pb.sql(sql),
pb.equals("accountId", s.getAccountId()),
pb.equals("companyId", s.getAddresseeId())
);
return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate));
}
} }

View file

@ -0,0 +1,98 @@
package ru.spcex.clearing.service.executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.sdf.SDf04;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.model.Result;
import ru.spcex.platform.enumeration.RegistryDesignation;
import ru.spcex.platform.enumeration.RegistryInstrumentType;
import ru.spcex.platform.enumeration.RegistryUnit;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
@Service
public class Sdf04Executor extends AbstractExecutor<SDf04> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final ImdgProvider imdgProvider;
private final Imdg<Registry> registryImdg;
public Sdf04Executor(ImdgProvider imdgProvider) {
this.imdgProvider = imdgProvider;
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
}
@Override
public String exportTableName() {
return "";
}
@Override
public boolean isNeedToSendCommand() {
return false;
}
@Override
public void sendCommand(KafkaSender kafkaSender, Result result) {
}
public Result execute(Collection<SDf04> sdf, StatementRequest statementRequest) {
Result result = new Result();
Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId();
result.setGenerationId(generationIdForGroup);
for (SDf04 sdf04 : sdf) {
//обычно мы ищем по группу sdf04, здесь как будто всегда только одна запись, todo нужно прочекать этот момент
log.debug("Process sdf04 record; sdf04.id: {}", sdf04.getId());
Collection<String> fullNames = Collections.emptyList(); //fixme что значит registry.fullName=sDf04.(sbanknam1, sbanknam2 и т.д.)
Collection<Registry> registries = selectRegistryForSDF04(sdf04.getC_acc_cred(), fullNames);
registries.forEach(registry -> unlockRegistry(registry, new BigDecimal(sdf04.getPay_val())));
}
return result;
}
protected Collection<Registry> selectRegistryForSDF04(String account, Collection<String> fullNames) {
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
ImdgPredicate query = pb.and(
pb.and(
pb.equals("registryDesignation", RegistryDesignation.A.getKey()),
pb.equals("registryInstrumentType", RegistryInstrumentType.M.getKey()),
pb.or(pb.equals("registryUnit", RegistryUnit.F.getKey()),
pb.equals("registryUnit", RegistryUnit.B.getKey()))
),
pb.equals("account", account)
// ,
// pb.in("fullName", fullNames.toArray(new String[fullNames.size()]))
);
Collection<Registry> result = registryImdg.getCollectionObjectsByPredicate(query);
log.trace("Selected {} registry's by sql: {}", result.size(), query);
return result;
}
boolean unlockRegistry(Registry registry, BigDecimal value) {
if (RegistryUnit.F.equalsByKey(registry.getRegistryUnit())) {
if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO);
registry.setBalance(registry.getBalance().add(value));
return true;
} else if (RegistryUnit.B.equalsByKey(registry.getRegistryUnit())) {
if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO);
registry.setBalance(registry.getBalance().subtract(value));
return true;
} else {
log.warn("For registry {} registryUnit={} unlock operation not implemented.",
registry.getId(), registry.getRegistryUnit());
return false;
}
}
}

View file

@ -0,0 +1,105 @@
package ru.spcex.clearing.service.executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.sdf.SDf12;
import ru.clearing.classes.statics.data.sdf.SDf13;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.model.Result;
import ru.spcex.platform.enumeration.RegistryDesignation;
import ru.spcex.platform.enumeration.RegistryInstrumentType;
import ru.spcex.platform.enumeration.RegistryUnit;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import java.math.BigDecimal;
import java.util.Collection;
@Service
public class Sdf13Executor extends AbstractExecutor<SDf13> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<SDf12> sdf12Imdg;
private final ImdgProvider imdgProvider;
private final Imdg<Registry> registryImdg;
public Sdf13Executor(ImdgProvider imdgProvider) {
this.imdgProvider = imdgProvider;
this.sdf12Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf12, SDf12.class);
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
}
@Override
public String exportTableName() {
return "";
}
@Override
public boolean isNeedToSendCommand() {
return false;
}
@Override
public void sendCommand(KafkaSender kafkaSender, Result result) {
}
public Result execute(Collection<SDf13> sdf, StatementRequest statementRequest) {
Result result = new Result();
Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId();
result.setGenerationId(generationIdForGroup);
for (SDf13 sdf13 : sdf) {
//обычно мы ищем по группу sdf04, здесь как будто всегда только одна запись, todo нужно прочекать этот момент
SDf12 sDf12 = selectSdf12bySdf13(sdf13);
log.debug("Process sdf13 record; sdf13.id: {}", sdf13.getId());
Collection<Registry> registries = selectRegistryForSDF12(sDf12.getDepoCodeSender(), sDf12.getSecurityCode());
registries.forEach(registry -> unlockRegistry(registry, new BigDecimal(sDf12.getQuantity())));
}
return result;
}
protected SDf12 selectSdf12bySdf13(SDf13 sDf13) {
SDf12 sdf12 = sdf12Imdg.getSingleObjectByID(sDf13.getId());
log.trace("Selected sdf12 by sdf13");
return sdf12;
}
protected Collection<Registry> selectRegistryForSDF12(String account, String securityCode) {
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
ImdgPredicate query = pb.and(
pb.and(
pb.equals("registryDesignation", RegistryDesignation.A.getKey()),
pb.equals("registryInstrumentType", RegistryInstrumentType.M.getKey()),
pb.or(pb.equals("registryUnit", RegistryUnit.F.getKey()),
pb.equals("registryUnit", RegistryUnit.B.getKey()))
),
pb.equals("account", account),
pb.equals("securityCode", securityCode)
);
Collection<Registry> result = registryImdg.getCollectionObjectsByPredicate(query);
log.trace("Selected {} registry's by sql: {}", result.size(), query);
return result;
}
boolean unlockRegistry(Registry registry, BigDecimal value) {
if (RegistryUnit.F.equalsByKey(registry.getRegistryUnit())) {
if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO);
registry.setBalance(registry.getBalance().add(value));
return true;
} else if (RegistryUnit.B.equalsByKey(registry.getRegistryUnit())) {
if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO);
registry.setBalance(registry.getBalance().subtract(value));
return true;
} else {
log.warn("For registry {} registryUnit={} unlock operation not implemented.",
registry.getId(), registry.getRegistryUnit());
return false;
}
}
}

View file

@ -1,20 +1,27 @@
package ru.spcex.clearing.service.executors; package ru.spcex.clearing.service.executors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.account.AccountBalance; import ru.clearing.classes.statics.data.account.AccountBalance;
import ru.clearing.classes.statics.data.account.ClearingAccount;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.misc.Currency;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.sdf.SDf02; import ru.clearing.classes.statics.data.sdf.SDf02;
import ru.clearing.classes.statics.data.sdf.SDf57; import ru.clearing.classes.statics.data.sdf.SDf57;
import ru.clearing.classes.statics.data.security.Security; import ru.clearing.classes.statics.data.security.Security;
import ru.clearing.classes.statics.data.statement.Statement; import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.ContinueSessionBnRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.LoggingService; import ru.spcex.clearing.service.LoggingService;
import ru.spcex.clearing.service.model.Result; import ru.spcex.clearing.service.model.Result;
import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.service.validation.ValidationStored;
@ -36,6 +43,7 @@ import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
@ -53,8 +61,12 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
private final ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private final IMessageResolver errorResolver; private final IMessageResolver errorResolver;
private final Imdg<AccountBalance> accountBalanceImdg; private final Imdg<AccountBalance> accountBalanceImdg;
private final Imdg<ClearingAccount> clearingAccountImdg;
private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
private final Imdg<Security> securityImdg; private final Imdg<Security> securityImdg;
private final Imdg<Currency> currencyImdg;
private final IMessageResolver messageResolver; private final IMessageResolver messageResolver;
// private final Pair<>
public Sdf57Executor(@Qualifier("sdf57Validator") Function<SDf57, IValidator> sDf57Validator, public Sdf57Executor(@Qualifier("sdf57Validator") Function<SDf57, IValidator> sDf57Validator,
LoggingService errorLogger, LoggingService errorLogger,
@ -64,6 +76,9 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class); this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class);
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
this.sDf57Validator = sDf57Validator; this.sDf57Validator = sDf57Validator;
this.errorLogger = errorLogger; this.errorLogger = errorLogger;
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
@ -72,15 +87,24 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class); this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
} }
//todo доделать контроль sdf01 и sdf57
@Override @Override
public String exportTableName() { public String exportTableName() {
return null; return null;
} }
@Override @Override
public boolean isNeedToSendCommandToExport() { public boolean isNeedToSendCommand() {
return false; return true;
}//no need... }
@Override
public void sendCommand(KafkaSender kafkaSender, Result result) {
ContinueSessionBnRequest continueSessionBn = new ContinueSessionBnRequest();
continueSessionBn.setGenerationId(result.getGenerationId());
kafkaSender.sendRequestToQueue(Consts.CONTINUE_SESSION_BN_FIRST_PART, continueSessionBn);
}
//V - Изменение statement по sDf57 //V - Изменение statement по sDf57
// //
@ -127,9 +151,9 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
Account accountCred = validator.getStored(ValidationStored.Sdf57AccountCred); Account accountCred = validator.getStored(ValidationStored.Sdf57AccountCred);
//адресат CREDIT / владелец DEBIT //адресат CREDIT / владелец DEBIT
Optional<Statement> statementDeb = createStatementIfNeeded.apply(companyDeb, accountDeb, InOutDirection.in); Optional<Statement> statementDeb = createStatementIfNeeded.apply(companyDeb, accountDeb, InOutDirection.out);
//адресат DEBIT / владелец CREDIT //адресат DEBIT / владелец CREDIT
Optional<Statement> statementCred = createStatementIfNeeded.apply(companyCred, accountCred, InOutDirection.out); Optional<Statement> statementCred = createStatementIfNeeded.apply(companyCred, accountCred, InOutDirection.in);
Consumer<StmtCmpAcc> createRegistryIfNeeded = stmtCmpAcc -> { Consumer<StmtCmpAcc> createRegistryIfNeeded = stmtCmpAcc -> {
Statement stmt = stmtCmpAcc.statement(); Statement stmt = stmtCmpAcc.statement();
@ -145,12 +169,25 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
}; };
Consumer<RegistryDesignation> create = (dsgn) -> { Consumer<RegistryDesignation> create = (dsgn) -> {
Registry registry = createRegistryByStatement(stmt, company, account, dsgn); Registry registry = createRegistryByStatement(stmt, company, account, dsgn);
Registry registryF = registry.clone();
registryF.setRegistryUnit(RegistryUnit.F.getKey());
registryF.setRegistryCode(RegistryUtil.clearingCode(registryF));
registryF.setId(imdgProvider.getImdgIdGenerator().nextId());
Registry registryB = registry.clone();
registryB.setRegistryUnit(RegistryUnit.B.getKey());
registryB.setRegistryCode(RegistryUtil.clearingCode(registryB));
registryB.setId(imdgProvider.getImdgIdGenerator().nextId());
registryImdg.insert(registry); registryImdg.insert(registry);
registryImdg.insert(registryF);
registryImdg.insert(registryB);
}; };
//todo понять что происходит со инициатором/контрагентом, особенно если у нас только один Statement //todo понять что происходит со инициатором/контрагентом, особенно если у нас только один Statement
findReg(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A)); findReg(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A));
findReg(stmt, RegistryDesignation.D).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.D)); if (!StringUtils.isEmpty(sdf57.getSpecif()) && sdf57.getSpecif().contains("№")) {
//todo доделать 11. Идентификация средств УК на клиринговом счете
findReg(stmt, RegistryDesignation.D).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.D));
}
stmt.setOperationStatus(OperationStatus.Executed.getKey()); stmt.setOperationStatus(OperationStatus.Executed.getKey());
} else { } else {
stmt.setErrorCodeId(err.get().getSubject().getId()); // fixme ErrorText insert stmt.setErrorCodeId(err.get().getSubject().getId()); // fixme ErrorText insert
@ -181,9 +218,14 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
Statement statement = new Statement(); Statement statement = new Statement();
statement.setAddresseeId(companyDeb.getId()); statement.setAddresseeId(companyDeb.getId());
statement.setSenderId(Sender.Prc.getId()); statement.setSenderId(Sender.Prc.getId());
statement.setStatementType(StatementType.full.getKey()); statement.setStatementType(StatementType.incr.getKey());
statement.setContract(getContractFromSpecif(sdf57.getSpecif())); statement.setContract(getContractFromSpecif(sdf57.getSpecif()));
statement.setAccountId(accountDeb.getId()); statement.setAccountId(accountDeb.getId());
Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", "RUB"));
if (currency != null) {
statement.setSecurityId(currency.getId());
}
statement.setAccount(accountDeb.getAccount()); statement.setAccount(accountDeb.getAccount());
statement.setInOutDirection(inOutDirection.getKey()); statement.setInOutDirection(inOutDirection.getKey());
statement.setSettlementDate(payDate(sdf57.getPay_date())); statement.setSettlementDate(payDate(sdf57.getPay_date()));
@ -206,11 +248,23 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
rgs.setAccount(account.getAccount()); rgs.setAccount(account.getAccount());
rgs.setRegistryDesignation(designation.getKey()); rgs.setRegistryDesignation(designation.getKey());
rgs.setRegistryInstrumentType(RegistryInstrumentType.M.getKey()); rgs.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
rgs.setRegistryCapacity(RegistryCapacity.A.getKey());
ClearingAccount accountForStatement = clearingAccountImdg.getSingleObjectByID(statement.getAccountId());
if (accountForStatement != null) {
rgs.setRegistryCapacity(accountForStatement.getClearingAccountType());
}
rgs.setRegistryUnit(RegistryUnit.T.getKey()); rgs.setRegistryUnit(RegistryUnit.T.getKey());
rgs.setRegistryCode(RegistryUtil.clearingCode(rgs)); rgs.setRegistryCode(RegistryUtil.clearingCode(rgs));
//rgs.setTradingClearingRegistryId(); //todo !
//rgs.setTradingClearingRegistry(); //todo ! Collection<TradingClearingRegistry> tcrsByAccount = tradingClearingRegistryImdg.getCollectionObjectsByFieldValues(Map.of(
"moneyAccountId", statement.getAccountId()
));
if (!tcrsByAccount.isEmpty()) {
TradingClearingRegistry tcr = tcrsByAccount.iterator().next();
rgs.setTradingClearingRegistryId(tcr.getId());
rgs.setTradingClearingRegistry(tcr.getCode());
}
rgs.setRegistryStatus(RegistryStatus.PROC.getKey()); rgs.setRegistryStatus(RegistryStatus.PROC.getKey());
rgs.setSecurityId(statement.getSecurityId()); rgs.setSecurityId(statement.getSecurityId());
if (statement.getSecurityId() != null) { if (statement.getSecurityId() != null) {

View file

@ -0,0 +1,215 @@
package ru.spcex.clearing.service.executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.account.AccountBalance;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.sdf.SDf01;
import ru.clearing.classes.statics.data.sdf.SDf02;
import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.LoggingService;
import ru.spcex.clearing.service.model.Result;
import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.number.BigDecimalUtil;
import ru.spcex.platform.utils.validation.IValidator;
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
@Service
public class SdfLegacyExecutor extends AbstractExecutor<SDf01> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final static DateTimeFormatter datFormatter = DateTimeFormatter.ofPattern("dd.MM.yy");
private final Imdg<Statement> statementImdg;
private final Function<SDf01, IValidator> sDf01Validator;
private final LoggingService errorLogger;
private final Imdg<SDf02> sdf02Imdg;
private final ImdgProvider imdgProvider;
private final IMessageResolver errorResolver;
private final Imdg<AccountBalance> accountBalanceImdg;
public SdfLegacyExecutor(@Qualifier("sdf01Validator") Function<SDf01, IValidator> sDf01Validator,
LoggingService errorLogger,
ImdgProvider imdgProvider,
IMessageResolver errorResolver) {
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
;
this.sDf01Validator = sDf01Validator;
this.errorLogger = errorLogger;
this.imdgProvider = imdgProvider;
this.errorResolver = errorResolver;
}
@Override
public String exportTableName() {
return "DF-02";
}
@Override
public boolean isNeedToSendCommand() {
return true;
}
@Override
public void sendCommand(KafkaSender kafkaSender, Result result) {
ExportToFileRequest exportRequest = new ExportToFileRequest();
exportRequest.setSdfGroupId(result.getGenerationId());
exportRequest.setNameOfTable(exportTableName());
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest);
}
public Result execute(Collection<SDf01> sdf, StatementRequest statementRequest) {
Result result = new Result();
Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId();
result.setGenerationId(generationIdForGroup);
for (SDf01 sdf01 : sdf) {
IValidator validator = sDf01Validator.apply(sdf01);
Optional<EnumMessage> error = validator.tillFirstError();
Company company = validator.getStored(ValidationStored.Company);
if (statementRequest.getAccountCreationResults().size() == 0
&& ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
//на данном шаге company существует -> getId ok
//формируем пакетный запрос на добавление account
//ответ придет в этот же метод, process
result.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId()));
log.info("account {} for sdf01.id={} not found - send request for creation", sdf01.getAccount(), sdf01.getId());
continue;
} else if (ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
log.error("fatal error: resumed processing after generating accounts, but no account found for sdf01.id={}", sdf01.getId());
}
if (error.isPresent()) {
errorLogger.logError("sdf01.id={}", error.get(), sdf01.getId());
sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup));
continue;
}
Statement statement = statementImdg.getSingleObjectByFieldValues(Map.of("account", sdf01.getAccount()));
if (statement == null) {
statement = createFlow(sdf01,
company,
validator.getStored(ValidationStored.Account));
} else {
updateFlow(statement, sdf01,
validator.getStored(ValidationStored.Account));
}
SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup);
sdf02Imdg.insert(sdf02New);
statement.setOutSDfId(sdf02New.getId());
// AccountResult accountResult = accountBalanceService.createAccountBalance(statement.getAddresseeId(), statement.getAccountId(), statement.getAmount(),
// null/*statement.getCashMovementCurrencyCode()*/);
// if (accountResult.getError() != null) {
// statement.setErrorCodeId(accountResult.getError().getSubject().getId());
// todo statement.setErrorText(errorResolver.resolve(accountResult.getError()));
// } else {
// accountBalanceImdg.insert(accountResult.getAccount()); //insert == update?
// statement.setOperationStatus(OperationStatus.Executed.getKey());
// }
statementImdg.update(statement);
}
return result;
}
private Statement createFlow(SDf01 sdf01, Company company, Account account) {
Statement statement = new Statement();
statement.setAddresseeId(company.getId());
statement.setSenderId(Sender.Prc.getId());
statement.setCreated(Instant.now());
statement.setClearingDate(LocalDate.now());
statement.setStatementType(StatementType.full.getKey());
statement.setAccountId(account.getId());
statement.setAccount(sdf01.getAccount());
statement.setInOutDirection(InOutDirection.in.getKey());
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
statement.setOperationStatus(OperationStatus.Pending.getKey());
statement.setInSDfId(sdf01.getId());
statement.setInOutSDfType(InOutSDfType.type1.getKey());
statementImdg.insert(statement);
return statement;
}
private void updateFlow(Statement statement, SDf01 sdf01, Account account) {
statement.setUpdated(Instant.now());
statement.setAccountId(account.getId());
statement.setAccount(sdf01.getAccount());
statement.setInOutDirection(InOutDirection.in.getKey());
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
statementImdg.update(statement);
}
private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) {
AccountSdfRequestPart req = new AccountSdfRequestPart();
req.setAccount(account);
req.setCompanyId(companyId);
req.setAccountType(AccountType.Clrn.getKey());
req.setSdfId(sdf01Id);
return req;
}
private SDf02 createErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) {
SDf02 sDf02 = new SDf02();
sDf02.setCurr_code(sdf01.getCurr_code());
sDf02.setAccount(sdf01.getAccount());
sDf02.setRemainder(sdf01.getRemainder());
sDf02.setDeal(sdf01.getDeal());
sDf02.setAcc_code(sdf01.getAcc_code());
sDf02.setDat(sdf01.getDat());
sDf02.setMarket(sdf01.getMarket());
sDf02.setAcc_name(sdf01.getAcc_name());
sDf02.setAcc_type(sdf01.getAcc_type());
sDf02.setSumengage(sdf01.getSumengage());
sDf02.setSumunblock(sdf01.getSumunblock());
sDf02.setFile_type(sdf01.getFile_type());
sDf02.setInSDfId(sdf01.getId());
String errorId = error.getSubject().getId().toString();
sDf02.setResult(errorId.substring(errorId.length() - 3));
sDf02.setGenerationId(generationIdForGroup);
sDf02.setGenerationTime(Instant.now());
return sDf02;
}
private SDf02 createSuccessSdf02(SDf01 sdf01, Long generationIdForGroup) {
SDf02 sDf02 = new SDf02();
sDf02.setCurr_code(sdf01.getCurr_code());
sDf02.setAccount(sdf01.getAccount());
sDf02.setRemainder(sdf01.getRemainder());
sDf02.setDeal(sdf01.getDeal());
sDf02.setAcc_code(sdf01.getAcc_code());
sDf02.setDat(sdf01.getDat());
sDf02.setMarket(sdf01.getMarket());
sDf02.setAcc_name(sdf01.getAcc_name());
sDf02.setAcc_type(sdf01.getAcc_type());
sDf02.setSumengage(sdf01.getSumengage());
sDf02.setSumunblock(sdf01.getSumunblock());
sDf02.setFile_type(sdf01.getFile_type());
sDf02.setInSDfId(sdf01.getId());
sDf02.setGenerationId(generationIdForGroup);
sDf02.setGenerationTime(Instant.now());
sDf02.setResult("OK!");
return sDf02;
}
}

View file

@ -0,0 +1,93 @@
package ru.spcex.clearing.service.validation;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.sdf.SDf01;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.error.ClearingErrorInternal;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.enumeration.AccType;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.text.TextUtil;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
public enum Sdf01NewValidationRule implements IValidationRule<ImdgValidationContext<SDf01>> {
CompanyPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
SDf01 sdf01 = context.getValidatedObject();
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
if (TextUtil.isEmpty(sdf01.getDeal())) {
of(ClearingError.CompanyNotFoundB, sdf01.getDeal());
}
Company company = companyImdg.getSingleObjectBySQL("tradingCode = '" + sdf01.getDeal() + "'");
if (company == null) {
of(ClearingError.CompanyNotFoundB, sdf01.getDeal());
}
context.storeObject(ValidationStored.Sdf01Company, company);
return empty();
}
}, AccountType() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
SDf01 sdf01 = context.getValidatedObject();
if (!IEnumKey.contains(sdf01.getAcc_type(), AccType.A, AccType.B)) {
of(ClearingError.AccountWrongType, sdf01.getAcc_type());
}
return empty();
}
}, AccountPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
SDf01 sdf01 = context.getValidatedObject();
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
Account acc = accountImdg.getSingleObjectBySQL("account = '" + sdf01.getAccount()
+ "' and accountType='" + ru.spcex.platform.enumeration.AccountType.Clrn.getKey() + "'");
if (acc == null) {
return of (ClearingErrorInternal.AccountNotPresent, sdf01.getAccount());
}
context.storeObject(ValidationStored.Sdf01Account, acc);
return empty();
}
}, CurrencyCode() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
SDf01 sdf01 = context.getValidatedObject();
if (!ru.spcex.platform.enumeration.CurrencyCode.RUR.equalsByKey(sdf01.getCurr_code())) {
return of(ClearingError.CurrencyNotFound, sdf01.getCurr_code());
}
return empty();
}
}, DatIsCurrentDt() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy");
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
SDf01 sdf01 = context.getValidatedObject();
LocalDate parse;
try {
parse = LocalDate.parse(sdf01.getDat(), formatter);
} catch (Exception e) {
return of(ClearingError.OperationCanBeRunForTodayOnly, sdf01.getDat());
}
if (!LocalDate.now().equals(parse)) {
return of(ClearingError.OperationCanBeRunForTodayOnly, sdf01.getDat());
}
return empty();
}
};
@Override
public String ruleName() {
return "Sdf01NewValidationRule." + name();
}
}

View file

@ -4,5 +4,7 @@ public enum ValidationStored {
STradesCompany, STradesCounterCompany, STradesSecurity, STradesTradingClearingRegistry, STradesCompany, STradesCounterCompany, STradesSecurity, STradesTradingClearingRegistry,
Account, Company, Account, Company,
Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred,
Sdf01Company, Sdf01Account
} }

View file

@ -33,6 +33,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
private final ObligationAdmission obligationsAdmission; private final ObligationAdmission obligationsAdmission;
private final InclusionObligations inclusionObligations; private final InclusionObligations inclusionObligations;
private final InspectionObligations inspectionObligations;
private final FormingRegistersOnOS formingRegistersOnOS; private final FormingRegistersOnOS formingRegistersOnOS;
private final FormingPaymentInstruction formingPaymentInstruction; private final FormingPaymentInstruction formingPaymentInstruction;
private final UnlockResources unlockResources; private final UnlockResources unlockResources;
@ -51,7 +52,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
FormingRegistersOnOS formingRegistersOnOS, FormingRegistersOnOS formingRegistersOnOS,
FormingPaymentInstruction formingPaymentInstruction, FormingPaymentInstruction formingPaymentInstruction,
UnlockResources unlockResources, UnlockResources unlockResources,
FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver) { FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver, InspectionObligations inspectionObligations) {
super(imdgProvider, messageResolver); super(imdgProvider, messageResolver);
this.balanceRevise = balanceRevise; this.balanceRevise = balanceRevise;
this.dealsPrepare = dealsPrepare; this.dealsPrepare = dealsPrepare;
@ -64,6 +65,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
this.finishingSession = finishingSession; this.finishingSession = finishingSession;
this.endStageNotification = endStageNotification; this.endStageNotification = endStageNotification;
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
this.inspectionObligations = inspectionObligations;
} }
@Override @Override
@ -87,14 +89,14 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
} }
} }
public void continueSession(BaseRequest<?> req) { public void continueSessionFirstPart(BaseRequest<?> req) {
try { try {
if (!checkStage(TaskType.StartRevise)) { if (!checkStage(TaskType.StartRevise)) {
log.error("cannot continue session, current stage is {}", currStage.get()); log.error("cannot continue session, current stage is {}", currStage.get());
throw new StageException(); throw new StageException();
} }
//stage 0 // //stage 0
runStage(TaskType.ContinueRevise, balanceRevise); // runStage(TaskType.ContinueRevise, balanceRevise);
//stage 1 //stage 1
StageResult<List<ExecutionCommon>> dealsPreparationResult; StageResult<List<ExecutionCommon>> dealsPreparationResult;
{ {
@ -116,17 +118,22 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
{ {
InspectionPoolPayload companyIdPayload = new InspectionPoolPayload(); InspectionPoolPayload companyIdPayload = new InspectionPoolPayload();
companyIdPayload.setProcessedCompanyId(currSession.getCompanyId()); companyIdPayload.setProcessedCompanyId(currSession.getCompanyId());
runStage(TaskType.InspectionObligations, companyIdPayload, inclusionObligations); runStage(TaskType.InspectionObligations, companyIdPayload, inspectionObligations);
} }
//stage 6 //stage 6
runStage(TaskType.FormingRegistersOnOS, formingRegistersOnOS); //returns Collection<Registry> runStage(TaskType.FormingRegistersOnOS, formingRegistersOnOS); //returns Collection<Registry>
//stage 7 //stage 7
runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction); runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction);
//stage 8 } catch (StageException e) {
{ //already logged
UnlockResourcesPayload unlockResourcesPayload = new UnlockResourcesPayload(); }
//todo set arguments }
runStage(TaskType.UnlockResources, unlockResourcesPayload, unlockResources); //returns Collection<Registry>
public void continueSessionSecondPart(BaseRequest<?> req) {
try {
if (!checkStage(TaskType.FormingPaymentInstruction)) {
log.error("cannot continue session, current stage is {}", currStage.get());
throw new StageException();
} }
//stage 9 //stage 9
{ {

View file

@ -0,0 +1,165 @@
package ru.spcex.clearing.session.stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
import ru.clearing.classes.statics.data.execution.ExecutionFond;
import ru.clearing.classes.statics.data.misc.Session;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.session.stage.impl.*;
import ru.spcex.clearing.session.stage.task.*;
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
import ru.spcex.platform.enumeration.MarketType;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.SessionStatus;
import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import java.util.List;
@Service
public class PrimaryAuctionT0Session extends AbstractSession implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final BalanceRevise balanceRevise;
private final DealsPrepare dealsPrepare;
private final RequirementsAndObligationCreation requirementsAndObligationCreation;
private final ObligationAdmission obligationsAdmission;
private final InclusionObligations inclusionObligations;
private final FormingRegistersOnOS formingRegistersOnOS;
private final FormingPaymentInstruction formingPaymentInstruction;
private final UnlockResources unlockResources;
private final FinishingSession finishingSession;
private final EndStageNotification endStageNotification;
private final Imdg<ExecutionFond> executionFondImdg;
public PrimaryAuctionT0Session(
ImdgProvider imdgProvider,
BalanceRevise balanceRevise,
DealsPrepare dealsPrepare,
RequirementsAndObligationCreation requirementsAndObligationCreation,
ObligationAdmission obligationsAdmission,
InclusionObligations inclusionObligations,
FormingRegistersOnOS formingRegistersOnOS,
FormingPaymentInstruction formingPaymentInstruction,
UnlockResources unlockResources,
FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver) {
super(imdgProvider, messageResolver);
this.balanceRevise = balanceRevise;
this.dealsPrepare = dealsPrepare;
this.requirementsAndObligationCreation = requirementsAndObligationCreation;
this.obligationsAdmission = obligationsAdmission;
this.inclusionObligations = inclusionObligations;
this.formingRegistersOnOS = formingRegistersOnOS;
this.formingPaymentInstruction = formingPaymentInstruction;
this.unlockResources = unlockResources;
this.finishingSession = finishingSession;
this.endStageNotification = endStageNotification;
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
}
@Override
public void afterPropertiesSet() throws Exception {
dealsPrepare.searchForExecutions(ExecutionType.ExecutionFond);
ImdgPredicateBuilder execFondPb = executionFondImdg.predicateBuilder();
dealsPrepare.addExecutionFondCondition(execFondPb.regex("settlementCode", "^T0.*$"));
dealsPrepare.addExecutionFondCondition(execFondPb.equals("marketType", MarketType.PRMR.getKey()));
}
public void runSession(BaseRequest<?> req) {
if (!startSession()) {
return;
}
StageResult<?> submit = balanceRevise.submit(new Task<>(TaskType.StartRevise, null));
if (!submit.success) {
log.error("stage {} error={}", balanceRevise.getClass().getSimpleName(), messageResolver.resolve(submit.error));
endSession();
} else {
log.info("stage BalanceRevise success, waiting for a response from kafka");
}
}
public void continueSession(BaseRequest<?> req) {
try {
if (!checkStage(TaskType.StartRevise)) {
log.error("cannot continue session, current stage is {}", currStage.get());
throw new StageException();
}
//stage 0
runStage(TaskType.ContinueRevise, balanceRevise);
//stage 1
StageResult<List<ExecutionCommon>> dealsPreparationResult;
{
DealsPreparePayload payload = new DealsPreparePayload();
payload.setSessionId(currSession.getId());
dealsPreparationResult = runStage(TaskType.DealsPrepare , payload, dealsPrepare);
}
//stage 2
runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation);
//stage 3
runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission);
//stage 4
{
InclusionToPoolPayload inclusionToPoolPayload = new InclusionToPoolPayload();
inclusionToPoolPayload.setSessionType(currSession.getSessionType());
runStage(TaskType.InclusionToPool, inclusionToPoolPayload, inclusionObligations);
}
//stage 5
{
InspectionPoolPayload companyIdPayload = new InspectionPoolPayload();
companyIdPayload.setProcessedCompanyId(currSession.getCompanyId());
runStage(TaskType.InspectionObligations, companyIdPayload, inclusionObligations);
}
//stage 6
runStage(TaskType.FormingRegistersOnOS, formingRegistersOnOS); //returns Collection<Registry>
//stage 7
runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction);
//stage 8
{
UnlockResourcesPayload unlockResourcesPayload = new UnlockResourcesPayload();
//todo set arguments
runStage(TaskType.UnlockResources, unlockResourcesPayload, unlockResources); //returns Collection<Registry>
}
//stage 9
{
FinishingSessionPayload payload = new FinishingSessionPayload();
payload.setSessionId(currSession.getId());
runStage(TaskType.FinishingSession, payload, finishingSession);
}
{
EndStageNotificationPayload payload = new EndStageNotificationPayload();
payload.setSection(currSession.getSection());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
}
} catch (StageException e) {
//already logged
}
}
private boolean startSession() {
synchronized (this.currStage) {
if (this.currStage.get() != null) {
log.info("already running session.id={}", this.currSession.getId());
return false;
} else {
Session newSession = new Session();
newSession.setSection(Section.FOND.getKey());
newSession.setSessionType(SessionType.IPOT.getKey());
newSession.setSessionStatus(SessionStatus.CLRN.getKey());
//todo companyId/securityId/userId передается из сообщения очереди
sessionImdg.insert(newSession);
currSession = newSession;
log.info("started new session.id={}", this.currSession.getId());
currStage.set(TaskType.StartRevise);
return true;
}
}
}
}

View file

@ -19,6 +19,7 @@ import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.imdg.api.predicate.specific.StatementRevisePredicate; import ru.spcex.platform.imdg.api.predicate.specific.StatementRevisePredicate;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
@ -58,7 +59,8 @@ public class BalanceRevise implements ISessionStage {
return sendSdfs(); return sendSdfs();
} }
case ContinueRevise -> { case ContinueRevise -> {
cashFlow(); //((SdfClearingRequest) task.getData()).getGroupId() if needed //больше не используются, удалить после проверки
cashFlow(); //((SdfClearingRequest) task.getData()).getGroupId() if needed //todo убрать это отсюда
return revise(); return revise();
} }
default -> throw new IllegalStateException("unknown task " + task.getTaskType()); default -> throw new IllegalStateException("unknown task " + task.getTaskType());
@ -93,32 +95,31 @@ public class BalanceRevise implements ISessionStage {
Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL); Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL);
for (Statement stmt : stmts) { for (Statement stmt : stmts) {
String unformatted = "registry_designation = '%s' " + String unformatted = "%s and account = '%s' and securityId = %d";
"and registry_instrument_type = '%s' " +
"and registry_unit = '%s' " + RegistryTradingParams registryAMT = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
"and account = '%s' " + null, RegistryUnit.T);
"and securityId = %d"; RegistryTradingParams registryAMF = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
null, RegistryUnit.F);
RegistryTradingParams registryAMB = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
null, RegistryUnit.B);
String registrySqlAMT = String.format(unformatted, String registrySqlAMT = String.format(unformatted,
RegistryDesignation.A.getKey(), RegistryCodeSqlBuilder.getInstance(registryAMT).build(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.T.getKey(),
stmt.getAccount(), stmt.getAccount(),
stmt.getSecurityId() stmt.getSecurityId()
); );
String registrySqlAMF = String.format(unformatted, String registrySqlAMF = String.format(unformatted,
RegistryDesignation.A.getKey(), RegistryCodeSqlBuilder.getInstance(registryAMF).build(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.F.getKey(),
stmt.getAccount(), stmt.getAccount(),
stmt.getSecurityId() stmt.getSecurityId()
); );
String registrySqlAMB = String.format(unformatted, String registrySqlAMB = String.format(unformatted,
RegistryDesignation.A.getKey(), RegistryCodeSqlBuilder.getInstance(registryAMB).build(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.B.getKey(),
stmt.getAccount(), stmt.getAccount(),
stmt.getSecurityId() stmt.getSecurityId()
); );
Registry rgsAMT = registryImdg.getSingleObjectBySQL(registrySqlAMT); Registry rgsAMT = registryImdg.getSingleObjectBySQL(registrySqlAMT);
Registry rgsAMF = registryImdg.getSingleObjectBySQL(registrySqlAMF); Registry rgsAMF = registryImdg.getSingleObjectBySQL(registrySqlAMF);
Registry rgsAMB = registryImdg.getSingleObjectBySQL(registrySqlAMB); Registry rgsAMB = registryImdg.getSingleObjectBySQL(registrySqlAMB);
@ -152,14 +153,11 @@ public class BalanceRevise implements ISessionStage {
InOutSDfType.type1.getKey(), OperationStatus.Pending.getKey(), StatementType.full.getKey()); InOutSDfType.type1.getKey(), OperationStatus.Pending.getKey(), StatementType.full.getKey());
Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL); Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL);
for (Statement stmt : stmts) { for (Statement stmt : stmts) {
String registrySqlAMT = String.format("registry_designation = '%s' " +
"and registry_instrument_type = '%s' " + RegistryTradingParams registryAMT = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
"and registry_unit = '%s' " + null, RegistryUnit.T);
"and account = '%s' " + String registrySqlAMT = String.format("%s and account = '%s' and securityId = %d",
"and securityId = %d", RegistryCodeSqlBuilder.getInstance(registryAMT).build(),
RegistryDesignation.A.getKey(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.T.getKey(),
stmt.getAccount(), stmt.getAccount(),
stmt.getSecurityId() stmt.getSecurityId()
); );
@ -175,7 +173,7 @@ public class BalanceRevise implements ISessionStage {
} }
private void newSDf56(Statement statement) { private void newSDf56(Statement statement) {
log.debug("GALB request received; creating sdf56"); log.debug("creating sdf56");
SDf56 sDf56 = new SDf56(); SDf56 sDf56 = new SDf56();
sDf56.setNumber(idGenerator.nextId().toString()); sDf56.setNumber(idGenerator.nextId().toString());
Instant now = Instant.now(); Instant now = Instant.now();

View file

@ -12,12 +12,11 @@ import ru.spcex.clearing.session.stage.ISessionStage;
import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.StageResult;
import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.Task;
import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; import ru.spcex.clearing.session.stage.task.InspectionPoolPayload;
import ru.spcex.platform.enumeration.RegistryDesignation; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.enumeration.RegistryInstrumentType;
import ru.spcex.platform.enumeration.RegistryUnit;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
@ -62,15 +61,18 @@ public class InspectionObligations implements ISessionStage {
private StageResult inspectionPool(Long processedCompanyId) { private StageResult inspectionPool(Long processedCompanyId) {
String sqlCondition = String.format("registryDesignation in ('%s', '%s') and " + RegistryTradingParams registryTradingParamsOST = new RegistryTradingParams(RegistryDesignation.O,
"registryInstrumentType in ('%s', '%s') and " + RegistryInstrumentType.S,
"registryUnit = '%s' and " + null,
"registryStatus = '%s' and " + RegistryUnit.T);
"settlementDate = '%s'", RegistryTradingParams registryTradingParamsTMT = new RegistryTradingParams(RegistryDesignation.T,
RegistryDesignation.O.getKey(), RegistryDesignation.T.getKey(), RegistryInstrumentType.M,
RegistryInstrumentType.S.getKey(), RegistryInstrumentType.M.getKey(), null,
RegistryUnit.T.getKey(), RegistryUnit.T);
"POOL");
String sqlCondition = String.format("%s and registryStatus = '%s'",
RegistryCodeSqlBuilder.getInstance(registryTradingParamsOST, registryTradingParamsTMT).build(),
RegistryStatus.POOL.getKey());
Collection<Registry> obligations = registryImdg.getCollectionObjectsBySQL(sqlCondition); Collection<Registry> obligations = registryImdg.getCollectionObjectsBySQL(sqlCondition);
Map<Long, Map<Long, List<Registry>>> registryByGroupIdAndCompanyId = obligations.stream(). Map<Long, Map<Long, List<Registry>>> registryByGroupIdAndCompanyId = obligations.stream().

View file

@ -27,6 +27,8 @@ import java.util.Collection;
@Service @Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Deprecated
//не должен использоваться как stage в сессии, данная логика перенесена в statementService
public class UnlockResources implements ISessionStage { public class UnlockResources implements ISessionStage {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());

View file

@ -4,22 +4,17 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.platform.dictionary.*; import ru.clearing.platform.dictionary.CompanySymbolDictionary;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.company.validation.CompanySymbolNotExistRule;
import ru.spcex.clearing.company.validation.CompanySymbolOfSymbolNewRequestNotExistRule; import ru.spcex.clearing.company.validation.CompanySymbolOfSymbolNewRequestNotExistRule;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanyInfoUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanyNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest;
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule; import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
import ru.spcex.clearing.validation.common.rules.EnumPresentRule;
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
import ru.spcex.clearing.validation.common.rules.IdPresentRule; import ru.spcex.clearing.validation.common.rules.IdPresentRule;
import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.enumeration.WorkflowStatus;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
@ -33,16 +28,16 @@ import java.util.function.Function;
public class CompanySymbolValidationConfig { public class CompanySymbolValidationConfig {
@Bean("companySymbolNewRequestValidator") @Bean("companySymbolNewRequestValidator")
public Function<CompanySymbolUpdateRequest, IValidator> companySymbolNewRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) { public Function<CompanySymbolNewRequest, IValidator> companySymbolNewRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return companySymbolUpdateRequest -> { return companySymbolNewRequest -> {
ImdgValidationContext<CompanySymbolUpdateRequest> context = new ImdgValidationContext<>(); ImdgValidationContext<CompanySymbolNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(companySymbolUpdateRequest); context.setValidatedObject(companySymbolNewRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
addImdg.accept(IMDGDistributedNames.Map_CompanySymbols); addImdg.accept(IMDGDistributedNames.Map_CompanySymbols);
addImdg.accept(IMDGDistributedNames.Map_CompanySymbolDictionary); addImdg.accept(IMDGDistributedNames.Map_CompanySymbolDictionary);
addImdg.accept(IMDGDistributedNames.Map_Company); addImdg.accept(IMDGDistributedNames.Map_Company);
return new ValidatorImpl<>(context, return new ValidatorImpl<>(context,
FieldRequiredRule.instance("companyId", CompanySymbolUpdateRequest::getCompanyId, CompanyErrors.RequiredFieldEmpty), FieldRequiredRule.instance("companyId", CompanySymbolNewRequest::getCompanyId, CompanyErrors.RequiredFieldEmpty),
IdPresentRule.instance("companyId", IdPresentRule.instance("companyId",
CompanySymbolUpdateRequest::getCompanyId, CompanySymbolUpdateRequest::getCompanyId,
IMDGDistributedNames.Map_Company, IMDGDistributedNames.Map_Company,
@ -52,7 +47,7 @@ public class CompanySymbolValidationConfig {
// FieldRequiredRule.instance("companySymbol", CompanySymbolUpdateRequest::getCompanySymbol, CompanyErrors.RequiredFieldEmpty), // FieldRequiredRule.instance("companySymbol", CompanySymbolUpdateRequest::getCompanySymbol, CompanyErrors.RequiredFieldEmpty),
// FieldRequiredRule.instance("companySymbolValue", CompanySymbolUpdateRequest::getCompanySymbolValue, CompanyErrors.RequiredFieldEmpty), // FieldRequiredRule.instance("companySymbolValue", CompanySymbolUpdateRequest::getCompanySymbolValue, CompanyErrors.RequiredFieldEmpty),
DictionaryPresentRule.instance("companySymbol", DictionaryPresentRule.instance("companySymbol",
CompanySymbolUpdateRequest::getCompanySymbol, CompanySymbolNewRequest::getCompanySymbol,
IMDGDistributedNames.Map_CompanySymbolDictionary, IMDGDistributedNames.Map_CompanySymbolDictionary,
CompanySymbolDictionary.class, CompanySymbolDictionary.class,
CompanyErrors.RequiredFieldEmpty, CompanyErrors.RequiredFieldEmpty,
@ -104,4 +99,35 @@ public class CompanySymbolValidationConfig {
); );
}; };
} }
@Bean("companySymbolDeleteRequestValidator")
public Function<CommonDeleteRequest, IValidator> companySymbolDeleteRequestValidator(
Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation
) {
return companySymbolDeleteRequest -> {
ImdgValidationContext<CommonDeleteRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(companySymbolDeleteRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
addImdg.accept(IMDGDistributedNames.Map_Company);
addImdg.accept(IMDGDistributedNames.Map_DocumentTypeDictionary);
addImdg.accept(IMDGDistributedNames.Map_CompanySymbols);
return new ValidatorImpl<>(context,
IdPresentRule.instance("id",
CommonDeleteRequest::getId,
IMDGDistributedNames.Map_CompanySymbols,
CompanySymbols.class,
CompanyErrors.RequiredFieldEmpty,
CompanyErrors.RecordNotFound,
companySymbol -> {
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
Company company = companyImdg.getSingleObjectByID(companySymbol.getCompanyId());
if (company == null) {
return CompanyErrors.CompanyNotFound;
}
return null;
})
);
};
}
} }

View file

@ -7,14 +7,13 @@ import ru.clearing.classes.statics.data.profile.Contact;
import ru.clearing.platform.dictionary.ContactTypeDictionary; import ru.clearing.platform.dictionary.ContactTypeDictionary;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames; 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.ContactNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest;
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule; import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
import ru.spcex.clearing.validation.common.rules.EnumPresentRule;
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
import ru.spcex.clearing.validation.common.rules.IdPresentRule; import ru.spcex.clearing.validation.common.rules.IdPresentRule;
import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.ContactTypes;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
@ -92,4 +91,32 @@ public class ContactValidationConfig {
}; };
} }
@Bean("contactDeleteRequestValidator")
public Function<CommonDeleteRequest, IValidator> contactDeleteRequestValidator(
Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation
) {
return contactDeleteRequest -> {
ImdgValidationContext<CommonDeleteRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(contactDeleteRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
addImdg.accept(IMDGDistributedNames.Map_Company);
addImdg.accept(IMDGDistributedNames.Map_Contact);
return new ValidatorImpl<>(context,
IdPresentRule.instance("id",
CommonDeleteRequest::getId,
IMDGDistributedNames.Map_Contact,
Contact.class,
CompanyErrors.RequiredFieldEmpty,
CompanyErrors.RecordNotFound,
contact -> {
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
Company company = companyImdg.getSingleObjectByID(contact.getCompanyId());
if (company == null) {
return CompanyErrors.ContactNotFound;
}
return null;
})
);
};
}
} }

View file

@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.relation.Relation; import ru.clearing.classes.statics.data.company.relation.Relation;
import ru.clearing.platform.dictionary.ClearingCategoryDictionary; import ru.clearing.platform.dictionary.ClearingCategoryDictionary;
import ru.clearing.platform.dictionary.WorkflowStatusDictionary; import ru.clearing.platform.dictionary.ServiceStatusDictionary;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
@ -52,8 +52,8 @@ public class RelationValidationConfig {
CompanyErrors.WrongFieldValue), CompanyErrors.WrongFieldValue),
DictionaryPresentRule.instance("serviceStatus", DictionaryPresentRule.instance("serviceStatus",
RelationNewRequest::getServiceStatus, RelationNewRequest::getServiceStatus,
IMDGDistributedNames.Map_WorkflowStatusDictionary, IMDGDistributedNames.Map_ServiceStatusDictionary,
WorkflowStatusDictionary.class, ServiceStatusDictionary.class,
CompanyErrors.RequiredFieldEmpty, CompanyErrors.RequiredFieldEmpty,
CompanyErrors.WrongFieldValue) CompanyErrors.WrongFieldValue)
); );
@ -103,8 +103,8 @@ public class RelationValidationConfig {
// CompanyErrors.WrongFieldValue), // CompanyErrors.WrongFieldValue),
DictionaryPresentRule.instance("serviceStatus", DictionaryPresentRule.instance("serviceStatus",
RelationUpdateRequest::getServiceStatus, RelationUpdateRequest::getServiceStatus,
IMDGDistributedNames.Map_WorkflowStatusDictionary, IMDGDistributedNames.Map_ServiceStatusDictionary,
WorkflowStatusDictionary.class, ServiceStatusDictionary.class,
CompanyErrors.RequiredFieldEmpty, CompanyErrors.RequiredFieldEmpty,
CompanyErrors.WrongFieldValue) CompanyErrors.WrongFieldValue)
); );

View file

@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.Consts;
@ -20,6 +19,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanyNewRequest
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.CompanySymbol; import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.enumeration.UserRole; import ru.spcex.platform.enumeration.UserRole;
@ -46,15 +46,13 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
private final ImdgId idSequence; private final ImdgId idSequence;
private final Imdg<Company> companyIMap; private final Imdg<Company> companyIMap;
protected UserRoleVerification userRoleVerification; protected UserRoleVerification userRoleVerification;
private ValidationHelper validationHelper;
private Function<CompanyNewRequest, IValidator> companyNewRequestValidator;
private Function<CompanyNewRequest, IValidator> companyUpdateRequestValidator;
private Function<CommonDeleteRequest, IValidator> companyDeleteRequestValidator;
protected CompanySymbolService companySymbolService; protected CompanySymbolService companySymbolService;
protected AccountNotificationHelper accountNotification; protected AccountNotificationHelper accountNotification;
protected RelationService relationService; protected RelationService relationService;
private final ValidationHelper validationHelper;
private final Function<CompanyNewRequest, IValidator> companyNewRequestValidator;
private final Function<CompanyNewRequest, IValidator> companyUpdateRequestValidator;
private final Function<CommonDeleteRequest, IValidator> companyDeleteRequestValidator;
@Autowired @Autowired
public CompanyService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer, public CompanyService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
@ -134,7 +132,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
try { try {
if (req.getCompanySymbol() != null) { if (req.getCompanySymbol() != null) {
CompanySymbols newSymbol = companySymbolService.createCompanySymbol(transaction, company.getId(), req.getCompanySymbol(), req.getCompanySymbolValue()); CompanySymbols newSymbol = companySymbolService.createCompanySymbol(transaction, company.getId(), req.getCompanySymbol(), req.getCompanySymbolValue());
updateCompanyBySymbol(company, newSymbol); updateCompanyBySymbol(company, newSymbol, false);
} }
company.setWorkflowStatus(req.getWorkflowStatus()); company.setWorkflowStatus(req.getWorkflowStatus());
@ -215,20 +213,26 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
return null; return null;
} }
protected void updateCompanyBySymbol(Company company, CompanySymbols companySymbol) { protected void updateCompanyBySymbol(Company company, CompanySymbols companySymbol, boolean shouldBeDeleted) {
assert company.getId().equals(companySymbol.getCompanyId()); assert company.getId().equals(companySymbol.getCompanyId());
String companySymbolValue = companySymbol.getCompanySymbolValue();
String setUpValue = shouldBeDeletedOrSet(companySymbolValue, shouldBeDeleted);
if (CompanySymbol.TRDC.equalsByKey(companySymbol.getCompanySymbol())) { if (CompanySymbol.TRDC.equalsByKey(companySymbol.getCompanySymbol())) {
company.setTradingCode(companySymbol.getCompanySymbolValue()); company.setTradingCode(setUpValue);
} }
if (CompanySymbol.CLRC.equalsByKey(companySymbol.getCompanySymbol())) { if (CompanySymbol.CLRC.equalsByKey(companySymbol.getCompanySymbol())) {
company.setClearingCode(companySymbol.getCompanySymbolValue()); company.setClearingCode(setUpValue);
} }
if (CompanySymbol.RGRC.equalsByKey(companySymbol.getCompanySymbol())) { if (CompanySymbol.RGRC.equalsByKey(companySymbol.getCompanySymbol())) {
company.setRegistrationCode(companySymbol.getCompanySymbolValue()); company.setRegistrationCode(setUpValue);
} }
} }
public synchronized void updateCompanyBySymbol(ImdgTransaction transaction, CompanySymbols companySymbol) throws ClearingBaseException { private String shouldBeDeletedOrSet(String companySymbol, boolean shouldBeDeleted) {
return shouldBeDeleted ? "" : companySymbol;
}
public synchronized void updateCompanyBySymbol(ImdgTransaction transaction, CompanySymbols companySymbol, boolean shouldBeDeleted) throws ClearingBaseException {
if (companySymbol.getCompanyId() == null) { if (companySymbol.getCompanyId() == null) {
throw new IllegalArgumentException("Required companySymbol.companyId"); throw new IllegalArgumentException("Required companySymbol.companyId");
} }
@ -241,7 +245,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
if (company == null) { if (company == null) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyNotFound, companySymbol.getCompanyId())); throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyNotFound, companySymbol.getCompanyId()));
} }
updateCompanyBySymbol(company, companySymbol); updateCompanyBySymbol(company, companySymbol, shouldBeDeleted);
company.setUpdated(Instant.now()); company.setUpdated(Instant.now());
companyMap.update(company); companyMap.update(company);
log.debug("Company {} updated by change CompanySymbols {} ({})", log.debug("Company {} updated by change CompanySymbols {} ({})",

View file

@ -10,20 +10,24 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.spcex.clearing.util.services.RequestHelper; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts; 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.CompanySymbolNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.UserRole; import ru.spcex.platform.enumeration.UserRole;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.ImdgTransaction; import ru.spcex.platform.imdg.api.ImdgTransaction;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.error.ClearingBaseException; import ru.spcex.platform.utils.error.ClearingBaseException;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
@ -35,13 +39,13 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private final ImdgId idSequence; private final ImdgId idSequence;
protected CompanyService companyService;
private final RequestHelper requestHelper; private final RequestHelper requestHelper;
protected CompanyService companyService;
protected ValidationHelper validationHelper; protected ValidationHelper validationHelper;
protected UserRoleVerification userRoleVerification; protected UserRoleVerification userRoleVerification;
protected Function<CompanySymbolUpdateRequest, IValidator> companySymbolNewRequestValidator; protected Function<CompanySymbolNewRequest, IValidator> companySymbolNewRequestValidator;
protected Function<CompanySymbolUpdateRequest, IValidator> companySymbolUpdateRequestValidator; protected Function<CompanySymbolUpdateRequest, IValidator> companySymbolUpdateRequestValidator;
protected Function<CommonDeleteRequest, IValidator> companySymbolDeleteRequestValidator;
@Autowired @Autowired
public CompanySymbolService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer, public CompanySymbolService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
@ -50,7 +54,9 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
ValidationHelper validationHelper, ValidationHelper validationHelper,
UserRoleVerification userRoleVerification, UserRoleVerification userRoleVerification,
@Qualifier("companySymbolNewRequestValidator") @Qualifier("companySymbolNewRequestValidator")
Function<CompanySymbolUpdateRequest, IValidator> companySymbolNewRequestValidator, Function<CompanySymbolNewRequest, IValidator> companySymbolNewRequestValidator,
@Qualifier("companySymbolDeleteRequestValidator")
Function<CommonDeleteRequest, IValidator> companySymbolDeleteRequestValidator,
@Qualifier("companySymbolUpdateRequestValidator") @Qualifier("companySymbolUpdateRequestValidator")
Function<CompanySymbolUpdateRequest, IValidator> companySymbolUpdateRequestValidator Function<CompanySymbolUpdateRequest, IValidator> companySymbolUpdateRequestValidator
) { ) {
@ -64,16 +70,20 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
userRoleVerification.setRoleForVerification(UserRole.Admin); userRoleVerification.setRoleForVerification(UserRole.Admin);
this.companySymbolNewRequestValidator = companySymbolNewRequestValidator; this.companySymbolNewRequestValidator = companySymbolNewRequestValidator;
this.companySymbolUpdateRequestValidator = companySymbolUpdateRequestValidator; this.companySymbolUpdateRequestValidator = companySymbolUpdateRequestValidator;
this.companySymbolDeleteRequestValidator = companySymbolDeleteRequestValidator;
} }
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
callback(CompanySymbolUpdateRequest.class) callback(CompanySymbolNewRequest.class)
.setFunction(this::companySymbolNew) .setFunction(this::companySymbolNew)
.forDestination(Consts.DESTINATION_COMPANY_SYMBOL_NEW, callbacks::put); .forDestination(Consts.DESTINATION_COMPANY_SYMBOL_NEW, callbacks::put);
callback(CompanySymbolUpdateRequest.class) callback(CompanySymbolUpdateRequest.class)
.setFunction(this::companySymbolUpdate) .setFunction(this::companySymbolUpdate)
.forDestination(Consts.DESTINATION_COMPANY_SYMBOL_UPDATE, callbacks::put); .forDestination(Consts.DESTINATION_COMPANY_SYMBOL_UPDATE, callbacks::put);
callback(CommonDeleteRequest.class)
.setFunction(this::companySymbolDelete)
.forDestination(Consts.DESTINATION_COMPANY_SYMBOL_DELETE, callbacks::put);
init(); init();
} }
@ -82,8 +92,8 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
} }
public RequestInfoUpdate companySymbolNew(BaseRequest<CompanySymbolUpdateRequest> symbolRequest) { public RequestInfoUpdate companySymbolNew(BaseRequest<CompanySymbolNewRequest> symbolRequest) {
CompanySymbolUpdateRequest req = symbolRequest.getRequestPayload(); CompanySymbolNewRequest req = symbolRequest.getRequestPayload();
log.debug("CompanySymbolNewRequest received, id={}", symbolRequest.getId()); log.debug("CompanySymbolNewRequest received, id={}", symbolRequest.getId());
{ // validate { // validate
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(symbolRequest); RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(symbolRequest);
@ -107,7 +117,7 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
Imdg<CompanySymbols> companySymbolsTMap = transaction.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); Imdg<CompanySymbols> companySymbolsTMap = transaction.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
companySymbolsTMap.update(companySymbols); companySymbolsTMap.update(companySymbols);
try { try {
companyService.updateCompanyBySymbol(transaction, companySymbols); companyService.updateCompanyBySymbol(transaction, companySymbols, false);
} catch (ClearingBaseException e) { } catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg()); return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
} }
@ -141,15 +151,18 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
try { try {
Imdg<CompanySymbols> companySymbolsTMap = transaction.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); Imdg<CompanySymbols> companySymbolsTMap = transaction.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
companySymbols = companySymbolsTMap.getSingleObjectByID(req.getId()); companySymbols = companySymbolsTMap.getSingleObjectByID(req.getId());
// companySymbols.setCompanySymbol(req.getCompanySymbol()); по ТЗ не должен менятся при обновлении if (companySymbols == null) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyInfoNotFound, req.getId()));
}
if (!companySymbols.getCompanySymbol().equalsIgnoreCase(req.getCompanySymbolValue())) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.EditCompanySymbols, req.getId()));
}
companySymbols.setCompanySymbolValue(req.getCompanySymbolValue()); companySymbols.setCompanySymbolValue(req.getCompanySymbolValue());
companySymbolsTMap.update(companySymbols); companySymbolsTMap.update(companySymbols);
try { companyService.updateCompanyBySymbol(transaction, companySymbols, false);
companyService.updateCompanyBySymbol(transaction, companySymbols);
} catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
}
txOk = true; txOk = true;
} catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
} finally { } finally {
if (txOk) if (txOk)
transaction.commitTransaction(); transaction.commitTransaction();
@ -161,6 +174,42 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
return null; return null;
} }
public RequestInfoUpdate companySymbolDelete(BaseRequest<CommonDeleteRequest> symbolRequest) {
CommonDeleteRequest req = symbolRequest.getRequestPayload();
log.debug("CommonDeleteRequest for CompanySymbol received, id={}", symbolRequest.getId());
{ // validate
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(symbolRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
requestInfoUpdate = validationHelper.validateTillFirstError(symbolRequest, companySymbolDeleteRequestValidator);
if (requestInfoUpdate != null) return requestInfoUpdate;
}
CompanySymbols companySymbols;
ImdgTransaction transaction = imdgProvider.newTransaction();
transaction.beginTransaction();
boolean txOk = false;
try {
Imdg<CompanySymbols> companySymbolsTMap = transaction.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
companySymbols = companySymbolsTMap.getSingleObjectByID(req.getId());
if (companySymbols == null) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyInfoNotFound, req.getId()));
}
companySymbolsTMap.delete(companySymbols);
companyService.updateCompanyBySymbol(transaction, companySymbols, true);
txOk = true;
} catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
} finally {
if (txOk)
transaction.commitTransaction();
else
transaction.rollbackTransaction();
}
log.debug("successfully processed, id {}", companySymbols.getId());
return null;
}
public CompanySymbols createCompanySymbol(ImdgTransaction transaction, Long companyId, String companySymbol, String companySymbolValue) { public CompanySymbols createCompanySymbol(ImdgTransaction transaction, Long companyId, String companySymbol, String companySymbolValue) {
Objects.requireNonNull(companyId); Objects.requireNonNull(companyId);

View file

@ -12,6 +12,7 @@ import ru.clearing.classes.statics.data.profile.Contact;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts; 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.ContactNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
@ -31,6 +32,7 @@ public class ContactService extends QueueConsumer implements InitializingBean {
private final ValidationHelper validationHelper; private final ValidationHelper validationHelper;
private final Function<ContactNewRequest, IValidator> contactNewRequestValidator; private final Function<ContactNewRequest, IValidator> contactNewRequestValidator;
private final Function<ContactUpdateRequest, IValidator> contactUpdateRequestValidator; private final Function<ContactUpdateRequest, IValidator> contactUpdateRequestValidator;
private final Function<CommonDeleteRequest, IValidator> contactDeleteRequestValidator;
private final UserRoleVerification userRoleVerification; private final UserRoleVerification userRoleVerification;
@Autowired @Autowired
@ -40,6 +42,7 @@ public class ContactService extends QueueConsumer implements InitializingBean {
ValidationHelper validationHelper, ValidationHelper validationHelper,
UserRoleVerification userRoleVerification, UserRoleVerification userRoleVerification,
@Qualifier("contactNewRequestValidator") Function<ContactNewRequest, IValidator> contactNewRequestValidator, @Qualifier("contactNewRequestValidator") Function<ContactNewRequest, IValidator> contactNewRequestValidator,
@Qualifier("contactDeleteRequestValidator") Function<CommonDeleteRequest, IValidator> contactDeleteRequestValidator,
@Qualifier("contactUpdateRequestValidator") Function<ContactUpdateRequest, IValidator> contactUpdateRequestValidator) { @Qualifier("contactUpdateRequestValidator") Function<ContactUpdateRequest, IValidator> contactUpdateRequestValidator) {
super(kafkaQueue, kafkaProducer); super(kafkaQueue, kafkaProducer);
this.contactMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Contact, Contact.class); this.contactMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Contact, Contact.class);
@ -47,6 +50,7 @@ public class ContactService extends QueueConsumer implements InitializingBean {
this.userRoleVerification = userRoleVerification; this.userRoleVerification = userRoleVerification;
this.contactNewRequestValidator = contactNewRequestValidator; this.contactNewRequestValidator = contactNewRequestValidator;
this.contactUpdateRequestValidator = contactUpdateRequestValidator; this.contactUpdateRequestValidator = contactUpdateRequestValidator;
this.contactDeleteRequestValidator = contactDeleteRequestValidator;
} }
@Override @Override
@ -57,6 +61,9 @@ public class ContactService extends QueueConsumer implements InitializingBean {
callback(ContactUpdateRequest.class) callback(ContactUpdateRequest.class)
.setFunction(this::contactUpdate) .setFunction(this::contactUpdate)
.forDestination(Consts.DESTINATION_CONTACT_UPDATE, callbacks::put); .forDestination(Consts.DESTINATION_CONTACT_UPDATE, callbacks::put);
callback(CommonDeleteRequest.class)
.setFunction(this::companySymbolDelete)
.forDestination(Consts.DESTINATION_CONTACT_DELETE, callbacks::put);
init(); init();
} }
@ -98,4 +105,22 @@ public class ContactService extends QueueConsumer implements InitializingBean {
log.debug("successfully processed, id {}", contact.getId()); log.debug("successfully processed, id {}", contact.getId());
return null; return null;
} }
public RequestInfoUpdate companySymbolDelete(BaseRequest<CommonDeleteRequest> userRequest) {
log.debug("CommonDeleteRequest received for contact service.");
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, contactDeleteRequestValidator);
if (requestInfoUpdate != null) return requestInfoUpdate;
CommonDeleteRequest req = userRequest.getRequestPayload();
Contact contact = contactMap.getSingleObjectByID(req.getId());
contactMap.delete(contact);
log.debug("successfully deleted, id {}", contact.getId());
return null;
}
} }

View file

@ -9,11 +9,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.profile.ProfileDocument; import ru.clearing.classes.statics.data.profile.ProfileDocument;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.Consts;
@ -23,6 +21,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.company.ProfileDocumentUp
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.DocumentTypes; import ru.spcex.platform.enumeration.DocumentTypes;
import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.enumeration.WorkflowStatus;
@ -38,11 +37,6 @@ import java.util.function.Function;
@Service @Service
public class ProfileDocumentService extends QueueConsumer implements InitializingBean { public class ProfileDocumentService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private Imdg<ProfileDocument> profileDocumentMap;
private Imdg<Company> companyMap;
private ImdgProvider imdgProvider;
private AccountNotificationHelper accountNotificationHelper;
private final CompanyService companyService; private final CompanyService companyService;
private final Function<ProfileDocumentNewRequest, IValidator> profileDocumentNewRequestValidator; private final Function<ProfileDocumentNewRequest, IValidator> profileDocumentNewRequestValidator;
private final Function<ProfileDocumentUpdateRequest, IValidator> profileDocumentUpdateRequestValidator; private final Function<ProfileDocumentUpdateRequest, IValidator> profileDocumentUpdateRequestValidator;
@ -51,6 +45,10 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
private final UserRoleVerification userRoleVerification; private final UserRoleVerification userRoleVerification;
protected IMessageResolver messageResolver; protected IMessageResolver messageResolver;
protected RequestHelper requestHelper; protected RequestHelper requestHelper;
private Imdg<ProfileDocument> profileDocumentMap;
private Imdg<Company> companyMap;
private final ImdgProvider imdgProvider;
private final AccountNotificationHelper accountNotificationHelper;
@Autowired @Autowired
public ProfileDocumentService(Consumer<String, Object> kafkaQueue, public ProfileDocumentService(Consumer<String, Object> kafkaQueue,
@ -140,26 +138,25 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
deleteRequest, profileDocumentDeleteRequestValidator deleteRequest, profileDocumentDeleteRequestValidator
); );
if (requestInfoUpdate != null) return requestInfoUpdate; if (requestInfoUpdate != null) return requestInfoUpdate;
CommonDeleteRequest profileDocumentDeleteRequest = deleteRequest.getRequestPayload(); CommonDeleteRequest profileDocumentDeleteRequest = deleteRequest.getRequestPayload();
ProfileDocument profileDocument = profileDocumentMap.getSingleObjectByID(profileDocumentDeleteRequest.getId()); ProfileDocument profileDocument = profileDocumentMap.getSingleObjectByID(profileDocumentDeleteRequest.getId());
Company existCompany = profileDocument.getCompanyId() == null ? null : companyMap.getSingleObjectByID(profileDocument.getCompanyId());
if (existCompany == null) {
log.warn("Company {} not found by profileDocument {}", profileDocument.getCompanyId(), profileDocument.getId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId());
}
if (!WorkflowStatus.Active.equalsByKey(existCompany.getWorkflowStatus())) {
log.debug("Company {} not active", profileDocument.getCompanyId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId());
}
synchronized (companyService) { synchronized (companyService) {
Company existCompany = profileDocument.getCompanyId() == null ? null : companyMap.getSingleObjectByID(profileDocument.getCompanyId());
if (existCompany == null) {
log.warn("Company {} not found by profileDocument {}", profileDocument.getCompanyId(), profileDocument.getId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId());
}
if (!WorkflowStatus.Active.equalsByKey(existCompany.getWorkflowStatus())) {
log.debug("Company {} not active", profileDocument.getCompanyId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId());
}
ImdgTransaction transaction = imdgProvider.newTransaction(); ImdgTransaction transaction = imdgProvider.newTransaction();
transaction.beginTransaction(); transaction.beginTransaction();
boolean txOk = false; boolean txOk = false;
try { try {
companyService.relationService.cancelingOfAgreementUpdateRelation(transaction, profileDocument.getCompanyId()); companyService.relationService.cancelingOfAgreementUpdateRelation(transaction, profileDocument.getCompanyId());
Imdg<ProfileDocument> txProfileDocumentMap= transaction.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class); Imdg<ProfileDocument> txProfileDocumentMap = transaction.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class);
txProfileDocumentMap.delete(profileDocument); txProfileDocumentMap.delete(profileDocument);
txOk = true; txOk = true;
} finally { } finally {

View file

@ -12,15 +12,16 @@ import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.relation.Relation; import ru.clearing.classes.statics.data.company.relation.Relation;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts; 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.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.*; import ru.spcex.clearing.platform.messaging.domain.cud.company.RelationNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.RelationUpdateRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.enumeration.ClearingCategory;
import ru.spcex.platform.enumeration.ServiceProduct; import ru.spcex.platform.enumeration.ServiceProduct;
@ -30,7 +31,6 @@ import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.ImdgTransaction; import ru.spcex.platform.imdg.api.ImdgTransaction;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.error.ValidationException; import ru.spcex.platform.utils.error.ValidationException;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
@ -42,7 +42,7 @@ import java.util.function.Function;
import static ru.spcex.platform.enumeration.Service.FOND; import static ru.spcex.platform.enumeration.Service.FOND;
import static ru.spcex.platform.enumeration.Service.MKR; import static ru.spcex.platform.enumeration.Service.MKR;
import static ru.spcex.platform.enumeration.SessionStatus.CLOS; import static ru.spcex.platform.enumeration.ServiceStatus.Closed;
import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey; import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey;
@Service @Service
@ -59,9 +59,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
protected RequestHelper requestHelper; protected RequestHelper requestHelper;
protected ValidationHelper validationHelper; protected ValidationHelper validationHelper;
private Function<RelationNewRequest, IValidator> relationNewRequestValidator; private final Function<RelationNewRequest, IValidator> relationNewRequestValidator;
private Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator; private final Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator;
private Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator; private final Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator;
@Autowired @Autowired
public RelationService(Consumer<String, Object> kafkaQueue, public RelationService(Consumer<String, Object> kafkaQueue,
@ -117,7 +117,7 @@ public class RelationService extends QueueConsumer implements InitializingBean {
{ //проверка заполнен ли serviceStatus { //проверка заполнен ли serviceStatus
String serviceStatus = req.getServiceStatus(); String serviceStatus = req.getServiceStatus();
if (serviceStatus == null || serviceStatus.isEmpty()) { if (serviceStatus == null || serviceStatus.isEmpty()) {
Company company = companyMap.getSingleObjectByFieldValues(Map.of("id", req.getCompanyId())); Company company = companyMap.getSingleObjectByID(req.getCompanyId());
req.setServiceStatus(company.getWorkflowStatus()); req.setServiceStatus(company.getWorkflowStatus());
} }
} }
@ -168,7 +168,7 @@ public class RelationService extends QueueConsumer implements InitializingBean {
log.debug("Request has no status. Set status by resume: {}", relation.getServiceStatus()); log.debug("Request has no status. Set status by resume: {}", relation.getServiceStatus());
} else { } else {
String toStatus = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Active.getKey() : String toStatus = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Active.getKey() :
WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Closed.getKey() : WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus()) ? Closed.getKey() :
null; null;
log.debug("Request has no status. Set status by company[{}].status={}. Relation[{}].serviceSStatus={}", log.debug("Request has no status. Set status by company[{}].status={}. Relation[{}].serviceSStatus={}",
company.getId(), company.getWorkflowStatus(), toStatus); company.getId(), company.getWorkflowStatus(), toStatus);
@ -231,9 +231,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
} }
Company company = companyMap.getSingleObjectByID(relation.getConsumerId()); Company company = companyMap.getSingleObjectByID(relation.getConsumerId());
String toStatus = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Active.getKey() : String toStatus = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Active.getKey() :
WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus()) ? ServiceStatus.Closed.getKey() : WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus()) ? Closed.getKey() :
null; null;
if (ServiceStatus.Active.equalsByKey(toStatus) && ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) { if (ServiceStatus.Active.equalsByKey(toStatus) && Closed.equalsByKey(relation.getServiceStatus())) {
relation.setServiceStatus(ServiceStatus.Reopened.getKey()); relation.setServiceStatus(ServiceStatus.Reopened.getKey());
log.debug("Set status by resume: {}", relation.getServiceStatus()); log.debug("Set status by resume: {}", relation.getServiceStatus());
} else { } else {
@ -287,9 +287,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
ClearingMemberCategory clearingMemberCategory = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class).getSingleObjectByFieldValues(Map.of("companyId", companyId)); ClearingMemberCategory clearingMemberCategory = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class).getSingleObjectByFieldValues(Map.of("companyId", companyId));
WorkflowStatus workflowStatus = getEnumByKey(WorkflowStatus.class, company.getWorkflowStatus()); WorkflowStatus workflowStatus = getEnumByKey(WorkflowStatus.class, company.getWorkflowStatus());
ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory()); ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
String serviceStatus; String serviceStatus;
switch (Objects.requireNonNull(clearingCategory)){ switch (Objects.requireNonNull(clearingCategory)) {
case B: case B:
case I: case I:
case V: case V:
@ -313,10 +313,11 @@ public class RelationService extends QueueConsumer implements InitializingBean {
log.debug("New Relation[{}] created.", relation.getId()); log.debug("New Relation[{}] created.", relation.getId());
relationMap.insert(relation); relationMap.insert(relation);
} }
protected void cancelingOfAgreementUpdateRelation(ImdgTransaction transaction, Long companyId) { protected void cancelingOfAgreementUpdateRelation(ImdgTransaction transaction, Long companyId) {
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
Relation relation = relationMap.getSingleObjectByFieldValues(Map.of("consumerId", companyId)); Relation relation = relationMap.getSingleObjectByFieldValues(Map.of("consumerId", companyId));
relation.setServiceStatus(CLOS.getKey()); relation.setServiceStatus(Closed.getKey());
relationMap.update(relation); relationMap.update(relation);
log.debug("New Relation[{}] updated.", relation.getId()); log.debug("New Relation[{}] updated.", relation.getId());
} }
@ -356,8 +357,8 @@ public class RelationService extends QueueConsumer implements InitializingBean {
modified = true; modified = true;
} }
} else if (WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus())) { } else if (WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus())) {
if (!ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) { if (!Closed.equalsByKey(relation.getServiceStatus())) {
relation.setServiceStatus(ServiceStatus.Closed.getKey()); relation.setServiceStatus(Closed.getKey());
modified = true; modified = true;
} }
} }

View file

@ -3,17 +3,12 @@ package ru.spcex.clearing.company.validation;
import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.spcex.clearing.company.error.CompanyErrors; import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanyNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule; import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -21,10 +16,10 @@ import java.util.Optional;
/** /**
* Проверка наличия CompanySymbols с переданными в запросе companySymbol и companyId * Проверка наличия CompanySymbols с переданными в запросе companySymbol и companyId
*/ */
public class CompanySymbolOfSymbolNewRequestNotExistRule implements IValidationRule<ImdgValidationContext<CompanySymbolUpdateRequest>> { public class CompanySymbolOfSymbolNewRequestNotExistRule implements IValidationRule<ImdgValidationContext<CompanySymbolNewRequest>> {
@Override @Override
public Optional<EnumMessage> validate(ImdgValidationContext<CompanySymbolUpdateRequest> context) { public Optional<EnumMessage> validate(ImdgValidationContext<CompanySymbolNewRequest> context) {
CompanySymbolUpdateRequest request = context.getValidatedObject(); CompanySymbolNewRequest request = context.getValidatedObject();
Imdg<CompanySymbols> companySymbolsImdg = context.obtainMap(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); Imdg<CompanySymbols> companySymbolsImdg = context.obtainMap(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);

View file

@ -0,0 +1,18 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum AccType implements IEnumKey {
A("A"), B("B");
private final String key;
AccType(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}

View file

@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum MarketType implements IEnumKey { public enum MarketType implements IEnumKey {
PRMR("PRMR"); PRMR("PRMR"), SCND("SCND");
private final String key; private final String key;

View file

@ -6,7 +6,8 @@ public enum RegistryStatus implements IEnumKey {
OK("OK"), OK("OK"),
PROC("PROC"), PROC("PROC"),
NACK("NACK"), NACK("NACK"),
FAIL("FAIL") FAIL("FAIL"),
POOL("POOL")
; ;
private final String key; private final String key;

View file

@ -3,7 +3,9 @@ package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum SdfTable implements IEnumKey { public enum SdfTable implements IEnumKey {
SDF_01("SDF_01"), SDF_57("SDF_57"), SDF_09("SDF_09"), SDF_16("SDF_16"); SDF_01("SDF_01"), SDF_04("SDF_04"), SDF_08("SDF_08"),
SDF_13("SDF_13"), SDF_57("SDF_57"), SDF_09("SDF_09"),
SDF_16("SDF_16");
SdfTable(String key) { SdfTable(String key) {
this.key = key; this.key = key;

View file

@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum SessionType implements IEnumKey { public enum SessionType implements IEnumKey {
IPOB("IPOB"), IPO0("IPO0"), IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"),
; ;
SessionType(String key) { SessionType(String key) {

View file

@ -33,5 +33,25 @@
<groupId>ru.spcex.platform</groupId> <groupId>ru.spcex.platform</groupId>
<artifactId>platform-utils</artifactId> <artifactId>platform-utils</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View file

@ -52,6 +52,10 @@ public class RegistryCodeSqlBuilder {
} }
if (tradingParams.registryUnit() != null) { if (tradingParams.registryUnit() != null) {
condition.append(String.format("registryUnit = '%s'", tradingParams.registryUnit().getKey())); condition.append(String.format("registryUnit = '%s'", tradingParams.registryUnit().getKey()));
wasAddedCondition = true;
}
if (!wasAddedCondition) {
condition.delete(condition.length() - " and ".length(), condition.length());
} }
conditions.add(condition); conditions.add(condition);
} }

View file

@ -0,0 +1,61 @@
package ru.spcex.platform.imdg.api.predicate.specific;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import ru.spcex.platform.enumeration.*;
public class RegistryCodeSqlBuilderTest {
@Test
public void testBuildByOneObject() {
RegistryTradingParams registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R);
RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams);
String sql = registryCodeSqlBuilder.build();
Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql);
registryTradingParams = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R);
registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams);
sql = registryCodeSqlBuilder.build();
Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql);
registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R);
registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams);
sql = registryCodeSqlBuilder.build();
Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R')", sql);
}
@Test
public void testBuildByFewObjects() {
RegistryTradingParams registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R);
RegistryTradingParams registryTradingParams_second = new RegistryTradingParams(RegistryDesignation.O, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F);
RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second);
String sql = registryCodeSqlBuilder.build();
Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')" +
" or (registryDesignation = 'O' and registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql);
registryTradingParams_first = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R);
registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F);
registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second);
sql = registryCodeSqlBuilder.build();
Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R') or " +
"(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql);
registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R);
registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F);
registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second);
sql = registryCodeSqlBuilder.build();
Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R') or " +
"(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql);
}
@Test
public void test(){
RegistryTradingParams registryTradingParamsL = new RegistryTradingParams(RegistryDesignation.L,
RegistryInstrumentType.S, null, RegistryUnit.T);
RegistryTradingParams registryTradingParamsC = new RegistryTradingParams(RegistryDesignation.C,
RegistryInstrumentType.M, null, null);
RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParamsL, registryTradingParamsC);
Assertions.assertEquals("(registryDesignation = 'L' and registryInstrumentType = 'S' and registryUnit = 'T') or (registryDesignation = 'C' and registryInstrumentType = 'M')",
registryCodeSqlBuilder.build());
}
}

View file

@ -121,7 +121,8 @@ public interface Consts {
String SDF53_PROCESS = "sdf53-process"; String SDF53_PROCESS = "sdf53-process";
String SDF54_PROCESS = "sdf54-process"; String SDF54_PROCESS = "sdf54-process";
String SDF56_PROCESS = "sdf56-process"; String SDF56_PROCESS = "sdf56-process";
String SDF57_PROCESS = "sdf57-process"; String CONTINUE_SESSION_BN_FIRST_PART = "sdf57-process";
String CONTINUE_SESSION_BN_SECOND_PART = "sdf13-process";
String REVISE_PROCESS = "revise-process"; String REVISE_PROCESS = "revise-process";
String EXPORT_PROCESS = "export-process"; String EXPORT_PROCESS = "export-process";
String EXPORT_COMPLETED = "export_completed"; String EXPORT_COMPLETED = "export_completed";

View file

@ -0,0 +1,16 @@
package ru.spcex.clearing.platform.messaging.domain.cud.clearing;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ContinueSessionBnRequest {
@JsonProperty
private Long generationId;
public Long getGenerationId() {
return generationId;
}
public void setGenerationId(Long generationId) {
this.generationId = generationId;
}
}

View file

@ -0,0 +1,37 @@
package ru.spcex.clearing.platform.messaging.domain.cud.company;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CompanySymbolNewRequest {
@JsonProperty
public Long companyId;
@JsonProperty
private String companySymbol;
@JsonProperty
private String companySymbolValue;
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public String getCompanySymbol() {
return companySymbol;
}
public void setCompanySymbol(String companySymbol) {
this.companySymbol = companySymbol;
}
public String getCompanySymbolValue() {
return companySymbolValue;
}
public void setCompanySymbolValue(String companySymbolValue) {
this.companySymbolValue = companySymbolValue;
}
}