From 5b02f2d06f1aa92c6f8d9d648e3d1356aea5c2dd Mon Sep 17 00:00:00 2001 From: leoslopez Date: Thu, 29 Feb 2024 12:16:49 -0300 Subject: [PATCH 1/9] feat: get timezone offset --- .../Entities/ContactPoliciesTimeRestriction.cs | 1 + .../ContactPoliciesSettingsRepository.cs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Doppler.ContactPolicies.Data.Access/Entities/ContactPoliciesTimeRestriction.cs b/Doppler.ContactPolicies.Data.Access/Entities/ContactPoliciesTimeRestriction.cs index 56f84c9..10dd46b 100644 --- a/Doppler.ContactPolicies.Data.Access/Entities/ContactPoliciesTimeRestriction.cs +++ b/Doppler.ContactPolicies.Data.Access/Entities/ContactPoliciesTimeRestriction.cs @@ -7,5 +7,6 @@ public sealed class ContactPoliciesTimeRestriction public int? HourFrom { get; set; } public int? HourTo { get; set; } public bool WeekdaysEnabled { get; set; } + public int TimeZoneOffsetMinutes { get; set; } } } diff --git a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs index b997fe7..5ebf128 100644 --- a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs +++ b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs @@ -55,9 +55,11 @@ public async Task GetContactPoliciesTimeRestrict ucptr.HourFrom [HourFrom], ucptr.HourTo [HourTo], ucptr.WeekdaysEnabled [WeekdaysEnabled], - u.Email [AccountName] + u.Email [AccountName], + utz.Offset [TimeZoneOffsetMinutes] from [User] u left join [UserContactPolicyTimeRestriction] ucptr on u.IdUser = ucptr.IdUser + left join [UserTimeZone] utz on u.IdUserTimeZone = utz.IdUserTimeZone where u.IdUser = @IdUser;"; var queryParams = new { IdUser = idUser }; From 67ef950d0cdbc41a15d763c702bbf75daba154f1 Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 10:05:30 -0300 Subject: [PATCH 2/9] feat: add method to transform hour properly when the hour comes from ui, it will be transformed to UTC. And when it comes from DB, it will be transformed according to the user timezone. --- .../Extensions/MapperExtension.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs index b48e710..a35b87f 100644 --- a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs +++ b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs @@ -1,5 +1,6 @@ using Doppler.ContactPolicies.Business.Logic.DTO; using Doppler.ContactPolicies.Data.Access.Entities; +using System; using System.Collections.Generic; using System.Linq; @@ -71,5 +72,31 @@ public static ContactPoliciesTimeRestriction ToDao( WeekdaysEnabled = contactPoliciesTimeRestrictionDto.WeekdaysEnabled }; } + + private static int? ApplyHourOffset(int? hour, int offset, bool convertHourToUTC) + { + if (!hour.HasValue || offset == 0) + { + return hour; + } + + DateTime now = DateTime.Now; + DateTime auxDate = new DateTime(now.Year, now.Month, now.Day, hour.Value, 0, 0); + + int offsetMinutes = offset * (convertHourToUTC ? -1 : 1); + DateTime resultDate = auxDate.AddMinutes(offsetMinutes); + + var hour24 = resultDate.ToString("HH"); + + // when the offset is not an exact quantity of hours, for example: (GMT+09:30) Adelaide. + if (resultDate.Minute > 0) + { + return (int.Parse(hour24) + (convertHourToUTC ? 1 : 0)) % 24; + } + else + { + return int.Parse(hour24); + } + } } } From 29426413babb4fd30fbdd2dcf878f99a7c4d21ee Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 10:08:22 -0300 Subject: [PATCH 3/9] feat: transform hours on the GET request --- .../Extensions/MapperExtension.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs index a35b87f..a006b5d 100644 --- a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs +++ b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs @@ -50,8 +50,8 @@ public static ContactPoliciesTimeRestrictionDto ToDto( return new ContactPoliciesTimeRestrictionDto { TimeSlotEnabled = timeRestriction.TimeSlotEnabled, - HourFrom = timeRestriction.HourFrom, - HourTo = timeRestriction.HourTo, + HourFrom = ApplyHourOffset(timeRestriction.HourFrom, timeRestriction.TimeZoneOffsetMinutes, false), + HourTo = ApplyHourOffset(timeRestriction.HourTo, timeRestriction.TimeZoneOffsetMinutes, false), WeekdaysEnabled = timeRestriction.WeekdaysEnabled }; } From 7d95e7e5e795fb8071ef5f59b93b2c15e73eeb8d Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 10:09:43 -0300 Subject: [PATCH 4/9] feat: add method to obtain offset minutes on update --- .../ContactPoliciesSettingsRepository.cs | 15 +++++++++++++++ .../IContactPoliciesSettingsRepository.cs | 1 + 2 files changed, 16 insertions(+) diff --git a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs index 5ebf128..8eaeb3d 100644 --- a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs +++ b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs @@ -160,6 +160,21 @@ from [UserContactPolicyTimeRestriction] ucptr return await connection.QueryFirstOrDefaultAsync(query, queryParams); } + public async Task GetTimezoneOffsetMinutes(int idUser) + { + using var connection = _databaseConnectionFactory.GetConnection(); + const string query = + @"select + utz.Offset + from [User] u + left join [UserTimeZone] utz on u.IdUserTimeZone = utz.IdUserTimeZone + where u.IdUser = @IdUser"; + + var queryParams = new { IdUser = idUser }; + var result = await connection.QueryFirstOrDefaultAsync(query, queryParams); + return result?? 0; + } + #endregion } } diff --git a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/IContactPoliciesSettingsRepository.cs b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/IContactPoliciesSettingsRepository.cs index b2a7308..c7c5bbf 100644 --- a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/IContactPoliciesSettingsRepository.cs +++ b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/IContactPoliciesSettingsRepository.cs @@ -9,5 +9,6 @@ public interface IContactPoliciesSettingsRepository Task UpdateContactPoliciesSettingsAsync(int idUser, Entities.ContactPoliciesSettings contactPoliciesToInsert, ContactPoliciesTimeRestriction contactPoliciesTimeRestrictionToInsert); Task GetIdUserByAccountName(string accountName); Task GetContactPoliciesTimeRestrictionByIdUserAsync(int idUser); + Task GetTimezoneOffsetMinutes(int idUser); } } From 5ce2331539604b4e3af9bd86c7c911733aa75df1 Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 10:10:19 -0300 Subject: [PATCH 5/9] feat: transform hours on the PUT request --- .../Extensions/MapperExtension.cs | 7 ++++--- .../Services/ContactPoliciesService.cs | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs index a006b5d..9c546aa 100644 --- a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs +++ b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs @@ -57,7 +57,8 @@ public static ContactPoliciesTimeRestrictionDto ToDto( } public static ContactPoliciesTimeRestriction ToDao( - this ContactPoliciesTimeRestrictionDto contactPoliciesTimeRestrictionDto) + this ContactPoliciesTimeRestrictionDto contactPoliciesTimeRestrictionDto, + int timezoneOffsetMinutes) { if (contactPoliciesTimeRestrictionDto == null) { @@ -67,8 +68,8 @@ public static ContactPoliciesTimeRestriction ToDao( return new ContactPoliciesTimeRestriction { TimeSlotEnabled = contactPoliciesTimeRestrictionDto.TimeSlotEnabled, - HourFrom = contactPoliciesTimeRestrictionDto.HourFrom, - HourTo = contactPoliciesTimeRestrictionDto.HourTo, + HourFrom = ApplyHourOffset(contactPoliciesTimeRestrictionDto.HourFrom, timezoneOffsetMinutes, true), + HourTo = ApplyHourOffset(contactPoliciesTimeRestrictionDto.HourTo, timezoneOffsetMinutes, true), WeekdaysEnabled = contactPoliciesTimeRestrictionDto.WeekdaysEnabled }; } diff --git a/Doppler.ContactPolicies.Business.Logic/Services/ContactPoliciesService.cs b/Doppler.ContactPolicies.Business.Logic/Services/ContactPoliciesService.cs index 52e82ef..28ddffa 100644 --- a/Doppler.ContactPolicies.Business.Logic/Services/ContactPoliciesService.cs +++ b/Doppler.ContactPolicies.Business.Logic/Services/ContactPoliciesService.cs @@ -28,7 +28,8 @@ public async Task GetContactPoliciesSettingsByIdUser public async Task UpdateContactPoliciesSettingsAsync(int idUser, ContactPoliciesSettingsDto contactPoliciesSettings) { var contactPoliciesToUpdate = contactPoliciesSettings.ToDao(); - var timeRestrictionToUpdate = contactPoliciesSettings.TimeRestriction.ToDao(); + var timezoneOffsetMinutes = await _contactPoliciesSettingsRepository.GetTimezoneOffsetMinutes(idUser); + var timeRestrictionToUpdate = contactPoliciesSettings.TimeRestriction.ToDao(timezoneOffsetMinutes); await _contactPoliciesSettingsRepository.UpdateContactPoliciesSettingsAsync(idUser, contactPoliciesToUpdate, timeRestrictionToUpdate); } From 85994874512c504a259f92cfb13e113d25374043 Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 10:28:28 -0300 Subject: [PATCH 6/9] refactor: add enum to clarify hour conversion logic --- .../Extensions/MapperExtension.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs index 9c546aa..99a4e91 100644 --- a/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs +++ b/Doppler.ContactPolicies.Business.Logic/Extensions/MapperExtension.cs @@ -6,6 +6,12 @@ namespace Doppler.ContactPolicies.Business.Logic.Extensions { + public enum TimeZoneConversionEnum + { + CONVERT_TO_UTC, + CONVERT_TO_USERTIMEZONE, + } + public static class MapperExtension { public static ContactPoliciesSettingsDto ToDto( @@ -50,8 +56,8 @@ public static ContactPoliciesTimeRestrictionDto ToDto( return new ContactPoliciesTimeRestrictionDto { TimeSlotEnabled = timeRestriction.TimeSlotEnabled, - HourFrom = ApplyHourOffset(timeRestriction.HourFrom, timeRestriction.TimeZoneOffsetMinutes, false), - HourTo = ApplyHourOffset(timeRestriction.HourTo, timeRestriction.TimeZoneOffsetMinutes, false), + HourFrom = ApplyHourOffset(timeRestriction.HourFrom, timeRestriction.TimeZoneOffsetMinutes, TimeZoneConversionEnum.CONVERT_TO_USERTIMEZONE), + HourTo = ApplyHourOffset(timeRestriction.HourTo, timeRestriction.TimeZoneOffsetMinutes, TimeZoneConversionEnum.CONVERT_TO_USERTIMEZONE), WeekdaysEnabled = timeRestriction.WeekdaysEnabled }; } @@ -68,13 +74,13 @@ public static ContactPoliciesTimeRestriction ToDao( return new ContactPoliciesTimeRestriction { TimeSlotEnabled = contactPoliciesTimeRestrictionDto.TimeSlotEnabled, - HourFrom = ApplyHourOffset(contactPoliciesTimeRestrictionDto.HourFrom, timezoneOffsetMinutes, true), - HourTo = ApplyHourOffset(contactPoliciesTimeRestrictionDto.HourTo, timezoneOffsetMinutes, true), + HourFrom = ApplyHourOffset(contactPoliciesTimeRestrictionDto.HourFrom, timezoneOffsetMinutes, TimeZoneConversionEnum.CONVERT_TO_UTC), + HourTo = ApplyHourOffset(contactPoliciesTimeRestrictionDto.HourTo, timezoneOffsetMinutes, TimeZoneConversionEnum.CONVERT_TO_UTC), WeekdaysEnabled = contactPoliciesTimeRestrictionDto.WeekdaysEnabled }; } - private static int? ApplyHourOffset(int? hour, int offset, bool convertHourToUTC) + private static int? ApplyHourOffset(int? hour, int offset, TimeZoneConversionEnum conversion) { if (!hour.HasValue || offset == 0) { @@ -84,7 +90,7 @@ public static ContactPoliciesTimeRestriction ToDao( DateTime now = DateTime.Now; DateTime auxDate = new DateTime(now.Year, now.Month, now.Day, hour.Value, 0, 0); - int offsetMinutes = offset * (convertHourToUTC ? -1 : 1); + int offsetMinutes = offset * (conversion == TimeZoneConversionEnum.CONVERT_TO_UTC ? -1 : 1); DateTime resultDate = auxDate.AddMinutes(offsetMinutes); var hour24 = resultDate.ToString("HH"); @@ -92,7 +98,7 @@ public static ContactPoliciesTimeRestriction ToDao( // when the offset is not an exact quantity of hours, for example: (GMT+09:30) Adelaide. if (resultDate.Minute > 0) { - return (int.Parse(hour24) + (convertHourToUTC ? 1 : 0)) % 24; + return (int.Parse(hour24) + (conversion == TimeZoneConversionEnum.CONVERT_TO_UTC ? 1 : 0)) % 24; } else { From d1da682379197abc37048c301588bef4f17a9d3d Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 14:15:02 -0300 Subject: [PATCH 7/9] fix: unit test --- .../ContactPoliciesServiceTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs b/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs index 2e2ab5b..1bc5941 100644 --- a/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs +++ b/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs @@ -25,6 +25,8 @@ public async Task .Create(); var expectedTimeRestriction = fixture.Build() .With(x => x.AccountName, accountName) + .With(x => x.HourFrom, 1) + .With(x => x.HourTo, 2) .Create(); var contactPoliciesRepositoryMock = new Mock(); From e2f6046fa0a2f1e2959e1d0e0e1f2c62b883edc5 Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 17:31:04 -0300 Subject: [PATCH 8/9] test: add unit tests --- .../ContactPoliciesServiceTest.cs | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) diff --git a/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs b/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs index 1bc5941..8e709ca 100644 --- a/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs +++ b/Doppler.ContactPolicies.Business.Logic.Test/ContactPoliciesServiceTest.cs @@ -46,6 +46,147 @@ public async Task Assert.True(actual.Active); } + [Theory] + [InlineData(22, 23, 19, 20, -180)] + [InlineData(1, 2, 22, 23, -180)] + [InlineData(22, 23, 1, 2, 180)] + [InlineData(1, 2, 4, 5, 180)] + public async Task + GetContactPoliciesSettings_Should_Convert_TimeRestrictionHours_To_UserTimeZone_When_OffsetMinutes_ExactHours + ( + int hourFromInDB, + int hourToInDB, + int hourFromForResponse, + int hourToFoResponse, + int offsetMinutes + ) + { + // Arrange + var fixture = new Fixture(); + string accountName = "prueba@makingsense.com"; + var expected = fixture.Build() + .With(x => x.AccountName, accountName) + .With(x => x.Active, true) + .Create(); + var expectedTimeRestriction = fixture.Build() + .With(x => x.AccountName, accountName) + .With(x => x.HourFrom, hourFromInDB) + .With(x => x.HourTo, hourToInDB) + .With(x => x.TimeZoneOffsetMinutes, offsetMinutes) + .Create(); + + var contactPoliciesRepositoryMock = new Mock(); + contactPoliciesRepositoryMock.Setup(x => x.GetContactPoliciesSettingsByIdUserAsync(It.IsAny())) + .ReturnsAsync(expected).Verifiable(); + contactPoliciesRepositoryMock.Setup(x => x.GetContactPoliciesTimeRestrictionByIdUserAsync(It.IsAny())) + .ReturnsAsync(expectedTimeRestriction).Verifiable(); + + var contactPoliciesSut = new ContactPoliciesService(contactPoliciesRepositoryMock.Object); + + // Act + var actual = await contactPoliciesSut.GetContactPoliciesSettingsByIdUserAsync(It.IsAny()); + + // Assert + contactPoliciesRepositoryMock.Verify(); + Assert.Equal(actual.AccountName, expected.AccountName); + Assert.True(actual.Active); + Assert.Equal(actual.TimeRestriction.HourFrom, hourFromForResponse); + Assert.Equal(actual.TimeRestriction.HourTo, hourToFoResponse); + } + + [Theory] + [InlineData(22, 23, 19, 20, -150)] + [InlineData(1, 2, 22, 23, -150)] + [InlineData(22, 23, 0, 1, 150)] + [InlineData(1, 2, 3, 4, 150)] + public async Task + GetContactPoliciesSettings_Should_Convert_TimeRestrictionHours_To_UserTimeZone_When_OffsetMinutes_NonExactHours + ( + int hourFromInDB, + int hourToInDB, + int hourFromForResponse, + int hourToFoResponse, + int offsetMinutes + ) + { + // Arrange + var fixture = new Fixture(); + string accountName = "prueba@makingsense.com"; + var expected = fixture.Build() + .With(x => x.AccountName, accountName) + .With(x => x.Active, true) + .Create(); + var expectedTimeRestriction = fixture.Build() + .With(x => x.AccountName, accountName) + .With(x => x.HourFrom, hourFromInDB) + .With(x => x.HourTo, hourToInDB) + .With(x => x.TimeZoneOffsetMinutes, offsetMinutes) + .Create(); + + var contactPoliciesRepositoryMock = new Mock(); + contactPoliciesRepositoryMock.Setup(x => x.GetContactPoliciesSettingsByIdUserAsync(It.IsAny())) + .ReturnsAsync(expected).Verifiable(); + contactPoliciesRepositoryMock.Setup(x => x.GetContactPoliciesTimeRestrictionByIdUserAsync(It.IsAny())) + .ReturnsAsync(expectedTimeRestriction).Verifiable(); + + var contactPoliciesSut = new ContactPoliciesService(contactPoliciesRepositoryMock.Object); + + // Act + var actual = await contactPoliciesSut.GetContactPoliciesSettingsByIdUserAsync(It.IsAny()); + + // Assert + contactPoliciesRepositoryMock.Verify(); + Assert.Equal(actual.AccountName, expected.AccountName); + Assert.True(actual.Active); + Assert.Equal(actual.TimeRestriction.HourFrom, hourFromForResponse); + Assert.Equal(actual.TimeRestriction.HourTo, hourToFoResponse); + } + + [Theory] + [InlineData(null, null, null, null, 180)] + [InlineData(1, 2, 1, 2, 0)] + public async Task GetContactPoliciesSettings_ShouldNot_Convert_TimeRestrictionHours_When_OffsetMinutesIsZero_Or_HoursAreNull + ( + int? hourFromInDB, + int? hourToInDB, + int? hourFromForResponse, + int? hourToFoResponse, + int offsetMinutes + ) + { + // Arrange + var fixture = new Fixture(); + string accountName = "prueba@makingsense.com"; + var expected = fixture.Build() + .With(x => x.AccountName, accountName) + .With(x => x.Active, true) + .Create(); + var expectedTimeRestriction = fixture.Build() + .With(x => x.AccountName, accountName) + .With(x => x.HourFrom, hourFromInDB) + .With(x => x.HourTo, hourToInDB) + .With(x => x.TimeZoneOffsetMinutes, offsetMinutes) + .Create(); + + var contactPoliciesRepositoryMock = new Mock(); + contactPoliciesRepositoryMock.Setup(x => x.GetContactPoliciesSettingsByIdUserAsync(It.IsAny())) + .ReturnsAsync(expected).Verifiable(); + contactPoliciesRepositoryMock.Setup(x => x.GetContactPoliciesTimeRestrictionByIdUserAsync(It.IsAny())) + .ReturnsAsync(expectedTimeRestriction).Verifiable(); + + var contactPoliciesSut = new ContactPoliciesService(contactPoliciesRepositoryMock.Object); + + // Act + var actual = await contactPoliciesSut.GetContactPoliciesSettingsByIdUserAsync(It.IsAny()); + + // Assert + contactPoliciesRepositoryMock.Verify(); + Assert.Equal(actual.AccountName, expected.AccountName); + Assert.True(actual.Active); + Assert.Equal(actual.TimeRestriction.HourFrom, hourFromForResponse); + Assert.Equal(actual.TimeRestriction.HourTo, hourToFoResponse); + } + [Fact] public async Task UpdateContactPoliciesSettings_Should_InvokeContactPoliciesSettingsRepository_With_ProperParameters() @@ -93,5 +234,139 @@ public async Task Times.Once ); } + + [Theory] + [InlineData(22, 23, 19, 20, -180)] + [InlineData(1, 2, 22, 23, -180)] + [InlineData(22, 23, 1, 2, 180)] + [InlineData(1, 2, 4, 5, 180)] + public async Task + UpdateContactPoliciesSettings_Should_Convert_TimeRestrictionHours_To_UTC_When_OffsetMinutes_ExactHours + ( + int hourFromForDB, + int hourToForDB, + int hourFromInRequest, + int hourToInRequest, + int offsetMinutes + ) + { + // Arrange + var idUser = 1000; + + var excludedLists = new List + { + new ExcludedSubscribersLists() { Id = 1, Name = "Test" } + }; + + var fixture = new Fixture(); + var timeRestriction = new ContactPoliciesTimeRestrictionDto() + { + HourFrom = hourFromInRequest, + HourTo = hourToInRequest, + }; + var contactPoliciesSettingsDto = fixture.Build() + .With(x => x.ExcludedSubscribersLists, excludedLists) + .With(x => x.TimeRestriction, timeRestriction) + .Create(); + + var contactPoliciesSettingsRepositoryMock = new Mock(); + contactPoliciesSettingsRepositoryMock.Setup(x => x.GetTimezoneOffsetMinutes(It.IsAny())) + .ReturnsAsync(offsetMinutes).Verifiable(); + + var contactPoliciesSut = new ContactPoliciesService(contactPoliciesSettingsRepositoryMock.Object); + + // Act + await contactPoliciesSut.UpdateContactPoliciesSettingsAsync(idUser, contactPoliciesSettingsDto); + + // Assert + contactPoliciesSettingsRepositoryMock.Verify( + repo => repo.UpdateContactPoliciesSettingsAsync( + idUser, + It.Is(cps => + cps.AccountName == null + && cps.Active == contactPoliciesSettingsDto.Active + && cps.EmailsAmountByInterval == contactPoliciesSettingsDto.EmailsAmountByInterval + && cps.IntervalInDays == contactPoliciesSettingsDto.IntervalInDays + && cps.UserHasContactPolicies == false + && cps.ExcludedSubscribersLists.Count == contactPoliciesSettingsDto.ExcludedSubscribersLists.Count + && cps.ExcludedSubscribersLists[0] == contactPoliciesSettingsDto.ExcludedSubscribersLists[0] + ), + It.Is(cptr => + cptr.TimeSlotEnabled == contactPoliciesSettingsDto.TimeRestriction.TimeSlotEnabled + && cptr.HourFrom == hourFromForDB + && cptr.HourTo == hourToForDB + && cptr.WeekdaysEnabled == contactPoliciesSettingsDto.TimeRestriction.WeekdaysEnabled + ) + ), + Times.Once + ); + } + + [Theory] + [InlineData(22, 23, 19, 20, -150)] + [InlineData(1, 2, 22, 23, -150)] + [InlineData(22, 23, 0, 1, 150)] + [InlineData(1, 2, 3, 4, 150)] + public async Task + UpdateContactPoliciesSettings_Should_Convert_TimeRestrictionHours_To_UTC_When_OffsetMinutes_NonExactHours + ( + int hourFromForDB, + int hourToForDB, + int hourFromInRequest, + int hourToInRequest, + int offsetMinutes + ) + { + // Arrange + var idUser = 1000; + + var excludedLists = new List + { + new ExcludedSubscribersLists() { Id = 1, Name = "Test" } + }; + + var fixture = new Fixture(); + var timeRestriction = new ContactPoliciesTimeRestrictionDto() + { + HourFrom = hourFromInRequest, + HourTo = hourToInRequest, + }; + var contactPoliciesSettingsDto = fixture.Build() + .With(x => x.ExcludedSubscribersLists, excludedLists) + .With(x => x.TimeRestriction, timeRestriction) + .Create(); + + var contactPoliciesSettingsRepositoryMock = new Mock(); + contactPoliciesSettingsRepositoryMock.Setup(x => x.GetTimezoneOffsetMinutes(It.IsAny())) + .ReturnsAsync(offsetMinutes).Verifiable(); + + var contactPoliciesSut = new ContactPoliciesService(contactPoliciesSettingsRepositoryMock.Object); + + // Act + await contactPoliciesSut.UpdateContactPoliciesSettingsAsync(idUser, contactPoliciesSettingsDto); + + // Assert + contactPoliciesSettingsRepositoryMock.Verify( + repo => repo.UpdateContactPoliciesSettingsAsync( + idUser, + It.Is(cps => + cps.AccountName == null + && cps.Active == contactPoliciesSettingsDto.Active + && cps.EmailsAmountByInterval == contactPoliciesSettingsDto.EmailsAmountByInterval + && cps.IntervalInDays == contactPoliciesSettingsDto.IntervalInDays + && cps.UserHasContactPolicies == false + && cps.ExcludedSubscribersLists.Count == contactPoliciesSettingsDto.ExcludedSubscribersLists.Count + && cps.ExcludedSubscribersLists[0] == contactPoliciesSettingsDto.ExcludedSubscribersLists[0] + ), + It.Is(cptr => + cptr.TimeSlotEnabled == contactPoliciesSettingsDto.TimeRestriction.TimeSlotEnabled + && cptr.HourFrom == hourFromForDB + && cptr.HourTo == hourToForDB + && cptr.WeekdaysEnabled == contactPoliciesSettingsDto.TimeRestriction.WeekdaysEnabled + ) + ), + Times.Once + ); + } } } From 4b353668710e4e9b8a088e13e9366fefdf7ee5a2 Mon Sep 17 00:00:00 2001 From: leoslopez Date: Fri, 1 Mar 2024 17:31:25 -0300 Subject: [PATCH 9/9] fix: format --- .../ContactPoliciesSettingsRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs index 8eaeb3d..881ce5f 100644 --- a/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs +++ b/Doppler.ContactPolicies.Data.Access/Repositories/ContactPoliciesSettings/ContactPoliciesSettingsRepository.cs @@ -172,7 +172,7 @@ from [User] u var queryParams = new { IdUser = idUser }; var result = await connection.QueryFirstOrDefaultAsync(query, queryParams); - return result?? 0; + return result ?? 0; } #endregion