Deal — единая кодовая база
ci / build-test (push) Canceled after 0s

SaaS-мониторинг Telegram: ядро (модули Cards/Kanban/Pipeline/Tenants/Settings/
Discovery, Api, Infrastructure), сервисы telegram/ai/ml/storage, фронт Vue,
контракты и grpc-hosting, деплой-конфиги (dev/prod/observability/CI-раннер),
Gitea Actions CI, документация (ТЗ, техдок, api-map, код-стайл, планы, бэклог).

Текущее состояние: все этапы роадмапа 0–12 закрыты, сборка 5 sln 0/0,
тесты 1340/130/52/38/9 зелёные.
This commit is contained in:
Rustam Khalimov
2026-09-11 23:56:47 +03:00
commit 27c7831910
1383 changed files with 158436 additions and 0 deletions
@@ -0,0 +1,229 @@
namespace Deal.Modules.Settings.Application.Models;
/// <summary>
/// Публичный снимок настроек тенанта — тело ответа GET/PATCH /api/settings.
/// </summary>
public sealed record PublicSettingsDto
{
/// <summary>
/// Авто-архивация выполненных/отклонённых карточек.
/// </summary>
public bool AutoArchive { get; init; }
/// <summary>
/// Дней до авто-архивации карточки
/// </summary>
public int ArchiveAfterDays { get; init; }
/// <summary>
/// Дней хранения в архиве до очистки.
/// </summary>
public int ArchiveClearDays { get; init; }
/// <summary>
/// Дней хранения в корзине до очистки.
/// </summary>
public int TrashClearDays { get; init; }
/// <summary>
/// Минимальная длина сообщения для -1 фильтра
/// </summary>
public int MinLen { get; init; }
/// <summary>
/// Стоп-фразы -1 фильтра.
/// </summary>
public IReadOnlyList<string> StopPhrases { get; init; } = Array.Empty<string>();
/// <summary>
/// Локальный ML-слой включён.
/// </summary>
public bool MlEnabled { get; init; }
/// <summary>
/// Полный выключатель ИИ
/// </summary>
public bool AiEnabled { get; init; }
/// <summary>
/// ИИ-фильтр (страж) входящих включён.
/// </summary>
public bool AiFilterEnabled { get; init; }
/// <summary>
/// Промпт классификатора входящих
/// </summary>
public string AiPrompt { get; init; } = string.Empty;
/// <summary>
/// Промпт ИИ-фильтра входящих.
/// </summary>
public string AiFilterPrompt { get; init; } = string.Empty;
/// <summary>
/// Промпт структуры карточки
/// </summary>
public string CardPrompt { get; init; } = string.Empty;
/// <summary>
/// Тип собираемых заявок
/// </summary>
public string WantedType { get; init; } = string.Empty;
/// <summary>
/// Без указания суммы не создавать карточку найма.
/// </summary>
public bool BudgetRequiredHire { get; init; }
/// <summary>
/// Без указания суммы не создавать карточку заказа.
/// </summary>
public bool BudgetRequiredOrder { get; init; }
/// <summary>
/// Подпись найма на карточке.
/// </summary>
public string HireLabel { get; init; } = string.Empty;
/// <summary>
/// Подпись разового заказа на карточке.
/// </summary>
public string OrderLabel { get; init; } = string.Empty;
/// <summary>
/// Описание сферы
/// </summary>
public string DomainDescription { get; init; } = string.Empty;
/// <summary>
/// Общие слова-маркеры заявок сферы.
/// </summary>
public IReadOnlyList<string> DomainKeywords { get; init; } = Array.Empty<string>();
/// <summary>
/// Маркеры найма
/// </summary>
public IReadOnlyList<string> HireMarkers { get; init; } = Array.Empty<string>();
/// <summary>
/// Термины грейдов/уровней.
/// </summary>
public IReadOnlyList<string> LevelTerms { get; init; } = Array.Empty<string>();
/// <summary>
/// Маркеры резюме соискателей.
/// </summary>
public IReadOnlyList<string> ResumeMarkers { get; init; } = Array.Empty<string>();
/// <summary>
/// Отсекать резюме соискателей на.
/// </summary>
public bool BlockResumes { get; init; }
/// <summary>
/// Глобальные исключения по ключевым словам/фразам/технологиям
/// </summary>
public IReadOnlyList<string> ExcludeKeywords { get; init; } = Array.Empty<string>();
/// <summary>
/// Глобальные исключения по локации/языку
/// </summary>
public IReadOnlyList<string> ExcludeLocations { get; init; } = Array.Empty<string>();
/// <summary>
/// Глобальные исключения по типу заявки
/// </summary>
public IReadOnlyList<string> ExcludeTypes { get; init; } = Array.Empty<string>();
/// <summary>
/// Нижняя граница глобального исключения по бюджету
/// </summary>
public int ExcludeBudgetFrom { get; init; }
/// <summary>
/// Верхняя граница глобального исключения по бюджету
/// </summary>
public int ExcludeBudgetTo { get; init; }
/// <summary>
/// Личная библиотека промптов пользователя.
/// </summary>
public IReadOnlyList<MyPromptDto> MyPrompts { get; init; } = Array.Empty<MyPromptDto>();
/// <summary>
/// Общие напоминания включены.
/// </summary>
public bool RemindersEnabled { get; init; }
/// <summary>
/// Конвертация бюджетов карточек включена.
/// </summary>
public bool ConversionOn { get; init; }
/// <summary>
/// Целевая валюта конвертации.
/// </summary>
public string TargetCurrency { get; init; } = string.Empty;
/// <summary>
/// Источник курсов
/// </summary>
public string RateSource { get; init; } = string.Empty;
/// <summary>
/// Авто-мониторинг новых чатов/каналов.
/// </summary>
public bool AutoMonitorNew { get; init; }
/// <summary>
/// Суточный лимит авто-вступлений Discovery
/// </summary>
public int DiscJoinLimit { get; init; }
/// <summary>
/// Нижняя граница паузы между авто-вступлениями, сек
/// </summary>
public int DiscJoinDelayMin { get; init; }
/// <summary>
/// Верхняя граница паузы между авто-вступлениями, сек
/// </summary>
public int DiscJoinDelayMax { get; init; }
/// <summary>
/// Размер выборки сообщений при оценке канала
/// </summary>
public int DiscEvalSample { get; init; }
/// <summary>
/// Процент подходящих сообщений для оценки канала
/// </summary>
public int DiscEvalThreshold { get; init; }
/// <summary>
/// Стоп-кран авто-вступлений Discovery.
/// </summary>
public bool DiscPaused { get; init; }
/// <summary>
/// Состояние колонок канбана.
/// </summary>
public IReadOnlyDictionary<string, object?> ColState { get; init; } =
new Dictionary<string, object?>();
/// <summary>
/// Активный AI-провайдер
/// </summary>
public string AiProvider { get; init; } = string.Empty;
/// <summary>
/// Публичные конфигурации AI-провайдеров
/// </summary>
public IReadOnlyDictionary<string, AiConfigPublicDto> AiConfigs { get; init; } =
new Dictionary<string, AiConfigPublicDto>();
/// <summary>
/// Статический список AI-провайдеров.
/// </summary>
public IReadOnlyList<ProviderPublicDto> Providers { get; init; } = Array.Empty<ProviderPublicDto>();
}