Refactoring after review

This commit is contained in:
Mikhail Trofimov 2025-07-03 14:06:20 +00:00
parent 307f43f49b
commit 3ed2902219
46 changed files with 1198 additions and 640 deletions

View file

@ -0,0 +1,91 @@
package ru.nbch.credit_tracker.builder;
import org.apache.commons.lang3.StringUtils;
import ru.nbch.credit_tracker.entities.signal_package.Person;
import ru.nbch.credit_tracker.service.indic.PersonService;
import ru.nbch.credit_tracker.utils.CTUtil;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
public class PersonFactoryBuilder {
private final static DateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy");
private final static String DEFAULT_DATE = "01.01.2000";
private final static String IP = "0";
private final static String OKSM = "999";
private final static String CONSENT_PURPOSE = "16";
private final static String REPORT_USER = "АО «НБКИ»";
private final static String LIABILITY = "1";
private final static String CONSENT_PERIOD = "3";
private final static String REPORT_USER_REG_NUM = "1057746710713";
private final static String REPORT_USER_TAX_ID = "7703548386";
private final static String CONSENT_HASH = "hash";
private final static String CONSENT_DIV_CODE = "000-000";
private final static String INQ_PURPOSE = "16";
private PersonService.PersonData personData;
private String uid;
public static PersonFactoryBuilder builder() {
return new PersonFactoryBuilder();
}
public PersonFactoryBuilder personData(PersonService.PersonData personData) {
this.personData = personData;
return this;
}
public PersonFactoryBuilder uid(String uid) {
this.uid = uid;
return this;
}
public Person build() {
if (personData == null) {
return null;
}
PersonService.NameData nameData = personData.getName();
PersonService.PassportData passportData = personData.getPassport();
Person person = new Person();
person.setS(nameData.getLastName());
person.setN(nameData.getFirstName());
person.setM(StringUtils.isNotBlank(nameData.getMiddleName()) ? nameData.getMiddleName() : null);
person.setD(DATE_FORMAT.format(CTUtil.localDatetoDate(nameData.getBirthDate())));
person.setPn(getPn(passportData.getSerNum(), passportData.getIdNum()));
person.setPd(passportData.getIssDate() != null ? DATE_FORMAT.format(CTUtil.localDatetoDate(passportData.getIssDate())) : DEFAULT_DATE);
person.setDt(StringUtils.isNotBlank(passportData.getIdType2()) ? passportData.getIdType2() : passportData.getIdType());
person.setIp(IP);
person.setUid(uid);
person.setOksm(OKSM);
person.setConsentDate(DATE_FORMAT.format(CTUtil.localDatetoDate(LocalDate.now())));
person.setConsentPurpose(CONSENT_PURPOSE);
person.setReportUser(REPORT_USER);
person.setLiability(LIABILITY);
person.setConsentPeriod(CONSENT_PERIOD);
person.setAgrDate(DATE_FORMAT.format(CTUtil.localDatetoDate(LocalDate.now())));
person.setReportUserRegNum(REPORT_USER_REG_NUM);
person.setReportUserTaxID(REPORT_USER_TAX_ID);
person.setConsentHash(CONSENT_HASH);
person.setCs(person.getS());
person.setConsentN(person.getN());
person.setConsentM(person.getM());
person.setConsentBd(person.getD());
person.setConsentPn(person.getPn());
person.setConsentPd(person.getPd());
person.setConsentDivCode(CONSENT_DIV_CODE);
person.setConsentDt(person.getDt());
person.setInqPurpose(INQ_PURPOSE);
return person;
}
private String getPn(String serNum, String idNum) {
String normSerNum = CTUtil.normalize(serNum);
String normIdNum = CTUtil.normalize(idNum);
return StringUtils.isNotBlank(normSerNum) ? normSerNum + normIdNum : normIdNum;
}
}

View file

