Files
Bridge-and-Join-s/internal/lkgateway/participant_form_test.go
T
fontvielle c021fb8273 Анкета участника M2M: сформировать → проверить → отправить в НРД (обычный канал)
Требование НРД при подключении к сервису M2M (МОСТ): зарегистрировать организацию
в справочнике участников анкетой M2MTransferParticipantForm, иначе сервис отбивает
запросы кодом M2M14. Регистрация идёт ОБЫЧНЫМ каналом (письмом на M2MOST@nsd.ru с
вложением), не через M2M-шлюз.

- Новая страница /admin/setup/participant-form (participant_form.go):
  предзаполнение из автоопределения DEPO (ИНН, наименования, код депозитария),
  правка оператором, валидация (формат ИНН/кодов + m2m.HandbookParticipant.Validate),
  предпросмотр анкеты, «Скачать» (windows-1251) и «Отправить в НРД» письмом с
  вложением-анкетой.
- Генерация XML строкой-шаблоном по образцу НРД (namespace participant/form,
  CreationTimestamp по МСК, блоки Eng/BrokerPlace — опциональны), кодировка
  windows-1251 через nsdxml.EncodeWindows1251; экранирование текста только & < >.
- Почта: выделен транспорт smtpDeliver из sendSMTP; добавлены buildMIMEAttach
  (multipart/mixed + base64-вложение) и sendSMTPAttach.
- Тесты: валидация, генерация XML (Eng/BrokerPlace), cp1251 round-trip, MIME-вложение.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XG3zNMMf2LMoDpXo22mwMX
2026-10-15 18:20:03 +03:00

101 lines
3.5 KiB
Go

package lkgateway
import (
"strings"
"testing"
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdxml"
)
func validPF() participantFormData {
return participantFormData{
INN: "7703807489", FullName: `ООО "Фонтвьель"`, ShortName: "Фонтвьель",
DisplayName: "Фонтвьель", DepoCode: "MC0413600000",
}
}
func TestParticipantFormValidate(t *testing.T) {
if errs := participantFormValidate(validPF()); len(errs) != 0 {
t.Fatalf("корректная анкета должна проходить, получили: %v", errs)
}
bad := validPF()
bad.INN = "770380748" // 9 цифр
if errs := participantFormValidate(bad); len(errs) == 0 {
t.Fatal("ИНН из 9 цифр должен отклоняться")
}
bad = validPF()
bad.DepoCode = "XX0413600000"
if errs := participantFormValidate(bad); len(errs) == 0 {
t.Fatal("код не в формате MC+10 должен отклоняться")
}
bad = validPF()
bad.DisplayName = ""
if errs := participantFormValidate(bad); len(errs) == 0 {
t.Fatal("пустой DisplayName должен отклоняться")
}
bad = validPF()
bad.BrokerCode = "MC12" // неверный формат
if errs := participantFormValidate(bad); len(errs) == 0 {
t.Fatal("неверный код брокера должен отклоняться")
}
}
func TestParticipantFormXML(t *testing.T) {
x := participantFormXML(validPF())
for _, want := range []string{
`encoding="windows-1251"`,
`<pf:M2MTransferParticipantForm`,
`http://nsd.ru/schemas/m2m/participant/form`,
`<m2m:INN>7703807489</m2m:INN>`,
`<m2m:DepositoryPlace>`,
`<m2m:ParticipantCode>MC0413600000</m2m:ParticipantCode>`,
`(МСК)`,
} {
if !strings.Contains(x, want) {
t.Errorf("XML должен содержать %q\n---\n%s", want, x)
}
}
if strings.Contains(x, "<m2m:Eng>") {
t.Error("без англ. полей блок Eng не должен появляться")
}
if strings.Contains(x, "<m2m:BrokerPlace>") {
t.Error("без кода брокера блок BrokerPlace не должен появляться")
}
// С англ. и брокером — блоки появляются.
d := validPF()
d.EngFull, d.BrokerCode = "Fontvielle LLC", "MC0413600001"
x2 := participantFormXML(d)
if !strings.Contains(x2, "<m2m:Eng>") || !strings.Contains(x2, "Fontvielle LLC") {
t.Error("с англ. наименованием блок Eng обязателен")
}
if !strings.Contains(x2, "<m2m:BrokerPlace>") || !strings.Contains(x2, "MC0413600001") {
t.Error("с кодом брокера блок BrokerPlace обязателен")
}
}
func TestParticipantFormBytesCP1251(t *testing.T) {
b, err := participantFormBytes(validPF())
if err != nil {
t.Fatal(err)
}
// Декод обратно из 1251 — кириллица восстанавливается.
got := string(nsdxml.DecodeWindows1251(b))
if !strings.Contains(got, `ООО "Фонтвьель"`) {
t.Errorf("после cp1251 round-trip потеряна кириллица:\n%s", got)
}
}
func TestBuildMIMEAttach(t *testing.T) {
msg := string(buildMIMEAttach("a@b.ru", []string{"M2MOST@nsd.ru"}, "Тема", "тело", "form.xml", []byte("<xml/>"), "application/xml"))
for _, want := range []string{
"multipart/mixed; boundary=",
"Content-Disposition: attachment; filename=\"form.xml\"",
"Content-Transfer-Encoding: base64",
"To: M2MOST@nsd.ru",
} {
if !strings.Contains(msg, want) {
t.Errorf("MIME должен содержать %q", want)
}
}
}