From e9fddbe3ed0e73769bcd6a1867aa5507b84ac531 Mon Sep 17 00:00:00 2001 From: duykasama Date: Thu, 14 Mar 2024 01:38:55 +0700 Subject: [PATCH 1/2] [Admin dashboard][Duy] Setup dashboard endpoint --- Domus.Api/Controllers/AdminController.cs | 28 +++++++++++++++++++ Domus.Service/Implementations/AdminService.cs | 23 +++++++++++++++ Domus.Service/Interfaces/IAdminService.cs | 10 +++++++ .../Dashboard/GetDashboardInfoRequest.cs | 7 +++++ .../Models/Responses/DashboardResponse.cs | 15 ++++++++++ 5 files changed, 83 insertions(+) create mode 100644 Domus.Api/Controllers/AdminController.cs create mode 100644 Domus.Service/Implementations/AdminService.cs create mode 100644 Domus.Service/Interfaces/IAdminService.cs create mode 100644 Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs create mode 100644 Domus.Service/Models/Responses/DashboardResponse.cs diff --git a/Domus.Api/Controllers/AdminController.cs b/Domus.Api/Controllers/AdminController.cs new file mode 100644 index 0000000..d4c1771 --- /dev/null +++ b/Domus.Api/Controllers/AdminController.cs @@ -0,0 +1,28 @@ +using Domus.Api.Controllers.Base; +using Domus.Service.Constants; +using Domus.Service.Interfaces; +using Domus.Service.Models.Requests.Dashboard; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Domus.Api.Controllers; + +[Authorize(Roles = UserRoleConstants.ADMIN, AuthenticationSchemes = "Bearer")] +[Route("api/[controller]")] +public class AdminController : BaseApiController +{ + private readonly IAdminService _adminService; + + public AdminController(IAdminService adminService) + { + _adminService = adminService; + } + + [HttpGet("dashboard")] + public async Task Dashboard([FromQuery] GetDashboardInfoRequest request) + { + return await ExecuteServiceLogic( + async () => await _adminService.GetDashboardInfo(request).ConfigureAwait(false) + ).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/Domus.Service/Implementations/AdminService.cs b/Domus.Service/Implementations/AdminService.cs new file mode 100644 index 0000000..3a7b864 --- /dev/null +++ b/Domus.Service/Implementations/AdminService.cs @@ -0,0 +1,23 @@ +using Domus.Service.Interfaces; +using Domus.Service.Models; +using Domus.Service.Models.Requests.Dashboard; +using Domus.Service.Models.Responses; + +namespace Domus.Service.Implementations; + +public class AdminService : IAdminService +{ + public async Task GetDashboardInfo(GetDashboardInfoRequest request) + { + var dashboardResponse = new DashboardResponse(); + dashboardResponse.RevenueByMonths.Add(new() + { + Revenue = 1999.99f, + MonthAsNumber = 1, + MonthAsString = "January" + }); + + await Task.CompletedTask; + return new ServiceActionResult(true) { Data = dashboardResponse }; + } +} \ No newline at end of file diff --git a/Domus.Service/Interfaces/IAdminService.cs b/Domus.Service/Interfaces/IAdminService.cs new file mode 100644 index 0000000..664ae8b --- /dev/null +++ b/Domus.Service/Interfaces/IAdminService.cs @@ -0,0 +1,10 @@ +using Domus.Common.Interfaces; +using Domus.Service.Models; +using Domus.Service.Models.Requests.Dashboard; + +namespace Domus.Service.Interfaces; + +public interface IAdminService : IAutoRegisterable +{ + Task GetDashboardInfo(GetDashboardInfoRequest request); +} \ No newline at end of file diff --git a/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs b/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs new file mode 100644 index 0000000..313ed7e --- /dev/null +++ b/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs @@ -0,0 +1,7 @@ +namespace Domus.Service.Models.Requests.Dashboard; + +public class GetDashboardInfoRequest +{ + public DateOnly StartDate { get; set; } + public DateOnly EndDate { get; set; } +} \ No newline at end of file diff --git a/Domus.Service/Models/Responses/DashboardResponse.cs b/Domus.Service/Models/Responses/DashboardResponse.cs new file mode 100644 index 0000000..313271c --- /dev/null +++ b/Domus.Service/Models/Responses/DashboardResponse.cs @@ -0,0 +1,15 @@ +namespace Domus.Service.Models.Responses; + +public class DashboardResponse +{ + public float TotalRevenue { get; set; } + public int NewUsersCount { get; set; } + public IList RevenueByMonths { get; set; } = new List(); +} + +public class RevenueByMonth +{ + public string MonthAsString { get; set; } + public int MonthAsNumber { get; set; } + public float Revenue { get; set; } +} \ No newline at end of file From 67a644f277e7ec3aec879c019a608c4a9d6a9b4b Mon Sep 17 00:00:00 2001 From: duykasama Date: Fri, 15 Mar 2024 19:21:18 +0700 Subject: [PATCH 2/2] [Admin dashboard][Duy] Get annual revenue --- Domus.Service/Implementations/AdminService.cs | 71 ++++++++++++++++--- .../Dashboard/GetDashboardInfoRequest.cs | 8 ++- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/Domus.Service/Implementations/AdminService.cs b/Domus.Service/Implementations/AdminService.cs index 3a7b864..21b475a 100644 --- a/Domus.Service/Implementations/AdminService.cs +++ b/Domus.Service/Implementations/AdminService.cs @@ -1,23 +1,74 @@ -using Domus.Service.Interfaces; +using System.Globalization; +using Domus.DAL.Interfaces; +using Domus.Service.Enums; +using Domus.Service.Interfaces; using Domus.Service.Models; using Domus.Service.Models.Requests.Dashboard; using Domus.Service.Models.Responses; +using Microsoft.EntityFrameworkCore; namespace Domus.Service.Implementations; public class AdminService : IAdminService { + private readonly IContractRepository _contractRepository; + private readonly IQuotationRevisionRepository _quotationRevisionRepository; + + public AdminService(IContractRepository contractRepository, IQuotationRevisionRepository quotationRevisionRepository) + { + _contractRepository = contractRepository; + _quotationRevisionRepository = quotationRevisionRepository; + } + public async Task GetDashboardInfo(GetDashboardInfoRequest request) { + var contracts = await (await _contractRepository.FindAsync(c => + !c.IsDeleted + && c.Status == ContractStatus.SIGNED + && c.SignedAt.HasValue + && c.SignedAt.Value.Year == request.Year)) + .ToListAsync(); + var dashboardResponse = new DashboardResponse(); - dashboardResponse.RevenueByMonths.Add(new() - { - Revenue = 1999.99f, - MonthAsNumber = 1, - MonthAsString = "January" - }); - - await Task.CompletedTask; + + for (var i = 1; i <= 12; i++) + { + var contractsByMonth = contracts.Where(c => c.SignedAt.HasValue && c.SignedAt.Value.Month == i); + var revenueByMonth = await (await _quotationRevisionRepository.FindAsync(qr => + contractsByMonth.Select(c => c.QuotationRevisionId).Contains(qr.Id))) + .Select(qr => qr.TotalPrice) + .SumAsync(); + + dashboardResponse.RevenueByMonths.Add(new() + { + Revenue = (float)revenueByMonth, + MonthAsNumber = i, + MonthAsString = GetMonthAsString(i) + }); + } + + dashboardResponse.TotalRevenue = dashboardResponse.RevenueByMonths.Select(rbm => rbm.Revenue).Sum(); + return new ServiceActionResult(true) { Data = dashboardResponse }; } -} \ No newline at end of file + + private string GetMonthAsString(int month) + { + return month switch + { + 1 => "January", + 2 => "February", + 3 => "March", + 4 => "April", + 5 => "May", + 6 => "June", + 7 => "July", + 8 => "August", + 9 => "September", + 10 => "October", + 11 => "November", + 12 => "December", + _ => throw new ArgumentOutOfRangeException(nameof(month), month, null) + }; + } +} diff --git a/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs b/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs index 313ed7e..571ae09 100644 --- a/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs +++ b/Domus.Service/Models/Requests/Dashboard/GetDashboardInfoRequest.cs @@ -1,7 +1,9 @@ -namespace Domus.Service.Models.Requests.Dashboard; +using System.ComponentModel.DataAnnotations; + +namespace Domus.Service.Models.Requests.Dashboard; public class GetDashboardInfoRequest { - public DateOnly StartDate { get; set; } - public DateOnly EndDate { get; set; } + [Range(typeof(int),"1970", "2030")] + public int Year { get; set; } } \ No newline at end of file