dictionaries.xml (data.sql) поправил опечатки в LICC, добавил юниттест

This commit is contained in:
AKurakin 2024-07-01 14:36:31 +03:00
parent 1ec5303b12
commit 4b1a834883
5 changed files with 194 additions and 14 deletions

View file

@ -112,6 +112,11 @@
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>

View file

@ -62,7 +62,7 @@
<documentType id="19" code="XCNT" name="Документ о расторжении Договора клиринга"/>
<documentType id="20" code="LICD" name="Документ о дилерской лицензии"/>
<documentType id="21" code="LICT" name="Документ о лицензии по управлению ЦБ"/>
<documentType id="22" code="LICС" name="Документ о лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)"/>
<documentType id="22" code="LICC" name="Документ о лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)"/>
<documentType id="23" code="LICF" name="Документ о лицензии форекс-дилера"/>
<documentType id="24" code="LICM" name="Документ о лицензии на управление инвестиционными фондами, паевыми инвестиционными фондами, негосударственными пенсионными фондами"/>
<companySymbol id="1" code="INN" name="Индивидуальный налоговый номер" shortname="ИНН"/>
@ -76,7 +76,7 @@
<companySymbol id="9" code="OGRN" name="Основной государственный регистрационный номер" shortname="ОГРН"/>
<companySymbol id="10" code="LICD" name="Номер дилерской лицензии" shortname="Дилерская деятельность"/>
<companySymbol id="11" code="LICT" name="Номер лицензии по управлению ЦБ" shortname="Управление ценными бумагами"/>
<companySymbol id="12" code="LICС" name="Номер лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)" shortname="Брокерская деятельность ПФИ"/>
<companySymbol id="12" code="LICC" name="Номер лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)" shortname="Брокерская деятельность ПФИ"/>
<companySymbol id="13" code="LICF" name="Номер лицензии форекс-дилера" shortname="Деятельность форекс-дилера"/>
<companySymbol id="14" code="LICR" name="Номер брокерской лицензии" shortname="Брокерская деятельность"/>
<companySymbol id="15" code="TRDC" name="Код участника торгов" shortname="Биржевой код"/>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?-->
<meta version="3.12.2.95">
<meta version="3.12.2.96">
<!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" -->
<!--Здесь словари-->
<enums>
@ -920,7 +920,7 @@
<clearingDate type="6" name="Текущая дата" shortname="Дата" visible="false" searchable="true" sortable="true" ignore="true"/>
</errorText>
<clientCode name="Коды клиентов компании" destination="client-codes" class="ru.clearing.classes.statics.data.account.ClientCode" logUpdates="true" table="client_сode">
<clientCode name="Коды клиентов компании" destination="client-codes" class="ru.clearing.classes.statics.data.account.ClientCode" logUpdates="true" table="client_code">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" searchable="true" sortable="true" visible="true" link="company" linkCode="shortName"/>
<code type="2" length="255" name="Код клиента" shortname="Код клиента" searchable="true" sortable="true" visible="true"/>
@ -1498,7 +1498,7 @@
<counterPartyId type="1" dbname="Идентификатор компании-партнера, с которой заключена сделка" name="Наименование компании-партнера, с которой заключена сделка" shortname="Партнер" visible="false" searchable="true" sortable="true" link="company" linkCode="shortName"/>
<counterPartyTradingClearingRegistryId type="1" dbname="Идентификатор торгово-клирингового регистра партнера" name="Торгово-клиринговый регистр партнера" shortname="ТКР партнера" visible="true" searchable="true" sortable="true" link="tradingClearingRegistry" linkCode="code" ignore="true"/>
<counterPartyTradingClearingRegistry type="2" length="20" dbname="Торгово-клиринговый регистр партнера" name="Торгово-клиринговый регистр партнера" shortname="ТКР партнера" visible="true" searchable="true" sortable="true" />
<coverageStatus type="12" dbname="Код статуса достаточности обеспечения" name="Cтатус достаточности обеспечения" shortname="Обеспеченность" searchable="true" sortable="true" link="allowed"/>
<coverageStatus type="12" dbname="Код статуса достаточности обеспечения" name="Статус достаточности обеспечения" shortname="Обеспеченность" searchable="true" sortable="true" link="allowed"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
<id type="1" name="Идентификатор записи" shortname="ID" visible="false" searchable="true" sortable="true"/>
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" visible="false" searchable="true" sortable="true"/>
@ -1537,7 +1537,7 @@
<settlementDate type="6" name="Дата расчетов" shortname="Дата расчетов" visible="true" searchable="true" sortable="true"/>
<settlementCurrency type="12" dbname="Код валюты расчетов по инструменту" name="Валюта расчетов по инструменту" shortname="Валюта" visible="true" searchable="true" sortable="true" link="currencyCode" linkCode="code"/>
<exchangeExecutionMicroseconds type="4" name="Микросекунды заключения сделки в Торговой системе" shortname="Микросекунды заключения сделки" visible="true" searchable="true" sortable="true"/>
<coverageStatus type="12" dbname="Код статуса достаточности обеспечения" name="Cтатус достаточности обеспечения" shortname="Обеспеченность" searchable="true" sortable="true" link="allowed"/>
<coverageStatus type="12" dbname="Код статуса достаточности обеспечения" name="Статус достаточности обеспечения" shortname="Обеспеченность" searchable="true" sortable="true" link="allowed"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
</executionFond>
<executionCurrency name="Сделки с валютными инструментами" destination="execution-currency" class="ru.clearing.classes.statics.data.execution.ExecutionCurrency" logUpdates="true" table="execution_currency">
@ -1565,7 +1565,7 @@
<side type="12" dbname="Код направления сделки" name="Направление сделки" shortname="Направление" visible="true" searchable="true" sortable="true" link="side"/>
<currencyCode type="12" name="Код валюты лота" shortname="Код валюты лота" searchable="true" sortable="true" link="currencyCode" linkCode="code"/>
<settlementOrganization type="2" length="255" name="Наименование расчетной организации" shortname="Расчетная организация" searchable="true" sortable="true" visible="true"/>
<coverageStatus type="12" dbname="Код статуса достаточности обеспечения" name="Cтатус достаточности обеспечения" shortname="Обеспеченность" searchable="true" sortable="true" link="allowed"/>
<coverageStatus type="12" dbname="Код статуса достаточности обеспечения" name="Статус достаточности обеспечения" shortname="Обеспеченность" searchable="true" sortable="true" link="allowed"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
<clearingDate type="6" name="Дата клиринга" shortname="Дата клиринга" visible="false" searchable="true" sortable="true"/>
<id type="1" name="Идентификатор записи" shortname="ID" visible="false" searchable="true" sortable="true"/>
@ -1658,8 +1658,8 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
<validFromDate type="6" name="Дата начала cессии" shortname="Дата начала cессии" searchable="true" sortable="true"/>
<validToDate type="6" name="Дата окончания cессии" shortname="Дата окончания cессии" searchable="true" sortable="true"/>
<validFromDate type="6" name="Дата начала сессии" shortname="Дата начала сессии" searchable="true" sortable="true"/>
<validToDate type="6" name="Дата окончания сессии" shortname="Дата окончания сессии" searchable="true" sortable="true"/>
<companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" searchable="true" sortable="true" visible="true" link="company" linkCode="shortName"/>
<companyFullName type="2" length="255" name="Полное наименование компании" shortname="Полное наименование компании" searchable="true" sortable="true" visible="true"/>
<inn type="2" length="255" name="Идентификационный номер налогоплательщика (ИНН)" shortname="ИНН" searchable="true" sortable="true" visible="true"/>
@ -1695,8 +1695,8 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
<validFromDate type="6" name="Дата начала cессии" shortname="Дата начала cессии" searchable="true" sortable="true"/>
<validToDate type="6" name="Дата окончания cессии" shortname="Дата окончания cессии" searchable="true" sortable="true"/>
<validFromDate type="6" name="Дата начала сессии" shortname="Дата начала сессии" searchable="true" sortable="true"/>
<validToDate type="6" name="Дата окончания сессии" shortname="Дата окончания сессии" searchable="true" sortable="true"/>
<companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" searchable="true" sortable="true" visible="true" link="company" linkCode="shortName"/>
<companyFullName type="2" name="Полное наименование компании" shortname="Полное наименование компании" searchable="true" sortable="true" length="255" visible="true"/>
<inn type="2" length="255" name="Идентификационный номер налогоплательщика (ИНН)" shortname="ИНН" searchable="true" sortable="true" visible="true"/>
@ -1765,7 +1765,7 @@
<settlementDate type="6" name="Дата расчетов" shortname="Дата расчетов" searchable="true" sortable="true" visible="true"/>
<creditLeg_amount type="10" name="Сумма отправителя" shortname="Сумма отправителя" searchable="true" sortable="true" visible="true"/>
<debitLeg_amount type="10" name="Сумма получателя" shortname="Сумма получателя" searchable="true" sortable="true" visible="true"/>
<creditLeg_accountId type="1" dbname="Идентификатор счета отправителя" name="Cчет отправителя" shortname="Счет отправителя" searchable="true" sortable="true" link="account" ignore="true"/>
<creditLeg_accountId type="1" dbname="Идентификатор счета отправителя" name="Счет отправителя" shortname="Счет отправителя" searchable="true" sortable="true" link="account" ignore="true"/>
<credit_csAccount type="2" length="255" name="Корреспондентский счет отправителя" shortname="Корр. счет отправителя" searchable="true" sortable="true" ignore="true"/>
<creditLeg_account type="2" length="50" name="Счет отправителя" shortname="Счет отправителя" searchable="true" sortable="true" visible="true"/>
<debitLeg_accountId type="1" dbname="Идентификатор счета получателя" name="Счет получателя" shortname="Счет получателя" searchable="true" sortable="true" link="account" ignore="true"/>

