Skip to content

fix: исправить условие «нуждается в привязке» для проектов-сериалов#4131

Open
claude[bot] wants to merge 3 commits intomasterfrom
claude/issue-3860-20260403-1311
Open

fix: исправить условие «нуждается в привязке» для проектов-сериалов#4131
claude[bot] wants to merge 3 commits intomasterfrom
claude/issue-3860-20260403-1311

Conversation

@claude
Copy link
Copy Markdown
Contributor

@claude claude bot commented Apr 3, 2026

Что сделано

  • Исправлен метод GetKogdaIgraMissingGames() в ProjectRepository.cs

Проблема: Проекты-сериалы пропадали из выборки «надо привязать», если хотя бы одна из привязанных КИ-игр завершилась менее 60 дней назад. Условие hasNonStaleKogdaIgra (игра с End > now - 60 дней) исключало весь проект, даже если все игры фактически уже прошли.

Новое условие: Показывать проект как кандидата привязки если:

  1. Нет КИ-привязки вообще, ИЛИ
  2. Все привязанные КИ-игры уже завершились (End < now) И в проекте продолжается активность (обновление за последние 60 дней)

Closes #3860

Generated with Claude Code

Проекты-сериалы пропадали из выборки, если хотя бы одна привязанная КИ-игра
завершилась менее 60 дней назад. Новое условие: показывать проект как кандидата
привязки если привязок нет совсем, или все привязанные игры уже прошли (End < now)
И в проекте продолжается активность (обновление <60 дней).

Closes #3860

Co-authored-by: Leonid Tsarev <leotsarev@users.noreply.github.com>
@leotsarev
Copy link
Copy Markdown
Member

@claude мне кажется ошибка в логике. Давай напишем юнит тесты на условие фильтрации, и так разберемся все ли верно.

@claude
Copy link
Copy Markdown
Contributor Author

claude bot commented Apr 3, 2026

Claude finished @leotsarev's task in 6m 36s —— View job


Юнит-тесты добавлены

  • Прочитать текущий код фильтрации
  • Найти существующие тестовые проекты
  • Вынести предикат фильтрации в KogdaIgraMissingGamesPredicate.NeedsBinding() (internal static)
  • Написать 16 юнит-тестов на все граничные случаи
  • Запустить тесты — все прошли ✅
  • Закоммитить и запушить

Что сделано:

Логика фильтрации вынесена из ProjectRepository в отдельный internal static метод KogdaIgraMissingGamesPredicate.NeedsBinding(), который тестируется напрямую в JoinRpg.DataModel.Mocks (этот проект уже настроен через InternalsVisibleTo).

16 тестов, все зелёные:

Сценарий Ожидание
Нет привязок, активный проект включить ✅
Нет привязок, устаревший проект включить ✅
Будущая игра (End > now), активный проект исключить ✅
Будущая игра, устаревший проект исключить ✅
End == now (граница) исключить ✅
Прошедшая игра (End < now), активный проект включить ✅
Прошедшая игра, устаревший проект исключить ✅
Обновлено ровно 60 дней назад (граница) исключить ✅
Обновлено 59 дней назад (чуть меньше порога) включить ✅
Только неактивная привязка (Active=false), активный включить ✅
Только неактивная привязка, устаревший включить ✅
Смешанный: одна прошедшая + одна будущая исключить ✅
Несколько прошедших игр, активный проект включить ✅
Несколько прошедших игр, устаревший исключить ✅
Игра с End=null, активный проект включить ⚠️
Игра с End=null, устаревший проект исключить ⚠️

⚠️ Потенциальный баг — End=null:

Если у КИ-игры End=null (дата окончания не заполнена), то null >= now в C# возвращает false, и hasActiveOrFutureGame = false. Это значит, что проект с привязанной игрой без даты окончания попадёт в выборку как "нуждающийся в привязке" (если недавно обновлялся). Скорее всего, логичнее считать такую игру «будущей» и исключать проект из выборки. Нужно ваше решение: фикс (g.End == null || g.End >= now) или такое поведение ожидаемо?
| Branch

