feat: track crawl run employee changes and verify dismissals
This commit is contained in:
@@ -8,7 +8,7 @@ from zoneinfo import ZoneInfo
|
||||
from sqlalchemy import Select, Text, and_, desc, func, or_, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models import CrawlRun, Employee
|
||||
from app.models import CrawlError, CrawlRun, CrawlRunEmployeeChange, Employee
|
||||
|
||||
EMPLOYEE_SORTS = {
|
||||
"full_name": Employee.full_name,
|
||||
@@ -175,6 +175,26 @@ def run_payload(run: CrawlRun | None) -> dict[str, Any] | None:
|
||||
}
|
||||
|
||||
|
||||
def run_detail_payload(db: Session, run: CrawlRun | None) -> dict[str, Any] | None:
|
||||
if not run:
|
||||
return None
|
||||
changes = db.scalars(
|
||||
select(CrawlRunEmployeeChange)
|
||||
.where(CrawlRunEmployeeChange.crawl_run_id == run.id)
|
||||
.order_by(CrawlRunEmployeeChange.created_at, CrawlRunEmployeeChange.id)
|
||||
).all()
|
||||
errors = db.scalars(select(CrawlError).where(CrawlError.crawl_run_id == run.id).order_by(CrawlError.created_at)).all()
|
||||
grouped_changes = {"new": [], "missing_from_source": [], "dismissed": []}
|
||||
for change in changes:
|
||||
grouped_changes.setdefault(change.change_type, []).append(_change_payload(change))
|
||||
return {
|
||||
**(run_payload(run) or {}),
|
||||
"changes_detail_available": bool(changes),
|
||||
"changes": grouped_changes,
|
||||
"errors": [_crawl_error_payload(error) for error in errors],
|
||||
}
|
||||
|
||||
|
||||
def format_admin_datetime(value: Any) -> str:
|
||||
if not value:
|
||||
return "Не указано"
|
||||
@@ -200,6 +220,52 @@ def _run_status_display(status: str | None) -> str:
|
||||
return labels.get(status or "", status or "Не указано")
|
||||
|
||||
|
||||
def _change_payload(change: CrawlRunEmployeeChange) -> dict[str, Any]:
|
||||
return {
|
||||
"id": change.id,
|
||||
"employee_id": change.employee_id,
|
||||
"profile_key": change.profile_key,
|
||||
"profile_url": change.profile_url,
|
||||
"full_name": change.full_name,
|
||||
"change_type": change.change_type,
|
||||
"change_type_display": _change_type_display(change.change_type),
|
||||
"profile_available": change.profile_available,
|
||||
"profile_available_display": _profile_available_display(change.profile_available),
|
||||
"message": change.message,
|
||||
"created_at": change.created_at.isoformat() if change.created_at else None,
|
||||
"created_display": format_admin_datetime(change.created_at),
|
||||
}
|
||||
|
||||
|
||||
def _crawl_error_payload(error: CrawlError) -> dict[str, Any]:
|
||||
return {
|
||||
"id": error.id,
|
||||
"crawl_run_id": error.crawl_run_id,
|
||||
"profile_url": error.profile_url,
|
||||
"error_type": error.error_type,
|
||||
"message": error.message,
|
||||
"created_at": error.created_at.isoformat() if error.created_at else None,
|
||||
"created_display": format_admin_datetime(error.created_at),
|
||||
}
|
||||
|
||||
|
||||
def _change_type_display(change_type: str | None) -> str:
|
||||
labels = {
|
||||
"new": "Новый",
|
||||
"missing_from_source": "Потеряшка",
|
||||
"dismissed": "Уволен",
|
||||
}
|
||||
return labels.get(change_type or "", change_type or "Не указано")
|
||||
|
||||
|
||||
def _profile_available_display(value: bool | None) -> str:
|
||||
if value is True:
|
||||
return "Профиль доступен"
|
||||
if value is False:
|
||||
return "Профиль недоступен"
|
||||
return "Не проверялось"
|
||||
|
||||
|
||||
def _count_section_items(sections: list[dict[str, Any]], section_type: str) -> int:
|
||||
total = 0
|
||||
for section in sections:
|
||||
|
||||
Reference in New Issue
Block a user