@ -6,22 +6,44 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import ru.nbch.credit_tracker.entities.response.errors.CommonError;
import ru.nbch.credit_tracker.exceptions.SignalErrorException;
import ru.nbch.credit_tracker.entities.response.errors.*;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.exceptions.SignalException;
import ru.nbch.credit_tracker.utils.error.SimpleMessageResolver;
import java.nio.charset.Charset;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = SignalErrorException.class, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<CommonError> handleInvalidUser(SignalErrorException ex) {
private final SimpleMessageResolver messageResolver = new SimpleMessageResolver();
@ExceptionHandler(value = SignalException.class, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<CommonError> handleClientException(SignalException ex) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("application", "xml", Charset.forName("windows-1251")));
if (ex.isUserError()) {
return new ResponseEntity<>(ex.getError(), headers, HttpStatus.BAD_REQUEST);
CommonError commonError = getCommonError(ex);
commonError.setStatus("error");
commonError.setErrorCode(ex.getErrorMessage().getSubject().getErrorCode());
commonError.setErrorText(messageResolver.resolve(ex.getErrorMessage()));
if (ex instanceof SignalClientException) {
return new ResponseEntity<>(commonError, headers, HttpStatus.BAD_REQUEST);
} else {
return new ResponseEntity<>(ex.getError(), headers, HttpStatus.INTERNAL_SERVER_ERROR);
return new ResponseEntity<>(commonError, headers, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private static CommonError getCommonError(SignalException ex) {
CommonError commonError;
switch (ex.getErrorFormat()) {
case MonitoringError -> commonError = new MonitoringError();
case MonitoringActivePackagesError -> commonError = new MonitoringActivePackagesError();
case MonitoringDownloadError -> commonError = new MonitoringDownloadError();
case MonitoringReportListError -> commonError = new MonitoringReportListError();
case MonitoringPackageDeleteError -> commonError = new MonitoringPackageDeleteError();
default -> throw new IllegalStateException("Unsupported error format: " + ex.getErrorFormat());
}
return commonError;
}
}

View file

@ -1,8 +1,8 @@
package ru.nbch.credit_tracker.service.xml.jaxb;
package ru.nbch.credit_tracker.config.xml;
import jakarta.xml.bind.JAXBException;
import org.springframework.stereotype.Service;
import org.xml.sax.SAXException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.response.errors.MonitoringError;
import ru.nbch.credit_tracker.entities.response.monitoring_signal_response.MonitoringSignalResponse;
@ -10,32 +10,22 @@ import ru.nbch.credit_tracker.entities.response.online_download.OnlineDownloadRe
import ru.nbch.credit_tracker.entities.response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.entities.response.success.MonitoringResponse;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.XmlProcessorImplAnyClasses;
import ru.nbch.credit_tracker.service.xml.stax.SgnlReportStatusStaxReader;
import ru.nbch.credit_tracker.service.xml.stax.StaxReader;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import ru.nbch.credit_tracker.service.xml.stax.XmlProcessorStaxImpl;
import javax.xml.XMLConstants;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stax.StAXSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
@Configuration
public class XmlConfig {
@Service
public class XmlUtilService {
public IXmlProcessor createJaxbProcessor() throws JAXBException {
@Bean
public IXmlProcessor xmlProcessor() throws JAXBException {
return new XmlProcessorImplAnyClasses(Charset.forName("windows-1251"),
// unmarshalling classes
MonitoringRequest.class,
@ -48,24 +38,10 @@ public class XmlUtilService {
MonitoringSignalResponse.class);
}
@Bean
public StaxXmlProcessor staxXmlProcessor() {
List<StaxReader<?>> staxReader = new ArrayList<>();
staxReader.add(new SgnlReportStatusStaxReader());
return new XmlProcessorStaxImpl(staxReader);
}
public void validateXMLByXSD(InputStream xmlStream, String xsdPath) throws IOException, XMLStreamException, SAXException {
SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File(xsdPath));
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
Validator validator = schema.newValidator();
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(xmlStream);
validator.validate(new StAXSource(xmlStreamReader));
}
}

View file

@ -7,7 +7,7 @@ import java.time.LocalDateTime;
@Getter
@Setter
public class HitsData {
public class Hit {
private Integer id;
private Integer packageId;
private String subjectId;

View file

@ -1,9 +1,6 @@
package ru.nbch.credit_tracker.entities.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;
import java.time.LocalDateTime;
@ -11,7 +8,8 @@ import java.time.LocalDateTime;
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class SubjectData {
@Builder
public class PhoneFidMap {
private Integer id;
private Integer packageId;
private String subjectId;

View file

@ -1,5 +1,6 @@
package ru.nbch.credit_tracker.entities.dto;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@ -7,7 +8,8 @@ import java.time.LocalDateTime;
@Getter
@Setter
public class PackageData {
@Builder
public class UserPackage {
private Integer id;
private String userId;
private String packageName;

View file

@ -0,0 +1,41 @@
package ru.nbch.credit_tracker.enums;
import java.util.Arrays;
import java.util.Collections;
public class EnumKeyMessage {
private final IEnumKeyCode subject;
/**
* Параметры для подстановки в текст сообщения. Все Serializable.
* args not null.
*/
private Object[] args;
public EnumKeyMessage(IEnumKeyCode subject) {
this.subject = subject;
this.args = Collections.emptyList().toArray(new Object[0]);
}
public EnumKeyMessage(IEnumKeyCode subject, Object... args) {
this.subject = subject;
this.args = args;
}
public IEnumKeyCode getSubject() {
return subject;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
@Override
public String toString() {
return "EnumKeyMessage{subject=" + subject + ", args: " + Arrays.toString(args) + "}";
}
}

View file

@ -0,0 +1,102 @@
package ru.nbch.credit_tracker.enums;
import java.io.Serializable;
import java.util.Objects;
public interface IEnumKeyCode extends Serializable {
String getKey();
String getCode();
default boolean equalsByKey(String key) {
return key != null && getKey().equalsIgnoreCase(key);
}
/**
* Проверяет что среди данного набора Enum, присутствует элемент с данным id
* id может быть null
*/
static <T extends Enum<T> & IEnumKeyCode> boolean contains(String id, T... enumSet) {
for (T e : enumSet) {
if (Objects.equals(id, e.getKey()))
return true;
}
return false;
}
static <T extends Enum<T> & IEnumKeyCode> boolean containsIgnoreCase(String id, T... enumSet) {
for (T e : enumSet) {
if (e.getKey() != null && e.getKey().equalsIgnoreCase(id)) {
return true;
}
}
return false;
}
static <T extends Enum<T> & IEnumKeyCode> boolean contains(T e, T... enumSet) {
for (T enumEl : enumSet) {
if (enumEl.equals(e))
return true;
}
return false;
}
/**
* Проверяет что среди всех Enum данного класса, присутствует элемент с данным id
* id может быть null
*/
static <T extends Enum<T> & IEnumKeyCode> boolean contains(String key, Class<T> enumClass) {
for (T e : enumClass.getEnumConstants()) {
if (Objects.equals(key, e.getKey()))
return true;
}
return false;
}
/**
* Возвращает Enum по id, если в заданном классе такой определен
* id может быть null
*
* @return Enum если нашел, иначе <tt>null</tt>
*/
static <T extends Enum<T> & IEnumKeyCode> T getEnumByKey(Class<T> enumClass, String key) {
for (T e : enumClass.getEnumConstants()) {
if (Objects.equals(key, e.getKey()))
return e;
}
return null;
}
static <T extends Enum<T> & IEnumKeyCode> T getEnumByKeyOrUndefined(Class<T> enumClass, String key) {
T enumByKey = getEnumByKey(enumClass, key);
return enumByKey == null ? getUndefined(enumClass) : enumByKey;
}
static <T extends Enum<T> & IEnumKeyCode> T getUndefined(Class<T> enumClass) {
T enumByKey = getEnumByKey(enumClass, UNDEFINED_VALUE);
if (enumByKey == null) {
throw new IllegalArgumentException("Undefined value not found in enum " + enumClass);
}
return enumByKey;
}
default boolean theSameAs(Object other) {
if (!(other instanceof IEnumKeyCode otherCasted)) {
return false;
}
return this.getKey().equalsIgnoreCase(otherCasted.getKey());
}
default String getErrorCode() {
String key = getKey();
String[] split = key.split("\\.");
if (split.length < 1) return null;
String s = split[split.length - 1];
if (!s.matches("\\d+")) return null;
return s;
}
static String getKeyOrNull(IEnumKeyCode enumVal) {
return enumVal == null ? null : enumVal.getKey();
}
String UNDEFINED_VALUE = "_Undefined";
}

View file

@ -1,9 +1,6 @@
package ru.nbch.credit_tracker.enums;
import lombok.Getter;
@Getter
public enum SignalError {
public enum SignalError implements IEnumKeyCode {
ERROR_001("001", "Ошибка распаковки архива"),
ERROR_002("002", "Отсутствует обязательный элемент: "),
ERROR_003("003", "Элемент ClientId не соответствует формату XXXXXXXXX"),
@ -31,4 +28,16 @@ public enum SignalError {
this.code = code;
this.message = message;
}
@Override
public String getKey() {
return message;
}
@Override
public String getCode() {
return code;
}
}

View file

@ -0,0 +1,10 @@
package ru.nbch.credit_tracker.enums;
public enum XmlErrorFormat {
MonitoringActivePackagesError,
MonitoringDownloadError,
MonitoringError,
MonitoringPackageDeleteError,
MonitoringReportListError
}

View file

@ -0,0 +1,13 @@
package ru.nbch.credit_tracker.exceptions;
import lombok.Getter;
import ru.nbch.credit_tracker.enums.EnumKeyMessage;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
@Getter
public class SignalClientException extends SignalException {
public SignalClientException(EnumKeyMessage errorMessage, XmlErrorFormat errorFormat) {
super(errorMessage, errorFormat);
}
}

View file

@ -1,29 +0,0 @@
package ru.nbch.credit_tracker.exceptions;
import lombok.Getter;
import ru.nbch.credit_tracker.entities.response.errors.CommonError;
import ru.nbch.credit_tracker.enums.SignalError;
@Getter
public class SignalErrorException extends RuntimeException {
private final boolean isUserError;
private final CommonError error;
public SignalErrorException(SignalError signalError, String tag, CommonError error, boolean isUserError) {
this.isUserError = isUserError;
this.error = createErrorMessage(error, signalError, tag);
}
private CommonError createErrorMessage(CommonError errorMessage, SignalError error, String tag) {
errorMessage.setStatus("error");
errorMessage.setErrorCode(error.getCode());
if (tag != null) {
errorMessage.setErrorText(error.getMessage() + " " + tag);
} else {
errorMessage.setErrorText(error.getMessage());
}
return errorMessage;
}
}

View file

@ -0,0 +1,17 @@
package ru.nbch.credit_tracker.exceptions;
import lombok.Getter;
import ru.nbch.credit_tracker.enums.EnumKeyMessage;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
@Getter
public class SignalException extends RuntimeException {
private final EnumKeyMessage errorMessage;
private final XmlErrorFormat errorFormat;
public SignalException(EnumKeyMessage errorMessage,
XmlErrorFormat errorFormat) {
this.errorMessage = errorMessage;
this.errorFormat = errorFormat;
}
}

View file

@ -0,0 +1,12 @@
package ru.nbch.credit_tracker.exceptions;
import ru.nbch.credit_tracker.enums.EnumKeyMessage;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
public class SignalServerException extends SignalException {
public SignalServerException(EnumKeyMessage errorMessage, XmlErrorFormat errorFormat) {
super(errorMessage, errorFormat);
}
}

View file

@ -8,35 +8,41 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.entities.response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.response.errors.*;
import ru.nbch.credit_tracker.entities.response.active_packages.Package;
import ru.nbch.credit_tracker.entities.response.active_packages.Packages;
import ru.nbch.credit_tracker.entities.response.success.MonitoringPackageDeleteResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringReportListResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringResponse;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.exceptions.SignalErrorException;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.service.SignalService;
import ru.nbch.credit_tracker.service.indic.PhoneService;
import ru.nbch.credit_tracker.service.scoring.AuthorizationService;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.XmlUtilService;
import ru.nbch.credit_tracker.utils.CTUtil;
import ru.nbch.credit_tracker.utils.ValidationUtil;
import ru.nbch.credit_tracker.utils.ZipUtils;
import java.io.File;
import java.util.HashSet;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static ru.nbch.credit_tracker.utils.error.ExceptionUtils.clientExcp;
import static ru.nbch.credit_tracker.utils.error.ExceptionUtils.serverExcp;
@Slf4j
@Service
public class SignalFacade {
@ -46,7 +52,7 @@ public class SignalFacade {
private final AuthorizationService authorizationService;
private final SignalService signalService;
private final SignalRestService signalRestService;
private final XmlUtilService xmlUtilService;
private final IXmlProcessor xmlProcessor;
private final ExecutorService executor;
@ -55,89 +61,62 @@ public class SignalFacade {
AuthorizationService authorizationService,
SignalService signalService,
SignalRestService signalRestService,
XmlUtilService xmlUtilService,
IXmlProcessor xmlProcessor,
@Qualifier("executorService") ExecutorService executor) {
this.config = config;
this.authorizationService = authorizationService;
this.signalService = signalService;
this.signalRestService = signalRestService;
this.xmlUtilService = xmlUtilService;
this.xmlProcessor = xmlProcessor;
this.executor = executor;
}
public ResponseEntity<MonitoringResponse> setupMonitoring(MultipartFile file) {
// первичные валидации
if (file.isEmpty()) {
throw new SignalErrorException(SignalError.ERROR_001, null, new MonitoringError(), true);
}
if (!isZipFile(file)) {
throw new SignalErrorException(SignalError.ERROR_001, null, new MonitoringError(), true);
if (file.isEmpty() || !isZipFile(file)) {
throw clientExcp(SignalError.ERROR_001, XmlErrorFormat.MonitoringError);
}
// Валидация Архива на количетсво файлов, размер и расширение
try (ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream())) {
int fileCount = 0;
ZipEntry xmlEntry = null;
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
if (!entry.isDirectory()) {
fileCount++;
if (fileCount > 1) { // Архив должен содержать ровно один XML-файл
throw new SignalErrorException(SignalError.ERROR_001, null, new MonitoringError(), true);
}
if (!entry.getName().toLowerCase().endsWith(".xml")) { // Файл должен быть с расширением xml
throw new SignalErrorException(SignalError.ERROR_001, null, new MonitoringError(), true);
}
xmlEntry = entry;
} else {
throw new SignalErrorException(SignalError.ERROR_001, null, new MonitoringError(), true); // Архив должен содержать ровно один XML-файл. Никаких доп директорий
}
zipInputStream.closeEntry();
entry = zipInputStream.getNextEntry();
}
if (fileCount == 0) { // Архив должен содержать ровно один XML-файл
throw new SignalErrorException(SignalError.ERROR_001, null, new MonitoringError(), true);
}
if (xmlEntry.getSize() > MAX_XML_FILE_SIZE) { // максимально 2 Гб до запаковки
throw new SignalErrorException(SignalError.ERROR_009, null, new MonitoringError(), true);
}
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_100, null, new MonitoringError(), false);
}
// Теперь знаем, что в архиве лежит ровно один файл с раширением xml и он весит меньше 2гб. Можно валидировать сам xml
// Пробуем распарсить xml
MonitoringRequest monitoringRequest;
Integer packageId;
try (ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream())) {
ZipInputStream zipInputStream = null;
try {
zipInputStream = new ZipInputStream(file.getInputStream());
Optional<ZipEntry> xmlFileEntry = ZipUtils.extractValidEntry(zipInputStream);
if (xmlFileEntry.isEmpty()) {
throw clientExcp(SignalError.ERROR_001, XmlErrorFormat.MonitoringError);
}
if (xmlFileEntry.get().getSize() > MAX_XML_FILE_SIZE) {
throw clientExcp(SignalError.ERROR_009, XmlErrorFormat.MonitoringError);
}
zipInputStream.close();
zipInputStream = new ZipInputStream(file.getInputStream());
zipInputStream.getNextEntry();
IXmlProcessor processor = xmlUtilService.createJaxbProcessor();
monitoringRequest = processor.read(zipInputStream, MonitoringRequest.class);
monitoringRequest = xmlProcessor.read(zipInputStream, MonitoringRequest.class);
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_100, null, new MonitoringError(), false);
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
} finally {
if (zipInputStream != null) {
try {
zipInputStream.close();
} catch (IOException e) {
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
}
}
}
// валидация xml
try {
validateMonitoringRequest(monitoringRequest);
} catch (SignalErrorException e) {
ValidationUtil.validateMonitoringRequest(monitoringRequest);
} catch (SignalClientException e) {
signalService.rejectPackage(monitoringRequest);
throw e;
}
@ -147,22 +126,22 @@ public class SignalFacade {
AuthorizationService.AuthResult authResult = authorizationService.findAuthInfo(monitoringRequest.getUserId(), monitoringRequest.getPassword());
if (!authResult.isSuccess()) {
signalService.rejectPackage(monitoringRequest);
throw new SignalErrorException(authResult.getError(), null, new MonitoringError(), true);
throw clientExcp(authResult.getError(), XmlErrorFormat.MonitoringError);
}
// проверка на уникальность пакета
if (signalService.isPackageNotUnique(monitoringRequest)) {
signalService.rejectPackage(monitoringRequest);
throw new SignalErrorException(SignalError.ERROR_007, null, new MonitoringError(), true);
throw clientExcp(SignalError.ERROR_007, XmlErrorFormat.MonitoringError);
}
packageId = signalService.registerPackage(monitoringRequest);
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_100, null, new MonitoringError(), false);
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
}
// в отдельном потоке запускаем поиск фидов и расчет флагов просрочек
@ -171,58 +150,6 @@ public class SignalFacade {
return ResponseEntity.ok().body(new MonitoringResponse());
}
private void validateMonitoringRequest(MonitoringRequest request) throws SignalErrorException {
if (request == null) {
throw new SignalErrorException(SignalError.ERROR_011, null, new MonitoringError(), true);
}
validateReruqredTags(request);
validateTagsTypes(request);
}
private void validateReruqredTags(MonitoringRequest request) throws SignalErrorException {
if (request.getUserId() == null) {
throw new SignalErrorException(SignalError.ERROR_002, "UserId", new MonitoringError(), true);
}
if (request.getPackageName() == null) {
throw new SignalErrorException(SignalError.ERROR_002, "PackageName", new MonitoringError(), true);
}
if (request.getPassword() == null) {
throw new SignalErrorException(SignalError.ERROR_002, "Password", new MonitoringError(), true);
}
if (request.getSubjects() == null) {
throw new SignalErrorException(SignalError.ERROR_002, "Subjects", new MonitoringError(), true);
}
if (request.getSubjects().getSubject().isEmpty()) {
throw new SignalErrorException(SignalError.ERROR_002, "Subject", new MonitoringError(), true);
}
}
private void validateTagsTypes(MonitoringRequest request) throws SignalErrorException {
if (!ValidationUtil.validatePackageName(request.getPackageName())) {
throw new SignalErrorException(SignalError.ERROR_008, null, new MonitoringError(), true);
}
Set<String> uniqueIds = new HashSet<>();
for (Subject subject : request.getSubjects().getSubject()) {
if (!ValidationUtil.validatePhone(subject.getClientId())) {
throw new SignalErrorException(SignalError.ERROR_003, null, new MonitoringError(), true);
}
if (!ValidationUtil.validateNPId(subject.getId())) {
throw new SignalErrorException(SignalError.ERROR_010, null, new MonitoringError(), true);
}
// проверка на уникальность Id внутри одного пакета
if (!uniqueIds.add(subject.getId())) {
throw new SignalErrorException(SignalError.ERROR_004, subject.getId(), new MonitoringError(), true);
}
}
}
private void registerFidsAndDebts(Integer packageId, String packageName) {
executor.execute(() -> {
try {
@ -232,14 +159,14 @@ public class SignalFacade {
// TODO validate xsd?
if (signalRestService.update(signals)) {
log.info("Package was successfully registered in signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.setPackageStatus(packageId, Status.ON_MONITORING);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
} else {
log.info("Package registration was rejected by signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.setPackageStatus(packageId, Status.ERROR);
signalService.updatePackageStatus(packageId, Status.ERROR);
}
}
} catch (Exception e) {
signalService.setPackageStatus(packageId, Status.ERROR);
signalService.updatePackageStatus(packageId, Status.ERROR);
log.error("Ошибка при поиске фидов или расчете флагов просрочек. Package_id {}", packageId, e);
}
});
@ -255,46 +182,65 @@ public class SignalFacade {
try {
AuthorizationService.AuthResult authResult = authorizationService.findAuthInfo(activePackagesRequest.getUserId(), activePackagesRequest.getPassword());
if (!authResult.isSuccess()) {
throw new SignalErrorException(authResult.getError(), null, new MonitoringActivePackagesError(), true);
throw clientExcp(authResult.getError(), XmlErrorFormat.MonitoringActivePackagesError);
}
MonitoringActivePackagesResponse response = signalService.findActivePackages(activePackagesRequest.getUserId());
if (response != null) {
List<UserPackage> activePackages = signalService.findActivePackages(activePackagesRequest.getUserId());
if (!activePackages.isEmpty()) {
MonitoringActivePackagesResponse response = new MonitoringActivePackagesResponse();
response.setStatus("OK");
response.setMembercode(activePackagesRequest.getUserId().substring(0, 6));
Packages packages = new Packages();
activePackages.forEach(data -> {
Package pack = new Package();
pack.setPackageName(data.getPackageName());
pack.setCreatedAt(data.getCreatedAt() != null ? data.getCreatedAt().toString() : null);
packages.getPackages().add(pack);
});
response.setPackages(packages);
return ResponseEntity.ok(response);
} else {
throw new SignalErrorException(SignalError.ERROR_015, null, new MonitoringActivePackagesError(), true);
throw clientExcp(SignalError.ERROR_015, XmlErrorFormat.MonitoringActivePackagesError);
}
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_013, null, new MonitoringActivePackagesError(), false);
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringActivePackagesError);
}
}
public ResponseEntity<MonitoringPackageDeleteResponse> deletePackage(String username, String packageName) {
try {
if (!signalService.isPackageExists(username, packageName)) {
throw new SignalErrorException(SignalError.ERROR_016, packageName, new MonitoringPackageDeleteError(), true);
throw clientExcp(SignalError.ERROR_016, XmlErrorFormat.MonitoringPackageDeleteError, packageName);
}
MonitoringPackageDeleteResponse response = signalService.deletePackage(username, packageName);
LocalDateTime deactivatedAt = LocalDateTime.now();
signalService.deletePackage(username, packageName, deactivatedAt);
MonitoringPackageDeleteResponse response = new MonitoringPackageDeleteResponse();
response.setStatus("Deleted");
response.setPackageName(packageName);
response.setDeactivatedAt(deactivatedAt.toString());
signalRestService.deletePackage(username, packageName);
log.info("Package {} deleted", packageName);
return ResponseEntity.ok(response);
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_017, null, new MonitoringPackageDeleteError(), false);
throw serverExcp(SignalError.ERROR_017, XmlErrorFormat.MonitoringPackageDeleteError);
}
}
public ResponseEntity<MonitoringReportListResponse> getReportList(String username, String packageName) {
try {
if (!signalService.isPackageExists(username, packageName)) {
throw new SignalErrorException(SignalError.ERROR_016, packageName, new MonitoringReportListError(), true);
throw clientExcp(SignalError.ERROR_016, XmlErrorFormat.MonitoringReportListError, packageName);
}
String memberCode = username.substring(0, 6);
@ -306,7 +252,7 @@ public class SignalFacade {
MonitoringReportListResponse.Reports reports = new MonitoringReportListResponse.Reports();
File[] files = folder.listFiles();
if (files == null) {
throw new SignalErrorException(SignalError.ERROR_012, packageName, new MonitoringReportListError(), true);
throw clientExcp(SignalError.ERROR_012, XmlErrorFormat.MonitoringReportListError, packageName);
}
for (File file : files) {
if (file.isFile() && file.getName().startsWith(filePrefix)) {
@ -315,7 +261,7 @@ public class SignalFacade {
}
if (reports.getReports().isEmpty()) {
throw new SignalErrorException(SignalError.ERROR_012, packageName, new MonitoringReportListError(), true);
throw clientExcp(SignalError.ERROR_012, XmlErrorFormat.MonitoringReportListError, packageName);
} else {
MonitoringReportListResponse response = new MonitoringReportListResponse();
response.setPackageName(packageName);
@ -324,14 +270,14 @@ public class SignalFacade {
}
} else {
log.error("Пакет {} был найден в бд для memberCode {}, но ни одного архива не было найдено в папке {}", packageName, username, dirPath);
throw new SignalErrorException(SignalError.ERROR_013, packageName, new MonitoringReportListError(), true);
throw clientExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringReportListError, packageName);
}
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_013, null, new MonitoringReportListError(), false);
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringReportListError);
}
}
@ -347,15 +293,15 @@ public class SignalFacade {
return ResponseEntity.ok().body(new FileUrlResource(file.getPath()));
}
} else {
throw new SignalErrorException(SignalError.ERROR_014, null, new MonitoringDownloadError(), true);
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError);
}
throw new SignalErrorException(SignalError.ERROR_014, null, new MonitoringDownloadError(), true);
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError);
} catch (Exception e) {
if (e instanceof SignalErrorException) {
throw (SignalErrorException) e;
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
log.error(e.getMessage(), e);
throw new SignalErrorException(SignalError.ERROR_013, null, new MonitoringDownloadError(), false);
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringDownloadError);
}
}
}

View file

@ -0,0 +1,14 @@
package ru.nbch.credit_tracker.mapper.signal;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import ru.nbch.credit_tracker.entities.dto.Hit;
import java.util.List;
@Mapper
public interface HitsMapper {
void insertHits(@Param("hits") List<Hit> hits);
}

View file

@ -0,0 +1,21 @@
package ru.nbch.credit_tracker.mapper.signal;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import java.util.List;
@Mapper
public interface PhoneFidMapMapper {
void registerSubjects(@Param("subjects") List<Subject> subjects, @Param("packageId") Integer packageId);
List<PhoneFidMap> findPhoneFidMaps(@Param("packageId") Integer packageId);
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Integer packageId);
void updatePhoneFidMaps(@Param("subjects") List<PhoneFidMap> subjects);
}

View file

@ -1,48 +0,0 @@
package ru.nbch.credit_tracker.mapper.signal;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import ru.nbch.credit_tracker.entities.dto.HitsData;
import ru.nbch.credit_tracker.entities.dto.PackageData;
import ru.nbch.credit_tracker.entities.dto.SubjectData;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import java.time.LocalDateTime;
import java.util.List;
@Mapper
public interface SignalMapper {
boolean isPackageNotUnique(@Param("userId") String userId, @Param("packageName") String packageName);
boolean isPackageExists(@Param("userId") String userId, @Param("packageName") String packageName, @Param("status") String status);
void deletePackage(@Param("userId") String userId, @Param("packageName") String packageName, @Param("status") String newStatus, @Param("previousStatus") String previousStatus, @Param("deactivatedAt") LocalDateTime deactivatedAt);
Integer registerPackage(@Param("request") MonitoringRequest request, @Param("creadedAt") LocalDateTime creadedAt, @Param("status") String status);
void registerSubjects(@Param("subjects") List<Subject> subjects, @Param("packageId") Integer packageId);
void insertPackage(@Param("request") MonitoringRequest request, @Param("creadedAt") LocalDateTime creadedAt, @Param("status") String status);
void registerSubjectsFidAndDebts(@Param("id") Integer id, @Param("fid") Integer fid, @Param("flagDebt5000") Integer flagDebt5000, @Param("flag90") Integer flag90, @Param("calculatedAt") LocalDateTime calculatedAt);
void setPackageStatus(@Param("packageId") Integer packageId, @Param("status") String status);
List<SubjectData> findSubjectsData(@Param("packageId") Integer packageId);
List<SubjectData> findFullSubjectsData(@Param("packageId") Integer packageId);
PackageData findPackageData(@Param("id") Integer id);
List<PackageData> findPackageDataList(@Param("userId") String userId, @Param("status") String status);
List<PackageData> findPackagesByStatus(@Param("status") String status);
void setHits(@Param("hits") List<HitsData> hits);
void updateSubjects(@Param("subjects") List<SubjectData> subjects);
void setPackageLastDownloadedReport(@Param("id") Integer id, @Param("fileName") String fileName);
}

View file

@ -0,0 +1,31 @@
package ru.nbch.credit_tracker.mapper.signal;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import java.time.LocalDateTime;
import java.util.List;
@Mapper
public interface UserPackageMapper {
boolean isPackageNotUnique(@Param("userId") String userId, @Param("packageName") String packageName);
boolean isPackageExists(@Param("userId") String userId, @Param("packageName") String packageName, @Param("status") String status);
void deletePackage(@Param("userId") String userId, @Param("packageName") String packageName, @Param("status") String newStatus, @Param("previousStatus") String previousStatus, @Param("deactivatedAt") LocalDateTime deactivatedAt);
Integer insertPackage(@Param("userPackage") UserPackage userPackage);
void updatePackageStatus(@Param("packageId") Integer packageId, @Param("status") String status);
void updatePackageLastDownloadedReport(@Param("id") Integer id, @Param("fileName") String fileName);
UserPackage findPackage(@Param("id") Integer id);
List<UserPackage> findUserPackages(@Param("userId") String userId, @Param("status") String status);
List<UserPackage> findAllPackagesByStatus(@Param("status") String status);
}

View file

@ -3,9 +3,9 @@ package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.HitsData;
import ru.nbch.credit_tracker.entities.dto.PackageData;
import ru.nbch.credit_tracker.entities.dto.SubjectData;
import ru.nbch.credit_tracker.entities.dto.Hit;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.response.monitoring_signal_response.*;
import ru.nbch.credit_tracker.entities.response.online_download.Inquiry;
import ru.nbch.credit_tracker.entities.response.online_download.OnlineDownloadReport;
@ -14,7 +14,6 @@ import ru.nbch.credit_tracker.entities.response.online_report.Report;
import ru.nbch.credit_tracker.entities.response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.XmlUtilService;
import ru.nbch.credit_tracker.utils.CTUtil;
import java.io.ByteArrayInputStream;
@ -36,16 +35,16 @@ public class MonitoringService {
private final SignalRestService signalRestService;
private final SignalService signalService;
private final XmlUtilService xmlUtilService;
private final IXmlProcessor xmlProcessor;
private final CreditTrackerSettings config;
public MonitoringService(SignalRestService signalRestService,
SignalService signalService,
XmlUtilService xmlUtilService,
IXmlProcessor xmlProcessor,
CreditTrackerSettings config) {
this.signalRestService = signalRestService;
this.signalService = signalService;
this.xmlUtilService = xmlUtilService;
this.xmlProcessor = xmlProcessor;
this.config = config;
}
@ -57,13 +56,13 @@ public class MonitoringService {
private void monitor() {
log.info("Start monitoring");
List<PackageData> packages = signalService.findPackagesOnMonitoring();
for (PackageData packageData : packages) {
log.info("Processing package {}", packageData.getPackageName());
SgnlOnlineReport onlineReports = signalRestService.getReports(packageData.getUserId().substring(0, 6) + "_" + packageData.getPackageName());
List<UserPackage> packages = signalService.findPackagesOnMonitoring();
for (UserPackage userPackage : packages) {
log.info("Processing package {}", userPackage.getPackageName());
SgnlOnlineReport onlineReports = signalRestService.getReports(userPackage.getUserId().substring(0, 6) + "_" + userPackage.getPackageName());
if (onlineReports == null) {
log.info("No reports found for package {}", packageData.getPackageName());
log.info("No reports found for package {}", userPackage.getPackageName());
continue;
}
@ -71,7 +70,7 @@ public class MonitoringService {
.filter(fileName -> CTUtil.parseDateFromReportFileName(fileName) != null).toList(); // TODO оптимизировать
if (fileNames.isEmpty()) {
log.info("No new report found for package {}", packageData.getPackageName());
log.info("No new report found for package {}", userPackage.getPackageName());
continue;
}
@ -79,16 +78,16 @@ public class MonitoringService {
.orElseGet(Collections::emptyList)
.stream().max(Comparator.comparing(CTUtil::parseDateFromReportFileName)); // отфильтровали только те имена, которые парсятся в дату, так что null тут не придет
LocalDateTime lastDownloadedReportDate = CTUtil.parseDateFromReportFileName(packageData.getLastDownloadedReport());
LocalDateTime lastDownloadedReportDate = CTUtil.parseDateFromReportFileName(userPackage.getLastDownloadedReport());
if (packageData.getLastDownloadedReport() != null) {
log.info("Last downloaded report found for package {}. Last Downloaded Report Name: {}", packageData.getPackageName(), packageData.getLastDownloadedReport());
if (userPackage.getLastDownloadedReport() != null) {
log.info("Last downloaded report found for package {}. Last Downloaded Report Name: {}", userPackage.getPackageName(), userPackage.getLastDownloadedReport());
} else {
log.info("Last Downloaded Report Name is empty");
}
OnlineDownloadReport report = null;
if (packageData.getLastDownloadedReport() == null && newReport.isPresent()) {
if (userPackage.getLastDownloadedReport() == null && newReport.isPresent()) {
report = loadReport(newReport.get()); // по этому пакету еще не было загруженных отчетов, продолжаем работу с полученным
} else if (lastDownloadedReportDate != null && newReport.isPresent()) {
LocalDateTime newReportDate = CTUtil.parseDateFromReportFileName(newReport.get());
@ -97,28 +96,28 @@ public class MonitoringService {
}
}
if (report == null) {
log.info("Report was not loaded for package {}", packageData.getPackageName());
log.info("Report was not loaded for package {}", userPackage.getPackageName());
continue;
}
MonitoringSignalResponse response = generateResponse(packageData, report.getPersons().getPersons());
String fileName = createResponseFile(packageData, response);
MonitoringSignalResponse response = generateResponse(userPackage, report.getPersons().getPersons());
String fileName = createResponseFile(userPackage, response);
if (fileName != null) {
log.info("New report fileName: {}", fileName);
updateSignalHits(packageData, response, fileName);
signalService.updateLastDownloadedReport(packageData.getId(), newReport.get());
updateSignalHits(userPackage, response, fileName);
signalService.updateLastDownloadedReport(userPackage.getId(), newReport.get());
} else {
log.info("Report was not created for package {}", packageData.getPackageName());
log.info("Report was not created for package {}", userPackage.getPackageName());
}
}
log.info("Finish monitoring");
}
private MonitoringSignalResponse generateResponse(PackageData packageData, List<Person> persons) {
private MonitoringSignalResponse generateResponse(UserPackage userPackage, List<Person> persons) {
MonitoringSignalResponse response = new MonitoringSignalResponse();
response.setPackageName(packageData.getPackageName()); // Имя пакета, переданного при установке
response.setPackageName(userPackage.getPackageName()); // Имя пакета, переданного при установке
Subjects subjects = new Subjects();
List<SubjectData> subjectDataList = signalService.findFullSubjectsData(packageData.getId());
List<PhoneFidMap> phoneFidMapList = signalService.findFullSubjectsData(userPackage.getId());
for (Person person : persons) {
Signals signals = new Signals();
for (Inquiry inquiry : person.getInquiries()) {
@ -135,7 +134,7 @@ public class MonitoringService {
// Если есть хотя бы один заполненный сигнал, значит заполняем остальные данные
if (!signals.getSignals().isEmpty()) {
subjectDataList.stream().filter(p -> p.getSubjectId().equals(person.getUid())).findFirst().ifPresent(subjectData -> {
phoneFidMapList.stream().filter(p -> p.getSubjectId().equals(person.getUid())).findFirst().ifPresent(subjectData -> {
Subject subject = new Subject();
subject.setId(subjectData.getSubjectId()); // Уникальный идентификатор субъекта (равен Id из XML-пакета при установке мониторинга)
subject.setClientId(subjectData.getPhone());
@ -150,18 +149,17 @@ public class MonitoringService {
return response;
}
private String createResponseFile(PackageData packageData, MonitoringSignalResponse response) {
private String createResponseFile(UserPackage userPackage, MonitoringSignalResponse response) {
try {
String fileName = CTUtil.generateResponseReportFileName(packageData.getUserId(), packageData.getPackageName());
String filePath = config.getLoadDir() + File.separator + packageData.getUserId().substring(0, 6) + File.separator;
String fileName = CTUtil.generateResponseReportFileName(userPackage.getUserId(), userPackage.getPackageName());
String filePath = config.getLoadDir() + File.separator + userPackage.getUserId().substring(0, 6) + File.separator;
File folder = new File(filePath);
if (!folder.exists()) {
folder.mkdir();
}
IXmlProcessor processor = xmlUtilService.createJaxbProcessor();
String xmlStr = processor.asString(response, true);
String xmlStr = xmlProcessor.asString(response, true);
byte[] xmlBytes = xmlStr.getBytes(Charset.forName("windows-1251"));
try (FileOutputStream fos = new FileOutputStream(filePath + fileName + ".zip");
@ -179,23 +177,23 @@ public class MonitoringService {
return null;
}
private void updateSignalHits(PackageData packageData, MonitoringSignalResponse response, String reportFileName) {
log.info("Updating signal hits for {}", packageData.getPackageName());
private void updateSignalHits(UserPackage userPackage, MonitoringSignalResponse response, String reportFileName) {
log.info("Updating signal hits for {}", userPackage.getPackageName());
LocalDateTime responseSentAt = LocalDateTime.now();
List<HitsData> hits = new ArrayList<>();
List<Hit> hits = new ArrayList<>();
response.getSubjects().getSubjects().forEach(subject -> {
subject.getSignals().getSignals().forEach(signal -> {
HitsData hitsData = new HitsData();
hitsData.setPackageId(packageData.getId());
hitsData.setSubjectId(subject.getId());
hitsData.setSignalType(1);
hitsData.setResponseSentAt(responseSentAt);
hitsData.setReportFileName(reportFileName);
hits.add(hitsData);
Hit hit = new Hit();
hit.setPackageId(userPackage.getId());
hit.setSubjectId(subject.getId());
hit.setSignalType(1);
hit.setResponseSentAt(responseSentAt);
hit.setReportFileName(reportFileName);
hits.add(hit);
});
});
signalService.setHits(hits);
log.info("Signal hits updated for package {}", packageData.getPackageName());
signalService.insertHits(hits);
log.info("Signal hits updated for package {}", userPackage.getPackageName());
}
private OnlineDownloadReport loadReport(String reportName) {
@ -206,8 +204,7 @@ public class MonitoringService {
OnlineDownloadReport report;
try (GZIPInputStream zipInputStream = new GZIPInputStream(new ByteArrayInputStream(archive))) {
IXmlProcessor processor = xmlUtilService.createJaxbProcessor();
report = processor.read(zipInputStream, OnlineDownloadReport.class);
report = xmlProcessor.read(zipInputStream, OnlineDownloadReport.class);
} catch (Exception e) {
log.error(e.getMessage(), e);

View file

@ -1,31 +1,25 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.builder.PersonFactoryBuilder;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.HitsData;
import ru.nbch.credit_tracker.entities.dto.PackageData;
import ru.nbch.credit_tracker.entities.dto.SubjectData;
import ru.nbch.credit_tracker.entities.dto.Hit;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.entities.response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.response.active_packages.Package;
import ru.nbch.credit_tracker.entities.response.active_packages.Packages;
import ru.nbch.credit_tracker.entities.response.success.MonitoringPackageDeleteResponse;
import ru.nbch.credit_tracker.entities.signal_package.Auth;
import ru.nbch.credit_tracker.entities.signal_package.Person;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.mapper.signal.SignalMapper;
import ru.nbch.credit_tracker.service.indic.FlagsService;
import ru.nbch.credit_tracker.service.indic.PersonService;
import ru.nbch.credit_tracker.service.indic.PhoneService;
import ru.nbch.credit_tracker.utils.CTUtil;
import ru.nbch.credit_tracker.service.signal.HitsService;
import ru.nbch.credit_tracker.service.signal.PhoneFidMapService;
import ru.nbch.credit_tracker.service.signal.UserPackageService;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@ -36,10 +30,10 @@ import java.util.Objects;
@Service
public class SignalService {
private final static DateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy");
private final CreditTrackerSettings config;
private final SignalMapper mapper;
private final HitsService hitsService;
private final UserPackageService userPackageService;
private final PhoneFidMapService phoneFidMapService;
private final PhoneService phoneService;
private final FlagsService flagsService;
private final PersonService personService;
@ -47,53 +41,77 @@ public class SignalService {
private final int batchSize = 10000;
public SignalService(CreditTrackerSettings config,
SignalMapper mapper,
HitsService hitsService,
UserPackageService userPackageService,
PhoneFidMapService phoneFidMapService,
PhoneService phoneService,
FlagsService flagsService,
PersonService personService) {
this.config = config;
this.mapper = mapper;
this.hitsService = hitsService;
this.userPackageService = userPackageService;
this.phoneFidMapService = phoneFidMapService;
this.phoneService = phoneService;
this.flagsService = flagsService;
this.personService = personService;
}
public boolean isPackageNotUnique(MonitoringRequest request) {
String userId = request.getUserId();
return mapper.isPackageNotUnique(userId.substring(0, 6), request.getPackageName());
return userPackageService.isPackageNotUnique(request.getUserId(), request.getPackageName());
}
public Integer registerPackage(MonitoringRequest request) {
Integer packageId = mapper.registerPackage(request, LocalDateTime.now(), Status.PROCESSING.name());
UserPackage userPackage = UserPackage.builder()
.userId(request.getUserId())
.packageName(request.getPackageName())
.createdAt(LocalDateTime.now())
.status(Status.PROCESSING.name())
.build();
Integer packageId = userPackageService.insertPackage(userPackage);
List<Subject> subjects = request.getSubjects().getSubject();
for (int i = 0; i < subjects.size(); i += batchSize) {
int end = Math.min(i + batchSize, subjects.size());
mapper.registerSubjects(subjects.subList(i, end), packageId);
phoneFidMapService.registerSubjects(subjects.subList(i, end), packageId); // TODO преобразовывать список в List<PhoneFidMap> ?
}
return packageId;
}
public List<PhoneService.FidsPhoneData> registerSubjectsFidAndDebts(Integer packageId) {
List<SubjectData> subjects = mapper.findSubjectsData(packageId);
List<PhoneFidMap> subjects = phoneFidMapService.findPhoneFidMaps(packageId);
return updateFlags(subjects, packageId);
}
public List<PhoneService.FidsPhoneData> updateFlags(List<SubjectData> subjects, Integer packageId) {
List<PhoneService.FidsPhoneData> fidsPhoneDataList = phoneService.findFidsPhoneData(subjects, true);
public List<PhoneService.FidsPhoneData> updateFlags(List<PhoneFidMap> subjects, Integer packageId) {
List<PhoneService.FidsPhoneData> fidsPhoneDataList = phoneService.findFidsPhoneData(subjects);
LocalDateTime calculatedAt = LocalDateTime.now();
for (int i = 0; i < fidsPhoneDataList.size(); i += batchSize) {
int end = Math.min(i + batchSize, fidsPhoneDataList.size());
List<PhoneService.FidsPhoneData> currentList = fidsPhoneDataList.subList(i, end);
Map<Integer, FlagsService.FlagsData> flagsDataMap = flagsService.findFlags(currentList.stream().map(PhoneService.FidsPhoneData::getFid).filter(Objects::nonNull).toList());
List<SubjectData> subjectToUpdate = new ArrayList<>();
List<PhoneFidMap> subjectToUpdate = new ArrayList<>();
currentList.forEach(data -> {
SubjectData subject;
PhoneFidMap subject;
if (data.getFid() != null) {
FlagsService.FlagsData flagsData = flagsDataMap.get(data.getFid());
subject = new SubjectData(data.getId(), packageId, data.getSubjectId(), data.getPhone(), data.getFid(), flagsData.getFlagDebt5000(), flagsData.getFlag90days(), calculatedAt);
subject = PhoneFidMap.builder()
.id(data.getId())
.packageId(packageId)
.subjectId(data.getSubjectId())
.phone(data.getPhone())
.fid(data.getFid())
.flagDebt5000(flagsData.getFlagDebt5000())
.flag90days(flagsData.getFlag90days())
.calculatedAt(calculatedAt)
.build();
} else {
subject = new SubjectData(data.getId(), packageId, data.getSubjectId(), data.getPhone(), null, null, null, calculatedAt);
subject = PhoneFidMap.builder()
.id(data.getId())
.packageId(packageId)
.subjectId(data.getSubjectId())
.phone(data.getPhone())
.calculatedAt(calculatedAt)
.build();
}
subjectToUpdate.add(subject);
});
@ -101,7 +119,7 @@ public class SignalService {
int updateBatchSize = batchSize / 8; // 8 параметров на одну запись для обновления. Максимальное количество параметров ~65000
for (int j = 0; j < subjectToUpdate.size(); j += updateBatchSize) {
int endIndex = Math.min(j + updateBatchSize, subjectToUpdate.size());
mapper.updateSubjects(subjectToUpdate.subList(j, endIndex));
phoneFidMapService.updatePhoneFidMaps(subjectToUpdate.subList(j, endIndex));
}
}
@ -109,18 +127,24 @@ public class SignalService {
}
public void rejectPackage(MonitoringRequest request) {
mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name());
UserPackage userPackage = UserPackage.builder()
.userId(request.getUserId())
.packageName(request.getPackageName())
.createdAt(LocalDateTime.now())
.status(Status.REJECTED.name())
.build();
userPackageService.insertPackage(userPackage);
}
public void setPackageStatus(Integer packageId, Status status) {
mapper.setPackageStatus(packageId, status.name());
public void updatePackageStatus(Integer packageId, Status status) {
userPackageService.updatePackageStatus(packageId, status);
}
public Signals buildSignals(Integer packageId, List<PhoneService.FidsPhoneData> fids) {
PackageData packageData = mapper.findPackageData(packageId);
UserPackage userPackage = userPackageService.findPackage(packageId);
Signals signals = new Signals();
signals.setOnline("2"); // Всегда=2 (только онлайн-сигналы)
signals.setId(packageData.getUserId().substring(0, 6) + "_" + packageData.getPackageName()); // <MEMBERCODE>_<PackageName>
signals.setId(userPackage.getUserId().substring(0, 6) + "_" + userPackage.getPackageName()); // <MEMBERCODE>_<PackageName>
Auth auth = new Auth();
auth.setUser(config.getSignalsuser());
signals.setAuth(auth);
@ -143,7 +167,10 @@ public class SignalService {
fidsPhoneData.forEach(data -> {
if (data.getFid() != null) {
PersonService.PersonData personData = personFidMap.get(data.getFid());
Person person = getPerson(personData, data.getSubjectId());
Person person = PersonFactoryBuilder.builder()
.personData(personData)
.uid(data.getSubjectId())
.build();
if (person != null) {
persons.add(person);
}
@ -152,101 +179,31 @@ public class SignalService {
return persons;
}
private Person getPerson(PersonService.PersonData personData, String id) {
if (personData == null) {
return null;
}
PersonService.NameData nameData = personData.getName();
PersonService.PassportData passportData = personData.getPassport();
Person person = new Person();
person.setS(nameData.getLastName());
person.setN(nameData.getFirstName());
person.setM(StringUtils.isNotBlank(nameData.getMiddleName()) ? nameData.getMiddleName() : null);
person.setD(DATE_FORMAT.format(CTUtil.localDatetoDate(nameData.getBirthDate())));
person.setPn(getPn(passportData.getSerNum(), passportData.getIdNum()));
person.setPd(passportData.getIssDate() != null ? DATE_FORMAT.format(CTUtil.localDatetoDate(passportData.getIssDate())) : "01.01.2000");
person.setDt(StringUtils.isNotBlank(passportData.getIdType2()) ? passportData.getIdType2() : passportData.getIdType());
person.setIp("0");
person.setUid(id);
person.setOksm("999");
person.setConsentDate(DATE_FORMAT.format(CTUtil.localDatetoDate(LocalDate.now())));
person.setConsentPurpose("16");
person.setReportUser("АО «НБКИ»");
person.setLiability("1");
person.setConsentPeriod("3");
person.setAgrDate(DATE_FORMAT.format(CTUtil.localDatetoDate(LocalDate.now())));
person.setReportUserRegNum("1057746710713");
person.setReportUserTaxID("7703548386");
person.setConsentHash("hash");
person.setCs(person.getS());
person.setConsentN(person.getN());
person.setConsentM(person.getM());
person.setConsentBd(person.getD());
person.setConsentPn(person.getPn());
person.setConsentPd(person.getPd());
person.setConsentDivCode("000-000");
person.setConsentDt(person.getDt());
person.setInqPurpose("16");
return person;
}
private String getPn(String serNum, String idNum) {
String normSerNum = CTUtil.normalize(serNum);
String normIdNum = CTUtil.normalize(idNum);
return StringUtils.isNotBlank(normSerNum) ? normSerNum + normIdNum : normIdNum;
}
public MonitoringActivePackagesResponse findActivePackages(String userId) {
String memberCode = userId.substring(0, 6);
MonitoringActivePackagesResponse activePackages = new MonitoringActivePackagesResponse();
activePackages.setStatus("OK");
activePackages.setMembercode(memberCode);
Packages packages = new Packages();
mapper.findPackageDataList(memberCode, Status.ON_MONITORING.name()).forEach(data -> {
Package pack = new Package();
pack.setPackageName(data.getPackageName());
pack.setCreatedAt(data.getCreatedAt() != null ? data.getCreatedAt().toString() : null);
packages.getPackages().add(pack);
});
activePackages.setPackages(packages);
if (packages.getPackages() == null || packages.getPackages().isEmpty()) {
return null;
}
return activePackages;
public List<UserPackage> findActivePackages(String userId) {
return userPackageService.findUserPackages(userId, Status.ON_MONITORING);
}
public boolean isPackageExists(String username, String packageName) {
return mapper.isPackageExists(username.substring(0, 6), packageName, Status.ON_MONITORING.name());
return userPackageService.isPackageExists(username, packageName, Status.ON_MONITORING);
}
public MonitoringPackageDeleteResponse deletePackage(String username, String packageName) {
LocalDateTime deactivatedAt = LocalDateTime.now();
mapper.deletePackage(username.substring(0, 6), packageName, Status.DELETED.name(), Status.ON_MONITORING.name(), deactivatedAt);
MonitoringPackageDeleteResponse deleteResponse = new MonitoringPackageDeleteResponse();
deleteResponse.setStatus("Deleted");
deleteResponse.setPackageName(packageName);
deleteResponse.setDeactivatedAt(deactivatedAt.toString());
return deleteResponse;
public void deletePackage(String username, String packageName, LocalDateTime deactivatedAt) {
userPackageService.deletePackage(username, packageName, Status.DELETED, Status.ON_MONITORING, deactivatedAt);
}
public List<PackageData> findPackagesOnMonitoring() {
return mapper.findPackagesByStatus(Status.ON_MONITORING.name());
public List<UserPackage> findPackagesOnMonitoring() {
return userPackageService.findAllPackagesByStatus(Status.ON_MONITORING);
}
public List<SubjectData> findFullSubjectsData(Integer packageId) {
return mapper.findFullSubjectsData(packageId);
public List<PhoneFidMap> findFullSubjectsData(Integer packageId) {
return phoneFidMapService.findFullPhoneFidMap(packageId);
}
public void setHits(List<HitsData> hits) {
mapper.setHits(hits);
public void insertHits(List<Hit> hits) {
hitsService.insertHits(hits);
}
public void updateLastDownloadedReport(Integer id, String fileName) {
mapper.setPackageLastDownloadedReport(id, fileName);
userPackageService.updatePackageLastDownloadedReport(id, fileName);
}
}

View file

@ -3,8 +3,8 @@ package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.PackageData;
import ru.nbch.credit_tracker.entities.dto.SubjectData;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.service.indic.PhoneService;
@ -42,32 +42,32 @@ public class UpdatingFlagsService {
private void update() {
log.info("Start updating flags");
List<PackageData> packages = signalService.findPackagesOnMonitoring();
for (PackageData packageData : packages) {
log.info("Updating flags for Package {}", packageData.getPackageName());
List<SubjectData> subjects = signalService.findFullSubjectsData(packageData.getId())
List<UserPackage> packages = signalService.findPackagesOnMonitoring();
for (UserPackage userPackage : packages) {
log.info("Updating flags for Package {}", userPackage.getPackageName());
List<PhoneFidMap> subjects = signalService.findFullSubjectsData(userPackage.getId())
.stream().filter(subject -> subject.getCalculatedAt() != null && hasDaysPassed(subject.getCalculatedAt())).toList();
updateFlags(packageData.getId(), subjects, packageData.getPackageName());
updateFlags(userPackage.getId(), subjects, userPackage.getPackageName());
}
log.info("Finish updating flags");
}
private void updateFlags(Integer packageId, List<SubjectData> subjects, String packageName) {
private void updateFlags(Integer packageId, List<PhoneFidMap> subjects, String packageName) {
try {
signalService.setPackageStatus(packageId, Status.PROCESSING);
signalService.updatePackageStatus(packageId, Status.PROCESSING);
List<PhoneService.FidsPhoneData> phoneFidsData = signalService.updateFlags(subjects, packageId);
if (!phoneFidsData.isEmpty()) {
Signals signals = signalService.buildSignals(packageId, phoneFidsData);
if (signalRestService.update(signals)) {
log.info("Flags were updated successfully. PackageId: {} PackageName: {}. Package status changed to ON_MONITORING", packageId, packageName);
signalService.setPackageStatus(packageId, Status.ON_MONITORING);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
} else {
log.info("Updated package registration was rejected by signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.setPackageStatus(packageId, Status.ERROR);
signalService.updatePackageStatus(packageId, Status.ERROR);
}
} else {
log.info("No flags were updated for package id {}. Package status changed to ON_MONITORING", packageId);
signalService.setPackageStatus(packageId, Status.ON_MONITORING);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
}
} catch (Exception e) {
log.error("Ошибка при поиске фидов или перерасчете флагов просрочек. Package_id {}", packageId, e);

View file

@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.entities.dto.SubjectData;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.mapper.indic.PhoneMapper;
import java.time.LocalDate;
@ -20,16 +20,12 @@ public class PhoneService {
this.mapper = mapper;
}
public List<FidsPhoneData> findFidsPhoneData(List<SubjectData> subjects) {
return findFidsPhoneData(subjects, false);
}
public List<FidsPhoneData> findFidsPhoneData(List<SubjectData> subjects, boolean processNullFids) {
public List<FidsPhoneData> findFidsPhoneData(List<PhoneFidMap> subjects) {
List<FidsPhoneData> fidsPhoneDataList = new ArrayList<>();
int batchSize = 10000;
for (int i = 0; i < subjects.size(); i += batchSize) {
int end = Math.min(i + batchSize, subjects.size());
List<SubjectData> currentSubjects = subjects.subList(i, end);
List<PhoneFidMap> currentSubjects = subjects.subList(i, end);
List<String> phones = currentSubjects.stream().map(subject -> "9" + subject.getPhone()).toList();
List<FidsData> fidsData = mapper.findFids(phones);
@ -40,7 +36,7 @@ public class PhoneService {
Integer fid = fidsMap.get(phone);
if (fid != null) {
fidsPhoneDataList.add(new FidsPhoneData(subject.getId(), fid, subject.getPhone(), subject.getSubjectId()));
} else if (processNullFids) {
} else {
fidsPhoneDataList.add(new FidsPhoneData(subject.getId(), null, subject.getPhone(), subject.getSubjectId()));
}
});

View file

@ -0,0 +1,21 @@
package ru.nbch.credit_tracker.service.signal;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.entities.dto.Hit;
import ru.nbch.credit_tracker.mapper.signal.HitsMapper;
import java.util.List;
@Service
public class HitsService {
private final HitsMapper mapper;
public HitsService(HitsMapper mapper) {
this.mapper = mapper;
}
public void insertHits(List<Hit> hits) {
mapper.insertHits(hits);
}
}

View file

@ -0,0 +1,34 @@
package ru.nbch.credit_tracker.service.signal;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
import java.util.List;
@Service
public class PhoneFidMapService {
private final PhoneFidMapMapper mapper;
public PhoneFidMapService(PhoneFidMapMapper mapper) {
this.mapper = mapper;
}
public void registerSubjects(List<Subject> subjects, Integer packageId) {
mapper.registerSubjects(subjects, packageId);
}
public List<PhoneFidMap> findPhoneFidMaps(Integer packageId) {
return mapper.findPhoneFidMaps(packageId);
}
public List<PhoneFidMap> findFullPhoneFidMap(Integer packageId) {
return mapper.findFullPhoneFidMap(packageId);
}
public void updatePhoneFidMaps(List<PhoneFidMap> subjects) {
mapper.updatePhoneFidMaps(subjects);
}
}

View file

@ -15,7 +15,6 @@ import ru.nbch.credit_tracker.entities.response.external_errors.SgnlReport;
import ru.nbch.credit_tracker.entities.response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.XmlUtilService;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import java.io.ByteArrayOutputStream;
@ -35,14 +34,17 @@ public class SignalRestService {
private static String DOWNLOAD_REPORT_URI = "onlinedownload";
private final RestTemplate restTemplate;
private final XmlUtilService xmlUtilService;
private final IXmlProcessor xmlProcessor;
private final StaxXmlProcessor staxProcessor;
private final String authToken;
public SignalRestService(@Qualifier(value = "restTemplate") RestTemplate restTemplate,
XmlUtilService xmlUtilService,
IXmlProcessor xmlProcessor,
StaxXmlProcessor staxProcessor,
CreditTrackerSettings config) throws Exception {
this.restTemplate = restTemplate;
this.xmlUtilService = xmlUtilService;
this.xmlProcessor = xmlProcessor;
this.staxProcessor = staxProcessor;
this.authToken = buildToken(config.getSignalsToken(), config.getSignalsuser());
}
@ -64,8 +66,7 @@ public class SignalRestService {
// good response
return true;
} else if (response.getStatusCode().value() == 200 && response.getBody() != null) {
StaxXmlProcessor staxXmlProcessor = xmlUtilService.staxXmlProcessor();
SgnlReport error = staxXmlProcessor.read(response.getBody(), SgnlReport.class);
SgnlReport error = staxProcessor.read(response.getBody(), SgnlReport.class);
if (error.getError().getDescription() != null) {
log.error("Ошибка при постановке пакета на мониторинг в официальный сервис сигналов: {}", error.getError().getDescription());
} else {
@ -92,8 +93,7 @@ public class SignalRestService {
);
String answer = response.getBody();
StaxXmlProcessor staxXmlProcessor = xmlUtilService.staxXmlProcessor();
SgnlReport error = staxXmlProcessor.read(answer, SgnlReport.class);
SgnlReport error = staxProcessor.read(answer, SgnlReport.class);
if (error.getError().getDescription() != null) {
log.error("Ошибка при удалении пакета из сервиса НБКИ. packCode={}. Описание: {}", packCode, error.getError().getDescription());
}
@ -116,15 +116,13 @@ public class SignalRestService {
String answer = response.getBody();
StaxXmlProcessor staxXmlProcessor = xmlUtilService.staxXmlProcessor();
SgnlReport error = staxXmlProcessor.read(answer, SgnlReport.class);
SgnlReport error = staxProcessor.read(answer, SgnlReport.class);
if (error.getError().getDescription() != null) {
log.error("Ошибка при получении пакета из сервиса НБКИ. packCode={}. Описание: {}", packCode, error.getError().getDescription());
return null;
}
try {
IXmlProcessor processor = xmlUtilService.createJaxbProcessor();
return processor.read(answer, SgnlOnlineReport.class);
return xmlProcessor.read(answer, SgnlOnlineReport.class);
} catch (Exception e) {
log.error("Ошибка при получении пакета из сервиса НБКИ. Код ошибки: {} packCode={}", response.getStatusCode().value(), packCode);
return null;
@ -148,8 +146,7 @@ public class SignalRestService {
byte[] answer = response.getBody();
if (isXmlError(response.getBody())) {
StaxXmlProcessor staxXmlProcessor = xmlUtilService.staxXmlProcessor();
SgnlReport error = staxXmlProcessor.read(answer, SgnlReport.class);
SgnlReport error = staxProcessor.read(answer, SgnlReport.class);
if (error.getError().getDescription() != null) {
log.error("Ошибка при скачивание отчета. fNameReport={}. Описание: {}", reportName, error.getError().getDescription());
return null;
@ -175,8 +172,7 @@ public class SignalRestService {
}
private Resource compressFile(Signals signals) throws Exception {
IXmlProcessor processor = xmlUtilService.createJaxbProcessor();
String requestData = processor.asString(signals, false);
String requestData = xmlProcessor.asString(signals, false);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream)) {

View file

@ -0,0 +1,55 @@
package ru.nbch.credit_tracker.service.signal;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class UserPackageService {
private final UserPackageMapper mapper;
public UserPackageService(UserPackageMapper mapper) {
this.mapper = mapper;
}
public boolean isPackageNotUnique(String userId, String packageName) {
return mapper.isPackageNotUnique(userId.substring(0, 6), packageName);
}
public boolean isPackageExists(String userId, String packageName, Status status) {
return mapper.isPackageExists(userId.substring(0, 6), packageName, status.name());
}
public void deletePackage(String userId, String packageName, Status newStatus, Status previousStatus, LocalDateTime deactivatedAt) {
mapper.deletePackage(userId.substring(0, 6), packageName, newStatus.name(), previousStatus.name(), deactivatedAt);
}
public Integer insertPackage(UserPackage userPackage) {
return mapper.insertPackage(userPackage);
}
public void updatePackageStatus(Integer packageId, Status status) {
mapper.updatePackageStatus(packageId, status.name());
}
public void updatePackageLastDownloadedReport(Integer id, String fileName) {
mapper.updatePackageLastDownloadedReport(id, fileName);
}
public UserPackage findPackage(Integer id) {
return mapper.findPackage(id);
}
public List<UserPackage> findUserPackages(String userId, Status status) {
return mapper.findUserPackages(userId.substring(0, 6), status.name());
}
public List<UserPackage> findAllPackagesByStatus(Status status) {
return mapper.findAllPackagesByStatus(status.name());
}
}

View file

@ -1,29 +1,82 @@
package ru.nbch.credit_tracker.utils;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import static ru.nbch.credit_tracker.utils.error.ExceptionUtils.clientExcp;
public class ValidationUtil {
private static String phoneRegex = "^\\d{9}$";
private static String packageNameRegex = "^[A-Z0-9_]{1,22}$";
private static String npIdRegex = "^\\S{1,36}$";
public static void validateMonitoringRequest(MonitoringRequest request) throws SignalClientException {
if (request == null) {
throw clientExcp(SignalError.ERROR_011, XmlErrorFormat.MonitoringError);
}
public static boolean validatePhone(String input) {
if (request.getUserId() == null) {
throw clientExcp(SignalError.ERROR_002, XmlErrorFormat.MonitoringError, "UserId");
}
if (request.getPackageName() == null) {
throw clientExcp(SignalError.ERROR_002, XmlErrorFormat.MonitoringError, "PackageName");
}
if (request.getPassword() == null) {
throw clientExcp(SignalError.ERROR_002, XmlErrorFormat.MonitoringError, "Password");
}
if (request.getSubjects() == null) {
throw clientExcp(SignalError.ERROR_002, XmlErrorFormat.MonitoringError, "Subjects");
}
if (request.getSubjects().getSubject().isEmpty()) {
throw clientExcp(SignalError.ERROR_002, XmlErrorFormat.MonitoringError, "Subject");
}
if (!validatePackageName(request.getPackageName())) {
throw clientExcp(SignalError.ERROR_008, XmlErrorFormat.MonitoringError, "Subject");
}
Set<String> uniqueIds = new HashSet<>();
for (Subject subject : request.getSubjects().getSubject()) {
if (!validatePhone(subject.getClientId())) {
throw clientExcp(SignalError.ERROR_003, XmlErrorFormat.MonitoringError);
}
if (!validateNPId(subject.getId())) {
throw clientExcp(SignalError.ERROR_010, XmlErrorFormat.MonitoringError);
}
// проверка на уникальность Id внутри одного пакета
if (!uniqueIds.add(subject.getId())) {
throw clientExcp(SignalError.ERROR_004, XmlErrorFormat.MonitoringError, subject.getId());
}
}
}
private static boolean validatePhone(String input) {
if(input == null) {
return false;
}
return Pattern.matches(phoneRegex, input);
}
public static boolean validatePackageName(String input) {
private static boolean validatePackageName(String input) {
if(input == null) {
return false;
}
return Pattern.matches(packageNameRegex, input);
}
public static boolean validateNPId(String input) {
private static boolean validateNPId(String input) {
if(input == null) {
return false;
}

View file

@ -0,0 +1,28 @@
package ru.nbch.credit_tracker.utils;
import java.io.IOException;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ZipUtils {
public static Optional<ZipEntry> extractValidEntry(ZipInputStream inputStream) throws IOException {
Optional<ZipEntry> zipEntry = Optional.empty();
ZipEntry entry;
while ((entry = inputStream.getNextEntry()) != null) {
if (!entry.isDirectory()) {
if (zipEntry.isPresent()) {
//если мы уже нашли валидный xml файл, то обработка всего файла недоступна, возвращаем пустой entry
return Optional.empty();
}
if (entry.getName().toLowerCase().endsWith(".xml")) { // Файл должен быть с расширением xml
zipEntry = Optional.of(entry);
}
}
inputStream.closeEntry();
}
return zipEntry;
}
}

View file

@ -0,0 +1,18 @@
package ru.nbch.credit_tracker.utils.error;
import ru.nbch.credit_tracker.enums.EnumKeyMessage;
import ru.nbch.credit_tracker.enums.IEnumKeyCode;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.exceptions.SignalServerException;
public class ExceptionUtils {
public static SignalClientException clientExcp(IEnumKeyCode enumKeyCode, XmlErrorFormat xmlErrorFormat, Object... args) {
return new SignalClientException(new EnumKeyMessage(enumKeyCode, args), xmlErrorFormat);
}
public static SignalServerException serverExcp(IEnumKeyCode enumKeyCode, XmlErrorFormat xmlErrorFormat, Object... args) {
return new SignalServerException(new EnumKeyMessage(enumKeyCode, args), xmlErrorFormat);
}
}

View file

@ -0,0 +1,13 @@
package ru.nbch.credit_tracker.utils.error;
import ru.nbch.credit_tracker.enums.EnumKeyMessage;
import java.util.Arrays;
public class SimpleMessageResolver {
public String resolve(EnumKeyMessage errorMessage) {
if (errorMessage == null) return "null";
return String.format("%s %s", errorMessage.getSubject().getKey(), Arrays.toString(errorMessage.getArgs()));
}
}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ru.nbch.credit_tracker.mapper.signal.HitsMapper">
<insert id="insertHits" parameterType="java.util.List">
INSERT INTO signals_hits (package_id, subject_id, signal_type, response_sent_at, report_file_name)
values
<foreach collection="hits" item="hit" separator=",">
(#{hit.packageId}, #{hit.subjectId}, #{hit.signalType}, #{hit.responseSentAt}, #{hit.reportFileName})
</foreach>
</insert>
</mapper>

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper">
<resultMap id="PhoneFidMapResultMap" type="ru.nbch.credit_tracker.entities.dto.PhoneFidMap">
<result property="id" column="id"/>
<result property="packageId" column="package_id"/>
<result property="subjectId" column="subject_id"/>
<result property="phone" column="phone"/>
<result property="fid" column="fid"/>
<result property="flagDebt5000" column="flag_debt5000"/>
<result property="flag90days" column="flag_90_12"/>
<result property="calculatedAt" column="calculated_at"/>
</resultMap>
<insert id="registerSubjects" parameterType="java.util.List">
INSERT INTO signals_phone_fid_map (subject_id, phone, fid, package_id)
values
<foreach collection="subjects" item="subject" separator=",">
(#{subject.id}, #{subject.clientId}, NULL, #{packageId})
</foreach>
</insert>
<update id="updatePhoneFidMaps" parameterType="java.util.List">
<foreach collection="subjects" item="subject" separator=";">
UPDATE signals_phone_fid_map
SET
package_id = #{subject.packageId},
subject_id = #{subject.subjectId},
phone = #{subject.phone},
fid = #{subject.fid},
flag_debt5000 = #{subject.flagDebt5000},
flag_90_12 = #{subject.flag90days},
calculated_at = #{subject.calculatedAt}
WHERE id = #{subject.id}
</foreach>
</update>
<select id="findPhoneFidMaps" resultMap="PhoneFidMapResultMap" resultType="java.util.List">
SELECT id, subject_id, phone
FROM signals_phone_fid_map
WHERE package_id = #{packageId}
</select>
<select id="findFullPhoneFidMap" resultMap="PhoneFidMapResultMap" resultType="java.util.List">
SELECT id,
package_id,
subject_id,
phone,
fid,
flag_90_12,
flag_debt5000,
calculated_at
FROM signals_phone_fid_map
WHERE package_id = #{packageId}
</select>
</mapper>

View file

@ -1,156 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ru.nbch.credit_tracker.mapper.signal.SignalMapper">
<resultMap id="subjectDataResultMap" type="ru.nbch.credit_tracker.entities.dto.SubjectData">
<result property="id" column="id"/>
<result property="packageId" column="package_id"/>
<result property="subjectId" column="subject_id"/>
<result property="phone" column="phone"/>
<result property="fid" column="fid"/>
<result property="flagDebt5000" column="flag_debt5000"/>
<result property="flag90days" column="flag_90_12"/>
<result property="calculatedAt" column="calculated_at"/>
</resultMap>
<resultMap id="packageDataResultMap" type="ru.nbch.credit_tracker.entities.dto.PackageData">
<result property="id" column="id"/>
<result property="userId" column="membercode"/>
<result property="packageName" column="package_name"/>
<result property="createdAt" column="created_at"/>
<result property="status" column="status"/>
<result property="lastDownloadedReport" column="last_downloaded_report"/>
</resultMap>
<select id="isPackageNotUnique" resultType="boolean">
SELECT COUNT(*) > 0
FROM signals_user_packages
WHERE membercode IS NOT NULL
AND LEFT(membercode, 6) = #{userId}
AND package_name = #{packageName}
</select>
<select id="isPackageExists" resultType="boolean">
SELECT COUNT(*) > 0
FROM signals_user_packages
WHERE membercode IS NOT NULL
AND LEFT(membercode, 6) = #{userId}
AND package_name = #{packageName}
AND status = #{status}
</select>
<update id="deletePackage">
UPDATE signals_user_packages
SET status = #{status}, deactivated_at = #{deactivatedAt}
WHERE membercode IS NOT NULL AND LEFT(membercode, 6) = #{userId} AND package_name = #{packageName} AND status =
#{previousStatus}
</update>
<select id="registerPackage" resultType="java.lang.Integer"
parameterType="ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest">
INSERT INTO signals_user_packages (membercode, package_name, created_at, status)
values (#{request.userId}, #{request.packageName}, #{creadedAt}, #{status}) RETURNING id
</select>
<insert id="insertPackage"
parameterType="ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest">
INSERT INTO signals_user_packages (membercode, package_name, created_at, status)
values (#{request.userId}, #{request.packageName}, #{creadedAt}, #{status})
</insert>
<insert id="registerSubjects" parameterType="java.util.List">
INSERT INTO signals_phone_fid_map (subject_id, phone, fid, package_id)
values
<foreach collection="subjects" item="subject" separator=",">
(#{subject.id}, #{subject.clientId}, NULL, #{packageId})
</foreach>
</insert>
<insert id="setHits" parameterType="java.util.List">
INSERT INTO signals_hits (package_id, subject_id, signal_type, response_sent_at, report_file_name)
values
<foreach collection="hits" item="hit" separator=",">
(#{hit.packageId}, #{hit.subjectId}, #{hit.signalType}, #{hit.responseSentAt}, #{hit.reportFileName})
</foreach>
</insert>
<update id="updateSubjects" parameterType="java.util.List">
<foreach collection="subjects" item="subject" separator=";">
UPDATE signals_phone_fid_map
SET
package_id = #{subject.packageId},
subject_id = #{subject.subjectId},
phone = #{subject.phone},
fid = #{subject.fid},
flag_debt5000 = #{subject.flagDebt5000},
flag_90_12 = #{subject.flag90days},
calculated_at = #{subject.calculatedAt}
WHERE id = #{subject.id}
</foreach>
</update>
<update id="registerSubjectsFidAndDebts">
UPDATE signals_phone_fid_map
SET fid = #{fid}, flag_debt5000 = #{flagDebt5000}, flag_90_12 = #{flag90}, calculated_at = #{calculatedAt}
WHERE id = #{id}
</update>
<update id="setPackageStatus">
UPDATE signals_user_packages
SET status = #{status}
WHERE id = #{packageId}
</update>
<update id="setPackageLastDownloadedReport">
UPDATE signals_user_packages
SET last_downloaded_report = #{fileName}
WHERE id = #{id}
</update>
<select id="findSubjectsData" resultMap="subjectDataResultMap" resultType="java.util.List">
SELECT id, subject_id, phone
FROM signals_phone_fid_map
WHERE package_id = #{packageId}
</select>
<select id="findFullSubjectsData" resultMap="subjectDataResultMap" resultType="java.util.List">
SELECT id,
package_id,
subject_id,
phone,
fid,
flag_90_12,
flag_debt5000,
calculated_at
FROM signals_phone_fid_map
WHERE package_id = #{packageId}
</select>
<select id="findPackageData" resultMap="packageDataResultMap"
resultType="ru.nbch.credit_tracker.entities.dto.PackageData">
SELECT membercode, package_name
FROM signals_user_packages
WHERE id = #{id}
LIMIT 1
</select>
<select id="findPackageDataList" resultMap="packageDataResultMap"
resultType="ru.nbch.credit_tracker.entities.dto.PackageData">
SELECT package_name, created_at
FROM signals_user_packages
WHERE membercode IS NOT NULL
AND LEFT(membercode, 6) = #{userId}
AND status = #{status}
</select>
<select id="findPackagesByStatus" resultMap="packageDataResultMap"
resultType="ru.nbch.credit_tracker.entities.dto.PackageData">
SELECT id, membercode, package_name, created_at, last_downloaded_report
FROM signals_user_packages
WHERE status = #{status}
</select>
</mapper>

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ru.nbch.credit_tracker.mapper.signal.UserPackageMapper">
<resultMap id="packageDataResultMap" type="ru.nbch.credit_tracker.entities.dto.UserPackage">
<result property="id" column="id"/>
<result property="userId" column="membercode"/>
<result property="packageName" column="package_name"/>
<result property="createdAt" column="created_at"/>
<result property="status" column="status"/>
<result property="lastDownloadedReport" column="last_downloaded_report"/>
</resultMap>
<select id="isPackageNotUnique" resultType="boolean">
SELECT COUNT(*) > 0
FROM signals_user_packages
WHERE membercode IS NOT NULL
AND LEFT(membercode, 6) = #{userId}
AND package_name = #{packageName}
</select>
<select id="isPackageExists" resultType="boolean">
SELECT COUNT(*) > 0
FROM signals_user_packages
WHERE membercode IS NOT NULL
AND LEFT(membercode, 6) = #{userId}
AND package_name = #{packageName}
AND status = #{status}
</select>
<update id="deletePackage">
UPDATE signals_user_packages
SET status = #{status}, deactivated_at = #{deactivatedAt}
WHERE membercode IS NOT NULL AND LEFT(membercode, 6) = #{userId} AND package_name = #{packageName} AND status =
#{previousStatus}
</update>
<select id="insertPackage" resultType="java.lang.Integer"
parameterType="ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest">
INSERT INTO signals_user_packages (membercode, package_name, created_at, status)
values (#{userPackage.userId}, #{userPackage.packageName}, #{userPackage.createdAt}, #{userPackage.status}) RETURNING id
</select>
<update id="updatePackageStatus">
UPDATE signals_user_packages
SET status = #{status}
WHERE id = #{packageId}
</update>
<update id="updatePackageLastDownloadedReport">
UPDATE signals_user_packages
SET last_downloaded_report = #{fileName}
WHERE id = #{id}
</update>
<select id="findPackage" resultMap="packageDataResultMap"
resultType="ru.nbch.credit_tracker.entities.dto.UserPackage">
SELECT membercode, package_name
FROM signals_user_packages
WHERE id = #{id}
LIMIT 1
</select>
<select id="findUserPackages" resultMap="packageDataResultMap"
resultType="ru.nbch.credit_tracker.entities.dto.UserPackage">
SELECT package_name, created_at
FROM signals_user_packages
WHERE membercode IS NOT NULL
AND LEFT(membercode, 6) = #{userId}
AND status = #{status}
</select>
<select id="findAllPackagesByStatus" resultMap="packageDataResultMap"
resultType="ru.nbch.credit_tracker.entities.dto.UserPackage">
SELECT id, membercode, package_name, created_at, last_downloaded_report
FROM signals_user_packages
WHERE status = #{status}
</select>
</mapper>

View file

@ -0,0 +1,156 @@
package ru.nbch.credit_tracker.utils;
import jakarta.xml.bind.JAXBException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.XmlProcessorImplAnyClasses;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@SpringBootTest(classes = {UtilTest.TestConfig.class})
public class UtilTest {
private final IXmlProcessor xmlProcessor;
@Autowired
public UtilTest(IXmlProcessor xmlProcessor) {
this.xmlProcessor = xmlProcessor;
}
@Configuration
public static class TestConfig {
@Bean
public IXmlProcessor xmlProcessor() throws JAXBException {
return new XmlProcessorImplAnyClasses(Charset.forName("windows-1251"),
MonitoringRequest.class);
}
}
private static Stream<Arguments> entryTestCases() {
return Stream.of(
Arguments.of(
"/monitoring_request/valid_request.zip",
true
),
Arguments.of(
"/monitoring_request/directory_request.zip",
false
)
,
Arguments.of(
"/monitoring_request/empty_request.zip",
false
)
,
Arguments.of(
"/monitoring_request/many_files_request.zip",
false
)
,
Arguments.of(
"/monitoring_request/txt_request.zip",
false
)
);
}
@ParameterizedTest(name = "[{index}] PATH: [ {0} ] EXPECTED: [ {1} ]")
@MethodSource("entryTestCases")
void testExtractEntryFromZip(String path, boolean expected) {
ZipInputStream zipInputStream;
Optional<ZipEntry> xmlFileEntry;
try {
zipInputStream = new ZipInputStream(getClass().getResourceAsStream(path));
xmlFileEntry = ZipUtils.extractValidEntry(zipInputStream);
Assertions.assertEquals(expected, xmlFileEntry.isPresent());
zipInputStream.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Stream<Arguments> validationTestCases() {
return Stream.of(
Arguments.of(
"/monitoring_request/valid_request.zip",
null,
null
),
Arguments.of(
"/monitoring_request/invalid_xml.zip",
SignalError.ERROR_011,
Collections.emptyList().toArray(new Object[0])
)
,
Arguments.of(
"/monitoring_request/no_required_tag_request.zip",
SignalError.ERROR_002,
new Object[]{"Password"}
),
Arguments.of(
"/monitoring_request/invalid_phone_request.zip",
SignalError.ERROR_003,
Collections.emptyList().toArray(new Object[0])
),
Arguments.of(
"/monitoring_request/invalid_id_request.zip",
SignalError.ERROR_010,
Collections.emptyList().toArray(new Object[0])
),
Arguments.of(
"/monitoring_request/no_unique_ids_request.zip",
SignalError.ERROR_004,
new Object[]{"abc125"}
)
);
}
@ParameterizedTest(name = "[{index}] PATH: [ {0} ] SIGNALERROR: [ {1} ] ARGS [ {2} ]")
@MethodSource("validationTestCases")
void testMonitoringRequestValidation(String path, SignalError signalError, Object[] args) {
ZipInputStream zipInputStream = null;
MonitoringRequest monitoringRequest;
try {
zipInputStream = new ZipInputStream(getClass().getResourceAsStream(path));
zipInputStream.getNextEntry();
monitoringRequest = xmlProcessor.read(zipInputStream, MonitoringRequest.class);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (zipInputStream != null) {
try {
zipInputStream.close();
} catch (IOException e) {
throw new RuntimeException();
}
}
}
SignalClientException ex = null;
try {
ValidationUtil.validateMonitoringRequest(monitoringRequest);
} catch (SignalClientException e) {
ex = e;
}
if (ex != null) {
Assertions.assertEquals(signalError, ex.getErrorMessage().getSubject());
Assertions.assertArrayEquals(args, ex.getErrorMessage().getArgs());
}
}
}

Binary file not shown.

Binary file not shown.