View file

@ -0,0 +1,175 @@
package ru.spcex.clearing.backendapi.meta;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* Проверяет словари на опечатки: пустые значения, сочетание кириллицы и латиницы в одном слове.
* dictionaries.xml
* data_initial.xml
* data_register_code.xml
*/
public class DataXmlTest {
private Logger log = LoggerFactory.getLogger(getClass());
@Test
public void testMetaXml() throws IOException {
verifyXML(new File("src/main/resources/meta/meta.xml"));
}
/**
* Проверка XML (data.xml aka dictionaries.xml)
*
* @throws IOException
*/
@Test
public void testDictionariesXml() throws IOException {
verifyXML(new File("src/main/resources/meta/dictionaries.xml"));
}
@Test
public void testDataInitialXml() throws IOException {
verifyXML(new File("src/main/resources/meta/data_initial.xml"));
}
@Test
public void testDataRegisterCodeXml() throws IOException {
verifyXML(new File("src/main/resources/meta/data_register_code.xml"));
}
protected void verifyXML(File xmlFile) throws IOException {
XmlMapper xmlObjectMapper = new XmlMapper();
xmlObjectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
xmlObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// Это юнит-тест с внутренними данными, парсинг DTD выключать не обязательно.
Map<String, Object> root = xmlObjectMapper.readValue(xmlFile, Map.class);
Assertions.assertNotNull(root, "Empty XML in file " + xmlFile);
String errors = verifyNode(xmlFile.getName(), root);
Assertions.assertNull(errors, errors);
}
private String verifyNode(String path, Map<String, Object> node) {
for (Map.Entry<String, Object> item : node.entrySet()) {
String name = item.getKey();
if (!verifyText(name)) {
return path + "> node name \"" + name + "\" has error";
}
String thisPath = path + "/" + name;
if (item.getValue() instanceof Map itemValue) {
String error = verifyNode(thisPath, itemValue);
if (error != null)
return error;
} else if (item.getValue() instanceof String text) {
if (!verifyText(text)) {
return thisPath + "> has error in content: \"" + text + "\"";
}
} else if (item.getValue() instanceof List values) {
for (Object o : values) {
if (o instanceof Map itemMap) {
String error = verifyNode(thisPath, itemMap);
if (error != null)
return error;
} else if (o instanceof String oVal) {
if (!verifyText(oVal)) {
return thisPath + "> one of values in node \"" + oVal + "\" has error";
}
} else if (o == null) {
// nothing
} else {
throw new IllegalArgumentException(thisPath + "> Unsupported one of value type " + o.getClass().getSimpleName() + " for verification");
}
}
} else if (item.getValue() == null) {
// nothing
} else {
throw new IllegalArgumentException(thisPath + "> Unsupported value type " + item.getValue().getClass().getSimpleName() + " for verification");
}
}
return null;
}
final char[] CYRILLICS;
final char[] LATINS;
{
CYRILLICS = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя".toCharArray();
LATINS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
Arrays.sort(CYRILLICS);
Arrays.sort(LATINS);
}
/**
* Проверяет смесь кириллицы и латиницы в одном слове
*
* @param text
* @return
*/
boolean verifyText(String text) {
boolean word = false, cyrillic = false, latin = false;
if (text != null) {
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
boolean isWhitespace = Character.isWhitespace(c);
boolean isCyrillic = Arrays.binarySearch(CYRILLICS, c) >= 0;
boolean isLatin = Arrays.binarySearch(LATINS, c) >= 0;
assert !(isCyrillic && isLatin);
assert !(isWhitespace && (isCyrillic || isLatin));
if (word && isWhitespace) {
word = false; // слово закончилось
if (cyrillic && latin)
return false; // Смесь кириллицы и латиницы
} else if (!word && !isWhitespace) {
word = true; // новое слово
cyrillic = latin = false;
}
cyrillic |= isCyrillic;
latin |= isLatin;
}
if (cyrillic && latin)
return false; // Смесь кириллицы и латиницы
}
return true;
}
@Test
public void selfTest() {
verifyText(null);
Assertions.assertTrue(verifyText(""));
Assertions.assertTrue(verifyText("A"));
Assertions.assertTrue(verifyText(" A "));
Assertions.assertTrue(verifyText("A call of"));
Assertions.assertTrue(verifyText("The spring of spin winter."));
Assertions.assertTrue(verifyText("Пользователь user текст обычный."));
Assertions.assertTrue(verifyText("АККаунт mixED 102E333C"));
Assertions.assertTrue(verifyText("АКК_аунт mi_xED 10-+*/2E333C"));
Assertions.assertTrue(verifyText("XML"));
Assertions.assertTrue(verifyText("Same sample apple"));
Assertions.assertTrue(verifyText("По tExT кРАям"));
Assertions.assertFalse(verifyText("Пользоватьель userтекст обычный."));
Assertions.assertFalse(verifyText("ХML"));
Assertions.assertFalse(verifyText("XМL"));
Assertions.assertFalse(verifyText("XMЛ"));
Assertions.assertFalse(verifyText(" ХML"));
Assertions.assertFalse(verifyText(" XМL"));
Assertions.assertFalse(verifyText(" XMЛ"));
Assertions.assertFalse(verifyText("ХML "));
Assertions.assertFalse(verifyText("XМL "));
Assertions.assertFalse(verifyText("XMЛ "));
Assertions.assertFalse(verifyText("12XM_Л34"));
Assertions.assertFalse(verifyText("Same sample аррlе"));
Assertions.assertFalse(verifyText("Same samplе apple"));
Assertions.assertFalse(verifyText("Same sample аpple"));
Assertions.assertFalse(verifyText("client_сode"));
}
}

View file

@ -126,7 +126,7 @@ INSERT INTO DOCUMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (20, 'LICD', 'Док
INSERT INTO DOCUMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (21, 'LICT', 'Документ о лицензии по управлению ЦБ') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO DOCUMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (22, 'LICС', 'Документ о лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO DOCUMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (22, 'LICC', 'Документ о лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO DOCUMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (23, 'LICF', 'Документ о лицензии форекс-дилера') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -154,7 +154,7 @@ INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (10, 'LI
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (11, 'LICT', 'Номер лицензии по управлению ЦБ', 'Управление ценными бумагами') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (12, 'LICС', 'Номер лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)', 'Брокерская деятельность ПФИ') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (12, 'LICC', 'Номер лицензии по брокерской деятельности ПФИ (производных финансовых инструментов)', 'Брокерская деятельность ПФИ') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;
INSERT INTO COMPANY_SYMBOL_DICTIONARY(ID, CODE, NAME, SHORTNAME) values (13, 'LICF', 'Номер лицензии форекс-дилера', 'Деятельность форекс-дилера') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME, SHORTNAME = EXCLUDED.SHORTNAME;