From dcf6690dd7e5fc510c9256c28b569ee5934c27ed Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Thu, 10 Mar 2022 22:58:35 +0100 Subject: [PATCH 1/9] new models --- .../Infrastructure/InMemoryContext.cs | 18 +++-- .../V2/Controllers/Api/TaskController.cs | 5 ++ .../Infrastructure/Database/BitsContext.cs | 21 ++++-- .../Infrastructure/Database/Bits_Hall.cs | 5 ++ .../Infrastructure/Database/Bits_Match.cs | 65 +++++++++++++++++++ .../Infrastructure/Database/Bits_Team.cs | 5 ++ .../Infrastructure/Database/IBitsContext.cs | 12 ++-- .../Database/ISnittlistanContext.cs | 1 - .../Database/SnittlistanContext.cs | 1 - Snittlistan.Web/Snittlistan.Web.csproj | 1 + 10 files changed, 119 insertions(+), 15 deletions(-) create mode 100644 Snittlistan.Web/Infrastructure/Database/Bits_Match.cs diff --git a/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs b/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs index 8d787a1b..edce7438 100644 --- a/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs +++ b/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs @@ -1,4 +1,6 @@ -using System.Collections; +#nullable enable + +using System.Collections; using System.Collections.ObjectModel; using System.Data.Entity; using System.Data.Entity.Infrastructure; @@ -6,9 +8,8 @@ using System.Reflection; using Snittlistan.Web.Infrastructure.Database; -#nullable enable - namespace Snittlistan.Test.ApiControllers.Infrastructure; + public sealed class InMemoryDbSet : IDbSet, IDbAsyncEnumerable where T : class { private readonly IdGenerator _generator; @@ -112,6 +113,9 @@ public InMemoryContext() ChangeLogs = new InMemoryDbSet(generator); KeyValueProperties = new InMemoryDbSet(generator); SentEmails = new InMemoryDbSet(generator); + Match = new InMemoryDbSet(generator); + TeamRef = new InMemoryDbSet(generator); + OilProfile = new InMemoryDbSet(generator); } public IDbSet PublishedTasks { get; } @@ -130,7 +134,13 @@ public InMemoryContext() public IDbSet SentEmails { get; } - public DbChangeTracker ChangeTracker => throw new NotImplementedException(); + public DbChangeTracker ChangeTracker { get; } = null!; + + public IDbSet Match { get; } + + public IDbSet TeamRef { get; } + + public IDbSet OilProfile { get; } public int SaveChanges() { diff --git a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs index 12882c6a..8c1f6b43 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs @@ -19,6 +19,11 @@ namespace Snittlistan.Web.Areas.V2.Controllers.Api; [OnlyLocalAllowed] public class TaskController : AbstractApiController { + public async Task Get() + { + return Ok(await CompositionRoot.Databases.Bits.Match.FirstOrDefaultAsync()); + } + public async Task Post(TaskRequest request) { Logger.InfoFormat("Received task {taskJson}", request.TaskJson); diff --git a/Snittlistan.Web/Infrastructure/Database/BitsContext.cs b/Snittlistan.Web/Infrastructure/Database/BitsContext.cs index 1eea7dce..a909cafa 100644 --- a/Snittlistan.Web/Infrastructure/Database/BitsContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/BitsContext.cs @@ -1,7 +1,6 @@ -using Npgsql.NameTranslation; -using System.Data.Entity; +#nullable enable -#nullable enable +using Npgsql.NameTranslation; namespace Snittlistan.Web.Infrastructure.Database; @@ -11,13 +10,25 @@ public class BitsContext : DbContext, IBitsContext public IDbSet Hallar { get; set; } = null!; + public IDbSet Match { get; set; } = null!; + + public IDbSet TeamRef { get; set; } = null!; + + public IDbSet OilProfile { get; set; } = null!; + protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); System.Data.Entity.Database.SetInitializer(new NullDatabaseInitializer()); NpgsqlSnakeCaseNameTranslator mapper = new(); _ = modelBuilder.HasDefaultSchema("bits"); - modelBuilder.Properties().Configure(x => x.HasColumnName(mapper.TranslateMemberName(x.ClrPropertyInfo.Name))); - modelBuilder.Types().Configure(x => x.ToTable(mapper.TranslateMemberName(x.ClrType.Name.Replace("Bits", string.Empty)))); + modelBuilder.Properties().Configure(x => x.HasColumnName( + mapper.TranslateMemberName(x.ClrPropertyInfo.Name))); + modelBuilder.Types().Configure(x => x.ToTable( + mapper.TranslateMemberName(x.ClrType.Name.Replace("Bits_", string.Empty)))); + + _ = modelBuilder.Entity() + .HasRequired(p => p.AwayTeamRef) + .WithMany(x => x.Matches); } } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs b/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs index d4a52e8c..7aee02da 100644 --- a/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs +++ b/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs @@ -1,9 +1,14 @@ #nullable enable +using System.ComponentModel.DataAnnotations; + namespace Snittlistan.Web.Infrastructure.Database; public class Bits_Hall { + [Key] + public int HallId { get; set; } + public int ExternalHallId { get; set; } public string HallName { get; set; } = null!; diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs b/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs new file mode 100644 index 00000000..2df1c544 --- /dev/null +++ b/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs @@ -0,0 +1,65 @@ +#nullable enable + +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Snittlistan.Web.Infrastructure.Database; + +/* + * SELECT + m.external_match_id, + tr_home.team_name AS home_team_name, + tr_home.team_alias AS home_team_alias, + tr_away.team_name AS away_team_name, + tr_away.team_alias AS away_team_alias, + op.oil_profile_name, + hr.hall_name +FROM + bits.match m + JOIN bits.team_ref tr_home ON m.match_home_team_ref_id = tr_home.team_ref_id + JOIN bits.team_ref tr_away ON m.match_away_team_ref_id = tr_away.team_ref_id + JOIN bits.oil_profile op ON m.match_oil_profile_id = op.oil_profile_id + JOIN bits.hall_ref hr ON m.match_hall_ref_id = hr.hall_ref_id +WHERE + m.external_match_id = 3235829; + + */ +public class Bits_Match +{ + [Key] + public int MatchId { get; set; } + + public int ExternalMatchId { get; set; } + + [Column("match_home_team_ref_id")] + public int HomeTeamRefId { get; set; } + + public virtual Bits_TeamRef HomeTeamRef { get; set; } = null!; + + [Column("match_away_team_ref_id")] + public int AwayTeamRefId { get; set; } + + public virtual Bits_TeamRef AwayTeamRef { get; set; } = null!; + + [Column("match_oil_profile_id")] + public int OilProfileId { get; set; } + + public virtual Bits_OilProfile OilProfile { get; set; } = null!; +} +public class Bits_TeamRef +{ + [Key] + public int TeamRefId { get; set; } + + public virtual ICollection Matches { get; set; } = null!; +} +public class Bits_OilProfile +{ + [Key] + public int OilProfileId { get; set; } +} +public class Bits_HallRef +{ + [Key] + public int HallRefId { get; set; } +} diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_Team.cs b/Snittlistan.Web/Infrastructure/Database/Bits_Team.cs index 9a38ce71..7f2e978d 100644 --- a/Snittlistan.Web/Infrastructure/Database/Bits_Team.cs +++ b/Snittlistan.Web/Infrastructure/Database/Bits_Team.cs @@ -1,9 +1,14 @@ #nullable enable +using System.ComponentModel.DataAnnotations; + namespace Snittlistan.Web.Infrastructure.Database; public class Bits_Team { + [Key] + public int TeamId { get; set; } + public int ExternalTeamId { get; set; } public string TeamName { get; set; } = null!; diff --git a/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs b/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs index 6f2e820a..829d21c7 100644 --- a/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs @@ -1,12 +1,16 @@ - -using System.Data.Entity; - -#nullable enable +#nullable enable namespace Snittlistan.Web.Infrastructure.Database; + public interface IBitsContext { public IDbSet Teams { get; } public IDbSet Hallar { get; } + + public IDbSet Match { get; } + + public IDbSet TeamRef { get; } + + public IDbSet OilProfile { get; } } diff --git a/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs b/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs index 6dbec398..ce3e56d2 100644 --- a/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs @@ -1,6 +1,5 @@ #nullable enable -using System.Data.Entity; using System.Data.Entity.Infrastructure; namespace Snittlistan.Web.Infrastructure.Database; diff --git a/Snittlistan.Web/Infrastructure/Database/SnittlistanContext.cs b/Snittlistan.Web/Infrastructure/Database/SnittlistanContext.cs index 0c693043..494499f8 100644 --- a/Snittlistan.Web/Infrastructure/Database/SnittlistanContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/SnittlistanContext.cs @@ -1,7 +1,6 @@ #nullable enable using Npgsql.NameTranslation; -using System.Data.Entity; namespace Snittlistan.Web.Infrastructure.Database; diff --git a/Snittlistan.Web/Snittlistan.Web.csproj b/Snittlistan.Web/Snittlistan.Web.csproj index a1397c3b..0ab0f203 100644 --- a/Snittlistan.Web/Snittlistan.Web.csproj +++ b/Snittlistan.Web/Snittlistan.Web.csproj @@ -155,6 +155,7 @@ Index.cshtml + From 82b0395ddb1534897aad81ee6672a01528c69f7c Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Tue, 15 Mar 2022 19:01:35 +0100 Subject: [PATCH 2/9] maybe query correct? --- .../Infrastructure/InMemoryContext.cs | 20 ++++----- .../Areas/V1/Controllers/SearchController.cs | 4 +- .../V2/Controllers/Api/TaskController.cs | 17 +++++++- .../Infrastructure/Database/BitsContext.cs | 17 +++++--- .../Infrastructure/Database/Bits_Hall.cs | 10 +++-- .../Infrastructure/Database/Bits_HallRef.cs | 21 ++++++++++ .../Infrastructure/Database/Bits_Match.cs | 42 ++++++++----------- .../Database/Bits_OilProfile.cs | 16 +++++++ .../Infrastructure/Database/Bits_TeamRef.cs | 26 ++++++++++++ .../Infrastructure/Database/IBitsContext.cs | 4 +- Snittlistan.Web/Snittlistan.Web.csproj | 3 ++ .../Views/Emails/UpdateRoster.cshtml | 11 ++++- Snittlistan.Web/Web.config | 2 +- 13 files changed, 144 insertions(+), 49 deletions(-) create mode 100644 Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs create mode 100644 Snittlistan.Web/Infrastructure/Database/Bits_OilProfile.cs create mode 100644 Snittlistan.Web/Infrastructure/Database/Bits_TeamRef.cs diff --git a/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs b/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs index edce7438..de413739 100644 --- a/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs +++ b/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs @@ -107,8 +107,8 @@ public InMemoryContext() IdGenerator generator = new(); PublishedTasks = new InMemoryDbSet(generator); Tenants = new InMemoryDbSet(generator); - Teams = new InMemoryDbSet(generator); - Hallar = new InMemoryDbSet(generator); + Team = new InMemoryDbSet(generator); + Hall = new InMemoryDbSet(generator); RosterMails = new InMemoryDbSet(generator); ChangeLogs = new InMemoryDbSet(generator); KeyValueProperties = new InMemoryDbSet(generator); @@ -120,9 +120,15 @@ public InMemoryContext() public IDbSet PublishedTasks { get; } - public IDbSet Teams { get; } + public IDbSet Team { get; } - public IDbSet Hallar { get; } + public IDbSet Hall { get; } + + public IDbSet Match { get; } + + public IDbSet TeamRef { get; } + + public IDbSet OilProfile { get; } public IDbSet Tenants { get; } @@ -136,12 +142,6 @@ public InMemoryContext() public DbChangeTracker ChangeTracker { get; } = null!; - public IDbSet Match { get; } - - public IDbSet TeamRef { get; } - - public IDbSet OilProfile { get; } - public int SaveChanges() { return 0; diff --git a/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs b/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs index d75c560a..4b47e3f5 100644 --- a/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs +++ b/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs @@ -16,7 +16,7 @@ public JsonResult TeamsQuickSearch(string term) } var query = - from team in CompositionRoot.Databases.Bits.Teams + from team in CompositionRoot.Databases.Bits.Team where team.TeamAlias.StartsWith(term) orderby team.TeamAlias select new @@ -35,7 +35,7 @@ public JsonResult LocationsQuickSearch(string term) } var query = - from hall in CompositionRoot.Databases.Bits.Hallar + from hall in CompositionRoot.Databases.Bits.Hall where hall.HallName.StartsWith(term) orderby hall.HallName select new diff --git a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs index 8c1f6b43..439c4d4b 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs @@ -21,7 +21,22 @@ public class TaskController : AbstractApiController { public async Task Get() { - return Ok(await CompositionRoot.Databases.Bits.Match.FirstOrDefaultAsync()); + var query = + from m in CompositionRoot.Databases.Bits.Match + where m.MatchId == 6422 + select new + { + m.ExternalMatchId, + HomeTeamName = m.HomeTeamRef.TeamName, + AwayTeamName = m.AwayTeamRef.TeamName, + m.MatchDateTime, + m.HallRef.HallRefId, + HallRef_HallName = m.HallRef.HallName, + HallName = m.HallRef.Hall!.HallName ?? "" + }; + var result = await query + .FirstOrDefaultAsync(); + return Ok(result); } public async Task Post(TaskRequest request) diff --git a/Snittlistan.Web/Infrastructure/Database/BitsContext.cs b/Snittlistan.Web/Infrastructure/Database/BitsContext.cs index a909cafa..99f2a545 100644 --- a/Snittlistan.Web/Infrastructure/Database/BitsContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/BitsContext.cs @@ -6,9 +6,15 @@ namespace Snittlistan.Web.Infrastructure.Database; public class BitsContext : DbContext, IBitsContext { - public IDbSet Teams { get; set; } = null!; + public BitsContext() + { + Configuration.AutoDetectChangesEnabled = false; + Configuration.LazyLoadingEnabled = false; + } + + public IDbSet Team { get; set; } = null!; - public IDbSet Hallar { get; set; } = null!; + public IDbSet Hall { get; set; } = null!; public IDbSet Match { get; set; } = null!; @@ -27,8 +33,9 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) modelBuilder.Types().Configure(x => x.ToTable( mapper.TranslateMemberName(x.ClrType.Name.Replace("Bits_", string.Empty)))); - _ = modelBuilder.Entity() - .HasRequired(p => p.AwayTeamRef) - .WithMany(x => x.Matches); + _ = modelBuilder.Entity() + .HasOptional(x => x.Hall) + .WithOptionalDependent(x => x!.HallRef) + .Map(x => x.MapKey("hall_id")); } } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs b/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs index 7aee02da..f127f4d2 100644 --- a/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs +++ b/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs @@ -7,9 +7,13 @@ namespace Snittlistan.Web.Infrastructure.Database; public class Bits_Hall { [Key] - public int HallId { get; set; } + public int HallId { get; private set; } - public int ExternalHallId { get; set; } + public int ExternalHallId { get; private set; } - public string HallName { get; set; } = null!; + public string HallName { get; private set; } = string.Empty; + + public int HallRefId { get; set; } + + public Bits_HallRef HallRef { get; private set; } = null!; } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs b/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs new file mode 100644 index 00000000..791bea5d --- /dev/null +++ b/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs @@ -0,0 +1,21 @@ +#nullable enable + +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Snittlistan.Web.Infrastructure.Database; + +public class Bits_HallRef +{ + [Key] + public int HallRefId { get; private set; } + + public int ExternalHallId { get; private set; } + + //[ForeignKey(nameof(Hall))] + //public int HallId { get; private set; } + + public string HallName { get; private set; } = string.Empty; + + public Bits_Hall? Hall { get; private set; } +} diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs b/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs index 2df1c544..912ea668 100644 --- a/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs +++ b/Snittlistan.Web/Infrastructure/Database/Bits_Match.cs @@ -27,39 +27,33 @@ bits.match m public class Bits_Match { [Key] - public int MatchId { get; set; } + public int MatchId { get; private set; } - public int ExternalMatchId { get; set; } + public int ExternalMatchId { get; private set; } + + public DateTime MatchDateTime { get; private set; } [Column("match_home_team_ref_id")] - public int HomeTeamRefId { get; set; } + [ForeignKey(nameof(HomeTeamRef))] + public int HomeTeamRefId { get; private set; } - public virtual Bits_TeamRef HomeTeamRef { get; set; } = null!; + public virtual Bits_TeamRef HomeTeamRef { get; private set; } = null!; [Column("match_away_team_ref_id")] - public int AwayTeamRefId { get; set; } + [ForeignKey(nameof(AwayTeamRef))] + public int AwayTeamRefId { get; private set; } - public virtual Bits_TeamRef AwayTeamRef { get; set; } = null!; + public virtual Bits_TeamRef AwayTeamRef { get; private set; } = null!; [Column("match_oil_profile_id")] - public int OilProfileId { get; set; } + [ForeignKey(nameof(OilProfile))] + public int OilProfileId { get; private set; } - public virtual Bits_OilProfile OilProfile { get; set; } = null!; -} -public class Bits_TeamRef -{ - [Key] - public int TeamRefId { get; set; } + public virtual Bits_OilProfile OilProfile { get; private set; } = null!; - public virtual ICollection Matches { get; set; } = null!; -} -public class Bits_OilProfile -{ - [Key] - public int OilProfileId { get; set; } -} -public class Bits_HallRef -{ - [Key] - public int HallRefId { get; set; } + [Column("match_hall_ref_id")] + [ForeignKey(nameof(HallRef))] + public int HallRefId { get; private set; } + + public Bits_HallRef HallRef { get; private set; } = null!; } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_OilProfile.cs b/Snittlistan.Web/Infrastructure/Database/Bits_OilProfile.cs new file mode 100644 index 00000000..e534b3c1 --- /dev/null +++ b/Snittlistan.Web/Infrastructure/Database/Bits_OilProfile.cs @@ -0,0 +1,16 @@ +#nullable enable + +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Snittlistan.Web.Infrastructure.Database; + +public class Bits_OilProfile +{ + [Key] + public int OilProfileId { get; set; } + + [InverseProperty(nameof(Bits_Match.OilProfile))] + public virtual ICollection Matches { get; set; } = + new HashSet(); +} diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_TeamRef.cs b/Snittlistan.Web/Infrastructure/Database/Bits_TeamRef.cs new file mode 100644 index 00000000..c87011f1 --- /dev/null +++ b/Snittlistan.Web/Infrastructure/Database/Bits_TeamRef.cs @@ -0,0 +1,26 @@ +#nullable enable + +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Snittlistan.Web.Infrastructure.Database; + +public class Bits_TeamRef +{ + [Key] + public int TeamRefId { get; private set; } + + public int ExternalTeamId { get; set; } + + public string TeamName { get; private set; } = string.Empty; + + public string TeamAlias { get; set; } = string.Empty; + + [InverseProperty(nameof(Bits_Match.HomeTeamRef))] + public virtual ICollection HomeMatches { get; private set; } = + new HashSet(); + + [InverseProperty(nameof(Bits_Match.AwayTeamRef))] + public virtual ICollection AwayMatches { get; private set; } = + new HashSet(); +} diff --git a/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs b/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs index 829d21c7..f96b22e1 100644 --- a/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs @@ -4,9 +4,9 @@ namespace Snittlistan.Web.Infrastructure.Database; public interface IBitsContext { - public IDbSet Teams { get; } + public IDbSet Team { get; } - public IDbSet Hallar { get; } + public IDbSet Hall { get; } public IDbSet Match { get; } diff --git a/Snittlistan.Web/Snittlistan.Web.csproj b/Snittlistan.Web/Snittlistan.Web.csproj index 0ab0f203..0d8f90e1 100644 --- a/Snittlistan.Web/Snittlistan.Web.csproj +++ b/Snittlistan.Web/Snittlistan.Web.csproj @@ -155,7 +155,10 @@ Index.cshtml + + + diff --git a/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml b/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml index 532e99c0..772863af 100644 --- a/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml +++ b/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml @@ -30,7 +30,16 @@ Content-Type: text/html; charset=utf-8 }