Вынесен предикат фильтрации в KogdaIgraMissingGamesPredicate.NeedsBinding()
для тестируемости. Добавлены 16 тестов, покрывающих все граничные случаи:
нет привязок, будущие/прошедшие игры, граница 60 дней,
неактивные привязки, смешанный сериал, End=null.

Co-authored-by: Leonid Tsarev <leotsarev@users.noreply.github.com>
/// 1. Нет активных КИ-привязок вообще, ИЛИ
/// 2. Все привязанные КИ-игры уже завершились (End &lt; now) И проект недавно обновлялся (&lt;60 дней)
/// </summary>
public static bool NeedsBinding(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Так работать не будет — нам нужно возвращать из этого метода Expression<Func<<>> иначе результат не будет транслироваться на сторону EF

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Используй LinqKit чтобы переиспользовать предикаты. Добавь информацию о использовании LINQKIT в документацию (создай отдельный файлик который описывает как писать Linq запросы с помощью LinqKit и сошлись на него в CLAUDE.MD

/// <summary>
/// Определяет, нуждается ли проект в привязке к КогдаИгра.
/// Проект попадает в выборку если:
/// 1. Нет активных КИ-привязок вообще, ИЛИ
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Давай условие DisableKogdaIgraMapping занесем внутрь этого метода

Copy link
Copy Markdown
Member

@leotsarev leotsarev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude fix

@claude
Copy link
Copy Markdown
Contributor Author

claude bot commented Apr 7, 2026

Claude finished @leotsarev's task in 6m 27s —— View job


Исправление по замечаниям ревью

  • Прочитать текущий код
  • Проверить наличие LinqKit в проекте (уже есть LinqKit.EntityFramework)
  • Рефакторинг: GetPredicate() возвращает Expression<Func<Project, DateTime, bool>>
  • Перенести условия Active и DisableKogdaIgraMapping внутрь предиката
  • Обновить ProjectRepository.cs — использовать предикат через Invoke
  • Обновить тесты под новый API
  • Создать документацию по LinqKit (docs/linq-queries.md)
  • Обновить CLAUDE.md со ссылкой на документацию
  • Запустить тесты — 18/18 зелёных
  • Закоммитить и запушить

Что сделано

KogdaIgraMissingGamesPredicate.cs — метод NeedsBinding(IEnumerable, DateTime, DateTime) заменён на GetPredicate(DateTime now), возвращающий Expression<Func<Project, DateTime, bool>>. Условия project.Active и project.Details.DisableKogdaIgraMapping перенесены внутрь предиката.

ProjectRepository.csGetKogdaIgraMissingGames теперь использует predicate.Invoke(project, update.LastUpdated) через LinqKit — выражение транслируется в SQL.

Тесты — обновлены: создают Project-объекты через вспомогательный CreateProject(), вызывают GetPredicate(Now).Compile()(project, lastUpdated). Добавлены 2 новых теста: DisableKogdaIgraMapping=true и Active=false.

docs/linq-queries.md — новый файл с описанием паттерна Expression + LinqKit: зачем, как определять, как использовать в EF, как тестировать.
| Branch

…gdaIgraMissingGamesPredicate

- GetPredicate() возвращает Expression для трансляции в SQL через LinqKit
- DisableKogdaIgraMapping и Active перенесены внутрь предиката
- ProjectRepository.GetKogdaIgraMissingGames использует predicate.Invoke()
- Тесты обновлены: создают Project-объекты и вызывают GetPredicate().Compile()()
- Добавлены тесты на DisableKogdaIgraMapping=true и Active=false
- Создан docs/linq-queries.md с документацией по LinqKit-паттерну
- CLAUDE.md обновлён со ссылкой на docs/linq-queries.md

Co-authored-by: Leonid Tsarev <leotsarev@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Поправить условие «нуждается в привязке» для сериалов

1 participant