Справочник M2M: ручная загрузка файла в формате НРД

Форма «Загрузка справочника из файла» на /admin/handbook принимает
подлинный формат НРД (hk:M2MTransferHandbook, windows-1251 — тот же,
что приходит пакетом #M2MTH и который отдаёт кнопка «XML»). Разбор и
сохранение идут тем же путём, что у поллера при ответе НРД:
nsdxml.Unmarshal → writeHandbookRawXML (сырой XML для байт-в-байт
выгрузки) → saveHandbookEx (плоский JSON) → перезапись FTV_M2M_HANDBOOK
в DEPO → синхронизация получателей в МНП. На сервер лицензий ручной файл
НЕ рассылается (saveHandbookEx push=false): справочник одного стенда не
должен становиться облачным для всех клиентов. Нужно для закрытого
контура и когда шлюз к НРД недоступен.

- handbook_import.go: обработчик importHandbook (POST /admin/handbook/import)
- nsdpoller.go: saveHandbook → saveHandbookEx(hb, push)
- admin.go: маршрут import, поле Flash, renderHandbook читает ?flash=
- admin_handbook.html: карточка загрузки + вывод flash

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XG3zNMMf2LMoDpXo22mwMX
This commit is contained in:
fontvielle
2026-10-15 11:18:50 +03:00
parent ba3ae22c49
commit 5beb726e5b
4 changed files with 114 additions and 6 deletions
+8 -4
View File
@@ -511,7 +511,7 @@ type claimData struct {
// клиента. SubstAs — под чьими данными ушло; этот XML в карточке — наша запись с реальным клиентом.
SubstAs string
Flash string
Fail *SendFailure // последняя неудачная отправка в НРД (sendfail.go)
Fail *SendFailure // последняя неудачная отправка в НРД (sendfail.go)
}
// statusData — данные страницы статуса.
@@ -570,6 +570,8 @@ func RegisterAdmin(mux *http.ServeMux, svc *Service, rc *RuntimeConfig, getOpts
a.exportHandbook(w, "json")
case p == "handbook/export.xml":
a.exportHandbook(w, "xml")
case p == "handbook/import":
a.importHandbook(w, r)
case p == "handbook":
a.renderHandbook(w, r)
case p == "help":
@@ -773,8 +775,8 @@ func (a *admin) renderClaim(w http.ResponseWriter, r *http.Request, svc *Service
}
render(w, a.claim, claimData{
Quik: quik, Watch: watch, DepoL: depoL, Fail: fail,
page: nowPage("Заявка", "claims"),
Claim: view, Depo: depo, SubstAs: substAs, Flash: r.URL.Query().Get("flash"),
page: nowPage("Заявка", "claims"),
Claim: view, Depo: depo, SubstAs: substAs, Flash: r.URL.Query().Get("flash"),
})
}
@@ -848,6 +850,7 @@ func (a *admin) downloadClaimXML(w http.ResponseWriter, r *http.Request, svc *Se
type handbookData struct {
page
At string
Flash string
Participants []HandbookEntry
CodesHTML template.HTML // справка по кодам ошибок/отказов M2M
Result HandbookResult // итог обработки справочника джобой Fancy bj2depo
@@ -855,8 +858,9 @@ type handbookData struct {
// renderHandbook показывает сохранённый справочник участников M2M с поиском.
// Места расчётов добавляются к участникам как строки с типом "place".
func (a *admin) renderHandbook(w http.ResponseWriter, _ *http.Request) {
func (a *admin) renderHandbook(w http.ResponseWriter, r *http.Request) {
data := handbookData{page: nowPage("Справочник участников", "handbook")}
data.Flash = r.URL.Query().Get("flash")
data.CodesHTML = template.HTML(m2mSpravkaHTML(false)) // справка по кодам ошибок
data.Result = depoHandbookResult(globalRC)
if raw, err := readHandbook(); err == nil {