package lkgateway // handbook_export.go — выгрузка справочника участников M2M со страницы // /admin/handbook в файлах JSON и XML. Данные — самый свежий справочник // (readHandbook): полученный от НРД #M2MTH, копия с сервера лицензий или // встроенный снимок. Только чтение, доступ — под админ-авторизацией /admin/*. import ( "bytes" "encoding/json" "encoding/xml" "net/http" "time" ) // hbEntryXML — запись справочника в XML (атрибутами, как плоский JSON). type hbEntryXML struct { INN string `xml:"inn,attr,omitempty"` Code string `xml:"code,attr,omitempty"` Kind string `xml:"kind,attr,omitempty"` Name string `xml:"name,attr,omitempty"` FullName string `xml:"fullName,attr,omitempty"` DisplayName string `xml:"displayName,attr,omitempty"` EngName string `xml:"engName,attr,omitempty"` } // hbExportXML — корень XML-выгрузки справочника. type hbExportXML struct { XMLName xml.Name `xml:"M2MHandbook"` At string `xml:"at,attr,omitempty"` Participants []hbEntryXML `xml:"Participants>Participant"` Places []hbEntryXML `xml:"SettlementPlaces>Place"` } func hbEntryToXML(e HandbookEntry) hbEntryXML { return hbEntryXML{INN: e.INN, Code: e.Code, Kind: e.Kind, Name: e.Name, FullName: e.FullName, DisplayName: e.DisplayName, EngName: e.EngName} } // exportHandbook отдаёт сохранённый справочник участников M2M файлом JSON или XML. func (a *admin) exportHandbook(w http.ResponseWriter, format string) { raw, err := readHandbook() if err != nil || len(raw) == 0 { http.Error(w, "Справочник ещё не загружен — запросите его у НРД.", http.StatusNotFound) return } var hb struct { At string `json:"at"` Participants []HandbookEntry `json:"participants"` Places []HandbookEntry `json:"settlement_places"` } if err := json.Unmarshal(raw, &hb); err != nil { http.Error(w, "Справочник повреждён: "+err.Error(), http.StatusInternalServerError) return } day := time.Now().Format("2006-01-02") if format == "xml" { doc := hbExportXML{At: hb.At} for _, p := range hb.Participants { doc.Participants = append(doc.Participants, hbEntryToXML(p)) } for _, p := range hb.Places { doc.Places = append(doc.Places, hbEntryToXML(p)) } out, err := xml.MarshalIndent(doc, "", " ") if err != nil { http.Error(w, "Не удалось сформировать XML: "+err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/xml; charset=utf-8") w.Header().Set("Content-Disposition", `attachment; filename="m2m-handbook-`+day+`.xml"`) w.Header().Set("Cache-Control", "no-store") _, _ = w.Write([]byte(xml.Header)) _, _ = w.Write(out) return } // JSON — отдаём сохранённый справочник как есть, с отступами для читаемости. var buf bytes.Buffer if json.Indent(&buf, raw, "", " ") != nil { buf.Reset() buf.Write(raw) } w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Disposition", `attachment; filename="m2m-handbook-`+day+`.json"`) w.Header().Set("Cache-Control", "no-store") _, _ = w.Write(buf.Bytes()) }