feat(bj): модуль ЛК на PostgreSQL, обмен с DEPO, боевой ЛК с имитатором НРД, QUIK, НПР

- bj_exchange и «кран» Fancy убраны: данные модуля ЛК в PostgreSQL (схема lk)
- трансферные таблицы FTV_M2M: создание при установке, события, справочник участников
- сверка с DEPO: счёт, ФИО, дата рождения, ИИС по договору, квал-инвестор из опции DEPO
- боевой ЛК ЕСИА Финанс при тестовом ИШ: журнал, отказ через DEPO, статусы в ЛК
- онлайн-лицензирование в bj, план тестирования M2M для контрагента (интерактивный HTML)
- модули QUIK МНП, экспорт QUIK, НПР/УДС; документы и тестовые материалы

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zuevav
2026-09-15 19:41:12 +03:00
parent 59fc774f08
commit da12a9ec1c
132 changed files with 29969 additions and 1089 deletions
+2 -1
View File
@@ -152,7 +152,8 @@ func TestValidatorsNegative(t *testing.T) {
{"UUID без дефисов", m2m.UUID("c02a1d5ec2af4799bab4953f133c5133aaaa")},
{"UUID с не-hex символом", m2m.UUID("c02a1d5e-c2af-4799-babZ-953f133c5133")},
{"UUID короткий", m2m.UUID("c02a1d5e-c2af-4799-bab4-953f133c513")},
{"SecurityCode короткий", m2m.SecurityCode("ABC")},
{"SecurityCode пустой", m2m.SecurityCode("")},
{"SecurityCode длиннее 12", m2m.SecurityCode("ABCDEFGHIJKLM")},
{"SecurityCode с lowercase", m2m.SecurityCode("mm0766162534")},
{"IdentityDocSerial пустой", m2m.IdentityDocSerial("")},
{"IdentityDocSerial с пробелом", m2m.IdentityDocSerial("45 12")},
+6 -4
View File
@@ -82,11 +82,13 @@ func (u UUID) Validate() error {
return nil
}
// Validate проверяет, что значение соответствует SecurityCodeType
// (ровно 12 символов из [0-9A-Z_/-]).
// Validate проверяет, что значение соответствует SecurityCodeType: символы из
// [0-9A-Z_/-], длина 1..12. Код НРД бумаги НЕ обязательно 12 символов и НЕ равен
// ISIN — напр. официальный тест-код Сбербанка на TEST3 = "SBER/03" (7 симв.,
// ответ НРД от 15.08.2026). Раньше требовали ровно 12 → падало на коротких кодах.
func (c SecurityCode) Validate() error {
if len(c) != 12 {
return fmt.Errorf("%w: SecurityCode длина %d, ожидается 12", ErrInvalid, len(c))
if n := len(c); n < 1 || n > 12 {
return fmt.Errorf("%w: SecurityCode длина %d, ожидается 1..12", ErrInvalid, n)
}
if !reSecurityCode.MatchString(string(c)) {
return fmt.Errorf("%w: SecurityCode %q содержит недопустимые символы", ErrInvalid, string(c))