feat(admin): эмулятор МНП — режим реальной записи в МНП на подставного клиента

Третий режим МНП (между «внутренняя имитация» и «боевая запись»): в bj цикл
идёт по обычному пользователю, а поручение в QUIK МНП уходит РЕАЛЬНО, но с
кодом другого, реально существующего в QUIK клиента (обобщение ручного теста
realtest «боевой ЛК → TEST3»).

- QuikMNPSettings: RealWrite + RealClientCode (валидация формата кода).
- Подмена кода — единая точка quikClientCodeFromPort (после ClientCodeMap);
  портфель не трогаем. quikActive: RealWrite только при devMode и непустом
  коде; Emulate (внутренняя имитация) в приоритете.
- Шаги боевого пути помечаются «[на подставного клиента <код>]» — видно в
  «Поручениях QUIK».
- Карточка МНП на /admin/emulators — три взаимоисключающих режима
  (выключено / имитация / реальная запись), поле кода, крупное предупреждение;
  отдельный красный баннер «Реальные поручения в МНП на клиента <код> (режим
  разработки)» — не смешиваем с баннером эмуляции НРД.
- disableEmulatorsIfDevOff сбрасывает и RealWrite (код остаётся, инертен),
  новость явно фиксирует прекращение реальных поручений.
This commit is contained in:
zuevav
2026-10-08 00:45:06 +03:00
parent 8e4cb5de19
commit 6c42e0378d
10 changed files with 293 additions and 81 deletions
+10 -2
View File
@@ -450,6 +450,7 @@ type page struct {
Now string
IsMockMode bool // true если ИШ или СКЗИ не настроены — обмена с НРД нет
MockReason string // короткое описание причины (у клиента — без «mock»)
MNPReal string // режим разработки: в боевую МНП пишутся РЕАЛЬНЫЕ поручения на подставного клиента (его код; пусто — режим выключен)
NPR bool // модуль «НПР / УДС» включён и разрешён лицензией
IGWDown string // ИШ НРД не отвечает: «N мин» (пусто — отвечает или не проверялся)
IGWDetail string
@@ -486,8 +487,9 @@ type homeData struct {
LKUrl string
// Состояние эмуляторов (dev-плитки дашборда, страница «Эмуляторы»).
NSDEmuOn bool
QuikEmuOn bool
NSDEmuOn bool
QuikEmuOn bool
QuikRealCode string // режим «реальная запись в МНП на подставного клиента» (код; пусто — выключен)
}
// claimsData — данные журнала.
@@ -615,6 +617,9 @@ func (a *admin) renderHome(w http.ResponseWriter, r *http.Request, svc *Service,
}
data.NSDEmuOn, _ = lkEmulateNSD(rc)
data.QuikEmuOn = rc.Snapshot().Quik.Emulate && devMode(rc)
if q := rc.Snapshot().Quik; q.RealWrite && devMode(rc) {
data.QuikRealCode = strings.TrimSpace(q.RealClientCode)
}
// Готовность — по тем же шагам, что в мастере настройки (с учётом лицензии).
for _, st := range setupSteps(rc) {
data.TotalCount++
@@ -916,6 +921,9 @@ func nowPage(title, active string) page {
}
p.MockReason += "эмулятор МНП QUIK включён — в боевую базу МНП ничего не пишется"
}
if s.Quik.RealWrite && p.DevMode {
p.MNPReal = strings.TrimSpace(s.Quik.RealClientCode)
}
}
return p
}