From 54d55cd9ae39d8a19819a56e4c4c6102e0556154 Mon Sep 17 00:00:00 2001 From: barhen Date: Sat, 3 Jun 2023 23:35:37 -0500 Subject: [PATCH] Dashboard Commit 3 --- Client/Biskilog Accounting.Client.csproj | 1 + Client/Pages/Dashboard/Dashboard.razor | 57 +--------------- Client/Pages/Dashboard/Dashboard.razor.cs | 36 ++++++++-- .../Elements/AnalyticsItemSmall.razor | 9 ++- .../Dashboard/Elements/ChartElement.razor | 58 ++++++++++++++++ .../Dashboard/Elements/ChartElement.razor.cs | 46 +++++++++++++ Client/_Imports.razor | 1 + Client/wwwroot/index.html | 2 + Server/Controllers/AnalyticsController.cs | 27 ++++++++ Server/Services/AnalyticalService.cs | 67 ++++++++++++++++++- Shared/CustomModels/WeeklySaleItem.cs | 15 +++++ Shared/Interfaces/IAnalytics.cs | 17 +++++ Shared/ServiceRepo/CalculatorService.cs | 2 +- 13 files changed, 275 insertions(+), 63 deletions(-) create mode 100644 Client/Pages/Dashboard/Elements/ChartElement.razor create mode 100644 Client/Pages/Dashboard/Elements/ChartElement.razor.cs create mode 100644 Shared/CustomModels/WeeklySaleItem.cs diff --git a/Client/Biskilog Accounting.Client.csproj b/Client/Biskilog Accounting.Client.csproj index f344a0f..2c81af8 100644 --- a/Client/Biskilog Accounting.Client.csproj +++ b/Client/Biskilog Accounting.Client.csproj @@ -19,6 +19,7 @@ + diff --git a/Client/Pages/Dashboard/Dashboard.razor b/Client/Pages/Dashboard/Dashboard.razor index 2f2a628..58e7963 100644 --- a/Client/Pages/Dashboard/Dashboard.razor +++ b/Client/Pages/Dashboard/Dashboard.razor @@ -12,7 +12,7 @@
- +
@@ -21,64 +21,13 @@
-
-
-
-
Total Revenue
-
-
-
-
-
- -
-
-
-
62% Company Growth
- -
-
-
- -
-
- 2022 -
$32.5k
-
-
-
-
- -
-
- 2021 -
$41.2k
-
-
-
-
-
-
+
- +
diff --git a/Client/Pages/Dashboard/Dashboard.razor.cs b/Client/Pages/Dashboard/Dashboard.razor.cs index e49e32c..cde908a 100644 --- a/Client/Pages/Dashboard/Dashboard.razor.cs +++ b/Client/Pages/Dashboard/Dashboard.razor.cs @@ -7,19 +7,22 @@ namespace Biskilog_Accounting.Client.Pages.Dashboard public partial class Dashboard { private TradeSummary m_tradeSummary { get; set; } = new TradeSummary(); + private List m_weeklySaleItems { get; set; } = new List { }; private string m_username { get; set; } = string.Empty; + private bool loadWeeklySales = true; protected override async Task OnInitializedAsync() { m_username = m_tokenService.GetUserNameFromToken(await m_tokenService.GetToken())!; - await GetSummary(); + await GetTradeSummary(); + await GetWeeklySales(); return; } - + /// /// Gets the tade summary /// /// - async Task GetSummary() + async Task GetTradeSummary() { try { @@ -32,7 +35,32 @@ namespace Biskilog_Accounting.Client.Pages.Dashboard m_tradeSummary = tradeSummary; StateHasChanged(); } - }catch (Exception ex) + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + /// + /// Gets the tade summary + /// + /// + async Task GetWeeklySales() + { + try + { + var response = await m_http.GetAsync("api/analytics/sales/weekly"); + if (response.IsSuccessStatusCode) + { + var jsonContent = await response.Content.ReadAsStringAsync(); + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + var sales = JsonSerializer.Deserialize>(jsonContent, options); + m_weeklySaleItems = sales; + loadWeeklySales = false; + StateHasChanged(); + } + } + catch (Exception ex) { Console.WriteLine(ex.Message); } diff --git a/Client/Pages/Dashboard/Elements/AnalyticsItemSmall.razor b/Client/Pages/Dashboard/Elements/AnalyticsItemSmall.razor index ca14085..fd23ef1 100644 --- a/Client/Pages/Dashboard/Elements/AnalyticsItemSmall.razor +++ b/Client/Pages/Dashboard/Elements/AnalyticsItemSmall.razor @@ -1,4 +1,7 @@ -
+@using Biskilog_Accounting.Shared.Interfaces +@inject ICalculator m_calculator + +
@@ -22,7 +25,7 @@
@Title -

@Value

- @Percentage % +
@(m_calculator.FormatMoneyWithCurrency(Value))
+ @(Percentage.ToString("0.00")) %
\ No newline at end of file diff --git a/Client/Pages/Dashboard/Elements/ChartElement.razor b/Client/Pages/Dashboard/Elements/ChartElement.razor new file mode 100644 index 0000000..4f032ec --- /dev/null +++ b/Client/Pages/Dashboard/Elements/ChartElement.razor @@ -0,0 +1,58 @@ +@using Biskilog_Accounting.Shared.CustomModels; +@using Biskilog_Accounting.Shared.Interfaces; +@inject ICalculator m_calculator + +@if (!IsLoading) +{ +
+
+
+
@Title
+ + + + +
+
+
@SubTitle
+ + + +
+
+
+ +
+
+ Best Day + @m_bestDay + @m_bestSales +
+
+
+
+ +
+
+ Worst Day + @m_worstDay + @m_worstSales +
+
+
+
+
+
+}else{ + +} \ No newline at end of file diff --git a/Client/Pages/Dashboard/Elements/ChartElement.razor.cs b/Client/Pages/Dashboard/Elements/ChartElement.razor.cs new file mode 100644 index 0000000..bf52f3d --- /dev/null +++ b/Client/Pages/Dashboard/Elements/ChartElement.razor.cs @@ -0,0 +1,46 @@ +using ApexCharts; +using Biskilog_Accounting.Shared.CustomModels; +using Microsoft.AspNetCore.Components; + +namespace Biskilog_Accounting.Client.Pages.Dashboard.Elements +{ + public partial class ChartElement + { + [Parameter] + public bool IsLoading { get; set; } + [Parameter] + public string Title { get; set; } = string.Empty; + [Parameter] + public string SubTitle { get; set; } = string.Empty; + [Parameter] + public List Series { get; set; } = new List(); + private ApexChartOptions m_options; + + private string m_bestDay { get; set; } = string.Empty; + private string m_worstDay { get; set; } = string.Empty; + private string m_bestSales { get; set; } = string.Empty; + private string m_worstSales { get; set; } = string.Empty; + protected override void OnParametersSet() + { + m_options = new ApexChartOptions + { + PlotOptions = new PlotOptions + { + Bar = new PlotOptionsBar + { + ColumnWidth = "7", + + } + } + }; + if (Series.Count > 1) + { + m_bestDay = Series.OrderByDescending(t => t.Total).First().Date.ToShortDateString(); + m_bestSales = m_calculator.FormatMoneyWithCurrency((double)Series.OrderByDescending(t => t.Total).First().Total); + m_worstDay = Series.OrderByDescending(t => t.Total).Last().Date.ToShortDateString(); + m_worstSales = m_calculator.FormatMoneyWithCurrency((double)Series.OrderByDescending(t => t.Total).Last().Total); + } + base.OnParametersSet(); + } + } +} diff --git a/Client/_Imports.razor b/Client/_Imports.razor index b7485da..bb5b0c1 100644 --- a/Client/_Imports.razor +++ b/Client/_Imports.razor @@ -5,3 +5,4 @@ @using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.JSInterop @using Biskilog_Accounting.Client +@using ApexCharts; \ No newline at end of file diff --git a/Client/wwwroot/index.html b/Client/wwwroot/index.html index 42dfb0b..5cc4985 100644 --- a/Client/wwwroot/index.html +++ b/Client/wwwroot/index.html @@ -47,6 +47,8 @@ 🗙
+ + diff --git a/Server/Controllers/AnalyticsController.cs b/Server/Controllers/AnalyticsController.cs index ba677ed..14dd1c8 100644 --- a/Server/Controllers/AnalyticsController.cs +++ b/Server/Controllers/AnalyticsController.cs @@ -41,6 +41,15 @@ namespace Biskilog_Accounting.Server.Controllers return m_analyticService.GetSalesTransaction(a_start, a_end); } /// + /// Endpoint to return analysis on Sales within a specified period + /// + [Authorize] + [HttpGet, Route("sales/weekly")] + public IEnumerable GetWeeklySalesAsync() + { + return m_analyticService.GetWeeklySalesTransaction().OrderBy(a => a.Date); + } + /// /// Endpoint to return analysis on in-debt customers /// /// @@ -106,5 +115,23 @@ namespace Biskilog_Accounting.Server.Controllers { return m_analyticService.GetTradeSummary(); } + /// + /// Endpoint to return analysis on recent transactions + /// + [Authorize] + [HttpGet, Route("sales/recent/{a_limit}")] + public IEnumerable GetRecentTransactions(int a_limit) + { + return m_analyticService.GetRecentSales(a_limit); + } + /// + /// Endpoint to return analysis on recent price changes + /// + [Authorize] + [HttpGet, Route("pricechanges/recent/{a_limit}")] + public IEnumerable GetRecentPricing(int a_limit) + { + return m_analyticService.GetRecentPriceChanges(a_limit); + } } } diff --git a/Server/Services/AnalyticalService.cs b/Server/Services/AnalyticalService.cs index 74f804f..66ff71b 100644 --- a/Server/Services/AnalyticalService.cs +++ b/Server/Services/AnalyticalService.cs @@ -177,6 +177,39 @@ namespace Biskilog_Accounting.Server.Services }; } + public IEnumerable GetRecentPriceChanges(int a_limit) + { + string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; + IEnumerable accessiblebranches = m_tokenService.BranchIds(token); + + return (from change in m_context.Tblpricechanges + join p in m_context.Tblproducts on change.Pcode equals p.Pcode + where accessiblebranches.Contains(change.BranchId) + orderby change.ChangeDate descending + select new ProductPriceChange + { + BranchId = change.BranchId, + ChangeDate = change.ChangeDate, + Pcode = change.Pcode, + CountId = change.CountId, + CurrentPrice = change.CurrentPrice, + PreviousPrice = change.PreviousPrice, + ProductName = p.ProductName + }).Take(a_limit); + } + + public IEnumerable GetRecentSales(int a_limit) + { + string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; + + if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) + { + IEnumerable accessiblebranches = m_tokenService.BranchIds(token); + return m_context.Tblcarts.Where(t => accessiblebranches.Contains(t.BranchId)).OrderByDescending(t => t.Date).Take(a_limit); + } + return new List(); + } + public IEnumerable GetSalesTransaction(DateTime a_start, DateTime a_end) { string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; @@ -196,8 +229,9 @@ namespace Biskilog_Accounting.Server.Services using (var command = m_context.Database.GetDbConnection().CreateCommand()) { - command.CommandText = "CALL GetTradeSummary(@p0)"; + command.CommandText = "CALL GetTradeSummary(@p0,@p1)"; command.Parameters.Add(new MySqlParameter("@p0", string.Join(", ", accessiblebranches.ToArray()))); + command.Parameters.Add(new MySqlParameter("@p1", 2)); m_context.Database.OpenConnection(); @@ -226,5 +260,36 @@ namespace Biskilog_Accounting.Server.Services } return new TradeSummary(); } + + public IEnumerable GetWeeklySalesTransaction() + { + string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; + + if (AuthEnums.Valid == m_tokenService.ValidateToken(token)) + { + IEnumerable accessiblebranches = m_tokenService.BranchIds(token); + + using (var command = m_context.Database.GetDbConnection().CreateCommand()) + { + command.CommandText = "CALL GetTradeSummary(@p0,@p1)"; + command.Parameters.Add(new MySqlParameter("@p0", string.Join(", ", accessiblebranches.ToArray()))); + command.Parameters.Add(new MySqlParameter("@p1", 7)); + + m_context.Database.OpenConnection(); + + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + yield return new WeeklySaleItem() + { + Date = reader.GetDateTime(0), + Total = reader.GetDecimal(1) + }; + } + } + } + } + } } } diff --git a/Shared/CustomModels/WeeklySaleItem.cs b/Shared/CustomModels/WeeklySaleItem.cs new file mode 100644 index 0000000..168d7a4 --- /dev/null +++ b/Shared/CustomModels/WeeklySaleItem.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Biskilog_Accounting.Shared.CustomModels +{ + public class WeeklySaleItem + { + public DateTime Date { get; set; } + public decimal? Total { get; set; } + public string BranchId { get; set; } = null!; + } +} diff --git a/Shared/Interfaces/IAnalytics.cs b/Shared/Interfaces/IAnalytics.cs index e5a545c..f2b07ca 100644 --- a/Shared/Interfaces/IAnalytics.cs +++ b/Shared/Interfaces/IAnalytics.cs @@ -13,6 +13,11 @@ namespace Biskilog_Accounting.Shared.Interfaces /// IEnumerable GetSalesTransaction(DateTime a_start, DateTime a_end); /// + /// Fetches a collection of sales transaction made within a one week period + /// + /// + IEnumerable GetWeeklySalesTransaction(); + /// /// Fetches a collection of in-debt customers /// IEnumerable GetInDebtCustomers(); @@ -54,5 +59,17 @@ namespace Biskilog_Accounting.Shared.Interfaces /// /// TradeSummary GetTradeSummary(); + /// + /// Fetches the most recent sales transactions + /// + /// The number of rows to return + /// + IEnumerable GetRecentSales(int a_limit); + /// + /// Fetches a collection of product price changes recently made + /// + /// the number of rows to return + /// + IEnumerable GetRecentPriceChanges(int a_limit); } } diff --git a/Shared/ServiceRepo/CalculatorService.cs b/Shared/ServiceRepo/CalculatorService.cs index 84b1c64..e312e95 100644 --- a/Shared/ServiceRepo/CalculatorService.cs +++ b/Shared/ServiceRepo/CalculatorService.cs @@ -31,7 +31,7 @@ namespace Biskilog_Accounting.Shared.ServiceRepo NumberFormatInfo numberFormatInfo = new CultureInfo(locale).NumberFormat; // Set the currency symbol to Ghanaian cedi - numberFormatInfo.CurrencySymbol = "GH₵"; + numberFormatInfo.CurrencySymbol = "GH₵ "; return numberFormatInfo; }