Анкета участника: ловить ответ НРД (M2MER с нулевым GUID) и показывать отправку/ответ

Ответ НРД на анкету приходит как M2MTransferResponse (M2MER) с нулевым GUID —
раньше он уходил в обработку перевода, «сделка не найдена», и отбрасывался.
Теперь нулевой GUID распознаётся как ответ на регистрацию участника:
- сырой XML сохраняется (captureNSDReply → nsd-replies);
- отправка анкеты и ответ НРД пишутся в participant-reg.json (время, пакет,
  наименование, статус, коды, текст НРД);
- на странице «Регистрация участника M2M» показываем: когда отправили и вердикт
  НРД («принял»/«отклонил» с текстом, напр. M2M37 «Некорректно указано
  наименование участника в анкете»).
Текст берётся из самого ответа (serviceErrorTexts) — карту кодов не трогаем.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
fontvielle
2026-10-21 18:01:50 +03:00
parent 416f9bdcd5
commit 07866526eb
4 changed files with 121 additions and 6 deletions
+27 -4
View File
@@ -355,6 +355,9 @@ func registerParticipantForm(mux *http.ServeMux, rc *RuntimeConfig, igwClient *i
break
}
flash, flashKind = "Анкета отправлена через ИШ ("+string(pkg)+", пакет id="+id+"). Ждём подтверждения регистрации от НРД.", "ok"
saveParticipantReg(func(rg *participantReg) {
*rg = participantReg{SentAt: time.Now(), PkgID: id, Name: d.FullName, Channel: igwChannel}
})
}
}
@@ -370,6 +373,24 @@ func participantRegStatus(rc *RuntimeConfig) string {
if rc == nil {
return ""
}
var out strings.Builder
// Последняя отправка анкеты и ответ НРД на неё (учёт в participant-reg.json).
if reg := loadParticipantReg(); !reg.SentAt.IsZero() {
out.WriteString(`<div class="note">Анкета отправлена через ИШ ` + reg.SentAt.Format("02.01.2006 15:04") + `, пакет ` + html.EscapeString(reg.PkgID))
if reg.Name != "" {
out.WriteString(`, наименование «` + html.EscapeString(reg.Name) + `»`)
}
out.WriteString(`. `)
switch {
case reg.RespAt.IsZero():
out.WriteString(`Ответ НРД пока не получен.`)
case strings.EqualFold(reg.Status, "ERROR"):
out.WriteString(`<b style="color:#b00">НРД отклонил</b> ` + reg.RespAt.Format("02.01 15:04") + `: ` + html.EscapeString(reg.RespText) + `. Исправьте указанное и отправьте снова.`)
default:
out.WriteString(`<b style="color:#2a7a2a">НРД принял</b> ` + reg.RespAt.Format("02.01 15:04") + `. ` + html.EscapeString(reg.RespText))
}
out.WriteString(`</div>`)
}
s := rc.Snapshot()
contour := map[string]string{"prod": "боевого", "guest": "гостевого", "test3": "тестового"}[contourOf(currentNSDProfile())]
if contour == "" {
@@ -382,13 +403,15 @@ func participantRegStatus(rc *RuntimeConfig) string {
}
}
if ok {
return `<div class="ok">В справочнике участников M2M ` + contour + ` контура: <b>есть</b> — ` +
out.WriteString(`<div class="ok">В справочнике участников M2M ` + contour + ` контура: <b>есть</b> — ` +
html.EscapeString(pickStr(hb.Name, hb.FullName)) + `, код ` + html.EscapeString(hb.Code) +
`, ИНН ` + html.EscapeString(hb.INN) + `. Регистрация подтверждена.</div>`
`, ИНН ` + html.EscapeString(hb.INN) + `. Регистрация подтверждена.</div>`)
return out.String()
}
return `<div class="note">В справочнике участников M2M ` + contour + ` контура нашей организации пока <b>нет</b>. ` +
out.WriteString(`<div class="note">В справочнике участников M2M ` + contour + ` контура нашей организации пока <b>нет</b>. ` +
`После приёма анкеты НРД организация появится в справочнике (обновляется каждые ~10 минут) — тогда здесь будет «есть». ` +
`Регистрацию подтверждает также ответный документ от НРД.</div>`
`Регистрацию подтверждает также ответный документ от НРД.</div>`)
return out.String()
}
func participantFormRender(w http.ResponseWriter, d participantFormData, errs []string, action, flash, flashKind, xmlPreview, regHTML string, igwConfigured, igwProd bool) {