From 0725e4f7cf4c6f723264b6d461b91c660d144cb7 Mon Sep 17 00:00:00 2001 From: ivarlovlie Date: Sun, 30 Oct 2022 22:40:03 +0700 Subject: feat: Apiwork --- .../src/Endpoints/V1/Entries/EntryQueryRoute.cs | 342 ++++++++++----------- 1 file changed, 171 insertions(+), 171 deletions(-) (limited to 'code/api/src/Endpoints/V1/Entries/EntryQueryRoute.cs') diff --git a/code/api/src/Endpoints/V1/Entries/EntryQueryRoute.cs b/code/api/src/Endpoints/V1/Entries/EntryQueryRoute.cs index ec6003c..03a64d2 100644 --- a/code/api/src/Endpoints/V1/Entries/EntryQueryRoute.cs +++ b/code/api/src/Endpoints/V1/Entries/EntryQueryRoute.cs @@ -2,185 +2,185 @@ namespace IOL.GreatOffice.Api.Endpoints.V1.Entries; public class EntryQueryRoute : RouteBaseSync.WithRequest.WithActionResult { - private readonly ILogger _logger; - private readonly AppDbContext _context; - - public EntryQueryRoute(ILogger logger, AppDbContext context) { - _logger = logger; - _context = context; - } - - /// - /// Get a list of entries based on a given query. - /// - /// - /// - /// - [ApiVersion(ApiSpecV1.VERSION_STRING)] - [BasicAuthentication(AppConstants.TOKEN_ALLOW_READ)] - [HttpPost("~/v{version:apiVersion}/entries/query")] - [ProducesResponseType(204)] - [ProducesResponseType(400, Type = typeof(KnownProblemModel))] - [ProducesResponseType(200, Type = typeof(EntryQueryResponse))] - public override ActionResult Handle(EntryQueryPayload entryQuery) { - var result = new TimeQueryDto(); - - Request.Headers.TryGetValue(AppHeaders.BROWSER_TIME_ZONE, out var timeZoneHeader); - var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneHeader.ToString().HasValue() ? timeZoneHeader.ToString() : "UTC"); - var offsetInHours = tz.BaseUtcOffset.Hours; - - // this is fine as long as the client is not connecting from Australia: Lord Howe Island - // according to https://en.wikipedia.org/wiki/Daylight_saving_time_by_country - if (tz.IsDaylightSavingTime(AppDateTime.UtcNow)) { - offsetInHours++; - } - - _logger.LogInformation("Request time zone (" + tz.Id + ") offset is: " + offsetInHours + " hours"); - var requestDateTime = TimeZoneInfo.ConvertTimeFromUtc(AppDateTime.UtcNow, tz); - _logger.LogInformation("Querying data with date time: " + requestDateTime.ToString("u")); - - var skipCount = 0; - if (entryQuery.Page > 1) { - skipCount = entryQuery.PageSize * entryQuery.Page; - } - - result.Page = entryQuery.Page; - result.PageSize = entryQuery.PageSize; - - var baseQuery = _context.TimeEntries - .AsNoTracking() - .Include(c => c.Category) - .Include(c => c.Labels) - .Where(c => c.UserId == LoggedInUser.Id) - .ConditionalWhere(entryQuery.Categories?.Any() ?? false, c => entryQuery.Categories.Any(p => p.Id == c.Category.Id)) - .ConditionalWhere(entryQuery.Labels?.Any() ?? false, c => c.Labels.Any(l => entryQuery.Labels.Any(p => p.Id == l.Id))) - .OrderByDescending(c => c.Start); - - switch (entryQuery.Duration) { - case TimeEntryQueryDuration.TODAY: - var baseTodaysEntries = baseQuery - .Where(c => DateTime.Compare(c.Start.AddHours(offsetInHours).Date, AppDateTime.UtcNow.Date) == 0); - var baseTodaysEntriesCount = baseTodaysEntries.Count(); - - if (baseTodaysEntriesCount == 0) { - return NoContent(); - } - - result.TotalSize = baseTodaysEntriesCount; - result.TotalPageCount = Convert.ToInt32(Math.Round((double)baseTodaysEntriesCount / entryQuery.PageSize)); - - var pagedTodaysEntries = baseTodaysEntries.Skip(skipCount).Take(entryQuery.PageSize); - - result.Results.AddRange(pagedTodaysEntries.Select(c => c.AsDto)); - break; - case TimeEntryQueryDuration.THIS_WEEK: - var lastMonday = AppDateTime.UtcNow.StartOfWeek(DayOfWeek.Monday); - - var baseEntriesThisWeek = baseQuery - .Where(c => c.Start.AddHours(offsetInHours).Date >= lastMonday.Date && c.Start.AddHours(offsetInHours).Date <= AppDateTime.UtcNow.Date); - - var baseEntriesThisWeekCount = baseEntriesThisWeek.Count(); - - if (baseEntriesThisWeekCount == 0) { - return NoContent(); - } - - result.TotalSize = baseEntriesThisWeekCount; - result.TotalPageCount = Convert.ToInt32(Math.Round((double)baseEntriesThisWeekCount / entryQuery.PageSize)); - - var pagedEntriesThisWeek = baseEntriesThisWeek.Skip(skipCount).Take(entryQuery.PageSize); - - result.Results.AddRange(pagedEntriesThisWeek.Select(c => c.AsDto)); - break; - case TimeEntryQueryDuration.THIS_MONTH: - var baseEntriesThisMonth = baseQuery - .Where(c => c.Start.AddHours(offsetInHours).Month == AppDateTime.UtcNow.Month - && c.Start.AddHours(offsetInHours).Year == AppDateTime.UtcNow.Year); - var baseEntriesThisMonthCount = baseEntriesThisMonth.Count(); - if (baseEntriesThisMonthCount == 0) { - return NoContent(); - } - - result.TotalSize = baseEntriesThisMonthCount; - result.TotalPageCount = Convert.ToInt32(Math.Round((double)baseEntriesThisMonthCount / entryQuery.PageSize)); - - var pagedEntriesThisMonth = baseEntriesThisMonth.Skip(skipCount).Take(entryQuery.PageSize); - - result.Results.AddRange(pagedEntriesThisMonth.Select(c => c.AsDto)); - break; - case TimeEntryQueryDuration.THIS_YEAR: - var baseEntriesThisYear = baseQuery - .Where(c => c.Start.AddHours(offsetInHours).Year == AppDateTime.UtcNow.Year); - - var baseEntriesThisYearCount = baseEntriesThisYear.Count(); - if (baseEntriesThisYearCount == 0) { - return NoContent(); - } - - result.TotalSize = baseEntriesThisYearCount; - result.TotalPageCount = Convert.ToInt32(Math.Round((double)baseEntriesThisYearCount / entryQuery.PageSize)); - - var pagedEntriesThisYear = baseEntriesThisYear.Skip(skipCount).Take(entryQuery.PageSize); - - result.Results.AddRange(pagedEntriesThisYear.Select(c => c.AsDto)); - break; - case TimeEntryQueryDuration.SPECIFIC_DATE: - var date = DateTime.SpecifyKind(entryQuery.SpecificDate, DateTimeKind.Utc); - var baseEntriesOnThisDate = baseQuery.Where(c => c.Start.AddHours(offsetInHours).Date == date.Date); - var baseEntriesOnThisDateCount = baseEntriesOnThisDate.Count(); - - if (baseEntriesOnThisDateCount == 0) { - return NoContent(); - } - - result.TotalSize = baseEntriesOnThisDateCount; - result.TotalPageCount = Convert.ToInt32(Math.Round((double)baseEntriesOnThisDateCount / entryQuery.PageSize)); - - var pagedEntriesOnThisDate = baseEntriesOnThisDate.Skip(skipCount).Take(entryQuery.PageSize); + private readonly ILogger _logger; + private readonly MainAppDatabase _database; + + public EntryQueryRoute(ILogger logger, MainAppDatabase database) { + _logger = logger; + _database = database; + } + + /// + /// Get a list of entries based on a given query. + /// + /// + /// + /// + [ApiVersion(ApiSpecV1.VERSION_STRING)] + [BasicAuthentication(AppConstants.TOKEN_ALLOW_READ)] + [HttpPost("~/v{version:apiVersion}/entries/query")] + [ProducesResponseType(204)] + [ProducesResponseType(400, Type = typeof(KnownProblemModel))] + [ProducesResponseType(200, Type = typeof(EntryQueryResponse))] + public override ActionResult Handle(EntryQueryPayload entryQuery) { + var result = new TimeQueryDto(); + + Request.Headers.TryGetValue(AppHeaders.BROWSER_TIME_ZONE, out var timeZoneHeader); + var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneHeader.ToString().HasValue() ? timeZoneHeader.ToString() : "UTC"); + var offsetInHours = tz.BaseUtcOffset.Hours; + + // this is fine as long as the client is not connecting from Australia: Lord Howe Island + // according to https://en.wikipedia.org/wiki/Daylight_saving_time_by_country + if (tz.IsDaylightSavingTime(AppDateTime.UtcNow)) { + offsetInHours++; + } + + _logger.LogInformation("Request time zone (" + tz.Id + ") offset is: " + offsetInHours + " hours"); + var requestDateTime = TimeZoneInfo.ConvertTimeFromUtc(AppDateTime.UtcNow, tz); + _logger.LogInformation("Querying data with date time: " + requestDateTime.ToString("u")); + + var skipCount = 0; + if (entryQuery.Page > 1) { + skipCount = entryQuery.PageSize * entryQuery.Page; + } + + result.Page = entryQuery.Page; + result.PageSize = entryQuery.PageSize; + + var baseQuery = _database.TimeEntries + .AsNoTracking() + .Include(c => c.Category) + .Include(c => c.Labels) + .Where(c => c.UserId == LoggedInUser.Id) + .ConditionalWhere(entryQuery.Categories?.Any() ?? false, c => entryQuery.Categories.Any(p => p.Id == c.Category.Id)) + .ConditionalWhere(entryQuery.Labels?.Any() ?? false, c => c.Labels.Any(l => entryQuery.Labels.Any(p => p.Id == l.Id))) + .OrderByDescending(c => c.Start); + + switch (entryQuery.Duration) { + case TimeEntryQueryDuration.TODAY: + var baseTodaysEntries = baseQuery + .Where(c => DateTime.Compare(c.Start.AddHours(offsetInHours).Date, AppDateTime.UtcNow.Date) == 0); + var baseTodaysEntriesCount = baseTodaysEntries.Count(); + + if (baseTodaysEntriesCount == 0) { + return NoContent(); + } + + result.TotalSize = baseTodaysEntriesCount; + result.TotalPageCount = Convert.ToInt32(Math.Round((double) baseTodaysEntriesCount / entryQuery.PageSize)); + + var pagedTodaysEntries = baseTodaysEntries.Skip(skipCount).Take(entryQuery.PageSize); + + result.Results.AddRange(pagedTodaysEntries.Select(c => c.AsDto)); + break; + case TimeEntryQueryDuration.THIS_WEEK: + var lastMonday = AppDateTime.UtcNow.StartOfWeek(DayOfWeek.Monday); + + var baseEntriesThisWeek = baseQuery + .Where(c => c.Start.AddHours(offsetInHours).Date >= lastMonday.Date && c.Start.AddHours(offsetInHours).Date <= AppDateTime.UtcNow.Date); + + var baseEntriesThisWeekCount = baseEntriesThisWeek.Count(); + + if (baseEntriesThisWeekCount == 0) { + return NoContent(); + } + + result.TotalSize = baseEntriesThisWeekCount; + result.TotalPageCount = Convert.ToInt32(Math.Round((double) baseEntriesThisWeekCount / entryQuery.PageSize)); + + var pagedEntriesThisWeek = baseEntriesThisWeek.Skip(skipCount).Take(entryQuery.PageSize); + + result.Results.AddRange(pagedEntriesThisWeek.Select(c => c.AsDto)); + break; + case TimeEntryQueryDuration.THIS_MONTH: + var baseEntriesThisMonth = baseQuery + .Where(c => c.Start.AddHours(offsetInHours).Month == AppDateTime.UtcNow.Month + && c.Start.AddHours(offsetInHours).Year == AppDateTime.UtcNow.Year); + var baseEntriesThisMonthCount = baseEntriesThisMonth.Count(); + if (baseEntriesThisMonthCount == 0) { + return NoContent(); + } + + result.TotalSize = baseEntriesThisMonthCount; + result.TotalPageCount = Convert.ToInt32(Math.Round((double) baseEntriesThisMonthCount / entryQuery.PageSize)); + + var pagedEntriesThisMonth = baseEntriesThisMonth.Skip(skipCount).Take(entryQuery.PageSize); + + result.Results.AddRange(pagedEntriesThisMonth.Select(c => c.AsDto)); + break; + case TimeEntryQueryDuration.THIS_YEAR: + var baseEntriesThisYear = baseQuery + .Where(c => c.Start.AddHours(offsetInHours).Year == AppDateTime.UtcNow.Year); + + var baseEntriesThisYearCount = baseEntriesThisYear.Count(); + if (baseEntriesThisYearCount == 0) { + return NoContent(); + } + + result.TotalSize = baseEntriesThisYearCount; + result.TotalPageCount = Convert.ToInt32(Math.Round((double) baseEntriesThisYearCount / entryQuery.PageSize)); + + var pagedEntriesThisYear = baseEntriesThisYear.Skip(skipCount).Take(entryQuery.PageSize); + + result.Results.AddRange(pagedEntriesThisYear.Select(c => c.AsDto)); + break; + case TimeEntryQueryDuration.SPECIFIC_DATE: + var date = DateTime.SpecifyKind(entryQuery.SpecificDate, DateTimeKind.Utc); + var baseEntriesOnThisDate = baseQuery.Where(c => c.Start.AddHours(offsetInHours).Date == date.Date); + var baseEntriesOnThisDateCount = baseEntriesOnThisDate.Count(); + + if (baseEntriesOnThisDateCount == 0) { + return NoContent(); + } + + result.TotalSize = baseEntriesOnThisDateCount; + result.TotalPageCount = Convert.ToInt32(Math.Round((double) baseEntriesOnThisDateCount / entryQuery.PageSize)); + + var pagedEntriesOnThisDate = baseEntriesOnThisDate.Skip(skipCount).Take(entryQuery.PageSize); - result.Results.AddRange(pagedEntriesOnThisDate.Select(c => c.AsDto)); - break; - case TimeEntryQueryDuration.DATE_RANGE: - if (entryQuery.DateRange.From == default) { - return BadRequest(new KnownProblemModel("Invalid query", "From date cannot be empty")); - } - - var fromDate = DateTime.SpecifyKind(entryQuery.DateRange.From, DateTimeKind.Utc); + result.Results.AddRange(pagedEntriesOnThisDate.Select(c => c.AsDto)); + break; + case TimeEntryQueryDuration.DATE_RANGE: + if (entryQuery.DateRange.From == default) { + return BadRequest(new KnownProblemModel("Invalid query", "From date cannot be empty")); + } + + var fromDate = DateTime.SpecifyKind(entryQuery.DateRange.From, DateTimeKind.Utc); - if (entryQuery.DateRange.To == default) { - return BadRequest(new KnownProblemModel("Invalid query", "To date cannot be empty")); - } + if (entryQuery.DateRange.To == default) { + return BadRequest(new KnownProblemModel("Invalid query", "To date cannot be empty")); + } - var toDate = DateTime.SpecifyKind(entryQuery.DateRange.To, DateTimeKind.Utc); + var toDate = DateTime.SpecifyKind(entryQuery.DateRange.To, DateTimeKind.Utc); - if (DateTime.Compare(fromDate, toDate) > 0) { - return BadRequest(new KnownProblemModel("Invalid query", "To date cannot be less than From date")); - } + if (DateTime.Compare(fromDate, toDate) > 0) { + return BadRequest(new KnownProblemModel("Invalid query", "To date cannot be less than From date")); + } - var baseDateRangeEntries = baseQuery - .Where(c => c.Start.AddHours(offsetInHours).Date > fromDate && c.Start.AddHours(offsetInHours).Date <= toDate); + var baseDateRangeEntries = baseQuery + .Where(c => c.Start.AddHours(offsetInHours).Date > fromDate && c.Start.AddHours(offsetInHours).Date <= toDate); - var baseDateRangeEntriesCount = baseDateRangeEntries.Count(); - if (baseDateRangeEntriesCount == 0) { - return NoContent(); - } + var baseDateRangeEntriesCount = baseDateRangeEntries.Count(); + if (baseDateRangeEntriesCount == 0) { + return NoContent(); + } - result.TotalSize = baseDateRangeEntriesCount; - result.TotalPageCount = Convert.ToInt32(Math.Round((double)baseDateRangeEntriesCount / entryQuery.PageSize)); + result.TotalSize = baseDateRangeEntriesCount; + result.TotalPageCount = Convert.ToInt32(Math.Round((double) baseDateRangeEntriesCount / entryQuery.PageSize)); - var pagedDateRangeEntries = baseDateRangeEntries.Skip(skipCount).Take(entryQuery.PageSize); + var pagedDateRangeEntries = baseDateRangeEntries.Skip(skipCount).Take(entryQuery.PageSize); - result.Results.AddRange(pagedDateRangeEntries.Select(c => c.AsDto)); - break; - default: - throw new ArgumentOutOfRangeException(nameof(entryQuery), "Unknown duration for query"); - } + result.Results.AddRange(pagedDateRangeEntries.Select(c => c.AsDto)); + break; + default: + throw new ArgumentOutOfRangeException(nameof(entryQuery), "Unknown duration for query"); + } - if (result.Results.Any() && result.Page == 0) { - result.Page = 1; - result.TotalPageCount = 1; - } + if (result.Results.Any() && result.Page == 0) { + result.Page = 1; + result.TotalPageCount = 1; + } - return Ok(result); - } -} + return Ok(result); + } +} \ No newline at end of file -- cgit v1.3