86 lines
3.0 KiB
Python
86 lines
3.0 KiB
Python
"""Уведомления в центр зоотехника по алертам feed_quality."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Iterable
|
|
|
|
from app.models.feed_alert import FeedAlert
|
|
from app.services.feed_quality.rules import (
|
|
EVENT_LEFT_IN_MIXER,
|
|
EVENT_LOADING_FAST,
|
|
EVENT_LOADING_TIME,
|
|
EVENT_MIX_TIME,
|
|
EVENT_OVERLOAD,
|
|
EVENT_UNDERLOAD,
|
|
SEVERITY_ERROR,
|
|
SEVERITY_WARNING,
|
|
settings_section_for_alert,
|
|
)
|
|
from app.services.feed_quality.settings_store import get_feed_quality_settings
|
|
from app.services.notification_center_service import create_notification, format_detail_timestamp
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_EVENT_TITLES = {
|
|
EVENT_OVERLOAD: "Перегруз при загрузке",
|
|
EVENT_UNDERLOAD: "Недогруз при загрузке",
|
|
EVENT_LOADING_TIME: "Долгая загрузка компонента",
|
|
EVENT_LOADING_FAST: "Быстрая загрузка компонента",
|
|
EVENT_MIX_TIME: "Отклонение смешивания",
|
|
EVENT_LEFT_IN_MIXER: "Остаток в миксере",
|
|
}
|
|
|
|
|
|
def _alert_title(alert: FeedAlert) -> str:
|
|
if alert.group_name and alert.event_type in (EVENT_OVERLOAD, EVENT_UNDERLOAD):
|
|
return "Отклонение при выгрузке"
|
|
return _EVENT_TITLES.get(alert.event_type, "Отклонение кормления")
|
|
|
|
|
|
def _alert_detail(alert: FeedAlert) -> str:
|
|
when = format_detail_timestamp(alert.created_at)
|
|
recipe = alert.recipe_name or "рейс"
|
|
return f"Рейс «{recipe}»: {alert.detail} — {when}"
|
|
|
|
|
|
def _should_notify(alert: FeedAlert) -> bool:
|
|
if alert.severity not in (SEVERITY_WARNING, SEVERITY_ERROR):
|
|
return False
|
|
section_key = settings_section_for_alert(
|
|
alert.event_type,
|
|
component_name=alert.component_name,
|
|
group_name=alert.group_name,
|
|
)
|
|
cfg = get_feed_quality_settings().get(section_key) or {}
|
|
if alert.severity == SEVERITY_ERROR:
|
|
return bool(cfg.get("notify_critical", True))
|
|
return bool(cfg.get("notify_warning", True))
|
|
|
|
|
|
def notify_feed_quality_alerts(alerts: Iterable[FeedAlert]) -> int:
|
|
"""Создаёт записи в «К» по флагам notify_* в настройках."""
|
|
count = 0
|
|
for alert in alerts:
|
|
if not _should_notify(alert):
|
|
continue
|
|
kind = "error" if alert.severity == SEVERITY_ERROR else "warning"
|
|
try:
|
|
create_notification(
|
|
title=_alert_title(alert),
|
|
detail=_alert_detail(alert),
|
|
kind=kind,
|
|
category="feed_quality",
|
|
page="reports",
|
|
link_kind="report_loading",
|
|
link_id=alert.loading_report_id,
|
|
)
|
|
count += 1
|
|
except Exception:
|
|
logger.exception(
|
|
"[FEED-QUALITY-NOTIFY] alert=%s report=%s",
|
|
alert.id,
|
|
alert.loading_report_id,
|
|
)
|
|
return count
|