This commit is contained in:
AKurakin 2023-04-01 21:41:46 +03:00
parent f99989145c
commit ee86ba8340
10 changed files with 354 additions and 2 deletions

View file

@ -92,7 +92,7 @@ import static ru.spcex.clearing.backendapi.controller.utils.MatcherFactory.using
BankAccountController.class,
//company
CompanyRoleSetController.class,
//fixme на 31.03.2023 нет такого класса DeleteCompanyController.class,
CompanyController.class,
EditClearingMemberCategoryController.class,
EditCompanyInfoController.class,
EditCompanySymbolController.class,

View file

@ -0,0 +1,68 @@
package ru.spcex.clearing.validation.common;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
import java.util.function.Function;
/**
* Проверка поля со значением из множества (enum)
* @param <R> Класс проверяемого объекта
* @param <E> Enum
*/
public record EnumPresentRule<R, E extends IEnumKey>(String fieldName,
Function<R, String> getter,
E[] enumValues,
boolean required,
IEnumId errorWrongEnumValue,
IEnumId errorEmptyRequiredValue) implements IValidationRule<ImdgValidationContext<R>> {
/**
* @param fieldName Название поля
* @param getter Метод получения проверяемого значения
* @param enumValues Значения из проверяемого множества (Enum.values())
* @param required Флаг обязательности
* @param <R> Класс проверяемого объекта
* @param <E> Enum
*/
public static <R, E extends IEnumKey> EnumPresentRule<R, E> instance(String fieldName,
Function<R, String> getter,
E[] enumValues,
boolean required,
IEnumId errorWrongEnumValue,
IEnumId errorEmptyRequiredValue) {
if (errorWrongEnumValue == null) throw new IllegalArgumentException("Empty errorWrongEnumValue");
if (required && errorEmptyRequiredValue == null) throw new IllegalArgumentException("Empty errorEmptyRequiredValue");
return new EnumPresentRule<>(fieldName, getter, enumValues, required, errorWrongEnumValue, errorEmptyRequiredValue);
}
/**
* @param fieldName Название поля
* @param getter Метод получения проверяемого значения
* @param enumValues Значения из проверяемого множества (Enum.values())
* @param <R> Класс проверяемого объекта
* @param <E> Enum
*/
public static <R, E extends IEnumKey> EnumPresentRule<R, E> instance(String fieldName,
Function<R, String> getter,
E[] enumValues,
IEnumId errorWrongEnumValue,
IEnumId errorEmptyRequiredValue) {
return new EnumPresentRule<>(fieldName, getter, enumValues, true, errorWrongEnumValue, errorEmptyRequiredValue);
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<R> context) {
R validatedObject = context.getValidatedObject();
String enumCode = getter.apply(validatedObject);
if (enumCode == null) return required ? of(errorEmptyRequiredValue, fieldName) : empty();
for (E enumValue : enumValues) {
if (enumValue.getKey().equals(enumCode)) return empty();
}
return of(errorWrongEnumValue, fieldName);
}
}

View file

@ -0,0 +1,37 @@
package ru.spcex.clearing.validation.common;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
import java.util.function.Function;
/**
* Проверка обязательности поля (not null)
* @param <R> Класс проверяемого объекта
* @param <V> Класс проверяемого значения
*/
public record FieldRequiredRule<R, V>(String fieldName, Function<R, V> getter, IEnumId errorEmptyRequiredValue) implements IValidationRule<ImdgValidationContext<R>> {
/**
* @param fieldName Название поля
* @param getter Метод получения значения
* @param <R> Класс проверяемого объекта
* @param <V> Класс проверяемого значения
*/
public static <R, V> FieldRequiredRule<R, V> instance(String fieldName, Function<R, V> getter, IEnumId errorEmptyRequiredValue) {
if (errorEmptyRequiredValue == null) throw new IllegalArgumentException("Empty errorEmptyRequiredValue");
return new FieldRequiredRule<>(fieldName, getter, errorEmptyRequiredValue);
}
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<R> context) {
R validatedObject = context.getValidatedObject();
V value = getter.apply(validatedObject);
if (value == null) return of(errorEmptyRequiredValue, fieldName);
return empty();
}
}

View file

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

View file

