public Cost(QueryTimePeriod period, UsageResponse response) { Period = period; Currency = ExtractCurrency(response); Categorized = OrganizeData(period, response); Total = Categorized.Values.SelectMany(vs => vs.Values).Sum(); }
public void CanMergeEmptyUsages() { var period = new QueryTimePeriod(DateTimeOffset.Now, DateTimeOffset.Now); var usage1 = new Cost(period, new UsageResponse(new UsageResponseProperties(new List <Column>(), new List <List <object> >()), null)); var usage2 = new Cost(period, new UsageResponse(new UsageResponseProperties(new List <Column>(), new List <List <object> >()), null)); Assert.NotNull(Cost.Aggregate(usage1, usage2)); Assert.NotNull(Cost.Aggregate(usage2, usage1)); }
public Cost( QueryTimePeriod period, string currency, IReadOnlyDictionary <string, SortedDictionary <DateTimeOffset, double> > categorized, double total) { Period = period; Currency = currency; Categorized = categorized; Total = total; }
private static IReadOnlyDictionary <string, SortedDictionary <DateTimeOffset, double> > OrganizeData( QueryTimePeriod period, UsageResponse response) { var result = new Dictionary <string, SortedDictionary <DateTimeOffset, double> >(); var cols = response.Properties.Columns; var dateIndex = cols.FindIndex(col => col.Name == "UsageDate"); var costIndex = cols.FindIndex(col => col.Name == "PreTaxCost"); var serviceNameIndex = cols.FindIndex(col => col.Name == "ServiceName"); foreach (var meterCategory in response.Properties.Rows.GroupBy(row => (string)row[serviceNameIndex])) { var category = string.IsNullOrWhiteSpace(meterCategory.Key) ? "uncategorized" : meterCategory.Key; result[category] = GenerateDataForCategory(category, meterCategory); } return(result); SortedDictionary <DateTimeOffset, double> GenerateDataForCategory(string meterCategory, IEnumerable <IReadOnlyList <object> > days) { return(new SortedDictionary <DateTimeOffset, double>(EnumerateDays().ToDictionary(kvp => kvp.Day, kvp => kvp.Cost))); IEnumerable <(DateTimeOffset Day, double Cost)> EnumerateDays() { var convertedDays = days.Select(x => new { date = ParseDate((long)x[dateIndex]), cost = (double)x[costIndex] }); var currentDay = period.From; foreach (var day in convertedDays.OrderBy(d => d.date)) { // we have to pad the data with zeroes because ChartJS can't handle it otherwise currentDay = currentDay.AddDays(1); while (currentDay < day.date) { yield return(currentDay, 0); currentDay = currentDay.AddDays(1); } yield return(currentDay, day.cost); } // we have to pad the data with zeroes because ChartJS can't handle it otherwise currentDay = currentDay.AddDays(1); while (currentDay <= period.To) { yield return(currentDay, 0); currentDay = currentDay.AddDays(1); } } } }
public string GetNextMonthLink(QueryTimePeriod period) { var now = DateTimeOffset.UtcNow; if (period.To >= now) { return(null); } return(Url.RouteUrl(nameof(Index), new { from = NextMonthStart(period.To), to = NextMonthEnd(period.To) })); }
public void CanSerializeQueryTimePeriodAsExpected() { var timePeriod = new QueryTimePeriod( from: new DateTimeOffset(2018, 11, 01, 00, 00, 00, TimeSpan.Zero), to: new DateTimeOffset(2018, 11, 30, 23, 59, 59, TimeSpan.Zero)); var expected = @"{ ""from"": ""2018-11-01T00:00:00+00:00"", ""to"": ""2018-11-30T23:59:59+00:00"" }"; Assert.Equal(expected, Serialize(timePeriod)); }
public string GetPrevMonthLink(QueryTimePeriod period) => Url.RouteUrl(nameof(Index), new { from = PrevMonthStart(period.From), to = PrevMonthEnd(period.From) });