# Runbook: пропали/не обновляются тикеры и счётчики

Документ — операционный runbook для инженеров поддержки и администраторов 1Формы: что делать, когда счётчики в шапке/виджетах «зависли» или расходятся с API, как быстро классифицировать сломанный контур (системные/пользовательские/чат-счётчики, обновление интерфейса), где снимать снимки (`/api/tickers/*`, `/api/chats/counters`), какие SP/кэши пересчитывать (`UserTickers_refresh`, `UserMenuItemTickers_refresh`, `SubcatTickers_refresh`), и какой минимальный набор данных приложить в задачу разработчикам.

## 1–2. Когда использовать и быстрая классификация проблемы

Признаки инцидента (когда применять runbook):

1. В шапке/виджетах счётчики пустые или «зависли».
2. После действий в комментариях (`прочитано`, `вопрос`, `ответ`) значения не меняются.
3. В API значения одни, в UI другие.
4. У части пользователей счётчики корректны, у части нет.

Сначала определить, какой контур сломан:

1. **Системные тикеры** (`unreadCommentsCount`, `questionsCount`, `badge`, `overDueTasksCount` и т.д.). Их порядок в панели навигации **жёстко зафиксирован в коде фронтенда** и не настраивается.
2. **Пользовательские тикеры** (админка `/administration/tickers`, таблица `MenuItemTicker`). Их порядок отображения управляется позицией строки в списке настроек (в обратном порядке).
3. **Чат-счётчики** (`/api/chats/counters`, unread по чатам/подпискам).
4. **Только UI-обновление** (в API уже верно, но экран не подтянул изменения).

## 3. Как это работает

### 3.1–2. API и источники значений

API для получения снимков тикеров:

- `GET /api/tickers/all` — основной снимок для интерфейса (системные + пользовательские + ассистентские).
- `GET /api/tickers/system` — системные тикеры (можно частично по списку ключей).
- `GET /api/tickers/custom` — пользовательские тикеры.
- `GET /api/tickers/refresh-cache` — принудительный refresh user cache.
- `GET /api/tickers/refresh-subcat-cache/{subcatId}` — refresh по подкатегории.

Источник значений (откуда берутся цифры):

Системные тикеры:

1. Платформа запрашивает системные тикеры по списку пользователей.
2. Если включено кэширование системных тикеров (настройка `UseSystemTickersCache`), значения читаются из кэша.
3. Если кэш пуст или данных недостаточно, выполняется пересчёт:
   - процедура `dbo.UserTickers_refresh`,
   - затем чтение через `dbo.GetSystemTickers`.

Среди значений, которые пересчитывает `UserTickers_refresh` и отдаёт `dbo.GetSystemTickers`, — счётчики `TotalTasksAssistant` («Задачи замещаемого сотрудника»: активные задачи, доступные пользователю по замещению через `fn_GetUserAssistants`) и `NewTasks` («Новые задачи»). «Новой» считается задача с флагом `Tasks.IsNew` — он сбрасывается при первом прочтении. Определение одинаково для MS SQL и PostgreSQL.

Пользовательские тикеры:

1. Состав и доступность тикеров — из настроек меню и прав пользователя.
2. Значения — из таблицы `UserMenuItemTickers` (или её кэша).
3. Пересчёт пользовательских значений:
   - процедура `dbo.UserMenuItemTickers_refresh`,
   - процедура `dbo.SubcatTickers_refresh`.

Грид «Задачи в работе» (не индикатор-счётчик, а список задач) — отдельный источник: функция `dbo.sub_Ticker_getTotalTaskCount`, вызывается через `SmartService.GetSystemTickersTaskIDs` (даёт список `TaskID`, дальше используется как фильтр для основного грид-запроса). Это отдельный от индикатора код, который должен логически совпадать с `UserTickers_refresh` — задача в том, чтобы грид и индикатор показывали один и тот же состав задач (включая задачи замещаемых пользователей через `fn_GetUserAssistants`).

### 3.3 Обновление в реальном времени

Почему значение в интерфейсе может отставать от API:

1. Сервер отправляет интерфейсу уведомление об изменении, если после пересчёта значения действительно отличаются от прежних.
2. Интерфейс регулярно перечитывает `tickers/all` по расписанию и при возврате пользователя в сеть или к активности.
3. После действий с комментариями (прочтение, новый комментарий, вопрос) интерфейс частично дочитывает `tickers/system`.
4. Для чат-бейджей отдельно используется `chats/counters` (по расписанию, по событию и по видимости вкладки).

