Первый коммит: модульный монолит ядра (.NET 10) и gRPC-сервисы ai/ml/telegram, фронтенд Vue 3/Vite/Tailwind, документация (ТЗ, инструкция пользователя, техдокументация, код-стайл), бэклог, скрипты развёртывания и архив прототипа LeadRadar.
37 lines
2.6 KiB
C#
37 lines
2.6 KiB
C#
using Deal.Modules.Cards.Application;
|
|
using Deal.Modules.Kanban.Application;
|
|
using Deal.Modules.Kanban.Application.Models;
|
|
|
|
namespace Deal.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// Единая точка перехода карточки между контейнерами — реализация порта <see cref="ICardMover"/>
|
|
/// (R4 этапа 9).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Маршрутизация цели живёт в домене: цель-стадия пространства «Выбранные»
|
|
/// (<see cref="CardsDefaultContainers"/>) переходит через <see cref="CardsService.MoveStageCardAsync"/> —
|
|
/// запись истории движения и сброс напоминания; остальные цели (доски/служебные зоны) — штатный перенос
|
|
/// дашборда <see cref="CardsService.MoveDashboardCardAsync"/> (журнал CardMoves, matchHits, обучение ML).
|
|
/// Адаптер только нормализует результаты обоих маршрутов к <see cref="CardMoveResultDto"/>; снимок карточки
|
|
/// эндпоинт перечитывает единым чтением. Scoped: зависимости живут в рамках tenant-запроса.
|
|
/// </remarks>
|
|
/// <param name="cardsService">Сервис карточек — единый домен перехода (стадии и контейнеры дашборда).</param>
|
|
public sealed class CardMover(CardsService cardsService) : ICardMover
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task<CardMoveResultDto> MoveAsync(
|
|
string cardId, string toContainerId, TransitionContext ctx, CancellationToken ct)
|
|
{
|
|
// Контекст перехода (инициатор/обучение) учтён внутри маршрутов: дашборд-перенос обучает ML по
|
|
// цели пользователя, переход по стадии пишет историю и сбрасывает напоминание. Отдельного
|
|
// ветвления по ctx сейчас нет — оно появится с политиками контейнеров (R4).
|
|
CardResultDto result = CardsDefaultContainers.Contains(toContainerId)
|
|
? await cardsService.MoveStageCardAsync(cardId, toContainerId, ct)
|
|
: await cardsService.MoveDashboardCardAsync(cardId, toContainerId, ct);
|
|
return result.Error is not null
|
|
? new CardMoveResultDto(result.Error, Exists: true)
|
|
: new CardMoveResultDto(null, Exists: result.Card is not null);
|
|
}
|
|
}
|