Инициализировать репозиторий «Дейл»

Первый коммит: модульный монолит ядра (.NET 10) и gRPC-сервисы
ai/ml/telegram, фронтенд Vue 3/Vite/Tailwind, документация (ТЗ,
инструкция пользователя, техдокументация, код-стайл), бэклог,
скрипты развёртывания и архив прототипа LeadRadar.
This commit is contained in:
Rustam Khalimov
2026-09-11 02:50:17 +03:00
commit 9e07568ddd
1402 changed files with 177470 additions and 0 deletions
@@ -0,0 +1,54 @@
namespace Deal.Modules.Discovery.Application;
/// <summary>
/// Статусы кандидата Discovery (колонка DiscCandidates.Status; discovery.py L171, api-map §4.8).
/// </summary>
/// <remarks>
/// Цепочка 1:1 с прототипом: new — найден поиском, ждёт оценки; review — оценён, ждёт решения (воркер/человек);
/// joined — вступили (только mark_joined: счётчик задачи + лог join_auto/join_manual); rejected — отклонён
/// (только mark_rejected: счётчик задачи + лог + чёрный список). Переводы в joined/rejected минуя mark_* —
/// запрещены (discovery.py L16–18). Активные статусы (python _ACTIVE_CANDIDATE L35) запрещают повторное
/// добавление источника в задачу.
/// </remarks>
public static class DiscoveryCandidateStatuses
{
/// <summary>
/// Найден поиском, ещё не оценён.
/// </summary>
public const string New = "new";
/// <summary>
/// Оценён (метки/фит проставлены), ждёт вступления/решения.
/// </summary>
public const string Review = "review";
/// <summary>
/// Вступили в источник (терминал: счётчик joined задачи).
/// </summary>
public const string Joined = "joined";
/// <summary>
/// Отклонён и помещен в чёрный список (терминал: счётчик rejected).
/// </summary>
public const string Rejected = "rejected";
/// <summary>
/// Статусы, при которых повторное добавление источника запрещено (python _ACTIVE_CANDIDATE L35).
/// </summary>
/// <param name="status">Статус кандидата.</param>
/// <returns>True — new/review/joined (add_candidate пропускает источник с логом skip).</returns>
public static bool IsActive(string status)
{
return status is New or Review or Joined;
}
/// <summary>
/// Разрешён ли перевод через set_candidate_status (python L503–504: только new/review).
/// </summary>
/// <param name="status">Запрашиваемый статус.</param>
/// <returns>True — new/review (joined/rejected выставляются только через mark_joined/mark_rejected).</returns>
public static bool IsTransitionAllowed(string status)
{
return status is New or Review;
}
}