@ -0,0 +1,48 @@
package ru.spcex.clearing.company.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.validation.common.FieldRequiredRule;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.validation.IValidator;
import ru.spcex.platform.utils.validation.ValidatorImpl;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
@Configuration
public class CompanyValidationConfig {
@Bean("companyNewRequestValidator")
public Function<CompanyNewRequest, IValidator> companyNewRequestValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return companyNewRequest -> {
ImdgValidationContext<CompanyNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(companyNewRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
// addImdg.accept(IMDGDistributedNames.Map_TaskDictionary);
// addImdg.accept(IMDGDistributedNames.Map_TaskStatusDictionary);
addImdg.accept(IMDGDistributedNames.Map_Company);
// addImdg.accept(IMDGDistributedNames.Map_Security);
return new ValidatorImpl<>(context
// ,
// FieldRequiredRule.instance("shortName", CompanyNewRequest::getShortName, CompanyErrors.RequiredFieldEmpty),
// FieldRequiredRule.instance("companySymbol", CompanyNewRequest::getCompanySymbol, CompanyErrors.RequiredFieldEmpty),
// FieldRequiredRule.instance("companySymbolValue", CompanyNewRequest::getCompanySymbolValue, CompanyErrors.RequiredFieldEmpty),
// FieldRequiredRule.instance("workflowStatus", CompanyNewRequest::getWorkflowStatus, CompanyErrors.RequiredFieldEmpty),
// DictionaryPresentRule.instance("workflowStatus",
// CompanyNewRequest::getWorkflowStatus,
// IMDGDistributedNames.Map_WorkflowStatus,
// WorkflowStatusDictionary.class),
);
};
}
}

View file

@ -0,0 +1,35 @@
package ru.spcex.clearing.company.error;
import ru.spcex.platform.utils.enumeration.IEnumId;
public enum CompanyErrors implements IEnumId {
GeneralError(3000L), // Общая ошибка модуля company-service
UserVerifyDenial(3001L), // 'Нет прав на проведение данной операции
RequiredFieldEmpty(3002L), // Не заданы обязательные поля %s.
DictionaryNotFound(3003L), // Запись с идентификатором %s в справочнике %s не найдена.
VrongFieldValue(3004L), // Неверное значение поля %s.
RecordAlreadyExist(3005L), // Запись с идентификатором %s уже существует.
RecordNotFound(3006L), // Запись с идентификатором %s не найдена.
CompanyALreadyExist(3010L), // Компания %s уже существует
CompanyNotFound(3011L), // Компания %s не найдена.
CompanyDisabled(3012L), // Компания %s неактивна.
ProfileNotFound(3013L), // Профиль компании %s не найден.
CompanyInfoNotFound(3014L), // Реквизит компании %s не найден.
ContactNotFound(3015L), // Контакт компании %s не найден.
CategoryNotFound(3016L), // Категория компании %s не найдена.
CategoryAlreadySet(3017L), // Компании %s уже присвоена категория %s.
CompanyAlreadyHas_(3018L), // У компании %s присутствуют обязательства.
;
private final Long id;
CompanyErrors(Long id) {
this.id = id;
}
@Override
public Long getId() {
return id;
}
}

View file

