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
+57 -5
View File
@@ -38,11 +38,18 @@ import (
// config — содержимое config.xml внутри пакета.
type config struct {
XMLName xml.Name `xml:"config"`
Name string `xml:"name"`
Package string `xml:"package"`
XMLName xml.Name `xml:"config"`
Name string `xml:"name"`
Package string `xml:"package"`
BusinessLine string `xml:"businessLine,omitempty"`
}
// BusinessLine — бизнес-линия для config.xml. С версии ИШ 107.0.0.904 при M2M
// ОБЯЗАТЕЛЬНО указывать "MOST"; на версиях младше — НЕ допускается. Пусто (по
// умолчанию) → элемент опускается (omitempty), т.е. совместимо со старым ИШ.
// Оператор ставит "MOST" в настройках НРД после обновления ИШ до 107.0.0.904+.
var BusinessLine string
// PackRequest упаковывает M2MTransferRequest в ZIP-архив для ИШ.
// docFileName — имя XML внутри архива (например "M2MTransferRequest.xml").
// Возвращает байты ZIP, готовые к отправке через POST /api/package/{channel}/file.
@@ -76,6 +83,51 @@ func PackXML(xmlBytes []byte, docFileName, packageType string) ([]byte, error) {
return packZIP(xmlBytes, docFileName, packageType)
}
// PackDepoOrder упаковывает XML депозитарного поручения (форма MF010, операции
// 16/16-1) в пакет ЭД типа ORDXM для отправки в НРД: config.xml с
// <package>K</package> и БЕЗ businessLine (это не M2M, а классическое поручение
// депо; см. «Инструкция по взаимодействию с НРД через Web-сервис», разд. 8.1).
// ИШ сам подписывает документ ГОСТ-подписью при отправке через REST API.
func PackDepoOrder(xmlBytes []byte, docFileName string) ([]byte, error) {
if len(xmlBytes) == 0 {
return nil, errors.New("igw: PackDepoOrder: xmlBytes пустой")
}
if docFileName == "" {
docFileName = "Poruchenie.xml"
}
return packZIPWith(xmlBytes, docFileName, "K", "")
}
// packZIPWith — как packZIP, но с явными package и businessLine (без глобальной
// BusinessLine), чтобы слать не-M2M документы (напр. поручение депо, package=K).
func packZIPWith(xmlBytes []byte, docFileName, pkg, businessLine string) ([]byte, error) {
var buf bytes.Buffer
w := zip.NewWriter(&buf)
fw, err := w.Create(docFileName)
if err != nil {
return nil, fmt.Errorf("igw: create %s in zip: %w", docFileName, err)
}
if _, err := fw.Write(xmlBytes); err != nil {
return nil, err
}
cfg := config{Name: docFileName, Package: pkg, BusinessLine: businessLine}
cfgBytes, err := xml.MarshalIndent(cfg, "", " ")
if err != nil {
return nil, fmt.Errorf("igw: marshal config.xml: %w", err)
}
cw, err := w.Create("config.xml")
if err != nil {
return nil, fmt.Errorf("igw: create config.xml in zip: %w", err)
}
if _, err := cw.Write(cfgBytes); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, fmt.Errorf("igw: close zip: %w", err)
}
return buf.Bytes(), nil
}
func packZIP(xmlBytes []byte, docFileName, packageType string) ([]byte, error) {
var buf bytes.Buffer
w := zip.NewWriter(&buf)
@@ -89,8 +141,8 @@ func packZIP(xmlBytes []byte, docFileName, packageType string) ([]byte, error) {
return nil, err
}
// 2. config.xml
cfg := config{Name: docFileName, Package: packageType}
// 2. config.xml (businessLine добавляется только если задан — см. BusinessLine)
cfg := config{Name: docFileName, Package: packageType, BusinessLine: BusinessLine}
cfgBytes, err := xml.MarshalIndent(cfg, "", " ")
if err != nil {
return nil, fmt.Errorf("igw: marshal config.xml: %w", err)