diff --git a/internal/lkgateway/lkportfolio.go b/internal/lkgateway/lkportfolio.go index 9f7fb47..2092db7 100644 --- a/internal/lkgateway/lkportfolio.go +++ b/internal/lkgateway/lkportfolio.go @@ -20,6 +20,7 @@ import ( "io" "log" "net/http" + "sort" "strings" "sync" "time" @@ -216,6 +217,7 @@ type LKPortfolioSyncState struct { Skipped []string Err string hash string + manual bool // ручная заливка («Залить сейчас»), не постоянное заполнение } var lkPortfolioState = struct { @@ -246,7 +248,7 @@ func lkPortfolioSyncTick(ctx context.Context, rc *RuntimeConfig, force bool) { s = &LKPortfolioSyncState{LK: pr.LK, Depo: pr.Depo} lkPortfolioState.m[pr.LK] = s } - s.Depo, s.CheckedAt = pr.Depo, time.Now() + s.Depo, s.CheckedAt, s.manual = pr.Depo, time.Now(), false if err != nil { if s.Err != err.Error() { log.Printf("lk-portfolio: %s ← %s: %v", pr.LK, pr.Depo, err) @@ -290,7 +292,8 @@ func lkPortfolioSyncTick(ctx context.Context, rc *RuntimeConfig, force bool) { } } -// lkPortfolioStates — состояние синхронизации для страницы настроек. +// lkPortfolioStates — состояние для страницы настроек: последняя ручная заливка сверху, затем клиенты +// постоянного заполнения. func lkPortfolioStates() []LKPortfolioSyncState { lkPortfolioState.Lock() defer lkPortfolioState.Unlock() @@ -298,9 +301,29 @@ func lkPortfolioStates() []LKPortfolioSyncState { for _, s := range lkPortfolioState.m { out = append(out, *s) } + sort.Slice(out, func(i, j int) bool { + if out[i].manual != out[j].manual { + return out[i].manual + } + return out[i].LK < out[j].LK + }) return out } +// lkPortfolioInSync — договор в постоянном заполнении (по списку или «для всех»). +func lkPortfolioInSync(rc *RuntimeConfig, lk string) bool { + ps := rc.Snapshot().LK.PortfolioSync + if ps.Enabled && ps.AllClients { + return true + } + for _, p := range ps.pairs() { + if p.LK == lk { + return true + } + } + return false +} + // registerLKPortfolioSync — POST /admin/setup/lk-portfolio: настройки и «синхронизировать сейчас». func registerLKPortfolioSync(mux *http.ServeMux, rc *RuntimeConfig) { // GET /admin/setup/lk-portfolio/clients?q= — поиск клиента DEPO для заливки портфеля. @@ -502,6 +525,14 @@ func lkPortfolioPushPair(ctx context.Context, rc *RuntimeConfig, pr lkPortfolioP lkPortfolioState.m[pr.LK] = s } s.Depo, s.CheckedAt, s.Skipped = pr.Depo, time.Now(), skipped + if !lkPortfolioInSync(rc, pr.LK) { + s.manual = true + for k, o := range lkPortfolioState.m { // от прежних ручных заливок — только последняя + if o.manual && k != pr.LK { + delete(lkPortfolioState.m, k) + } + } + } lkPortfolioState.Unlock() msg := "" if err != nil { diff --git a/internal/lkgateway/web/templates/admin_setup.html b/internal/lkgateway/web/templates/admin_setup.html index 3a8ded6..5b85b38 100644 --- a/internal/lkgateway/web/templates/admin_setup.html +++ b/internal/lkgateway/web/templates/admin_setup.html @@ -745,7 +745,7 @@ q.addEventListener('focus',function(){ if(!list.innerHTML) load(); }); })(); - {{range lkPortfolioStates}}
{{.LK}} ← {{.Depo}}: {{if .Err}}ошибка — {{.Err}}{{else if .PushedAt.IsZero}}сверено {{.CheckedAt.Format "15:04:05"}}, отправки ещё не было{{else}}отправлено {{.PushedAt.Format "02.01 15:04:05"}} ({{.Lines}} бумаг), сверено {{.CheckedAt.Format "15:04:05"}}{{end}}{{range .Skipped}}
пропущено: {{.}}{{end}}
{{end}} + {{range lkPortfolioStates}}
{{.LK}} ← {{.Depo}}: {{if .Err}}ошибка — {{.Err}}{{else if .PushedAt.IsZero}}сверено {{.CheckedAt.Format "15:04:05"}}, отправки ещё не было{{else}}отправлено {{.PushedAt.Format "02.01 15:04:05"}} ({{.Lines}} бумаг), сверено {{.CheckedAt.Format "15:04:05"}}{{end}}{{if .Skipped}}
пропущено бумаг: {{len .Skipped}} — без номера гос. регистрации{{range .Skipped}}
{{.}}
{{end}}
{{end}}
{{end}}
Тест «боевой ЛК → тестовый контур НРД» {{if .Settings.LK.RealNSDTest.Enabled}}включён{{else}}выключен{{end}}