Benjamin Arhen
2 years ago
15 changed files with 433 additions and 8 deletions
@ -0,0 +1,96 @@ |
|||||
|
using Biskilog_Accounting.Server.POSModels; |
||||
|
using Biskilog_Accounting.Server.Services; |
||||
|
using Biskilog_Accounting.Shared.CustomModels; |
||||
|
using Biskilog_Accounting.Shared.Interfaces; |
||||
|
using Biskilog_Accounting.Shared.POSModels; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.Net.Http.Headers; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Data.Entity; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Server.Controllers |
||||
|
{ |
||||
|
[Route("api/[controller]")]
|
||||
|
[ApiController] |
||||
|
public class AnalyticsController : ControllerBase |
||||
|
{ |
||||
|
private readonly IConnectionService m_connection; |
||||
|
private readonly ITokenService m_tokenService; |
||||
|
public AnalyticsController(ITokenService tokenService, IConnectionService connection) |
||||
|
{ |
||||
|
m_tokenService = tokenService; |
||||
|
m_connection = connection; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Endpoint to return analysis on CancelledSales within a specified period
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
[Authorize] |
||||
|
[HttpGet, Route("cancelledsales/{a_start}/{a_end}")] |
||||
|
public IEnumerable<CancelledSales> GetCancelledSalesAsync(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
string token = Request.Headers[HeaderNames.Authorization]!; |
||||
|
int? databaseId = m_tokenService.GetDatabaseIdFromToken(token); |
||||
|
string connectionString = m_connection.GetClientConnectionString(databaseId!.Value); |
||||
|
bool? comparisonMode = m_tokenService.GetComparison(token); |
||||
|
string? currentBranch = m_tokenService.GetBaseBranch(token); |
||||
|
|
||||
|
//Creates a new db context
|
||||
|
BiskAcdbContext newContext = (BiskAcdbContext)m_connection.PrepareDBContext(connectionString); |
||||
|
|
||||
|
AnalyticalService analysis = new(newContext, comparisonMode!.Value, currentBranch!); |
||||
|
var result = analysis.GetCancelledSales(a_start, a_end); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// Endpoint to return analysis on Sales within a specified period
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
[Authorize] |
||||
|
[HttpGet, Route("sales/{a_start}/{a_end}")] |
||||
|
public IEnumerable<Tblcart> GetSalesAsync(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
string token = Request.Headers[HeaderNames.Authorization]!; |
||||
|
int? databaseId = m_tokenService.GetDatabaseIdFromToken(token); |
||||
|
string connectionString = m_connection.GetClientConnectionString(databaseId!.Value); |
||||
|
bool? comparisonMode = m_tokenService.GetComparison(token); |
||||
|
string? currentBranch = m_tokenService.GetBaseBranch(token); |
||||
|
|
||||
|
//Creates a new db context
|
||||
|
BiskAcdbContext newContext = (BiskAcdbContext)m_connection.PrepareDBContext(connectionString); |
||||
|
|
||||
|
AnalyticalService analysis = new(newContext, comparisonMode!.Value, currentBranch!); |
||||
|
return analysis.GetSalesTransaction(a_start, a_end); |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// Endpoint to return analysis on in-debt customers
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
[Authorize] |
||||
|
[HttpGet, Route("debtors")] |
||||
|
public IEnumerable<InDebtCustomers> GetInDebtCustomers() |
||||
|
{ |
||||
|
string token = Request.Headers[HeaderNames.Authorization]!; |
||||
|
int? databaseId = m_tokenService.GetDatabaseIdFromToken(token); |
||||
|
string connectionString = m_connection.GetClientConnectionString(databaseId!.Value); |
||||
|
bool? comparisonMode = m_tokenService.GetComparison(token); |
||||
|
string? currentBranch = m_tokenService.GetBaseBranch(token); |
||||
|
|
||||
|
//Creates a new db context
|
||||
|
BiskAcdbContext newContext = (BiskAcdbContext)m_connection.PrepareDBContext(connectionString); |
||||
|
|
||||
|
AnalyticalService analysis = new(newContext, comparisonMode!.Value, currentBranch!); |
||||
|
return analysis.GetInDebtCustomers(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,165 @@ |
|||||
|
using Biskilog_Accounting.Server.POSModels; |
||||
|
using Biskilog_Accounting.Shared.CustomModels; |
||||
|
using Biskilog_Accounting.Shared.Interfaces; |
||||
|
using Biskilog_Accounting.Shared.POSModels; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using System.Data.Entity; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using static Microsoft.EntityFrameworkCore.DbLoggerCategory; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Server.Services |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the KPIs/ Analysis of operations made with the software
|
||||
|
/// </summary>
|
||||
|
public class AnalyticalService : IAnalytics |
||||
|
{ |
||||
|
private readonly BiskAcdbContext m_context; |
||||
|
private bool m_comparisonMode; |
||||
|
private string m_activeBranch; |
||||
|
public AnalyticalService(BiskAcdbContext a_context, bool a_comparisonMode, string a_activeBranchId) |
||||
|
{ |
||||
|
m_context = a_context; |
||||
|
m_comparisonMode = a_comparisonMode; |
||||
|
m_activeBranch = a_activeBranchId; |
||||
|
} |
||||
|
public IEnumerable<CancelledSales> GetCancelledSales(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
//If in comparison mode, the list is fetched from all branchid of the business
|
||||
|
if (m_comparisonMode) |
||||
|
{ |
||||
|
return from cSale in m_context.Tblcancelledtransactions |
||||
|
join aSale in m_context.Tblcarts on cSale.Transno equals aSale.Transno into activeSale |
||||
|
join cPurchase in m_context.Tblcustomerpurchases on cSale.Transno equals cPurchase.TransactionId into customerSales |
||||
|
from c in customerSales.DefaultIfEmpty() |
||||
|
join customer in m_context.Tblcustomers on c.CustomerId equals customer.CustomerId into Customers |
||||
|
from cc in Customers.DefaultIfEmpty() |
||||
|
where cSale.DateCancelled >= a_start && cSale.DateCancelled <= a_end |
||||
|
select new CancelledSales |
||||
|
{ |
||||
|
CancelledTransaction = cSale, |
||||
|
Value = activeSale.Sum(s => s.Total), |
||||
|
Customer = !String.IsNullOrEmpty(cc.CustomerId) ? $"{cc.Firstname} {cc.Surname}" : "Walk-IN Purchase" |
||||
|
}; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return from cSale in m_context.Tblcancelledtransactions |
||||
|
join aSale in m_context.Tblcarts on cSale.Transno equals aSale.Transno into activeSale |
||||
|
join cPurchase in m_context.Tblcustomerpurchases on cSale.Transno equals cPurchase.TransactionId into customerSales |
||||
|
from c in customerSales.DefaultIfEmpty() |
||||
|
join customer in m_context.Tblcustomers on c.CustomerId equals customer.CustomerId into Customers |
||||
|
from cc in Customers.DefaultIfEmpty() |
||||
|
where cSale.DateCancelled >= a_start && cSale.DateCancelled <= a_end && cSale.BranchId == m_activeBranch |
||||
|
select new CancelledSales |
||||
|
{ |
||||
|
CancelledTransaction = cSale, |
||||
|
Value = (from a in activeSale where a.BranchId == m_activeBranch select a.Total).Sum(), |
||||
|
Customer = !String.IsNullOrEmpty(cc.CustomerId) ? $"{cc.Firstname} {cc.Surname}" : "Walk-IN Purchase" |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<Dictionary<string, List<Tblcart>>> GetEmployeeSales(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<InDebtCustomers> GetInDebtCustomers() |
||||
|
{ |
||||
|
if (m_comparisonMode) |
||||
|
{ |
||||
|
return from c in m_context.Tblcustomers |
||||
|
join a in m_context.Customeraccounts on c.CustomerId equals a.CustomerId into CustomerAccounts |
||||
|
from ac in CustomerAccounts.OrderByDescending(ac => ac.Date).Take(1).DefaultIfEmpty() |
||||
|
where ac.Balance < 0 |
||||
|
orderby ac.Date descending |
||||
|
select new InDebtCustomers |
||||
|
{ |
||||
|
Customer = c, |
||||
|
Debt = ac != null ? ac.Balance : 0 |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<ProductItem> GetMostPurchasedItem(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<ProductItem> GetOutOfStockItems() |
||||
|
{ |
||||
|
//if (m_comparisonMode)
|
||||
|
//{
|
||||
|
// return from r in m_context.Restocklevels
|
||||
|
// join i in m_context.Tblinventories on r.ProductId equals i.Pcode
|
||||
|
// join p in m_context.Tblproducts on i.Pcode equals p.Pcode
|
||||
|
// where i.Quantity == r.WarnLevel
|
||||
|
// select new ProductItem
|
||||
|
// {
|
||||
|
// Product = p,
|
||||
|
// Stock = i,
|
||||
|
// Unitofmeasure =
|
||||
|
// }
|
||||
|
//}
|
||||
|
//else {
|
||||
|
//}
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<ProductPriceChange> GetPriceChanges(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
if (m_comparisonMode) |
||||
|
{ |
||||
|
return from change in m_context.Tblpricechanges |
||||
|
join p in m_context.Tblproducts on change.Pcode equals p.Pcode |
||||
|
where change.ChangeDate <= a_start && change.ChangeDate >= a_end |
||||
|
select new ProductPriceChange |
||||
|
{ |
||||
|
BranchId = change.BranchId, |
||||
|
ChangeDate = change.ChangeDate, |
||||
|
Pcode = change.Pcode, |
||||
|
CountId = change.CountId, |
||||
|
CurrentPrice = change.CurrentPrice, |
||||
|
PreviousPrice = change.PreviousPrice, |
||||
|
ProductName = p.ProductName |
||||
|
}; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return from change in m_context.Tblpricechanges |
||||
|
join p in m_context.Tblproducts on change.Pcode equals p.Pcode |
||||
|
where change.ChangeDate <= a_start && change.ChangeDate >= a_end && change.BranchId == m_activeBranch |
||||
|
select new ProductPriceChange |
||||
|
{ |
||||
|
BranchId = change.BranchId, |
||||
|
ChangeDate = change.ChangeDate, |
||||
|
Pcode = change.Pcode, |
||||
|
CountId = change.CountId, |
||||
|
CurrentPrice = change.CurrentPrice, |
||||
|
PreviousPrice = change.PreviousPrice, |
||||
|
ProductName = p.ProductName |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<Tblcart> GetSalesTransaction(DateTime a_start, DateTime a_end) |
||||
|
{ |
||||
|
//If in comparison mode, the list is fetched from all branchid of the business
|
||||
|
if (m_comparisonMode) |
||||
|
{ |
||||
|
return m_context.Tblcarts.Where(t => t.Date >= a_start && t.Date <= a_end); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return m_context.Tblcarts.Where(t => t.Date >= a_start && t.Date <= a_end && t.BranchId == m_activeBranch); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
using Biskilog_Accounting.Shared.POSModels; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Shared.CustomModels |
||||
|
{ |
||||
|
public class CancelledSales |
||||
|
{ |
||||
|
public Tblcancelledtransaction? CancelledTransaction { get; set; } |
||||
|
public string Customer { get; set; } = "WALK-IN Purchase"; |
||||
|
public decimal? Value { get; set; } |
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
using Biskilog_Accounting.Shared.POSModels; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Shared.CustomModels |
||||
|
{ |
||||
|
public class InDebtCustomers |
||||
|
{ |
||||
|
public Tblcustomer Customer { get; set; } |
||||
|
public decimal Debt { get; set; } = 0; |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
using Biskilog_Accounting.Shared.POSModels; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Shared.CustomModels |
||||
|
{ |
||||
|
public class ProductItem |
||||
|
{ |
||||
|
public Tblproduct? Product { get; set; } |
||||
|
public Tblinventory? Stock { get; set; } |
||||
|
public List<Unitofmeasure> Unitofmeasure { get; set; } = new List<Unitofmeasure>(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Shared.CustomModels |
||||
|
{ |
||||
|
public class ProductPriceChange |
||||
|
{ |
||||
|
public string? Pcode { get; set; } |
||||
|
public string? ProductName { get; set; } |
||||
|
public decimal? PreviousPrice { get; set; } |
||||
|
|
||||
|
public decimal? CurrentPrice { get; set; } |
||||
|
|
||||
|
public DateTime? ChangeDate { get; set; } |
||||
|
|
||||
|
public string BranchId { get; set; } = null!; |
||||
|
|
||||
|
public string CountId { get; set; } = null!; |
||||
|
} |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
using Biskilog_Accounting.Shared.CustomModels; |
||||
|
using Biskilog_Accounting.Shared.POSModels; |
||||
|
|
||||
|
namespace Biskilog_Accounting.Shared.Interfaces |
||||
|
{ |
||||
|
public interface IAnalytics |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of sales transaction made from the specified start date to the end date
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start">Specified Start Date</param>
|
||||
|
/// <param name="a_end">Specified end Date</param>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<Tblcart> GetSalesTransaction(DateTime a_start, DateTime a_end); |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of in-debt customers
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<InDebtCustomers> GetInDebtCustomers(); |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of Product Items which are currently out of stock
|
||||
|
/// </summary>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<ProductItem> GetOutOfStockItems(); |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of the most purchased Product Items within a specified date range
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<ProductItem> GetMostPurchasedItem(DateTime a_start, DateTime a_end); |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of cancelled transaction within a specified date range
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<CancelledSales> GetCancelledSales(DateTime a_start, DateTime a_end); |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of transaction made by employees within a specified date range
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
/// <returns>A dictionary of transactions made by employees with employee name as key</returns>
|
||||
|
IEnumerable<Dictionary<string, List<Tblcart>>> GetEmployeeSales(DateTime a_start, DateTime a_end); |
||||
|
/// <summary>
|
||||
|
/// Fetches a collection of product price changes with a specified date range
|
||||
|
/// </summary>
|
||||
|
/// <param name="a_start"></param>
|
||||
|
/// <param name="a_end"></param>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<ProductPriceChange> GetPriceChanges(DateTime a_start, DateTime a_end); |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue