diff --git a/src/api/SIGCM2.Application/Rubros/Common/RubroTreeBuilder.cs b/src/api/SIGCM2.Application/Rubros/Common/RubroTreeBuilder.cs index 3e92ddf..04c3fc0 100644 --- a/src/api/SIGCM2.Application/Rubros/Common/RubroTreeBuilder.cs +++ b/src/api/SIGCM2.Application/Rubros/Common/RubroTreeBuilder.cs @@ -12,7 +12,8 @@ public static class RubroTreeBuilder { public static IReadOnlyList Build( IEnumerable flat, - bool incluirInactivos) + bool incluirInactivos, + IReadOnlyDictionary avisoCounts) { var filtered = incluirInactivos ? flat.ToList() @@ -36,6 +37,7 @@ public static class RubroTreeBuilder Activo: r.Activo, ParentId: r.ParentId, TarifarioBaseId: r.TarifarioBaseId, + TieneAvisos: avisoCounts.GetValueOrDefault(r.Id, 0) > 0, Hijos: children); } diff --git a/src/api/SIGCM2.Application/Rubros/Dtos/RubroTreeNodeDto.cs b/src/api/SIGCM2.Application/Rubros/Dtos/RubroTreeNodeDto.cs index 1bf5468..2f4d2c6 100644 --- a/src/api/SIGCM2.Application/Rubros/Dtos/RubroTreeNodeDto.cs +++ b/src/api/SIGCM2.Application/Rubros/Dtos/RubroTreeNodeDto.cs @@ -10,4 +10,5 @@ public sealed record RubroTreeNodeDto( bool Activo, int? ParentId, int? TarifarioBaseId, + bool TieneAvisos, IReadOnlyList Hijos); diff --git a/src/api/SIGCM2.Application/Rubros/GetTree/GetRubroTreeQueryHandler.cs b/src/api/SIGCM2.Application/Rubros/GetTree/GetRubroTreeQueryHandler.cs index 6fcefcc..884b869 100644 --- a/src/api/SIGCM2.Application/Rubros/GetTree/GetRubroTreeQueryHandler.cs +++ b/src/api/SIGCM2.Application/Rubros/GetTree/GetRubroTreeQueryHandler.cs @@ -17,6 +17,7 @@ public sealed class GetRubroTreeQueryHandler : ICommandHandler> Handle(GetRubroTreeQuery query) { var all = await _repo.GetAllAsync(query.IncluirInactivos); - return RubroTreeBuilder.Build(all, query.IncluirInactivos); + // CAT-002: avisoCounts injected via IAvisoQueryRepository (wired in Batch 6) + return RubroTreeBuilder.Build(all, query.IncluirInactivos, new Dictionary()); } } diff --git a/tests/SIGCM2.Application.Tests/Rubros/RubroTreeBuilderTests.cs b/tests/SIGCM2.Application.Tests/Rubros/RubroTreeBuilderTests.cs index 14e8338..c56aa9a 100644 --- a/tests/SIGCM2.Application.Tests/Rubros/RubroTreeBuilderTests.cs +++ b/tests/SIGCM2.Application.Tests/Rubros/RubroTreeBuilderTests.cs @@ -18,7 +18,7 @@ public class RubroTreeBuilderTests [Fact] public void Build_empty_returns_empty_list() { - var result = RubroTreeBuilder.Build([], incluirInactivos: false); + var result = RubroTreeBuilder.Build([], incluirInactivos: false, new Dictionary()); result.Should().BeEmpty(); } @@ -30,7 +30,7 @@ public class RubroTreeBuilderTests { var rubros = new[] { MakeRubro(1, null, "Autos", 0) }; - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, new Dictionary()); result.Should().HaveCount(1); result[0].Id.Should().Be(1); @@ -50,7 +50,7 @@ public class RubroTreeBuilderTests MakeRubro(2, null, "Camiones", 1) }; - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, new Dictionary()); result.Should().HaveCount(3); result[0].Id.Should().Be(1); // Orden=0 @@ -70,7 +70,7 @@ public class RubroTreeBuilderTests MakeRubro(3, 2, "Compactos", 0), }; - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, new Dictionary()); result.Should().HaveCount(1); result[0].Id.Should().Be(1); @@ -91,7 +91,7 @@ public class RubroTreeBuilderTests MakeRubro(2, null, "Motos", 1, activo: false), }; - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, new Dictionary()); result.Should().HaveCount(1); result[0].Id.Should().Be(1); @@ -106,7 +106,7 @@ public class RubroTreeBuilderTests MakeRubro(2, null, "Motos", 1, activo: false), }; - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: true); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: true, new Dictionary()); result.Should().HaveCount(2); } @@ -125,7 +125,7 @@ public class RubroTreeBuilderTests MakeRubro(5, 1, "A", 0), }; - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, new Dictionary()); var hijos = result[0].Hijos; hijos.Should().HaveCount(4); @@ -135,6 +135,47 @@ public class RubroTreeBuilderTests hijos[3].Nombre.Should().Be("D"); // Orden=3 } + // ── TieneAvisos from avisoCounts dict ──────────────────────────────────── + + [Fact] + public void Build_SetsTieneAvisos_True_WhenCountGreaterThanZero() + { + var rubros = new[] + { + MakeRubro(1, null, "Autos", 0), + MakeRubro(2, null, "Motos", 1), + }; + var avisoCounts = new Dictionary { { 1, 2 }, { 2, 0 } }; + + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, avisoCounts); + + result.Single(n => n.Id == 1).TieneAvisos.Should().BeTrue(); + result.Single(n => n.Id == 2).TieneAvisos.Should().BeFalse(); + } + + [Fact] + public void Build_SetsTieneAvisos_False_WhenCountIsZero() + { + var rubros = new[] { MakeRubro(1, null, "Autos", 0) }; + var avisoCounts = new Dictionary { { 1, 0 } }; + + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, avisoCounts); + + result[0].TieneAvisos.Should().BeFalse(); + } + + [Fact] + public void Build_SetsTieneAvisos_False_WhenIdMissingFromDict() + { + // Stub semantics: missing key = 0 = false + var rubros = new[] { MakeRubro(1, null, "Autos", 0) }; + var avisoCounts = new Dictionary(); // empty dict + + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, avisoCounts); + + result[0].TieneAvisos.Should().BeFalse(); + } + // ── O(n) perf smoke test ────────────────────────────────────────────────── [Fact] @@ -148,7 +189,7 @@ public class RubroTreeBuilderTests rubros.Add(MakeRubro(i, 1, $"Child{i}", i - 2)); var sw = System.Diagnostics.Stopwatch.StartNew(); - var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false); + var result = RubroTreeBuilder.Build(rubros, incluirInactivos: false, new Dictionary()); sw.Stop(); result.Should().HaveCount(1);