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
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
public AccountNewRequest toRequest() {
var req = new AccountNewRequest();

View file

@ -32,16 +32,6 @@ public class AccountUpdateAction implements IAction<AccountUpdateRequest> {
@JsonProperty
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
public AccountUpdateRequest toRequest() {
var req = new AccountUpdateRequest();

View file

@ -51,31 +51,18 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
@Override
public Collection<EnumMessage> validate() {
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)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "correspondentAccount"));
}
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(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)) {
errors.add(new EnumMessage(BackEndError.ValidationError, "taxpayerIdentificationNumber"));
}
if ("RUB".equalsIgnoreCase(this.currency) && !StringUtils.hasLength(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;
}
@ -172,4 +159,12 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
public void setAccount(String 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")
private String account;
@Override
public Collection<EnumMessage> validate() {
return Collections.emptyList();
}
@Override
public BankAccountUpdateRequest toRequest() {
var req = new BankAccountUpdateRequest();

View file

@ -35,16 +35,6 @@ public class ClientCodeNewAction implements IAction<ClientCodeNewRequest> {
@JsonProperty
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
public ClientCodeNewRequest toRequest() {
var req = new ClientCodeNewRequest();

View file

@ -36,13 +36,6 @@ public class ClientCodeUpdateAction implements IAction<ClientCodeUpdateRequest>
@JsonProperty
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
public ClientCodeUpdateRequest toRequest() {

View file

@ -4,9 +4,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
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")
@JsonProperty
private Long companyId;
@ -18,8 +18,8 @@ public class CompanySymbolNewAction implements IAction<CompanySymbolUpdateReques
private String companySymbolValue;
@Override
public CompanySymbolUpdateRequest toRequest() {
CompanySymbolUpdateRequest request = new CompanySymbolUpdateRequest();
public CompanySymbolNewRequest toRequest() {
CompanySymbolNewRequest request = new CompanySymbolNewRequest();
request.setCompanyId(this.companyId);
request.setCompanySymbol(this.companySymbol);
request.setCompanySymbolValue(this.companySymbolValue);

View file

@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
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 java.math.BigDecimal;

View file

@ -36,16 +36,6 @@ public class PIClearingOutbondActionNew implements IAction<PIClearingOutbondActi
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
public PIClearingOutbondActionNewRequest toRequest() {
var req = new PIClearingOutbondActionNewRequest();

View file

@ -37,17 +37,6 @@ public class RSplitDepositActionNew implements IAction<RegistrySplitDepositActio
@JsonProperty
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
public RegistrySplitDepositActionRequest toRequest() {

View file

@ -27,15 +27,6 @@ public class TradingClearingRegistryNewAction implements IAction<TradingClearing
@JsonProperty
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
public TradingClearingRegistryNewRequest toRequest() {

View file

@ -35,15 +35,6 @@ public class TradingClearingRegistryUpdateAction implements IAction<TradingClear
@JsonProperty
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
public TradingClearingRegistryUpdateRequest toRequest() {

View file

@ -46,18 +46,6 @@ public class ClearingCalendarNewAction implements IAction<ClearingCalendarNewReq
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() {
return clearingDate;
}

View file

@ -52,21 +52,6 @@ public class ClearingCalendarUpdateAction implements IAction<ClearingCalendarUpd
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
public Long getId() {
return id;

View file

@ -78,23 +78,6 @@ public class PlannerNewAction implements IAction<PlannerNewRequest> {
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() {
return task;

View file

@ -62,20 +62,6 @@ public class PlannerTemplateNewAction implements IAction<PlannerTemplateNewReque
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() {
return task;

View file

@ -67,23 +67,6 @@ public class PlannerTemplateUpdateAction implements IAction<PlannerTemplateUpdat
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
public Long getId() {

View file

@ -84,27 +84,6 @@ public class PlannerUpdateAction implements IAction<PlannerUpdateRequest>, WithI
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
public Long getId() {
return id;

View file

@ -51,20 +51,6 @@ public class EquitySecurityNewAction implements IAction<EquitySecurityNewRequest
@JsonProperty
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
public EquitySecurityNewRequest toRequest() {
var req = new EquitySecurityNewRequest();

View file

@ -53,13 +53,6 @@ public class EquitySecurityUpdateAction implements IAction<EquitySecurityUpdateR
@JsonProperty
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
public EquitySecurityUpdateRequest toRequest() {

View file

@ -73,19 +73,6 @@ public class FixedIncomeSecurityNewAction implements IAction<FixedIncomeSecurity
@JsonProperty
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
public FixedIncomeSecurityNewRequest toRequest() {

View file

@ -75,14 +75,6 @@ public class FixedIncomeSecurityUpdateAction implements IAction<FixedIncomeSecur
@JsonProperty
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
public FixedIncomeSecurityUpdateRequest toRequest() {
var req = new FixedIncomeSecurityUpdateRequest();

View file

@ -74,29 +74,6 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
@JsonProperty
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
public MoneyMarketSecurityNewRequest toRequest() {

View file

@ -99,14 +99,6 @@ public class MoneyMarketSecurityUpdateAction implements IAction<MoneyMarketSecur
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)
@Override
public ActionType getActionType() {

View file

@ -82,7 +82,9 @@ public class MetaServer extends MetaBase {
log.warn("META SERVER >>> {}", e.getLocalizedMessage());
continue;
}
actionObjectsExtracted.put(actionElement.getDestination(), oe);
String actionDestination = // обычно бывают =null о этому эффективнее по имени класса а не по: objectElement.getSubscription().destination + "/"+ actionElement.getDestination();
oe.getClassName();
actionObjectsExtracted.put(actionDestination, oe);
}
}
} 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.security.KeycloakUtils;
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.imdg.IMDGDistributedNames;
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 ImdgId idGenerator;
private final ImdgProvider imdgProvider;
private final ActionMetaValidation actionMetaValidation;
private final ActionValidationProvider validation;
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.idGenerator = imdgProvider.getImdgIdGenerator();
this.imdgProvider = imdgProvider;
this.actionMetaValidation = actionMetaValidation;
this.validation = validation;
this.userImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class);
}
@ -112,6 +116,18 @@ public class OperatorImpl implements IOperator {
if (validationErrors.size() > 0) {
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 поиска других сущностей и т.д.
IValidator validator = validation.getValidator(destination, iAction);
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",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityNewAction",
"fields": [
{"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2578,6 +2580,8 @@
"confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true
@ -2770,6 +2774,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityNewAction",
"fields": [
{"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2823,6 +2829,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true
@ -2981,6 +2989,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityNewAction",
"fields": [
{"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -3054,6 +3064,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3131,6 +3143,8 @@
"confirmation": "securitySymbol,shortName",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3505,6 +3519,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeNewAction",
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false
@ -3538,6 +3554,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3648,6 +3666,8 @@
"confirmation": "companyId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryNewAction",
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -3673,6 +3693,8 @@
"confirmation": "companyId,code,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3925,6 +3947,8 @@
"confirmation": "contract,outboundAmount,refundDate",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.RSplitDepositActionNew",
"fields": [
{"code": "contract",
"type": 2,"length": 255,"name": "Договор","shortname": "Договор","required": true
@ -4006,6 +4030,8 @@
"confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountNewAction",
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -4031,6 +4057,8 @@
"confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
@ -4060,6 +4088,8 @@
"confirmation": "companyId,account",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [
{"code": "id",
"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",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction",
"fields": [
{"code": "currency",
"type": 12,"name": "Код валюты","shortname": "Валюта","required": true,"link": "currencyCode","linkCode": "code"
@ -4275,6 +4307,8 @@
"confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "bankAccount","linkCode": "id","required": true
@ -4489,6 +4523,8 @@
"name": "Новый шаблон расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateNewAction",
"fields": [
{"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4524,6 +4560,8 @@
"name": "Изменение шаблона расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "plannerTemplate","linkCode": "id","required": true
@ -4614,6 +4652,8 @@
"name": "Добавление записи в календарь",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarNewAction",
"fields": [
{"code": "clearingDate",
"type": 6,"name": "Дата","shortname": "Дата","required": true
@ -4633,6 +4673,8 @@
"name": "Изменение записи в календаре",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clearingCalendar","linkCode": "id","required": true
@ -4731,6 +4773,8 @@
"name": "Новое расписание",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerNewAction",
"fields": [
{"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4770,6 +4814,8 @@
"name": "Изменение расписания",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "planner","required": true,"linkCode": "id"
@ -6666,6 +6712,8 @@
"destination": "payment-instructions/clearing-outbound",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.payment.PIClearingOutbondActionNew",
"fields": [
{"code": "senderId",
"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"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<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"/>
<securitySymbol 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"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</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"/>
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" 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"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<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"/>
<securitySymbol 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="Наименование на английском"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</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"/>
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" 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"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<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"/>
<securitySymbol 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="Наименование на английском"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</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"/>
<instrumentType type="12" name="Наименование типа инструмента" shortname="Тип инструмента" link="instrumentType" required="true" enabled="false"/>
<securitySymbol type="2" length="255" name="Код инструмента" shortname="Код" enabled="false"/>
@ -732,7 +732,7 @@
<fullNameEng type="2" length="255" name="Полное наименование инструмента на английском" shortname="Наименование на английском"/>
<workflowStatus type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</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"/>
</delete>
</actions>
@ -818,7 +818,7 @@
<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"/>
<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"/>
<code type="2" length="255" name="Код клиента" shortname="Код клиента" required="true"/>
<tradingClearingRegistryId type="1" name="Торгово-клиринговый регистр" shortname="ТКР" link="tradingClearingRegistry" linkCode="code"/>
@ -826,7 +826,7 @@
<depoAccountId type="1" name="Номер депозитарного счета" shortname="Депозитарный счет" link="account" linkCode="account"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</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"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/>
<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"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<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"/>
<moneyAccountId type="1" name="Номер денежного счета" shortname="Денежный счет" link="account" linkCode="account" required="true"/>
<depoAccountId type="1" name="Номер депозитарного счета" shortname="Депозитарный счет" link="account" linkCode="account"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="workflowStatus"/>
</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"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="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"/>
<updatedAt field="updated" type="4" name="Дата и время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<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"/>
<outboundAmount type="10" 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"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<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"/>
<account type="2" length="50" name="Номер счета" shortname="Счет" required="true"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/>
<accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/>
</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"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName" enabled="false"/>
<account type="2" length="50" name="Номер счета" shortname="Счет" enabled="false"/>
<status type="12" name="Наименование статуса" shortname="Статус" link="serviceStatus"/>
<accountType type="12" name="Наименование типа счета" shortname="Тип" link="accountType" required="true" visible="false"/>
</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"/>
</delete>
</actions>
@ -995,7 +995,7 @@
<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"/>
<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"/>
<bankIdentificationCode 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"/>
<companyId type="1" name="Компания" shortname="Компания" link="company" linkCode="shortName" required="true"/>
</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"/>
<currency type="12" name="Код валюты" shortname="Валюта" link="currencyCode" linkCode="code"/>
<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"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions>
<post name="Новый шаблон расписания операционного дня">
<post name="Новый шаблон расписания операционного дня" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateNewAction">
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/>
<section type="12" name="Секция" shortname="Секция" link="section" linkCode="name" linkKeyCode="code"/>
@ -1064,7 +1064,7 @@
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/>
<securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName"/>
</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"/>
<task type="12" name="Наименование задачи" shortname="Задача" link="task" 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"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions>
<post name="Добавление записи в календарь">
<post name="Добавление записи в календарь" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarNewAction">
<clearingDate type="6" name="Дата" shortname="Дата" required="true"/>
<dayStatus type="12" name="Статус" shortname="Статус" link="dayStatus" required="true"/>
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/>
</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"/>
<clearingDate type="6" name="Дата" shortname="Дата" 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"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/>
<actions>
<post name="Новое расписание">
<post name="Новое расписание" class="ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerNewAction">
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<clearingDate type="6" name="Дата задачи" shortname="Дата задачи" required="true"/>
<taskTime type="5" name="Время задачи" shortname="Время задачи" required="true"/>
@ -1127,7 +1127,7 @@
<companyId type="1" name="Наименование компании" shortname="Компания" link="company" linkCode="shortName"/>
<securityId type="1" name="Наименование инструмента" shortname="Инструмент" link="security" linkCode="shortName"/>
</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"/>
<task type="12" name="Наименование задачи" shortname="Задача" link="task" required="true"/>
<clearingDate type="6" name="Дата задачи" shortname="Дата задачи" required="true"/>
@ -1554,7 +1554,7 @@
<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"/>
<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"/>
<addresseeId type="1" name="Участник получатель" shortname="Получатель" link="company" required="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.context.annotation.Bean;
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.validation.ActionMetaValidation;
import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
@ -18,8 +20,9 @@ public class IOperatorTest {
@Autowired
@Bean("iOperatorTest")
public OperatorImpl createIOperator(Producer<String, Object> kafka, ActionValidationProvider validationProvider) {
return new OperatorImpl(kafka, hazelcastServiceTest, validationProvider);
public OperatorImpl createIOperator(Producer<String, Object> kafka,
ActionMetaValidation actionMetaValidation, ActionValidationProvider validationProvider) {
return new OperatorImpl(kafka, hazelcastServiceTest, actionMetaValidation, validationProvider);
}
@Bean
@ -27,4 +30,10 @@ public class IOperatorTest {
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",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityNewAction",
"fields": [
{"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2578,6 +2580,8 @@
"confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.MoneyMarketSecurityUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true
@ -2770,6 +2774,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityNewAction",
"fields": [
{"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -2823,6 +2829,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,shareType",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.EquitySecurityUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true
@ -2981,6 +2989,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityNewAction",
"fields": [
{"code": "instrumentType",
"type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false
@ -3054,6 +3064,8 @@
"confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.FixedIncomeSecurityUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3131,6 +3143,8 @@
"confirmation": "securitySymbol,shortName",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true
@ -3505,6 +3519,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeNewAction",
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false
@ -3538,6 +3554,8 @@
"confirmation": "companyId,code,tradingClearingRegistryId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.ClientCodeUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3648,6 +3666,8 @@
"confirmation": "companyId,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryNewAction",
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -3673,6 +3693,8 @@
"confirmation": "companyId,code,moneyAccountId,depoAccountId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.TradingClearingRegistryUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clientCode","linkCode": "id","required": true
@ -3925,6 +3947,8 @@
"confirmation": "contract,outboundAmount,refundDate",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.registry.RSplitDepositActionNew",
"fields": [
{"code": "contract",
"type": 2,"length": 255,"name": "Договор","shortname": "Договор","required": true
@ -4006,6 +4030,8 @@
"confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountNewAction",
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
@ -4031,6 +4057,8 @@
"confirmation": "companyId,account,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
@ -4060,6 +4088,8 @@
"confirmation": "companyId,account",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction",
"fields": [
{"code": "id",
"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",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction",
"fields": [
{"code": "currency",
"type": 12,"name": "Код валюты","shortname": "Валюта","required": true,"link": "currencyCode","linkCode": "code"
@ -4275,6 +4307,8 @@
"confirmation": "currency,bankIdentificationCode,bankName,correspondentAccount,correspondentAccountName,taxpayerIdentificationNumber,taxRegistrationReasonCode,account,destination",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "bankAccount","linkCode": "id","required": true
@ -4489,6 +4523,8 @@
"name": "Новый шаблон расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateNewAction",
"fields": [
{"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4524,6 +4560,8 @@
"name": "Изменение шаблона расписания операционного дня",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerTemplateUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "plannerTemplate","linkCode": "id","required": true
@ -4614,6 +4652,8 @@
"name": "Добавление записи в календарь",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarNewAction",
"fields": [
{"code": "clearingDate",
"type": 6,"name": "Дата","shortname": "Дата","required": true
@ -4633,6 +4673,8 @@
"name": "Изменение записи в календаре",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.ClearingCalendarUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "clearingCalendar","linkCode": "id","required": true
@ -4731,6 +4773,8 @@
"name": "Новое расписание",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerNewAction",
"fields": [
{"code": "task",
"type": 12,"name": "Наименование задачи","shortname": "Задача","link": "task","required": true
@ -4770,6 +4814,8 @@
"name": "Изменение расписания",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.schedule.PlannerUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "planner","required": true,"linkCode": "id"
@ -6666,6 +6712,8 @@
"destination": "payment-instructions/clearing-outbound",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.payment.PIClearingOutbondActionNew",
"fields": [
{"code": "senderId",
"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.objects.BusinessObject;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
/**
@ -414,9 +412,9 @@ public class Registry extends BusinessObject implements Cloneable {
}
@Override
public Object clone() {
public Registry clone() {
try {
return super.clone();
return (Registry) super.clone();
} catch (CloneNotSupportedException e) {
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.Configuration;
import ru.spcex.clearing.service.executors.AbstractExecutor;
import ru.spcex.clearing.service.executors.Sdf01Executor;
import ru.spcex.clearing.service.executors.Sdf57Executor;
import ru.spcex.clearing.service.executors.*;
import ru.spcex.clearing.service.executors.SdfLegacyExecutor;
import ru.spcex.platform.enumeration.SdfTable;
import java.util.HashMap;
@ -14,11 +13,15 @@ import java.util.Map;
public class SdfExecutorsConfig {
@Bean("sdfExecutors")
public Map<SdfTable, AbstractExecutor<?>> executorsMap(Sdf01Executor sdf01Executor,
Sdf57Executor sdf57Executor) {
public Map<SdfTable, AbstractExecutor<?>> executorsMap(SdfLegacyExecutor sdf01Executor,
Sdf57Executor sdf57Executor,
Sdf04Executor sdf04Executor,
Sdf13Executor sdf13Executor) {
Map<SdfTable, AbstractExecutor<?>> executors = new HashMap<>();
executors.put(SdfTable.SDF_01, sdf01Executor);
executors.put(SdfTable.SDF_57, sdf57Executor);
executors.put(SdfTable.SDF_04, sdf04Executor);
executors.put(SdfTable.SDF_13, sdf13Executor);
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),
InsecurityObligation(5422L),
NewDealsNotFound(5423L),
//ошибки "перенесенные" из balance-service
CompanyNotFoundB(5211L),
CurrencyNotFound(5213L),
OperationCanBeRunForTodayOnly(5214L),
AccountWrongType(5216L),
;
private final Long id;

View file

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

View file

@ -62,8 +62,11 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
.setConsumer(primaryAuctionBnSession::runSession)
.forDestination(Task.startOfClearing.topic(), callbacks::put);
callback(Object.class)
.setConsumer(primaryAuctionBnSession::continueSession)
.forDestination(Consts.SDF57_PROCESS, callbacks::put);
.setConsumer(primaryAuctionBnSession::continueSessionFirstPart)
.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)
.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.stereotype.Service;
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.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdf01Request;
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.clearing.ContinueSessionBnRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
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.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.collection.Pair;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -40,6 +40,11 @@ public class StatementService extends QueueConsumer implements InitializingBean
private final Map<SdfTable, Imdg<? extends SpcexObjectBase>> sdfImdgs;
private final Map<SdfTable, AbstractExecutor<?>> executorsMap;
/**
* Пары sdf запросов пришедшие с модуля dbf-import
*/
private final Map<Long, Pair<StatementRequest, StatementRequest>> pairOfSdfRequest = new HashMap<>();
@Autowired
public StatementService(Consumer<String, Object> kafkaQueue,
ImdgProvider imdgProvider,
@ -52,6 +57,8 @@ public class StatementService extends QueueConsumer implements InitializingBean
this.executorsMap = executorsMap;
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_04, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf04, SDf04.class));
this.sdfImdgs.put(SdfTable.SDF_13, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf13, SDf13.class));
}
@Override
@ -64,31 +71,145 @@ public class StatementService extends QueueConsumer implements InitializingBean
private void process(BaseRequest<StatementRequest> systemRequest) {
StatementRequest statementRequest = systemRequest.getRequestPayload();
Collection<? extends SpcexObjectBase> sdfGroup;
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) {
sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of("generationId", statementRequest.getGroupId()));
sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of(
"generationId", statementRequest.getGroupId()));
} else {
//todo могут ли тут реквесты бегать по кругу, если да, то у нас проблемы
sdfGroup = statementRequest.getAccountCreationResults()
.stream()
.filter(part -> part.getErrorCode() == null) //fixme эти случае должны попадать в ошибочный sdf02
.map(part -> sdfImdg.getSingleObjectByID(part.getSdfId()))
.collect(Collectors.toList());
}
AbstractExecutor service = executorsMap.get(table);
AbstractExecutor service = executorsMap.get(SdfTable.SDF_01);
Result res = service.execute(sdfGroup, statementRequest);
if (res.getAccountRequests().size() != 0) {
kafkaSender.sendRequestToQueue(Consts.ACCOUNT_NEW_SDF01, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests()));
} else if (service.isNeedToSendCommandToExport()) {
ExportToFileRequest exportRequest = new ExportToFileRequest();
exportRequest.setSdfGroupId(res.getGenerationId());
exportRequest.setNameOfTable(service.exportTableName());
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest);
} else if (service.isNeedToSendCommand()) {
service.sendCommand(kafkaSender, res);
}
}
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) {
AccountSdf01Request r = new AccountSdf01Request();
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;
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 java.util.Collection;
@ -8,5 +9,6 @@ import java.util.Collection;
public abstract class AbstractExecutor<T> {
public abstract Result execute(Collection<T> sdf, StatementRequest statementRequest);
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.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.account.ClearingAccount;
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.SDf02;
import ru.clearing.classes.statics.data.security.Security;
import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.error.ClearingErrorInternal;
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.domain.cud.clearing.ContinueSessionBnRequest;
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.clearing.session.stage.util.RegistryUtil;
import ru.spcex.platform.enumeration.*;
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 ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
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.number.BigDecimalUtil;
import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
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.Consumer;
import java.util.function.Function;
@Service
public class Sdf01Executor 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 Imdg<Registry> registryImdg;
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;
private final Imdg<ClearingAccount> clearingAccountImdg;
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,
ImdgProvider imdgProvider,
IMessageResolver errorResolver) {
IMessageResolver errorResolver, IMessageResolver messageResolver) {
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.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.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.errorLogger = errorLogger;
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
public String exportTableName() {
return "DF-02";
return null;
}
@Override
public boolean isNeedToSendCommandToExport() {
public boolean isNeedToSendCommand() {
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) {
Result result = new Result();
Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId();
@ -76,76 +110,85 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
for (SDf01 sdf01 : sdf) {
IValidator validator = sDf01Validator.apply(sdf01);
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
&& ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
&& ClearingErrorInternal.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))) {
} 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());
}
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));
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);
Statement stmt = createSdf01Statement(sdf01, company, account);
SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup); //fixme тоже мб убрать
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);
stmt.setOutSDfId(sdf02New.getId());
statementImdg.update(stmt);
Optional<EnumMessage> err = validateActiveness(company, account);
if (err.isEmpty()) {
Consumer<Registry> update = rgs -> {
updateReg(stmt, rgs);
registryImdg.update(rgs);
};
Consumer<RegistryDesignation> create = (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(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;
}
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 final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy");
private Statement createSdf01Statement(SDf01 sdf01, Company company, Account account) {
Statement stmt = new Statement();
stmt.setAddresseeId(company.getId());
stmt.setAddresseeId(company.getId());
stmt.setSenderId(Sender.Prc.getId());
stmt.setStatementType(StatementType.full.getKey());
stmt.setAccountId(account.getId());
stmt.setAccount(account.getAccount());
stmt.setInOutDirection(InOutDirection.in.getKey());
stmt.setSettlementDate(LocalDate.parse(sdf01.getDat(), formatter));
if (sdf01.getRemainder() != null) {
stmt.setAmount(new BigDecimal(sdf01.getRemainder()));
}
stmt.setOperationStatus(OperationStatus.Pending.getKey());
stmt.setInSDfId(sdf01.getId());
stmt.setInOutSDfType(InOutSDfType.type1.getKey());
stmt.setCreated(Instant.now());
return stmt;
}
private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) {
@ -157,7 +200,6 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
return req;
}
private SDf02 createErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) {
SDf02 sDf02 = new SDf02();
sDf02.setCurr_code(sdf01.getCurr_code());
@ -200,4 +242,100 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
sDf02.setResult("OK!");
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;
import org.apache.commons.lang3.StringUtils;
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.account.ClearingAccount;
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.SDf02;
import ru.clearing.classes.statics.data.sdf.SDf57;
import ru.clearing.classes.statics.data.security.Security;
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.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.model.Result;
import ru.spcex.clearing.service.validation.ValidationStored;
@ -36,6 +43,7 @@ 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.Consumer;
import java.util.function.Function;
@ -53,8 +61,12 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
private final ImdgProvider imdgProvider;
private final IMessageResolver errorResolver;
private final Imdg<AccountBalance> accountBalanceImdg;
private final Imdg<ClearingAccount> clearingAccountImdg;
private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
private final Imdg<Security> securityImdg;
private final Imdg<Currency> currencyImdg;
private final IMessageResolver messageResolver;
// private final Pair<>
public Sdf57Executor(@Qualifier("sdf57Validator") Function<SDf57, IValidator> sDf57Validator,
LoggingService errorLogger,
@ -64,6 +76,9 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.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.errorLogger = errorLogger;
this.imdgProvider = imdgProvider;
@ -72,15 +87,24 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
}
//todo доделать контроль sdf01 и sdf57
@Override
public String exportTableName() {
return null;
}
@Override
public boolean isNeedToSendCommandToExport() {
return false;
}//no need...
public boolean isNeedToSendCommand() {
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);
}
//V - Изменение statement по sDf57
//
@ -127,9 +151,9 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
Account accountCred = validator.getStored(ValidationStored.Sdf57AccountCred);
//адресат CREDIT / владелец DEBIT
Optional<Statement> statementDeb = createStatementIfNeeded.apply(companyDeb, accountDeb, InOutDirection.in);
Optional<Statement> statementDeb = createStatementIfNeeded.apply(companyDeb, accountDeb, InOutDirection.out);
//адресат DEBIT / владелец CREDIT
Optional<Statement> statementCred = createStatementIfNeeded.apply(companyCred, accountCred, InOutDirection.out);
Optional<Statement> statementCred = createStatementIfNeeded.apply(companyCred, accountCred, InOutDirection.in);
Consumer<StmtCmpAcc> createRegistryIfNeeded = stmtCmpAcc -> {
Statement stmt = stmtCmpAcc.statement();
@ -145,12 +169,25 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
};
Consumer<RegistryDesignation> create = (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(registryF);
registryImdg.insert(registryB);
};
//todo понять что происходит со инициатором/контрагентом, особенно если у нас только один Statement
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());
} else {
stmt.setErrorCodeId(err.get().getSubject().getId()); // fixme ErrorText insert
@ -181,9 +218,14 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
Statement statement = new Statement();
statement.setAddresseeId(companyDeb.getId());
statement.setSenderId(Sender.Prc.getId());
statement.setStatementType(StatementType.full.getKey());
statement.setStatementType(StatementType.incr.getKey());
statement.setContract(getContractFromSpecif(sdf57.getSpecif()));
statement.setAccountId(accountDeb.getId());
Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", "RUB"));
if (currency != null) {
statement.setSecurityId(currency.getId());
}
statement.setAccount(accountDeb.getAccount());
statement.setInOutDirection(inOutDirection.getKey());
statement.setSettlementDate(payDate(sdf57.getPay_date()));
@ -206,11 +248,23 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
rgs.setAccount(account.getAccount());
rgs.setRegistryDesignation(designation.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.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.setSecurityId(statement.getSecurityId());
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,
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 InclusionObligations inclusionObligations;
private final InspectionObligations inspectionObligations;
private final FormingRegistersOnOS formingRegistersOnOS;
private final FormingPaymentInstruction formingPaymentInstruction;
private final UnlockResources unlockResources;
@ -51,7 +52,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
FormingRegistersOnOS formingRegistersOnOS,
FormingPaymentInstruction formingPaymentInstruction,
UnlockResources unlockResources,
FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver) {
FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver, InspectionObligations inspectionObligations) {
super(imdgProvider, messageResolver);
this.balanceRevise = balanceRevise;
this.dealsPrepare = dealsPrepare;
@ -64,6 +65,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
this.finishingSession = finishingSession;
this.endStageNotification = endStageNotification;
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
this.inspectionObligations = inspectionObligations;
}
@Override
@ -87,14 +89,14 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
}
}
public void continueSession(BaseRequest<?> req) {
public void continueSessionFirstPart(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 0
// runStage(TaskType.ContinueRevise, balanceRevise);
//stage 1
StageResult<List<ExecutionCommon>> dealsPreparationResult;
{
@ -116,17 +118,22 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
{
InspectionPoolPayload companyIdPayload = new InspectionPoolPayload();
companyIdPayload.setProcessedCompanyId(currSession.getCompanyId());
runStage(TaskType.InspectionObligations, companyIdPayload, inclusionObligations);
runStage(TaskType.InspectionObligations, companyIdPayload, inspectionObligations);
}
//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>
} catch (StageException e) {
//already logged
}
}
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
{

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.ImdgId;
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.utils.enumeration.IEnumKey;
@ -58,7 +59,8 @@ public class BalanceRevise implements ISessionStage {
return sendSdfs();
}
case ContinueRevise -> {
cashFlow(); //((SdfClearingRequest) task.getData()).getGroupId() if needed
//больше не используются, удалить после проверки
cashFlow(); //((SdfClearingRequest) task.getData()).getGroupId() if needed //todo убрать это отсюда
return revise();
}
default -> throw new IllegalStateException("unknown task " + task.getTaskType());
@ -93,32 +95,31 @@ public class BalanceRevise implements ISessionStage {
Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL);
for (Statement stmt : stmts) {
String unformatted = "registry_designation = '%s' " +
"and registry_instrument_type = '%s' " +
"and registry_unit = '%s' " +
"and account = '%s' " +
"and securityId = %d";
String unformatted = "%s and account = '%s' and securityId = %d";
RegistryTradingParams registryAMT = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
null, RegistryUnit.T);
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,
RegistryDesignation.A.getKey(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.T.getKey(),
RegistryCodeSqlBuilder.getInstance(registryAMT).build(),
stmt.getAccount(),
stmt.getSecurityId()
);
String registrySqlAMF = String.format(unformatted,
RegistryDesignation.A.getKey(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.F.getKey(),
RegistryCodeSqlBuilder.getInstance(registryAMF).build(),
stmt.getAccount(),
stmt.getSecurityId()
);
String registrySqlAMB = String.format(unformatted,
RegistryDesignation.A.getKey(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.B.getKey(),
RegistryCodeSqlBuilder.getInstance(registryAMB).build(),
stmt.getAccount(),
stmt.getSecurityId()
);
Registry rgsAMT = registryImdg.getSingleObjectBySQL(registrySqlAMT);
Registry rgsAMF = registryImdg.getSingleObjectBySQL(registrySqlAMF);
Registry rgsAMB = registryImdg.getSingleObjectBySQL(registrySqlAMB);
@ -152,14 +153,11 @@ public class BalanceRevise implements ISessionStage {
InOutSDfType.type1.getKey(), OperationStatus.Pending.getKey(), StatementType.full.getKey());
Collection<Statement> stmts = statementImdg.getCollectionObjectsBySQL(statementSQL);
for (Statement stmt : stmts) {
String registrySqlAMT = String.format("registry_designation = '%s' " +
"and registry_instrument_type = '%s' " +
"and registry_unit = '%s' " +
"and account = '%s' " +
"and securityId = %d",
RegistryDesignation.A.getKey(),
RegistryInstrumentType.M.getKey(),
RegistryUnit.T.getKey(),
RegistryTradingParams registryAMT = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M,
null, RegistryUnit.T);
String registrySqlAMT = String.format("%s and account = '%s' and securityId = %d",
RegistryCodeSqlBuilder.getInstance(registryAMT).build(),
stmt.getAccount(),
stmt.getSecurityId()
);
@ -175,7 +173,7 @@ public class BalanceRevise implements ISessionStage {
}
private void newSDf56(Statement statement) {
log.debug("GALB request received; creating sdf56");
log.debug("creating sdf56");
SDf56 sDf56 = new SDf56();
sDf56.setNumber(idGenerator.nextId().toString());
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.Task;
import ru.spcex.clearing.session.stage.task.InspectionPoolPayload;
import ru.spcex.platform.enumeration.RegistryDesignation;
import ru.spcex.platform.enumeration.RegistryInstrumentType;
import ru.spcex.platform.enumeration.RegistryUnit;
import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
@ -62,15 +61,18 @@ public class InspectionObligations implements ISessionStage {
private StageResult inspectionPool(Long processedCompanyId) {
String sqlCondition = String.format("registryDesignation in ('%s', '%s') and " +
"registryInstrumentType in ('%s', '%s') and " +
"registryUnit = '%s' and " +
"registryStatus = '%s' and " +
"settlementDate = '%s'",
RegistryDesignation.O.getKey(), RegistryDesignation.T.getKey(),
RegistryInstrumentType.S.getKey(), RegistryInstrumentType.M.getKey(),
RegistryUnit.T.getKey(),
"POOL");
RegistryTradingParams registryTradingParamsOST = new RegistryTradingParams(RegistryDesignation.O,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
RegistryTradingParams registryTradingParamsTMT = new RegistryTradingParams(RegistryDesignation.T,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
String sqlCondition = String.format("%s and registryStatus = '%s'",
RegistryCodeSqlBuilder.getInstance(registryTradingParamsOST, registryTradingParamsTMT).build(),
RegistryStatus.POOL.getKey());
Collection<Registry> obligations = registryImdg.getCollectionObjectsBySQL(sqlCondition);
Map<Long, Map<Long, List<Registry>>> registryByGroupIdAndCompanyId = obligations.stream().

View file

@ -27,6 +27,8 @@ import java.util.Collection;
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Deprecated
//не должен использоваться как stage в сессии, данная логика перенесена в statementService
public class UnlockResources implements ISessionStage {
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 ru.clearing.classes.statics.data.company.Company;
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.validation.CompanySymbolNotExistRule;
import ru.spcex.clearing.company.validation.CompanySymbolOfSymbolNewRequestNotExistRule;
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.CompanyInfoUpdateRequest;
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.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.IdPresentRule;
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.validation.ImdgValidationContext;
import ru.spcex.platform.utils.validation.IValidator;
@ -33,16 +28,16 @@ import java.util.function.Function;
public class CompanySymbolValidationConfig {
@Bean("companySymbolNewRequestValidator")
public Function<CompanySymbolUpdateRequest, IValidator> companySymbolNewRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return companySymbolUpdateRequest -> {
ImdgValidationContext<CompanySymbolUpdateRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(companySymbolUpdateRequest);
public Function<CompanySymbolNewRequest, IValidator> companySymbolNewRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return companySymbolNewRequest -> {
ImdgValidationContext<CompanySymbolNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(companySymbolNewRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
addImdg.accept(IMDGDistributedNames.Map_CompanySymbols);
addImdg.accept(IMDGDistributedNames.Map_CompanySymbolDictionary);
addImdg.accept(IMDGDistributedNames.Map_Company);
return new ValidatorImpl<>(context,
FieldRequiredRule.instance("companyId", CompanySymbolUpdateRequest::getCompanyId, CompanyErrors.RequiredFieldEmpty),
FieldRequiredRule.instance("companyId", CompanySymbolNewRequest::getCompanyId, CompanyErrors.RequiredFieldEmpty),
IdPresentRule.instance("companyId",
CompanySymbolUpdateRequest::getCompanyId,
IMDGDistributedNames.Map_Company,
@ -52,7 +47,7 @@ public class CompanySymbolValidationConfig {
// FieldRequiredRule.instance("companySymbol", CompanySymbolUpdateRequest::getCompanySymbol, CompanyErrors.RequiredFieldEmpty),
// FieldRequiredRule.instance("companySymbolValue", CompanySymbolUpdateRequest::getCompanySymbolValue, CompanyErrors.RequiredFieldEmpty),
DictionaryPresentRule.instance("companySymbol",
CompanySymbolUpdateRequest::getCompanySymbol,
CompanySymbolNewRequest::getCompanySymbol,
IMDGDistributedNames.Map_CompanySymbolDictionary,
CompanySymbolDictionary.class,
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.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactNewRequest;
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.EnumPresentRule;
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.ContactTypes;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
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.relation.Relation;
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.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
@ -52,8 +52,8 @@ public class RelationValidationConfig {
CompanyErrors.WrongFieldValue),
DictionaryPresentRule.instance("serviceStatus",
RelationNewRequest::getServiceStatus,
IMDGDistributedNames.Map_WorkflowStatusDictionary,
WorkflowStatusDictionary.class,
IMDGDistributedNames.Map_ServiceStatusDictionary,
ServiceStatusDictionary.class,
CompanyErrors.RequiredFieldEmpty,
CompanyErrors.WrongFieldValue)
);
@ -103,8 +103,8 @@ public class RelationValidationConfig {
// CompanyErrors.WrongFieldValue),
DictionaryPresentRule.instance("serviceStatus",
RelationUpdateRequest::getServiceStatus,
IMDGDistributedNames.Map_WorkflowStatusDictionary,
WorkflowStatusDictionary.class,
IMDGDistributedNames.Map_ServiceStatusDictionary,
ServiceStatusDictionary.class,
CompanyErrors.RequiredFieldEmpty,
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.CompanySymbols;
import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
@ -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.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.enumeration.UserRole;
@ -46,15 +46,13 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
private final ImdgId idSequence;
private final Imdg<Company> companyIMap;
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 AccountNotificationHelper accountNotification;
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
public CompanyService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
@ -134,7 +132,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
try {
if (req.getCompanySymbol() != null) {
CompanySymbols newSymbol = companySymbolService.createCompanySymbol(transaction, company.getId(), req.getCompanySymbol(), req.getCompanySymbolValue());
updateCompanyBySymbol(company, newSymbol);
updateCompanyBySymbol(company, newSymbol, false);
}
company.setWorkflowStatus(req.getWorkflowStatus());
@ -215,20 +213,26 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
return null;
}
protected void updateCompanyBySymbol(Company company, CompanySymbols companySymbol) {
protected void updateCompanyBySymbol(Company company, CompanySymbols companySymbol, boolean shouldBeDeleted) {
assert company.getId().equals(companySymbol.getCompanyId());
String companySymbolValue = companySymbol.getCompanySymbolValue();
String setUpValue = shouldBeDeletedOrSet(companySymbolValue, shouldBeDeleted);
if (CompanySymbol.TRDC.equalsByKey(companySymbol.getCompanySymbol())) {
company.setTradingCode(companySymbol.getCompanySymbolValue());
company.setTradingCode(setUpValue);
}
if (CompanySymbol.CLRC.equalsByKey(companySymbol.getCompanySymbol())) {
company.setClearingCode(companySymbol.getCompanySymbolValue());
company.setClearingCode(setUpValue);
}
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) {
throw new IllegalArgumentException("Required companySymbol.companyId");
}
@ -241,7 +245,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
if (company == null) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyNotFound, companySymbol.getCompanyId()));
}
updateCompanyBySymbol(company, companySymbol);
updateCompanyBySymbol(company, companySymbol, shouldBeDeleted);
company.setUpdated(Instant.now());
companyMap.update(company);
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.stereotype.Service;
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.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolNewRequest;
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.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.UserRole;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.ImdgTransaction;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.error.ClearingBaseException;
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 ImdgProvider imdgProvider;
private final ImdgId idSequence;
protected CompanyService companyService;
private final RequestHelper requestHelper;
protected CompanyService companyService;
protected ValidationHelper validationHelper;
protected UserRoleVerification userRoleVerification;
protected Function<CompanySymbolUpdateRequest, IValidator> companySymbolNewRequestValidator;
protected Function<CompanySymbolNewRequest, IValidator> companySymbolNewRequestValidator;
protected Function<CompanySymbolUpdateRequest, IValidator> companySymbolUpdateRequestValidator;
protected Function<CommonDeleteRequest, IValidator> companySymbolDeleteRequestValidator;
@Autowired
public CompanySymbolService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
@ -50,7 +54,9 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
ValidationHelper validationHelper,
UserRoleVerification userRoleVerification,
@Qualifier("companySymbolNewRequestValidator")
Function<CompanySymbolUpdateRequest, IValidator> companySymbolNewRequestValidator,
Function<CompanySymbolNewRequest, IValidator> companySymbolNewRequestValidator,
@Qualifier("companySymbolDeleteRequestValidator")
Function<CommonDeleteRequest, IValidator> companySymbolDeleteRequestValidator,
@Qualifier("companySymbolUpdateRequestValidator")
Function<CompanySymbolUpdateRequest, IValidator> companySymbolUpdateRequestValidator
) {
@ -64,16 +70,20 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
userRoleVerification.setRoleForVerification(UserRole.Admin);
this.companySymbolNewRequestValidator = companySymbolNewRequestValidator;
this.companySymbolUpdateRequestValidator = companySymbolUpdateRequestValidator;
this.companySymbolDeleteRequestValidator = companySymbolDeleteRequestValidator;
}
@Override
public void afterPropertiesSet() {
callback(CompanySymbolUpdateRequest.class)
callback(CompanySymbolNewRequest.class)
.setFunction(this::companySymbolNew)
.forDestination(Consts.DESTINATION_COMPANY_SYMBOL_NEW, callbacks::put);
callback(CompanySymbolUpdateRequest.class)
.setFunction(this::companySymbolUpdate)
.forDestination(Consts.DESTINATION_COMPANY_SYMBOL_UPDATE, callbacks::put);
callback(CommonDeleteRequest.class)
.setFunction(this::companySymbolDelete)
.forDestination(Consts.DESTINATION_COMPANY_SYMBOL_DELETE, callbacks::put);
init();
}
@ -82,8 +92,8 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
}
public RequestInfoUpdate companySymbolNew(BaseRequest<CompanySymbolUpdateRequest> symbolRequest) {
CompanySymbolUpdateRequest req = symbolRequest.getRequestPayload();
public RequestInfoUpdate companySymbolNew(BaseRequest<CompanySymbolNewRequest> symbolRequest) {
CompanySymbolNewRequest req = symbolRequest.getRequestPayload();
log.debug("CompanySymbolNewRequest received, id={}", symbolRequest.getId());
{ // validate
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);
companySymbolsTMap.update(companySymbols);
try {
companyService.updateCompanyBySymbol(transaction, companySymbols);
companyService.updateCompanyBySymbol(transaction, companySymbols, false);
} catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
}
@ -141,15 +151,18 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
try {
Imdg<CompanySymbols> companySymbolsTMap = transaction.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
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());
companySymbolsTMap.update(companySymbols);
try {
companyService.updateCompanyBySymbol(transaction, companySymbols);
} catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
}
companyService.updateCompanyBySymbol(transaction, companySymbols, false);
txOk = true;
} catch (ClearingBaseException e) {
return requestHelper.makeErrorResponse(symbolRequest, e.getEnumMsg());
} finally {
if (txOk)
transaction.commitTransaction();
@ -161,6 +174,42 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
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) {
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.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest;
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 Function<ContactNewRequest, IValidator> contactNewRequestValidator;
private final Function<ContactUpdateRequest, IValidator> contactUpdateRequestValidator;
private final Function<CommonDeleteRequest, IValidator> contactDeleteRequestValidator;
private final UserRoleVerification userRoleVerification;
@Autowired
@ -40,6 +42,7 @@ public class ContactService extends QueueConsumer implements InitializingBean {
ValidationHelper validationHelper,
UserRoleVerification userRoleVerification,
@Qualifier("contactNewRequestValidator") Function<ContactNewRequest, IValidator> contactNewRequestValidator,
@Qualifier("contactDeleteRequestValidator") Function<CommonDeleteRequest, IValidator> contactDeleteRequestValidator,
@Qualifier("contactUpdateRequestValidator") Function<ContactUpdateRequest, IValidator> contactUpdateRequestValidator) {
super(kafkaQueue, kafkaProducer);
this.contactMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Contact, Contact.class);
@ -47,6 +50,7 @@ public class ContactService extends QueueConsumer implements InitializingBean {
this.userRoleVerification = userRoleVerification;
this.contactNewRequestValidator = contactNewRequestValidator;
this.contactUpdateRequestValidator = contactUpdateRequestValidator;
this.contactDeleteRequestValidator = contactDeleteRequestValidator;
}
@Override
@ -57,6 +61,9 @@ public class ContactService extends QueueConsumer implements InitializingBean {
callback(ContactUpdateRequest.class)
.setFunction(this::contactUpdate)
.forDestination(Consts.DESTINATION_CONTACT_UPDATE, callbacks::put);
callback(CommonDeleteRequest.class)
.setFunction(this::companySymbolDelete)
.forDestination(Consts.DESTINATION_CONTACT_DELETE, callbacks::put);
init();
}
@ -98,4 +105,22 @@ public class ContactService extends QueueConsumer implements InitializingBean {
log.debug("successfully processed, id {}", contact.getId());
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.lang.NonNull;
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.profile.ProfileDocument;
import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
@ -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.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.DocumentTypes;
import ru.spcex.platform.enumeration.WorkflowStatus;
@ -38,11 +37,6 @@ import java.util.function.Function;
@Service
public class ProfileDocumentService extends QueueConsumer implements InitializingBean {
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 Function<ProfileDocumentNewRequest, IValidator> profileDocumentNewRequestValidator;
private final Function<ProfileDocumentUpdateRequest, IValidator> profileDocumentUpdateRequestValidator;
@ -51,6 +45,10 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
private final UserRoleVerification userRoleVerification;
protected IMessageResolver messageResolver;
protected RequestHelper requestHelper;
private Imdg<ProfileDocument> profileDocumentMap;
private Imdg<Company> companyMap;
private final ImdgProvider imdgProvider;
private final AccountNotificationHelper accountNotificationHelper;
@Autowired
public ProfileDocumentService(Consumer<String, Object> kafkaQueue,
@ -140,26 +138,25 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
deleteRequest, profileDocumentDeleteRequestValidator
);
if (requestInfoUpdate != null) return requestInfoUpdate;
CommonDeleteRequest profileDocumentDeleteRequest = deleteRequest.getRequestPayload();
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) {
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();
transaction.beginTransaction();
boolean txOk = false;
try {
companyService.relationService.cancelingOfAgreementUpdateRelation(transaction, profileDocument.getCompanyId());
Imdg<ProfileDocument> txProfileDocumentMap= transaction.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class);
companyService.relationService.cancelingOfAgreementUpdateRelation(transaction, profileDocument.getCompanyId());
Imdg<ProfileDocument> txProfileDocumentMap = transaction.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class);
txProfileDocumentMap.delete(profileDocument);
txOk = true;
} 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.relation.Relation;
import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.*;
import ru.spcex.clearing.platform.messaging.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.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.ClearingCategory;
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.ImdgProvider;
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.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.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;
@Service
@ -59,9 +59,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
protected RequestHelper requestHelper;
protected ValidationHelper validationHelper;
private Function<RelationNewRequest, IValidator> relationNewRequestValidator;
private Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator;
private Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator;
private final Function<RelationNewRequest, IValidator> relationNewRequestValidator;
private final Function<RelationUpdateRequest, IValidator> relationUpdateRequestValidator;
private final Function<CommonDeleteRequest, IValidator> relationDeleteRequestValidator;
@Autowired
public RelationService(Consumer<String, Object> kafkaQueue,
@ -117,7 +117,7 @@ public class RelationService extends QueueConsumer implements InitializingBean {
{ //проверка заполнен ли serviceStatus
String serviceStatus = req.getServiceStatus();
if (serviceStatus == null || serviceStatus.isEmpty()) {
Company company = companyMap.getSingleObjectByFieldValues(Map.of("id", req.getCompanyId()));
Company company = companyMap.getSingleObjectByID(req.getCompanyId());
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());
} else {
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;
log.debug("Request has no status. Set status by company[{}].status={}. Relation[{}].serviceSStatus={}",
company.getId(), company.getWorkflowStatus(), toStatus);
@ -231,9 +231,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
}
Company company = companyMap.getSingleObjectByID(relation.getConsumerId());
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;
if (ServiceStatus.Active.equalsByKey(toStatus) && ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) {
if (ServiceStatus.Active.equalsByKey(toStatus) && Closed.equalsByKey(relation.getServiceStatus())) {
relation.setServiceStatus(ServiceStatus.Reopened.getKey());
log.debug("Set status by resume: {}", relation.getServiceStatus());
} 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));
WorkflowStatus workflowStatus = getEnumByKey(WorkflowStatus.class, company.getWorkflowStatus());
ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
String serviceStatus;
switch (Objects.requireNonNull(clearingCategory)){
switch (Objects.requireNonNull(clearingCategory)) {
case B:
case I:
case V:
@ -313,10 +313,11 @@ public class RelationService extends QueueConsumer implements InitializingBean {
log.debug("New Relation[{}] created.", relation.getId());
relationMap.insert(relation);
}
protected void cancelingOfAgreementUpdateRelation(ImdgTransaction transaction, Long companyId) {
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
Relation relation = relationMap.getSingleObjectByFieldValues(Map.of("consumerId", companyId));
relation.setServiceStatus(CLOS.getKey());
relation.setServiceStatus(Closed.getKey());
relationMap.update(relation);
log.debug("New Relation[{}] updated.", relation.getId());
}
@ -356,8 +357,8 @@ public class RelationService extends QueueConsumer implements InitializingBean {
modified = true;
}
} else if (WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus())) {
if (!ServiceStatus.Closed.equalsByKey(relation.getServiceStatus())) {
relation.setServiceStatus(ServiceStatus.Closed.getKey());
if (!Closed.equalsByKey(relation.getServiceStatus())) {
relation.setServiceStatus(Closed.getKey());
modified = true;
}
}

View file

@ -3,17 +3,12 @@ package ru.spcex.clearing.company.validation;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.spcex.clearing.company.error.CompanyErrors;
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.CompanySymbolUpdateRequest;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolNewRequest;
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.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@ -21,10 +16,10 @@ import java.util.Optional;
/**
* Проверка наличия CompanySymbols с переданными в запросе companySymbol и companyId
*/
public class CompanySymbolOfSymbolNewRequestNotExistRule implements IValidationRule<ImdgValidationContext<CompanySymbolUpdateRequest>> {
public class CompanySymbolOfSymbolNewRequestNotExistRule implements IValidationRule<ImdgValidationContext<CompanySymbolNewRequest>> {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<CompanySymbolUpdateRequest> context) {
CompanySymbolUpdateRequest request = context.getValidatedObject();
public Optional<EnumMessage> validate(ImdgValidationContext<CompanySymbolNewRequest> context) {
CompanySymbolNewRequest request = context.getValidatedObject();
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;
public enum MarketType implements IEnumKey {
PRMR("PRMR");
PRMR("PRMR"), SCND("SCND");
private final String key;

View file

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

View file

@ -3,7 +3,9 @@ package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.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) {
this.key = key;

View file

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

View file

@ -33,5 +33,25 @@
<groupId>ru.spcex.platform</groupId>
<artifactId>platform-utils</artifactId>
</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>
</project>

View file

@ -52,6 +52,10 @@ public class RegistryCodeSqlBuilder {
}
if (tradingParams.registryUnit() != null) {
condition.append(String.format("registryUnit = '%s'", tradingParams.registryUnit().getKey()));
wasAddedCondition = true;
}
if (!wasAddedCondition) {
condition.delete(condition.length() - " and ".length(), condition.length());
}
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 SDF54_PROCESS = "sdf54-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 EXPORT_PROCESS = "export-process";
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;
}
}