@ -6,6 +6,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.company.Company;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
@ -14,19 +15,44 @@ 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.CompanyNewRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
//import ru.spcex.clearing.util.security.UserRoleVerification;
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.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.error.ValidationException;
import ru.spcex.platform.utils.validation.IValidator;
import java.time.Instant;
import java.util.Optional;
import java.util.function.Function;
@Service
public class CompanyService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<Company> companyMap;
private final ImdgId idSequence;
// protected UserRoleVerification userRoleVerification;
protected IMessageResolver messageResolver;
private Function<CompanyNewRequest, IValidator> companyNewRequestValidator;
@Autowired
public CompanyService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
ImdgProvider imdgProvider) {
ImdgProvider imdgProvider,
IMessageResolver messageResolver,
// , UserRoleVerification userRoleVerification
@Qualifier("companyNewRequestValidator")
Function<CompanyNewRequest, IValidator> companyNewRequestValidator
) {
super(kafkaQueue, kafkaProducer);
this.messageResolver = messageResolver;
this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
this.idSequence = imdgProvider.getImdgIdGenerator();
// this.userRoleVerification = userRoleVerification;
this.companyNewRequestValidator = companyNewRequestValidator;
}
@Override
@ -37,23 +63,87 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
callback(CompanyNewRequest.class)
.setConsumer(this::createCompany)
.forDestination(Consts.DESTINATION_COMPANY_NEW, callbacks::put);
callback(CompanyNewRequest.class)
.setConsumer(this::updateCompany)
.forDestination(Consts.DESTINATION_COMPANY_UPDATE, callbacks::put);
//todo IV - сообщения на добавления документа расторжения договора - см. Документ расторжения договора. profileDocument): необходимо обновить запись в company согласно описанию с тэгом "При обработке расторжения".
// callback(CompanyNewRequest.class)
// .setConsumer(this::updateCompany)
// .forDestination(Consts.DESTINATION_COMPANY_UPDATE, callbacks::put);
init();
}
protected void validateRole(BaseRequest<CompanyNewRequest> req) throws ValidationException {
Long requestor = null; // todo требуется передавать это значение из frontendapi! req.getUserId();
// if (!userRoleVerification.userHasRole(requestor, UserRole.Admin)) {
//
// };
}
void validate(CompanyNewRequest object) throws ValidationException {
IValidator validator = companyNewRequestValidator.apply(object);
Optional<EnumMessage> error = validator.tillFirstError();
if (error.isPresent()) {
log.warn("CompanyNewRequest validation error: {}", error.get());
String errorMsg = messageResolver.resolve(error.get());
// return new RequestInfoUpdate() // todo reply message
// .setId(userRequest.getId())
// .setStatus(Status.Error)
// .setMessage(errorMsg);
}
}
private void createCompany(BaseRequest<CompanyNewRequest> companyNewRequestBaseRequest) {
CompanyNewRequest req = companyNewRequestBaseRequest.getRequestPayload();
log.debug("company-new request received, BaseRequest.id = {}", companyNewRequestBaseRequest.getId());
try {
validateRole(companyNewRequestBaseRequest);
validate(req);
} catch (ValidationException e) {
throw new RuntimeException(e); // todo true return error
}
Company company = new Company();
company.setId(idSequence.nextId());
Instant now = Instant.now();
company.setCreated(now);
company.setUpdated(now);
company.setShortName(req.getShortName());
company.setFullName(req.getFullName());
company.setTradingCode(req.getTradingCode());
company.setClearingCode(req.getClearingCode());
company.setRegistrationCode(req.getRegistrationCode());
company.setWorkflowStatus(WorkflowStatus.Active.getKey());
// if (WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
//
// } else if (WorkflowStatus.Blocked.equalsByKey(company.getWorkflowStatus())) {
//
// }
companyMap.insert(company);
log.debug("company-new request processed, BaseRequest.id = {}, company.id={}",
companyNewRequestBaseRequest.getId(), company.getId());
}
private void updateCompany(BaseRequest<? /* todo type CompanyUpdateRequest*/> companyNewRequestBaseRequest) {
//todo update
// CompanyUpdateRequest req = companyUpdateRequestBaseRequest.getRequestPayload();
// log.debug("company-update request received, BaseRequest.id = {}", companyNewRequestBaseRequest.getId());
// Company company = new Company();
// company.setShortName(req.getShortName());
// company.setFullName(req.getFullName());
// company.setTradingCode(req.getTradingCode());
// company.setClearingCode(req.getClearingCode());
// company.setRegistrationCode(req.getRegistrationCode());
// companyMap.insert(company);
// log.debug("company-update request processed, BaseRequest.id = {}, company.id={}",
// companyNewRequestBaseRequest.getId(), company.getId());
}
private void deleteCompany(BaseRequest<CommonDeleteRequest> userRequest) {
CommonDeleteRequest req = userRequest.getRequestPayload();
log.debug("CommonDeleteRequest received id = {}", req.getId());

View file

@ -23,6 +23,7 @@ public interface Consts {
String DESTINATION_COMPANY_NEW = "company-new";
String DESTINATION_COMPANY_DELETE = "company-delete";
String DESTINATION_COMPANY_UPDATE = "company-update";
String DESTINATION_COMPANY_INFO_UPDATE = "company-info-update";
String DESTINATION_COMPANY_SYMBOL_UPDATE = "company-symbol-update";
String DESTINATION_CONTACT_UPDATE = "contact-update";

View file

@ -0,0 +1,39 @@
package ru.spcex.platform.utils.error;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import java.util.Arrays;
public class ClearingBaseException extends Exception {
final EnumMessage enumMsg;
public ClearingBaseException(EnumMessage msg) {
super(msg == null ? "" : msg.getSubject().getId() + " " + (msg.getArgs() == null ? "" : Arrays.toString(msg.getArgs())));
this.enumMsg = msg;
}
public <ErrorEnum extends IEnumId> ClearingBaseException(ErrorEnum code) {
this(new EnumMessage(code));
}
public <ErrorEnum extends IEnumId> ClearingBaseException(ErrorEnum code, String message) {
super(code == null ? message : code.getId() + " " + message);
this.enumMsg = new EnumMessage(code);
}
public <ErrorEnum extends IEnumId> ClearingBaseException(ErrorEnum code, String message, Throwable cause) {
super(code == null ? message : code.getId() + " " + message, cause);
this.enumMsg = new EnumMessage(code);
}
// public <ErrorEnum extends IEnumId> ClearingBaseException(String message, Throwable cause) {
// super(message, cause);
// this.enumMsg = new EnumMessage(ClearingError.GeneralError);
// }
public EnumMessage getEnumMsg() {
return enumMsg;
}
}

View file

@ -0,0 +1,20 @@
package ru.spcex.platform.utils.error;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
public class ValidationException extends ClearingBaseException {
public ValidationException(EnumMessage msg) {
super(msg);
}
public <ErrorEnum extends IEnumId> ValidationException(ErrorEnum code, String... args) {
super(new EnumMessage(code, args));
}
public <ErrorEnum extends IEnumId> ValidationException(ErrorEnum code, String message) {
super(code, message);
}
}