-

@Model.FormattedAuditLog.Title

+
+
Hemmalag
+
@Model.HomeTeamName
+
Bortalag
+
@Model.AwayTeamName
+
Datum
+
@Model.MatchDate
+
Online scoring
+
@Model.OnlineScoringLink
+
diff --git a/Snittlistan.Web/Web.config b/Snittlistan.Web/Web.config index 30a56855..3a1880f2 100644 --- a/Snittlistan.Web/Web.config +++ b/Snittlistan.Web/Web.config @@ -17,7 +17,7 @@ - + From cef9af959ff9947a854008c9b849f513b4ba2fb5 Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Wed, 16 Mar 2022 23:32:16 +0100 Subject: [PATCH 3/9] time to try --- .../Infrastructure/InMemoryContext.cs | 10 ++ .../Domain/MatchResult_MatchCommentary.cs | 2 + .../Areas/V1/Controllers/SearchController.cs | 2 +- .../V2/Controllers/Api/TaskController.cs | 126 ++++++++++++------ Snittlistan.Web/Areas/V2/WebsiteRoles.cs | 1 + Snittlistan.Web/Commands/CommandExecutor.cs | 1 + .../PublishRosterMailCommandHandler.cs | 15 ++- .../PublishRosterMailsCommandHandler.cs | 4 +- .../Attributes/SaveChangesAttribute.cs | 12 +- .../Infrastructure/CompositionRoot.cs | 1 + .../Infrastructure/Database/BitsContext.cs | 16 ++- .../Infrastructure/Database/Bits_Hall.cs | 4 +- .../Infrastructure/Database/Bits_HallRef.cs | 6 +- .../Database/Bits_VMatchHeadInfo.cs | 27 ++++ .../Infrastructure/Database/Databases.cs | 8 +- .../Database/DatabasesFactory.cs | 19 +++ .../Infrastructure/Database/IBitsContext.cs | 6 +- .../Database/ISnittlistanContext.cs | 2 +- Snittlistan.Web/Infrastructure/GuidBinder.cs | 5 +- .../Infrastructure/HandlerContext.cs | 4 + .../Installers/DatabaseContextInstaller.cs | 16 ++- Snittlistan.Web/Models/UpdateRosterEmail.cs | 28 +++- .../Models/UpdateRosterEmail_State.cs | 34 ++++- Snittlistan.Web/Snittlistan.Web.csproj | 2 + .../Views/Emails/UpdateRoster.cshtml | 14 +- Snittlistan.Web/Web.config | 2 +- 26 files changed, 282 insertions(+), 85 deletions(-) create mode 100644 Snittlistan.Web/Infrastructure/Database/Bits_VMatchHeadInfo.cs create mode 100644 Snittlistan.Web/Infrastructure/Database/DatabasesFactory.cs diff --git a/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs b/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs index de413739..cf5354a7 100644 --- a/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs +++ b/Snittlistan.Test/ApiControllers/Infrastructure/InMemoryContext.cs @@ -108,6 +108,7 @@ public InMemoryContext() PublishedTasks = new InMemoryDbSet(generator); Tenants = new InMemoryDbSet(generator); Team = new InMemoryDbSet(generator); + HallRef = new InMemoryDbSet(generator); Hall = new InMemoryDbSet(generator); RosterMails = new InMemoryDbSet(generator); ChangeLogs = new InMemoryDbSet(generator); @@ -116,12 +117,15 @@ public InMemoryContext() Match = new InMemoryDbSet(generator); TeamRef = new InMemoryDbSet(generator); OilProfile = new InMemoryDbSet(generator); + VMatchHeadInfo = new InMemoryDbSet(generator); } public IDbSet PublishedTasks { get; } public IDbSet Team { get; } + public IDbSet HallRef { get; } + public IDbSet Hall { get; } public IDbSet Match { get; } @@ -130,6 +134,8 @@ public InMemoryContext() public IDbSet OilProfile { get; } + public IDbSet VMatchHeadInfo { get; } + public IDbSet Tenants { get; } public IDbSet RosterMails { get; } @@ -151,4 +157,8 @@ public Task SaveChangesAsync() { return Task.FromResult(0); } + + public void Dispose() + { + } } diff --git a/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs b/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs index 90608b11..4daecc4a 100644 --- a/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs +++ b/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs @@ -168,6 +168,7 @@ await Transact(async session => session, eventStoreSession, Databases, + new(() => Databases), Container.Resolve(), Container.Resolve(), CurrentTenant, @@ -184,6 +185,7 @@ await Transact(async session => }; HandlerContext context = new( compositionRoot, + Databases, command, new("hostname", "favicon", "appleTouchIcon", "appleTouchIconSize", "webAppTitle", -1, "teamFullName"), Guid.NewGuid(), diff --git a/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs b/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs index 4b47e3f5..e6cbadf2 100644 --- a/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs +++ b/Snittlistan.Web/Areas/V1/Controllers/SearchController.cs @@ -43,6 +43,6 @@ orderby hall.HallName label = hall.HallName }; - return Json(term, JsonRequestBehavior.AllowGet); + return Json(query, JsonRequestBehavior.AllowGet); } } diff --git a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs index 439c4d4b..c818ca1f 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs @@ -21,21 +21,37 @@ public class TaskController : AbstractApiController { public async Task Get() { - var query = - from m in CompositionRoot.Databases.Bits.Match - where m.MatchId == 6422 - select new - { - m.ExternalMatchId, - HomeTeamName = m.HomeTeamRef.TeamName, - AwayTeamName = m.AwayTeamRef.TeamName, - m.MatchDateTime, - m.HallRef.HallRefId, - HallRef_HallName = m.HallRef.HallName, - HallName = m.HallRef.Hall!.HallName ?? "" - }; - var result = await query - .FirstOrDefaultAsync(); + //var query = + // from m in CompositionRoot.Databases.Bits.Match + // where m.MatchId == 6422 + // select new + // { + // m.ExternalMatchId, + // HomeTeamName = m.HomeTeamRef.TeamName, + // AwayTeamName = m.AwayTeamRef.TeamName, + // m.MatchDateTime, + // m.HallRef.HallRefId, + // HallRef_HallName = m.HallRef.HallName, + // HallName = m.HallRef.Hall!.HallName ?? "" + // }; + var result = await Transact(async databases => + { + var query = + from mhi in databases.Bits.VMatchHeadInfo + select new + { + mhi.ExternalMatchId, + mhi.HomeTeamName, + mhi.HomeTeamAlias, + mhi.AwayTeamName, + mhi.AwayTeamAlias, + mhi.OilProfileName, + mhi.HallName + }; + return await query + .FirstOrDefaultAsync(); + }); + return Ok(result); } @@ -76,32 +92,40 @@ public async Task Post(TaskRequest request) $"throttled due to unhandled exception (allowance = {cacheItem.Allowance:N2})"); } - // check for published task - PublishedTask? publishedTask = - await CompositionRoot.Databases.Snittlistan.PublishedTasks.SingleOrDefaultAsync( - x => x.MessageId == request.MessageId); - if (publishedTask is null) - { - return BadRequest($"No published task found with message id {request.MessageId}"); - } - - if (publishedTask.HandledDate.HasValue) - { - return Ok($"task with message id {publishedTask.MessageId} already handled"); - } - + IDisposable scope = NLog.NestedDiagnosticsLogicalContext.Push(taskObject.BusinessKey); try { - using IDisposable scope = NLog.NestedDiagnosticsLogicalContext.Push(taskObject.BusinessKey); - Logger.Info("Begin"); - bool handled = await HandleMessage( - taskObject, - request.CorrelationId ?? default, - request.MessageId ?? default); - if (handled) + Logger.Info("begin"); + IHttpActionResult result = await Transact(async databases => { - publishedTask.MarkHandled(DateTime.Now); - } + // check for published task + PublishedTask? publishedTask = + await databases.Snittlistan.PublishedTasks.SingleOrDefaultAsync( + x => x.MessageId == request.MessageId); + if (publishedTask is null) + { + return BadRequest($"no published task found with message id {request.MessageId}"); + } + + if (publishedTask.HandledDate.HasValue) + { + return Ok($"task with message id {publishedTask.MessageId} already handled"); + } + + bool handled = await HandleMessage( + taskObject, + request.CorrelationId ?? default, + request.MessageId ?? default, + databases); + if (handled) + { + publishedTask.MarkHandled(DateTime.Now); + } + + return Ok(); + }); + + return result; } catch (Exception ex) { @@ -114,29 +138,30 @@ await CompositionRoot.Databases.Snittlistan.PublishedTasks.SingleOrDefaultAsync( } finally { - Logger.Info("End"); + Logger.Info("end"); + scope.Dispose(); } - - return Ok(); } private async Task HandleMessage( TaskBase taskObject, Guid correlationId, - Guid causationId) + Guid causationId, + Databases databases) { Type handlerType = typeof(ITaskHandler<>).MakeGenericType(taskObject.GetType()); MethodInfo handleMethod = handlerType.GetMethod(nameof(ITaskHandler.Handle)); TaskPublisher taskPublisher = new( CompositionRoot.CurrentTenant, - CompositionRoot.Databases, + databases, CompositionRoot.MsmqFactory, correlationId, causationId); IHandlerContext handlerContext = (IHandlerContext)Activator.CreateInstance( typeof(HandlerContext<>).MakeGenericType(taskObject.GetType()), CompositionRoot, + databases, taskObject, CompositionRoot.CurrentTenant, correlationId, @@ -167,6 +192,21 @@ private async Task HandleMessage( return true; } + + private async Task Transact(Func> func) + { + using Databases databases = CompositionRoot.DatabasesFactory.Create(); + TResult result = await func.Invoke(databases); + int changesSaved = databases.Snittlistan.SaveChanges(); + if (changesSaved > 0) + { + Logger.InfoFormat( + "saved {changesSaved} to database", + changesSaved); + } + + return result; + } } public class TaskRequest diff --git a/Snittlistan.Web/Areas/V2/WebsiteRoles.cs b/Snittlistan.Web/Areas/V2/WebsiteRoles.cs index 4e79d1e8..0e0f4383 100644 --- a/Snittlistan.Web/Areas/V2/WebsiteRoles.cs +++ b/Snittlistan.Web/Areas/V2/WebsiteRoles.cs @@ -1,6 +1,7 @@ #nullable enable namespace Snittlistan.Web.Areas.V2; + public static class WebsiteRoles { // roles diff --git a/Snittlistan.Web/Commands/CommandExecutor.cs b/Snittlistan.Web/Commands/CommandExecutor.cs index b97ae0e9..a1a43295 100644 --- a/Snittlistan.Web/Commands/CommandExecutor.cs +++ b/Snittlistan.Web/Commands/CommandExecutor.cs @@ -39,6 +39,7 @@ public async Task Execute(TCommand command) IHandlerContext handlerContext = (IHandlerContext)Activator.CreateInstance( typeof(HandlerContext<>).MakeGenericType(command.GetType()), compositionRoot, + compositionRoot.Databases, command, compositionRoot.CurrentTenant, correlationId, diff --git a/Snittlistan.Web/Commands/PublishRosterMailCommandHandler.cs b/Snittlistan.Web/Commands/PublishRosterMailCommandHandler.cs index ce591307..604ebcfa 100644 --- a/Snittlistan.Web/Commands/PublishRosterMailCommandHandler.cs +++ b/Snittlistan.Web/Commands/PublishRosterMailCommandHandler.cs @@ -2,6 +2,7 @@ using Snittlistan.Web.Areas.V2.Domain; using Snittlistan.Web.Infrastructure; +using Snittlistan.Web.Infrastructure.Database; using Snittlistan.Web.Models; namespace Snittlistan.Web.Commands; @@ -9,7 +10,7 @@ namespace Snittlistan.Web.Commands; public class PublishRosterMailCommandHandler : HandleMailCommandHandler { - protected override Task CreateEmail(HandlerContext context) + protected override async Task CreateEmail(HandlerContext context) { Roster roster = CompositionRoot.DocumentSession .Include(x => x.Players) @@ -23,6 +24,8 @@ protected override Task CreateEmail(HandlerContext c ? CompositionRoot.DocumentSession.Load(roster.TeamLeader).Name : string.Empty; bool needsAccept = roster.AcceptedPlayers.Contains(context.Payload.PlayerId) == false; + Bits_VMatchHeadInfo matchHeadInfo = await context.Databases.Bits.VMatchHeadInfo.SingleAsync( + x => x.ExternalMatchId == roster.BitsMatchId); UpdateRosterEmail email = new( context.Payload.RecipientEmail, context.Payload.RecipientName, @@ -34,8 +37,14 @@ protected override Task CreateEmail(HandlerContext c roster.Turn, context.Payload.RosterLink, context.Payload.UserProfileLink, - needsAccept); - return Task.FromResult(email); + needsAccept, + matchHeadInfo.HomeTeamAlias, + matchHeadInfo.AwayTeamAlias, + matchHeadInfo.HallName, + matchHeadInfo.OilProfileId, + matchHeadInfo.OilProfileName, + matchHeadInfo.MatchDateTime); + return email; } protected override RatePerSeconds GetRate(HandlerContext context) diff --git a/Snittlistan.Web/Commands/PublishRosterMailsCommandHandler.cs b/Snittlistan.Web/Commands/PublishRosterMailsCommandHandler.cs index a92a4a14..36482d72 100644 --- a/Snittlistan.Web/Commands/PublishRosterMailsCommandHandler.cs +++ b/Snittlistan.Web/Commands/PublishRosterMailsCommandHandler.cs @@ -47,7 +47,7 @@ public override async Task Handle(HandlerContext context) string[] propertyKeys = affectedPlayers.Select(UserSettings.GetKey).ToArray(); Dictionary properties = Enumerable.ToDictionary( - await CompositionRoot.Databases.Snittlistan.KeyValueProperties.Where( + await context.Databases.Snittlistan.KeyValueProperties.Where( x => propertyKeys.Contains(x.Key)) .ToArrayAsync(), x => x.Key, @@ -100,7 +100,7 @@ await CompositionRoot.Databases.Snittlistan.KeyValueProperties.Where( } RosterMail rosterMail = - await CompositionRoot.Databases.Snittlistan.RosterMails.SingleAsync( + await context.Databases.Snittlistan.RosterMails.SingleAsync( x => x.RosterKey == context.Payload.RosterKey && x.PublishedDate == null); rosterMail.MarkPublished(DateTime.Now); } diff --git a/Snittlistan.Web/Infrastructure/Attributes/SaveChangesAttribute.cs b/Snittlistan.Web/Infrastructure/Attributes/SaveChangesAttribute.cs index a9cd1481..99d1ba76 100644 --- a/Snittlistan.Web/Infrastructure/Attributes/SaveChangesAttribute.cs +++ b/Snittlistan.Web/Infrastructure/Attributes/SaveChangesAttribute.cs @@ -1,12 +1,18 @@ -using System.Web.Http.Filters; +#nullable enable + +using System.Web.Http.Filters; using Snittlistan.Web.Controllers; namespace Snittlistan.Web.Infrastructure.Attributes; + public class SaveChangesAttribute : ActionFilterAttribute { - public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) + public override async Task OnActionExecutedAsync( + HttpActionExecutedContext actionExecutedContext, + CancellationToken cancellationToken) { - if (actionExecutedContext.ActionContext.ControllerContext.Controller is not AbstractApiController controller + if (actionExecutedContext.ActionContext.ControllerContext.Controller + is not AbstractApiController controller || actionExecutedContext.Exception != null) { return; diff --git a/Snittlistan.Web/Infrastructure/CompositionRoot.cs b/Snittlistan.Web/Infrastructure/CompositionRoot.cs index 41a6a4b4..0b00da01 100644 --- a/Snittlistan.Web/Infrastructure/CompositionRoot.cs +++ b/Snittlistan.Web/Infrastructure/CompositionRoot.cs @@ -15,6 +15,7 @@ public record CompositionRoot( Raven.Client.IDocumentSession DocumentSession, IEventStoreSession EventStoreSession, Databases Databases, + DatabasesFactory DatabasesFactory, MsmqFactory MsmqFactory, EventStore EventStore, Tenant CurrentTenant, diff --git a/Snittlistan.Web/Infrastructure/Database/BitsContext.cs b/Snittlistan.Web/Infrastructure/Database/BitsContext.cs index 99f2a545..d9419058 100644 --- a/Snittlistan.Web/Infrastructure/Database/BitsContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/BitsContext.cs @@ -14,6 +14,8 @@ public BitsContext() public IDbSet Team { get; set; } = null!; + public IDbSet HallRef { get; set; } = null!; + public IDbSet Hall { get; set; } = null!; public IDbSet Match { get; set; } = null!; @@ -22,6 +24,8 @@ public BitsContext() public IDbSet OilProfile { get; set; } = null!; + public IDbSet VMatchHeadInfo { get; set; } = null!; + protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); @@ -33,9 +37,13 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) modelBuilder.Types().Configure(x => x.ToTable( mapper.TranslateMemberName(x.ClrType.Name.Replace("Bits_", string.Empty)))); - _ = modelBuilder.Entity() - .HasOptional(x => x.Hall) - .WithOptionalDependent(x => x!.HallRef) - .Map(x => x.MapKey("hall_id")); + //.WithRequiredPrincipal(x => x.Hall!); + // .Map(x => x.MapKey("hall_id")); + //_ = modelBuilder.Entity() + // .HasOptional(x => x.Hall) + // .WithOptionalDependent(x => x!.HallRef) + // .Map(x => x.MapKey("hall_id")); + + //_ = modelBuilder.Entity } } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs b/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs index f127f4d2..42934325 100644 --- a/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs +++ b/Snittlistan.Web/Infrastructure/Database/Bits_Hall.cs @@ -13,7 +13,5 @@ public class Bits_Hall public string HallName { get; private set; } = string.Empty; - public int HallRefId { get; set; } - - public Bits_HallRef HallRef { get; private set; } = null!; + public Bits_HallRef HallRef { get; set; } = null!; } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs b/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs index 791bea5d..97c50762 100644 --- a/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs +++ b/Snittlistan.Web/Infrastructure/Database/Bits_HallRef.cs @@ -1,7 +1,6 @@ #nullable enable using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; namespace Snittlistan.Web.Infrastructure.Database; @@ -12,10 +11,7 @@ public class Bits_HallRef public int ExternalHallId { get; private set; } - //[ForeignKey(nameof(Hall))] - //public int HallId { get; private set; } + public int? HallId { get; private set; } public string HallName { get; private set; } = string.Empty; - - public Bits_Hall? Hall { get; private set; } } diff --git a/Snittlistan.Web/Infrastructure/Database/Bits_VMatchHeadInfo.cs b/Snittlistan.Web/Infrastructure/Database/Bits_VMatchHeadInfo.cs new file mode 100644 index 00000000..eb6b747d --- /dev/null +++ b/Snittlistan.Web/Infrastructure/Database/Bits_VMatchHeadInfo.cs @@ -0,0 +1,27 @@ +#nullable enable + +using System.ComponentModel.DataAnnotations; + +namespace Snittlistan.Web.Infrastructure.Database; + +public class Bits_VMatchHeadInfo +{ + [Key] + public int ExternalMatchId { get; private set; } + + public DateTime MatchDateTime { get; private set; } + + public string HomeTeamName { get; private set; } = string.Empty; + + public string HomeTeamAlias { get; private set; } = string.Empty; + + public string AwayTeamName { get; private set; } = string.Empty; + + public string AwayTeamAlias { get; private set; } = string.Empty; + + public int OilProfileId { get; private set; } + + public string OilProfileName { get; private set; } = string.Empty; + + public string HallName { get; private set; } = string.Empty; +} diff --git a/Snittlistan.Web/Infrastructure/Database/Databases.cs b/Snittlistan.Web/Infrastructure/Database/Databases.cs index 7aa0ce7e..88445c9c 100644 --- a/Snittlistan.Web/Infrastructure/Database/Databases.cs +++ b/Snittlistan.Web/Infrastructure/Database/Databases.cs @@ -2,7 +2,7 @@ namespace Snittlistan.Web.Infrastructure.Database; -public class Databases +public class Databases : IDisposable { public Databases( ISnittlistanContext snittlistanContext, @@ -15,4 +15,10 @@ public Databases( public ISnittlistanContext Snittlistan { get; } public IBitsContext Bits { get; } + + public void Dispose() + { + Snittlistan.Dispose(); + Bits.Dispose(); + } } diff --git a/Snittlistan.Web/Infrastructure/Database/DatabasesFactory.cs b/Snittlistan.Web/Infrastructure/Database/DatabasesFactory.cs new file mode 100644 index 00000000..8e74bc0d --- /dev/null +++ b/Snittlistan.Web/Infrastructure/Database/DatabasesFactory.cs @@ -0,0 +1,19 @@ +#nullable enable + +namespace Snittlistan.Web.Infrastructure.Database; + +public class DatabasesFactory +{ + private readonly Func databasesFactory; + + public DatabasesFactory(Func databasesFactory) + { + this.databasesFactory = databasesFactory; + } + + public Databases Create() + { + Databases databases = databasesFactory.Invoke(); + return databases; + } +} diff --git a/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs b/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs index f96b22e1..69929dcf 100644 --- a/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/IBitsContext.cs @@ -2,10 +2,12 @@ namespace Snittlistan.Web.Infrastructure.Database; -public interface IBitsContext +public interface IBitsContext : IDisposable { public IDbSet Team { get; } + public IDbSet HallRef { get; } + public IDbSet Hall { get; } public IDbSet Match { get; } @@ -13,4 +15,6 @@ public interface IBitsContext public IDbSet TeamRef { get; } public IDbSet OilProfile { get; } + + public IDbSet VMatchHeadInfo { get; } } diff --git a/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs b/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs index ce3e56d2..58d7c6e7 100644 --- a/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs +++ b/Snittlistan.Web/Infrastructure/Database/ISnittlistanContext.cs @@ -4,7 +4,7 @@ namespace Snittlistan.Web.Infrastructure.Database; -public interface ISnittlistanContext +public interface ISnittlistanContext : IDisposable { IDbSet PublishedTasks { get; } diff --git a/Snittlistan.Web/Infrastructure/GuidBinder.cs b/Snittlistan.Web/Infrastructure/GuidBinder.cs index 9cc2e9d9..4a3012b2 100644 --- a/Snittlistan.Web/Infrastructure/GuidBinder.cs +++ b/Snittlistan.Web/Infrastructure/GuidBinder.cs @@ -1,6 +1,9 @@ -using System.Web.Mvc; +#nullable enable + +using System.Web.Mvc; namespace Snittlistan.Web.Infrastructure; + public class GuidBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) diff --git a/Snittlistan.Web/Infrastructure/HandlerContext.cs b/Snittlistan.Web/Infrastructure/HandlerContext.cs index a7eb8589..4dfcb017 100644 --- a/Snittlistan.Web/Infrastructure/HandlerContext.cs +++ b/Snittlistan.Web/Infrastructure/HandlerContext.cs @@ -11,18 +11,22 @@ public class HandlerContext : IHandlerContext public HandlerContext( CompositionRoot compositionRoot, + Databases databases, TPayload payload, Tenant tenant, Guid correlationId, Guid causationId) { this.compositionRoot = compositionRoot; + Databases = databases; Payload = payload; Tenant = tenant; CorrelationId = correlationId; CausationId = causationId; } + public Databases Databases { get; } + public TPayload Payload { get; } public Tenant Tenant { get; } diff --git a/Snittlistan.Web/Infrastructure/Installers/DatabaseContextInstaller.cs b/Snittlistan.Web/Infrastructure/Installers/DatabaseContextInstaller.cs index 8f7f71d2..3dd0d126 100644 --- a/Snittlistan.Web/Infrastructure/Installers/DatabaseContextInstaller.cs +++ b/Snittlistan.Web/Infrastructure/Installers/DatabaseContextInstaller.cs @@ -10,20 +10,20 @@ namespace Snittlistan.Web.Infrastructure.Installers; public class DatabaseContextInstaller : IWindsorInstaller { - private readonly Func databases; + private readonly Func databasesFactory; private readonly Func, ComponentRegistration> func; - public DatabaseContextInstaller(Func databases) + public DatabaseContextInstaller(Func databasesFactory) { func = x => x.LifestylePerWebRequest(); - this.databases = databases; + this.databasesFactory = databasesFactory; } - public DatabaseContextInstaller(Func databases, LifestyleType lifestyleType) + public DatabaseContextInstaller(Func databasesFactory, LifestyleType lifestyleType) { func = x => x.LifeStyle.Is(lifestyleType); - this.databases = databases; + this.databasesFactory = databasesFactory; } public void Install(IWindsorContainer container, IConfigurationStore store) @@ -31,6 +31,10 @@ public void Install(IWindsorContainer container, IConfigurationStore store) _ = container.Register( func.Invoke( Component.For() - .UsingFactoryMethod(databases))); + .UsingFactoryMethod(databasesFactory))); + _ = container.Register( + Component.For() + .Instance(new DatabasesFactory(databasesFactory)) + .LifestyleSingleton()); } } diff --git a/Snittlistan.Web/Models/UpdateRosterEmail.cs b/Snittlistan.Web/Models/UpdateRosterEmail.cs index a91d4e87..a19f6b7d 100644 --- a/Snittlistan.Web/Models/UpdateRosterEmail.cs +++ b/Snittlistan.Web/Models/UpdateRosterEmail.cs @@ -19,7 +19,13 @@ public UpdateRosterEmail( int turn, Uri rosterLink, Uri userProfileLink, - bool needsAccept) + bool needsAccept, + string homeTeamAlias, + string awayTeamAlias, + string hallName, + int oilProfileId, + string oilProfileName, + DateTime matchDate) : base("UpdateRoster") { _state = new( @@ -33,7 +39,13 @@ public UpdateRosterEmail( turn, rosterLink, userProfileLink, - needsAccept); + needsAccept, + homeTeamAlias, + awayTeamAlias, + hallName, + oilProfileId, + oilProfileName, + matchDate); } public string PlayerEmail => _state.PlayerEmail; @@ -58,5 +70,17 @@ public UpdateRosterEmail( public bool NeedsAccept => _state.NeedsAccept; + public string HomeTeamAlias => _state.HomeTeamAlias; + + public string AwayTeamAlias => _state.AwayTeamAlias; + + public string HallName => _state.HallName; + + public int OilProfileId => _state.OilProfileId; + + public string OilProfileName => _state.OilProfileName; + + public DateTime MatchDate => _state.MatchDate; + public override EmailState State => _state; } diff --git a/Snittlistan.Web/Models/UpdateRosterEmail_State.cs b/Snittlistan.Web/Models/UpdateRosterEmail_State.cs index 29cb31c0..eef1b030 100644 --- a/Snittlistan.Web/Models/UpdateRosterEmail_State.cs +++ b/Snittlistan.Web/Models/UpdateRosterEmail_State.cs @@ -18,7 +18,13 @@ public UpdateRosterEmail_State( int turn, Uri rosterLink, Uri userProfileLink, - bool needsAccept) + bool needsAccept, + string homeTeamAlias, + string awayTeamAlias, + string hallName, + int oilProfileId, + string oilProfileName, + DateTime matchDate) : base(OwnerEmail, playerEmail, OwnerEmail, "Uttagning har uppdaterats") { PlayerEmail = playerEmail; @@ -32,6 +38,12 @@ public UpdateRosterEmail_State( RosterLink = rosterLink; UserProfileLink = userProfileLink; NeedsAccept = needsAccept; + HomeTeamAlias = homeTeamAlias; + AwayTeamAlias = awayTeamAlias; + HallName = hallName; + OilProfileId = oilProfileId; + OilProfileName = oilProfileName; + MatchDate = matchDate; } public string PlayerEmail { get; } @@ -56,6 +68,18 @@ public UpdateRosterEmail_State( public bool NeedsAccept { get; } + public string HomeTeamAlias { get; } + + public string AwayTeamAlias { get; } + + public string HallName { get; } + + public int OilProfileId { get; } + + public string OilProfileName { get; } + + public DateTime MatchDate { get; } + public override Email CreateEmail() { return new UpdateRosterEmail( @@ -69,6 +93,12 @@ public override Email CreateEmail() Turn, RosterLink, UserProfileLink, - NeedsAccept); + NeedsAccept, + HomeTeamAlias, + AwayTeamAlias, + HallName, + OilProfileId, + OilProfileName, + MatchDate); } } diff --git a/Snittlistan.Web/Snittlistan.Web.csproj b/Snittlistan.Web/Snittlistan.Web.csproj index 0d8f90e1..e77c3179 100644 --- a/Snittlistan.Web/Snittlistan.Web.csproj +++ b/Snittlistan.Web/Snittlistan.Web.csproj @@ -159,6 +159,8 @@ + + diff --git a/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml b/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml index 772863af..99b9bb30 100644 --- a/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml +++ b/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml @@ -32,13 +32,15 @@ Content-Type: text/html; charset=utf-8

Hemmalag
-
@Model.HomeTeamName
+
@Model.HomeTeamAlias
Bortalag
-
@Model.AwayTeamName
-
Datum
-
@Model.MatchDate
-
Online scoring
-
@Model.OnlineScoringLink
+
@Model.AwayTeamAlias
+
Plats
+
@Model.HallName
+
Oljeprofil
+
@Model.OilProfileName
+
När
+
@Model.MatchDate.ToString("", new System.Globalization.CultureInfo("sv-SE"))
Bord
diff --git a/Snittlistan.Web/Web.config b/Snittlistan.Web/Web.config index 3a1880f2..d4a4034f 100644 --- a/Snittlistan.Web/Web.config +++ b/Snittlistan.Web/Web.config @@ -17,7 +17,7 @@ - + From 3d699e0682b34a1e123d7f8d44985d490b4b96c0 Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Wed, 16 Mar 2022 23:46:58 +0100 Subject: [PATCH 4/9] almost there --- .../Domain/MatchResult_MatchCommentary.cs | 1 + .../V2/Controllers/Api/TaskController.cs | 36 ------------------- Snittlistan.Web/Commands/CommandExecutor.cs | 8 +++-- .../Controllers/AbstractController.cs | 1 + .../Infrastructure/HandlerContext.cs | 1 + Snittlistan.Web/TaskHandlers/TaskHandler.cs | 1 + 6 files changed, 10 insertions(+), 38 deletions(-) diff --git a/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs b/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs index 4daecc4a..2ca29492 100644 --- a/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs +++ b/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs @@ -176,6 +176,7 @@ await Transact(async session => Mock.Of(MockBehavior.Strict)); CommandExecutor commandExecutor = new( compositionRoot, + Databases, compositionRoot.CorrelationId, null, string.Empty); diff --git a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs index c818ca1f..9ecc3f41 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/Api/TaskController.cs @@ -19,42 +19,6 @@ namespace Snittlistan.Web.Areas.V2.Controllers.Api; [OnlyLocalAllowed] public class TaskController : AbstractApiController { - public async Task Get() - { - //var query = - // from m in CompositionRoot.Databases.Bits.Match - // where m.MatchId == 6422 - // select new - // { - // m.ExternalMatchId, - // HomeTeamName = m.HomeTeamRef.TeamName, - // AwayTeamName = m.AwayTeamRef.TeamName, - // m.MatchDateTime, - // m.HallRef.HallRefId, - // HallRef_HallName = m.HallRef.HallName, - // HallName = m.HallRef.Hall!.HallName ?? "" - // }; - var result = await Transact(async databases => - { - var query = - from mhi in databases.Bits.VMatchHeadInfo - select new - { - mhi.ExternalMatchId, - mhi.HomeTeamName, - mhi.HomeTeamAlias, - mhi.AwayTeamName, - mhi.AwayTeamAlias, - mhi.OilProfileName, - mhi.HallName - }; - return await query - .FirstOrDefaultAsync(); - }); - - return Ok(result); - } - public async Task Post(TaskRequest request) { Logger.InfoFormat("Received task {taskJson}", request.TaskJson); diff --git a/Snittlistan.Web/Commands/CommandExecutor.cs b/Snittlistan.Web/Commands/CommandExecutor.cs index a1a43295..33d8ecc8 100644 --- a/Snittlistan.Web/Commands/CommandExecutor.cs +++ b/Snittlistan.Web/Commands/CommandExecutor.cs @@ -1,6 +1,7 @@ #nullable enable using Snittlistan.Web.Infrastructure; +using Snittlistan.Web.Infrastructure.Database; using System.Reflection; namespace Snittlistan.Web.Commands; @@ -8,17 +9,20 @@ namespace Snittlistan.Web.Commands; public class CommandExecutor { private readonly CompositionRoot compositionRoot; + private readonly Databases databases; private readonly Guid correlationId; private readonly Guid? causationId; private readonly string createdBy; public CommandExecutor( CompositionRoot compositionRoot, + Databases databases, Guid correlationId, Guid? causationId, string createdBy) { this.compositionRoot = compositionRoot; + this.databases = databases; this.correlationId = correlationId; this.causationId = causationId; this.createdBy = createdBy; @@ -32,14 +36,14 @@ public async Task Execute(TCommand command) object handler = compositionRoot.Kernel.Resolve(handlerType); TaskPublisher taskPublisher = new( compositionRoot.CurrentTenant, - compositionRoot.Databases, + databases, compositionRoot.MsmqFactory, correlationId, causationId); IHandlerContext handlerContext = (IHandlerContext)Activator.CreateInstance( typeof(HandlerContext<>).MakeGenericType(command.GetType()), compositionRoot, - compositionRoot.Databases, + databases, command, compositionRoot.CurrentTenant, correlationId, diff --git a/Snittlistan.Web/Controllers/AbstractController.cs b/Snittlistan.Web/Controllers/AbstractController.cs index 12c5d5e9..618a9621 100644 --- a/Snittlistan.Web/Controllers/AbstractController.cs +++ b/Snittlistan.Web/Controllers/AbstractController.cs @@ -109,6 +109,7 @@ private CommandExecutor CreateCommandExecutor() { return new CommandExecutor( CompositionRoot, + CompositionRoot.Databases, CompositionRoot.CorrelationId, null, User.CustomIdentity.Name); diff --git a/Snittlistan.Web/Infrastructure/HandlerContext.cs b/Snittlistan.Web/Infrastructure/HandlerContext.cs index 4dfcb017..a101667b 100644 --- a/Snittlistan.Web/Infrastructure/HandlerContext.cs +++ b/Snittlistan.Web/Infrastructure/HandlerContext.cs @@ -44,6 +44,7 @@ public async Task ExecuteCommand(TCommand command) { CommandExecutor commandExecutor = new( compositionRoot, + Databases, CorrelationId, CausationId, "system"); diff --git a/Snittlistan.Web/TaskHandlers/TaskHandler.cs b/Snittlistan.Web/TaskHandlers/TaskHandler.cs index c784b8e1..43e8a945 100644 --- a/Snittlistan.Web/TaskHandlers/TaskHandler.cs +++ b/Snittlistan.Web/TaskHandlers/TaskHandler.cs @@ -18,6 +18,7 @@ public async Task Handle(HandlerContext context) TCommand command = CreateCommand(context.Payload); CommandExecutor commandExecutor = new( CompositionRoot, + CompositionRoot.Databases, context.CorrelationId, context.CausationId, "system"); From b6d80e2f6e63ef9b5f43375f48692a32be3b5f2f Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Wed, 16 Mar 2022 23:53:09 +0100 Subject: [PATCH 5/9] better date --- Snittlistan.Web/Views/Emails/UpdateRoster.cshtml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml b/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml index 99b9bb30..e9a2c80c 100644 --- a/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml +++ b/Snittlistan.Web/Views/Emails/UpdateRoster.cshtml @@ -40,7 +40,13 @@ Content-Type: text/html; charset=utf-8
Oljeprofil
@Model.OilProfileName
När
-
@Model.MatchDate.ToString("", new System.Globalization.CultureInfo("sv-SE"))
+
+ + + +
From 37a8165a6754e9afc1dc28163df0897ee3e9deab Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Thu, 17 Mar 2022 00:06:11 +0100 Subject: [PATCH 6/9] settings for delay --- .../V2/Controllers/AdminTasksController.cs | 22 ++++++++++++-- .../Areas/V2/Controllers/RosterController.cs | 9 +++--- .../Areas/V2/Views/AdminTasks/Features.cshtml | 9 ++++++ .../V2/Views/AdminTasks/Features.generated.cs | 30 +++++++++++++++++-- .../CreateRosterMailCommandHandler.cs | 4 ++- .../Commands/UpdateFeaturesCommandHandler.cs | 10 +++++-- .../Infrastructure/CompositionRoot.cs | 5 ++-- Snittlistan.Web/Models/TenantFeatures.cs | 7 ++++- 8 files changed, 80 insertions(+), 16 deletions(-) diff --git a/Snittlistan.Web/Areas/V2/Controllers/AdminTasksController.cs b/Snittlistan.Web/Areas/V2/Controllers/AdminTasksController.cs index 5c67a7a4..38c6c8f5 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/AdminTasksController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/AdminTasksController.cs @@ -12,6 +12,7 @@ using Snittlistan.Web.Infrastructure.Indexes; using Snittlistan.Web.Models; using Snittlistan.Web.Services; +using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Web; using System.Web.Mvc; @@ -271,17 +272,19 @@ await CompositionRoot.Databases.Snittlistan.KeyValueProperties.SingleOrDefaultAs public async Task Features(TenantFeaturesViewModel vm) { UpdateFeaturesCommandHandler.Command command = new( - vm.RosterMailEnabled); + vm.RosterMailEnabled, + vm.RosterMailDelayMinutes); await ExecuteCommand(command); return RedirectToAction("Index"); } - public class TenantFeaturesViewModel + public class TenantFeaturesViewModel : IValidatableObject { public TenantFeaturesViewModel(TenantFeatures tenantFeatures) { RosterMailEnabled = tenantFeatures.RosterMailEnabled; + RosterMailDelayMinutes = tenantFeatures.RosterMailDelayMinutes; } public TenantFeaturesViewModel() @@ -289,5 +292,20 @@ public TenantFeaturesViewModel() } public bool RosterMailEnabled { get; set; } + + public int RosterMailDelayMinutes { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (RosterMailDelayMinutes < 1) + { + yield return new("Must be at least 1", new[] { nameof(RosterMailDelayMinutes) }); + } + + if (RosterMailDelayMinutes > 60) + { + yield return new("Must be at most 60", new[] { nameof(RosterMailDelayMinutes) }); + } + } } } diff --git a/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs b/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs index 9cc361e7..e1b70e16 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs @@ -377,7 +377,7 @@ public ActionResult Print( } [Authorize(Roles = WebsiteRoles.Uk.UkTasks)] - public async Task EditPlayers(string rosterId) + public ActionResult EditPlayers(string rosterId) { Roster roster = CompositionRoot.DocumentSession .Include(r => r.Players) @@ -392,7 +392,6 @@ public async Task EditPlayers(string rosterId) .Where(p => p.PlayerStatus == Player.Status.Active) .ToList(); - TenantFeatures? features = await CompositionRoot.GetFeatures(); EditRosterPlayersViewModel vm = new() { RosterViewModel = CompositionRoot.DocumentSession.LoadRosterViewModel(roster), @@ -407,7 +406,7 @@ public async Task EditPlayers(string rosterId, RosterPlayersViewMo { if (ModelState.IsValid == false) { - return await EditPlayers(rosterId); + return EditPlayers(rosterId); } Roster roster = CompositionRoot.DocumentSession.Load(rosterId); @@ -488,8 +487,8 @@ public async Task EditPlayers(string rosterId, RosterPlayersViewMo break; } - TenantFeatures? features = await CompositionRoot.GetFeatures(); - if ((features?.RosterMailEnabled ?? false) == false) + TenantFeatures features = await CompositionRoot.GetFeatures(); + if (features.RosterMailEnabled) { Logger.Info("RosterMailEnabled evaluated to false"); break; diff --git a/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.cshtml b/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.cshtml index 7555c252..e70483bb 100644 --- a/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.cshtml +++ b/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.cshtml @@ -20,6 +20,15 @@ +
+ @Html.LabelFor(x => x.RosterMailDelayMinutes, new { @class = "control-label" }) +
+ @Html.TextBoxFor(x => x.RosterMailDelayMinutes) + + Antal minuter att vänta innan laguttagningarna skickas ut per mail, efter en uppdatering. + +
+
diff --git a/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.generated.cs b/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.generated.cs index 9592174f..9ab864e7 100644 --- a/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.generated.cs +++ b/Snittlistan.Web/Areas/V2/Views/AdminTasks/Features.generated.cs @@ -87,6 +87,32 @@ public override void Execute() +WriteLiteral("
\r\n "); + + + + #line 24 "..\..\Areas\V2\Views\AdminTasks\Features.cshtml" + Write(Html.LabelFor(x => x.RosterMailDelayMinutes, new { @class = "control-label" })); + + + #line default + #line hidden +WriteLiteral("\r\n
\r\n "); + + + + #line 26 "..\..\Areas\V2\Views\AdminTasks\Features.cshtml" + Write(Html.TextBoxFor(x => x.RosterMailDelayMinutes)); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n Antal mi" + +"nuter att vänta innan laguttagningarna skickas ut per mail, efter en uppdatering" + +".\r\n \r\n
\r\n
\r\n"); + + + WriteLiteral("
\r\n
\r\n" + " \r\n ( x => x with { - RosterMailEnabled = context.Payload.RosterMailEnabled + RosterMailEnabled = context.Payload.RosterMailEnabled, + RosterMailDelayMinutes = context.Payload.RosterMailDelayMinutes }, x => Logger.InfoFormat("before: {@x}", x), x => Logger.InfoFormat("after: {@x}", x)); @@ -36,5 +39,6 @@ await CompositionRoot.Databases.Snittlistan.KeyValueProperties.SingleOrDefaultAs } public record Command( - bool RosterMailEnabled); + bool RosterMailEnabled, + int RosterMailDelayMinutes); } diff --git a/Snittlistan.Web/Infrastructure/CompositionRoot.cs b/Snittlistan.Web/Infrastructure/CompositionRoot.cs index 0b00da01..e64686b5 100644 --- a/Snittlistan.Web/Infrastructure/CompositionRoot.cs +++ b/Snittlistan.Web/Infrastructure/CompositionRoot.cs @@ -37,11 +37,12 @@ public Guid CorrelationId } } - public async Task GetFeatures() + public async Task GetFeatures() { KeyValueProperty? settingsProperty = await Databases.Snittlistan.KeyValueProperties.SingleOrDefaultAsync( x => x.Key == TenantFeatures.Key && x.TenantId == CurrentTenant.TenantId); - return settingsProperty?.Value as TenantFeatures; + return settingsProperty?.Value as TenantFeatures + ?? TenantFeatures.Default; } } diff --git a/Snittlistan.Web/Models/TenantFeatures.cs b/Snittlistan.Web/Models/TenantFeatures.cs index da828174..171920df 100644 --- a/Snittlistan.Web/Models/TenantFeatures.cs +++ b/Snittlistan.Web/Models/TenantFeatures.cs @@ -3,7 +3,12 @@ namespace Snittlistan.Web.Models; public record TenantFeatures( - bool RosterMailEnabled) + bool RosterMailEnabled, + int RosterMailDelayMinutes) { public static string Key { get; } = "TenantFeatures"; + + public static TenantFeatures Default = new( + true, + 10); }; From 73537591ccd2949ebac92cc7ce73e753c210b4fa Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Thu, 17 Mar 2022 09:35:49 +0100 Subject: [PATCH 7/9] tracing --- Snittlistan.Web/Commands/CommandExecutor.cs | 3 +++ .../Commands/CreateRosterMailCommandHandler.cs | 3 ++- Snittlistan.Web/Infrastructure/TaskPublisher.cs | 8 +++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Snittlistan.Web/Commands/CommandExecutor.cs b/Snittlistan.Web/Commands/CommandExecutor.cs index 33d8ecc8..5be8ac76 100644 --- a/Snittlistan.Web/Commands/CommandExecutor.cs +++ b/Snittlistan.Web/Commands/CommandExecutor.cs @@ -1,5 +1,6 @@ #nullable enable +using NLog; using Snittlistan.Web.Infrastructure; using Snittlistan.Web.Infrastructure.Database; using System.Reflection; @@ -8,6 +9,7 @@ namespace Snittlistan.Web.Commands; public class CommandExecutor { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly CompositionRoot compositionRoot; private readonly Databases databases; private readonly Guid correlationId; @@ -31,6 +33,7 @@ public CommandExecutor( public async Task Execute(TCommand command) where TCommand : class { + Logger.Info("execute command {@command}", command); Type handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType()); MethodInfo handleMethod = handlerType.GetMethod(nameof(ICommandHandler.Handle)); object handler = compositionRoot.Kernel.Resolve(handlerType); diff --git a/Snittlistan.Web/Commands/CreateRosterMailCommandHandler.cs b/Snittlistan.Web/Commands/CreateRosterMailCommandHandler.cs index 4a72494b..4c623d29 100644 --- a/Snittlistan.Web/Commands/CreateRosterMailCommandHandler.cs +++ b/Snittlistan.Web/Commands/CreateRosterMailCommandHandler.cs @@ -16,9 +16,10 @@ from rosterMail in CompositionRoot.Databases.Snittlistan.RosterMails && rosterMail.PublishedDate == null select rosterMail.RosterKey; string[] rosterIds = await query.ToArrayAsync(); + Logger.InfoFormat("roster mails found: {@rosterIds}", rosterIds); if (rosterIds.Any() == false) { - TenantFeatures? features = await CompositionRoot.GetFeatures(); + TenantFeatures features = await CompositionRoot.GetFeatures(); _ = CompositionRoot.Databases.Snittlistan.RosterMails.Add( new(context.Payload.RosterKey)); PublishRosterMailsTask task = new( diff --git a/Snittlistan.Web/Infrastructure/TaskPublisher.cs b/Snittlistan.Web/Infrastructure/TaskPublisher.cs index 10ef3523..663dfc17 100644 --- a/Snittlistan.Web/Infrastructure/TaskPublisher.cs +++ b/Snittlistan.Web/Infrastructure/TaskPublisher.cs @@ -33,6 +33,7 @@ public TaskPublisher( public void PublishTask(TaskBase task, string createdBy) { + Logger.Info("{createdBy} publish task {@task}", createdBy, task); PublishedTask publishedTask = databases.Snittlistan.PublishedTasks.Add( PublishedTask.CreateImmediate( task, @@ -112,6 +113,11 @@ void DoPublishMessage(Tenant tenant, PublishedTask publishedTask) public void PublishDelayedTask(TaskBase task, DateTime publishDate, string createdBy) { + Logger.Info( + "{createdBy} publish delayed (@{publishDate}) task {@task}", + createdBy, + publishDate, + task); PublishedTask publishedTask = databases.Snittlistan.PublishedTasks.Add( PublishedTask.CreateDelayed( task, @@ -120,6 +126,6 @@ public void PublishDelayedTask(TaskBase task, DateTime publishDate, string creat causationId, publishDate, createdBy)); - Logger.Info("added delayed task: {@publishedTask}", publishedTask); + Logger.Info("added delayed task {@publishedTask}", publishedTask); } } From 89785032d241cd2c7ba1d55d1f535c6bbd93fe2a Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Thu, 17 Mar 2022 10:01:31 +0100 Subject: [PATCH 8/9] tracing --- .../Domain/MatchResult_MatchCommentary.cs | 4 +++- .../Infrastructure/CompositionRoot.cs | 24 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs b/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs index 2ca29492..802cd45b 100644 --- a/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs +++ b/Snittlistan.Test/Domain/MatchResult_MatchCommentary.cs @@ -1,5 +1,6 @@ #nullable enable +using Castle.Core.Logging; using EventStoreLite; using Moq; using NUnit.Framework; @@ -173,7 +174,8 @@ await Transact(async session => Container.Resolve(), CurrentTenant, Container.Resolve(), - Mock.Of(MockBehavior.Strict)); + Mock.Of(MockBehavior.Strict), + NullLogger.Instance); CommandExecutor commandExecutor = new( compositionRoot, Databases, diff --git a/Snittlistan.Web/Infrastructure/CompositionRoot.cs b/Snittlistan.Web/Infrastructure/CompositionRoot.cs index e64686b5..67f6863d 100644 --- a/Snittlistan.Web/Infrastructure/CompositionRoot.cs +++ b/Snittlistan.Web/Infrastructure/CompositionRoot.cs @@ -1,5 +1,6 @@ #nullable enable +using Castle.Core.Logging; using Castle.MicroKernel; using EventStoreLite; using Postal; @@ -20,7 +21,8 @@ public record CompositionRoot( EventStore EventStore, Tenant CurrentTenant, IEmailService EmailService, - IBitsClient BitsClient) + IBitsClient BitsClient, + ILogger Logger) { public Guid CorrelationId { @@ -42,7 +44,23 @@ public async Task GetFeatures() KeyValueProperty? settingsProperty = await Databases.Snittlistan.KeyValueProperties.SingleOrDefaultAsync( x => x.Key == TenantFeatures.Key && x.TenantId == CurrentTenant.TenantId); - return settingsProperty?.Value as TenantFeatures - ?? TenantFeatures.Default; + do + { + if (settingsProperty is null) + { + Logger.Info("no tenant features found"); + break; + } + + if (settingsProperty.Value is TenantFeatures tenantFeatures) + { + Logger.InfoFormat("found tenant features {@tenantFeatures}", tenantFeatures); + return tenantFeatures; + } + } + while (false); + + Logger.Warn("no tenant features found, or unusable"); + return TenantFeatures.Default; } } From a22dfa3b3f4a73e92d1323a239f24bffceb9e2aa Mon Sep 17 00:00:00 2001 From: Daniel Lidstrom Date: Thu, 17 Mar 2022 10:10:56 +0100 Subject: [PATCH 9/9] oups --- Snittlistan.Web/Areas/V2/Controllers/RosterController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs b/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs index e1b70e16..eb1b68c7 100644 --- a/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs +++ b/Snittlistan.Web/Areas/V2/Controllers/RosterController.cs @@ -488,7 +488,7 @@ public async Task EditPlayers(string rosterId, RosterPlayersViewMo } TenantFeatures features = await CompositionRoot.GetFeatures(); - if (features.RosterMailEnabled) + if (features.RosterMailEnabled == false) { Logger.Info("RosterMailEnabled evaluated to false"); break;