5beb726e5b
Форма «Загрузка справочника из файла» на /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
84 lines
4.2 KiB
Go
84 lines
4.2 KiB
Go
package lkgateway
|
|
|
|
// handbook_import.go — ручная загрузка справочника участников M2M со страницы
|
|
// /admin/handbook файлом в ПОДЛИННОМ формате НРД (hk:M2MTransferHandbook,
|
|
// windows-1251 — тот же, что НРД присылает пакетом #M2MTH и который отдаёт
|
|
// кнопка «XML»). Нужна для закрытого контура и когда шлюз к НРД недоступен.
|
|
//
|
|
// Обрабатываем ровно тем же путём, что и поллер при ответе НРД (nsdpoller.go):
|
|
// writeHandbookRawXML → saveHandbookEx(push=false) → перезапись FTV_M2M_HANDBOOK
|
|
// в DEPO → синхронизация получателей в МНП.
|
|
// На сервер лицензий файл НЕ рассылаем: ручная загрузка одного стенда не должна
|
|
// становиться облачным справочником для всех клиентов (push=false). Отметку живой
|
|
// связи с НРД тоже не ставим — это действие человека, а не ответ шлюза.
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/m2m"
|
|
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdxml"
|
|
)
|
|
|
|
// handbookUploadMaxBytes — предел размера загружаемого файла. Справочник НРД —
|
|
// сотни КБ; с запасом.
|
|
const handbookUploadMaxBytes = 16 << 20
|
|
|
|
// importHandbook — POST /admin/handbook/import: принять файл справочника в формате НРД.
|
|
func (a *admin) importHandbook(w http.ResponseWriter, r *http.Request) {
|
|
back := func(msg string) {
|
|
http.Redirect(w, r, "/admin/handbook?flash="+url.QueryEscape(msg), http.StatusSeeOther)
|
|
}
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
r.Body = http.MaxBytesReader(w, r.Body, handbookUploadMaxBytes)
|
|
f, hdr, err := r.FormFile("handbook")
|
|
if err != nil {
|
|
back("Загрузка справочника: файл не получен (" + err.Error() + ")")
|
|
return
|
|
}
|
|
defer f.Close()
|
|
raw, err := io.ReadAll(f)
|
|
if err != nil {
|
|
back("Загрузка справочника: не удалось прочитать файл: " + err.Error())
|
|
return
|
|
}
|
|
if len(raw) == 0 {
|
|
back("Загрузка справочника: файл пустой")
|
|
return
|
|
}
|
|
// Разбираем тем же парсером НРД, что и ответ шлюза (поддерживает windows-1251 по прологу).
|
|
var hb m2m.M2MTransferHandbook
|
|
if err := nsdxml.Unmarshal(raw, &hb); err != nil {
|
|
back("Загрузка справочника: это не справочник НРД (hk:M2MTransferHandbook) или файл повреждён: " + err.Error())
|
|
return
|
|
}
|
|
nP, nPl := len(hb.Participants.Participants), len(hb.SettlementPlaces.Places)
|
|
if nP == 0 {
|
|
back("Загрузка справочника: в файле нет ни одного участника — проверьте, тот ли это файл")
|
|
return
|
|
}
|
|
writeHandbookRawXML(raw) // подлинный XML — для выгрузки кнопкой «XML» байт в байт
|
|
changed := saveHandbookEx(&hb, false) // плоский JSON; на сервер лицензий НЕ рассылаем
|
|
if globalRC != nil {
|
|
go func(rc *RuntimeConfig) {
|
|
if err := depoWriteHandbook(rc); err != nil {
|
|
log.Printf("depo-events: справочник после ручной загрузки: %v", err)
|
|
}
|
|
}(globalRC)
|
|
quikRecipientsSyncAsync(globalRC) // депозитарии-получатели в МНП
|
|
}
|
|
note := ""
|
|
if !changed {
|
|
note = " (состав не изменился)"
|
|
}
|
|
log.Printf("lk-gateway: справочник M2M загружен ВРУЧНУЮ из файла %q: участников %d, мест расчётов %d, изменился=%v",
|
|
hdr.Filename, nP, nPl, changed)
|
|
back(fmt.Sprintf("Справочник загружен из файла %s: участников %d, мест расчётов %d%s.", hdr.Filename, nP, nPl, note))
|
|
}
|