From 9a227228e5bf5d3ed06399e946f386e792cec0a4 Mon Sep 17 00:00:00 2001 From: fontvielle Date: Thu, 22 Oct 2026 10:04:09 +0300 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=BD=D0=BA=D0=B5=D1=82=D0=B0=20=D1=83?= =?UTF-8?q?=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=B0:=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B8=D0=B7=20=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B9=20=D0=B1=D0=B0=D0=B7=D1=8B=20=D0=9D?= =?UTF-8?q?=D0=A0=D0=94,=20=D0=BF=D1=80=D1=8F=D0=BC=D1=8B=D0=B5=20=D0=BA?= =?UTF-8?q?=D0=B0=D0=B2=D1=8B=D1=87=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit НРД ответил M2M37 на анкету 21.10: в FullName ушло краткое наименование из DEPO. Теперь полное, краткое и отображаемое берутся из карточки нашей фирмы в справочнике НРД (НРД сверяет именно с клиентской базой); отображаемое = краткое, как советует НРД. Английские — только введённые. Кавычки «» “” приводятся к прямым ", как в базе НРД. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn --- internal/lkgateway/participant_form.go | 30 +++++++++++++++------ internal/lkgateway/participant_name_test.go | 29 ++++++++++++++++++++ internal/lkgateway/workhours.go | 2 +- 3 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 internal/lkgateway/participant_name_test.go diff --git a/internal/lkgateway/participant_form.go b/internal/lkgateway/participant_form.go index 593ce70..554f7ed 100644 --- a/internal/lkgateway/participant_form.go +++ b/internal/lkgateway/participant_form.go @@ -79,16 +79,18 @@ func participantFormPrefill(rc *RuntimeConfig) participantFormData { hb, ok = handbookByINN(d.INN) } if ok { - if d.FullName == "" { - d.FullName = strings.TrimSpace(pick(hb.FullName, hb.Name)) + // НРД сверяет наименования анкеты со своей клиентской базой (M2M37) — карточка в справочнике + // НРД главнее DEPO: в DEPO «наименование» бывает кратким (21.10.2026 краткое ушло в FullName). + // Английские — только если их ввели: в справочнике есть лишь краткое, полного нет. + if n := strings.TrimSpace(hb.FullName); n != "" { + d.FullName = n } - if d.ShortName == "" { - d.ShortName = strings.TrimSpace(hb.Name) + if n := strings.TrimSpace(hb.Name); n != "" && hb.FullName != "" { + d.ShortName, d.DisplayName = n, n // отображаемое НРД советует как краткое } - if d.DisplayName == "" { - d.DisplayName = strings.TrimSpace(pick(hb.DisplayName, hb.Name)) - } - if d.EngFull == "" { + if strings.TrimSpace(hb.FullName) != "" { + d.EngFull = "" + } else if d.EngFull == "" { d.EngFull = strings.TrimSpace(hb.EngName) } if hb.Kind == "broker" && d.BrokerCode == "" { @@ -144,6 +146,16 @@ func participantFormValidate(d participantFormData) []string { return errs } +// pfQuotes — кавычки как в клиентской базе НРД: прямые ". +var pfQuotes = strings.NewReplacer("«", `"`, "»", `"`, "“", `"`, "”", `"`, "„", `"`) + +// pfNames — наименования к виду базы НРД (кавычки, лишние пробелы). +func pfNames(d *participantFormData) { + for _, p := range []*string{&d.FullName, &d.ShortName, &d.DisplayName, &d.EngFull, &d.EngShort, &d.EngDisplay} { + *p = strings.Join(strings.Fields(pfQuotes.Replace(*p)), " ") + } +} + // pfx — экранирование текста XML-элемента (только & < >); кавычки в тексте // оставляем литеральными, как в образце анкеты НРД. var pfXMLEsc = strings.NewReplacer("&", "&", "<", "<", ">", ">") @@ -153,6 +165,7 @@ func pfx(s string) string { return pfXMLEsc.Replace(strings.TrimSpace(s)) } // participantFormXML — анкета в виде XML-строки (UTF-8) по образцу НРД // (M2MTransferParticipantForm.xsd). CreationTimestamp — по МСК. func participantFormXML(d participantFormData) string { + pfNames(&d) msk := time.FixedZone("МСК", 3*3600) ts := time.Now().In(msk).Format("2006-01-02T15:04:05") + "(МСК)" var b strings.Builder @@ -278,6 +291,7 @@ func registerParticipantForm(mux *http.ServeMux, rc *RuntimeConfig, igwClient *i EngDisplay: r.FormValue("eng_display"), DepoCode: r.FormValue("depo"), BrokerCode: r.FormValue("broker"), } } + pfNames(&d) // кавычки и пробелы — как в базе НРД, и в анкете, и в форме, и в статусе errs := participantFormValidate(d) if action == "download" { diff --git a/internal/lkgateway/participant_name_test.go b/internal/lkgateway/participant_name_test.go new file mode 100644 index 0000000..957bc17 --- /dev/null +++ b/internal/lkgateway/participant_name_test.go @@ -0,0 +1,29 @@ +package lkgateway + +import ( + "strings" + "testing" +) + +// Наименования в анкете — как в клиентской базе НРД: прямые кавычки, без лишних пробелов (M2M37). +func TestParticipantFormNames(t *testing.T) { + d := participantFormData{ + INN: "7703807489", DepoCode: "MC0413600000", + FullName: "Общество с ограниченной ответственностью «Инвестиционная Компания “Фонтвьель»", + ShortName: "ООО «ИК «Фонтвьель»", + DisplayName: "ООО «ИК «Фонтвьель»", + } + x := participantFormXML(d) + for _, want := range []string{ + `Общество с ограниченной ответственностью "Инвестиционная Компания "Фонтвьель"`, + `ООО "ИК "Фонтвьель"`, + `ООО "ИК "Фонтвьель"`, + } { + if !strings.Contains(x, want) { + t.Errorf("нет %s в\n%s", want, x) + } + } + if strings.Contains(x, "") { + t.Error("пустые английские наименования не должны попадать в анкету") + } +} diff --git a/internal/lkgateway/workhours.go b/internal/lkgateway/workhours.go index 662c76a..1d5479d 100644 --- a/internal/lkgateway/workhours.go +++ b/internal/lkgateway/workhours.go @@ -121,7 +121,7 @@ func (r *RuntimeConfig) UpdateWorkHours(w WorkHoursSettings) error { return r.save() } -// saveWorkHours — POST /admin/setup/workhours (шаг «Время и сеть», Настройка → Сервер). +// saveWorkHours — POST /admin/setup/workhours (шаг «Время и сеть», Настройка → НРД). func (h *setupHandlers) saveWorkHours(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method", http.StatusMethodNotAllowed)