Анкета участника: наименования из клиентской базы НРД, прямые кавычки

НРД ответил M2M37 на анкету 21.10: в FullName ушло краткое наименование
из DEPO. Теперь полное, краткое и отображаемое берутся из карточки нашей
фирмы в справочнике НРД (НРД сверяет именно с клиентской базой);
отображаемое = краткое, как советует НРД. Английские — только введённые.
Кавычки «» “” приводятся к прямым ", как в базе НРД.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
fontvielle
2026-10-22 10:04:09 +03:00
parent a2608076a4
commit 9a227228e5
3 changed files with 52 additions and 9 deletions
+22 -8
View File
@@ -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("&", "&amp;", "<", "&lt;", ">", "&gt;")
@@ -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" {
@@ -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{
`<m2m:FullName>Общество с ограниченной ответственностью "Инвестиционная Компания "Фонтвьель"</m2m:FullName>`,
`<m2m:ShortName>ООО "ИК "Фонтвьель"</m2m:ShortName>`,
`<m2m:DisplayName>ООО "ИК "Фонтвьель"</m2m:DisplayName>`,
} {
if !strings.Contains(x, want) {
t.Errorf("нет %s в\n%s", want, x)
}
}
if strings.Contains(x, "<m2m:Eng>") {
t.Error("пустые английские наименования не должны попадать в анкету")
}
}
+1 -1
View File
@@ -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)