## 4. Что смотреть при разборе (чек-лист)

Последовательность проверки:

1. Зафиксировать user id, время, какой именно счётчик «не сходится».
2. Снять API-снимок:
   - `GET /api/tickers/all`,
   - `GET /api/tickers/system`,
   - `GET /api/chats/counters` (если проблема чатовая).
3. Сравнить API и UI:
   - если API уже отдаёт неверное значение — причина на стороне данных или кэша;
   - если API верный, а интерфейс нет — причина в обновлении интерфейса (события или расписание).
4. Для системных тикеров проверить, не «завис» ли кеш:
   - вызвать `GET /api/tickers/refresh-cache`,
   - повторить `GET /api/tickers/system`.
5. Для пользовательских тикеров проверить админ-настройку и доступность тикера пользователю.
6. Для случаев после действий с комментариями проверить, что пришло событие обновления.
7. Проверить, активна ли у пользователя основная вкладка (часть обновлений приходит только в активную вкладку).
8. Если проблема локальна для отдельных пользователей — проверить группы/права и фактический набор доступных тикеров.

## 5. Симптом → вероятная причина → проверка

Сводка типичных симптомов:

| Симптом | Вероятная причина | Что проверить первым |
|---|---|---|
| В API `tickers/system` значение уже неверное | устаревший кэш или не выполнен пересчёт | `refresh-cache` + повтор `tickers/system` |
| Пользовательский тикер есть в админке, но не виден пользователю | нет прав на пункт меню или тикер | членство пользователя в группах (`MenuItemTickerGroup`) |
| После отметки «отвечено» или «прочитано» счётчик в интерфейсе не изменился | не сработало событие обновления | пришло ли событие обновления тикеров |
| Чат-бейдж не совпадает с остальными тикерами | расхождение между `tickers/*` и `chats/counters` | ответ `GET /api/chats/counters` и обновление `chats/counters` по расписанию |
| Только у одного пользователя «зависло» | персональный кэш или состояние | `refresh-cache`, состояние основной вкладки, повторный API-снимок |
| Грид «Задачи в работе» показывает отложенную (future `TaskStartTime`) задачу раньше времени старта | Известный регресс в `sub_Ticker_getTotalTaskCount`: фильтр по `TaskStartTime` потерян при доработке под «свои + замещаемые» | Сверить дату старта задачи; фильтр в текущей версии функции отсутствует |
| Счётчик «Новые задачи» (`NewTasks`) не совпадает с ожиданием пользователя | Флаг `Tasks.IsNew` сбрасывается при первом прочтении задачи: прочитанная, но не начатая задача из счётчика уходит | Сверить, открывал ли пользователь задачу; при расхождении между стендами движок БД ни при чём — определение общее для MS SQL и PostgreSQL |

## 6–8. SQL для быстрой диагностики, что приложить в задачу и связанные документы

SQL-блок для быстрой диагностики:

```sql
declare @user_id int = 0;
declare @ticker_id int = 0;

-- Кастомные значения по пользователю
select
        umit.UserID,
        umit.MenuItemTickerId,
        umit.ItemCount
from dbo.UserMenuItemTickers umit
where umit.UserID = @user_id
order by
        umit.MenuItemTickerId;

-- Настройки тикеров
select
        mit.Id,
        mit.MenuItemID,
        mit.TickerType,
        mit.SqlSPName,
        mit.DataSourceSettingId
from dbo.MenuItemTicker mit
where @ticker_id = 0 or
      mit.Id = @ticker_id
order by
        mit.Id;

-- Привязка тикера к группам
select
        mtg.MenuItemTickerID,
        mtg.GroupID
from dbo.MenuItemTickerGroup mtg
where @ticker_id = 0 or
      mtg.MenuItemTickerID = @ticker_id
order by
        mtg.MenuItemTickerID,
        mtg.GroupID;

-- Системные тикеры (результат расчёта)
exec dbo.GetSystemTickers
        @UserId = @user_id,
        @OnlineUserOnlyF = 0;
```

Что приложить в задачу разработчикам:

1. `userId`, часовой пояс, время инцидента.
2. Скриншот UI со значением счётчика.
3. Ответы `tickers/all`, `tickers/system`, `chats/counters` (если применимо).
4. Результаты SQL-блока выше.
5. Был ли вызван `refresh-cache` и что изменилось после него.

Связанные документы:

- [Списки и табличные представления (администрирование)](https://help.1forma.ru/domains/grids/admin.md)
