using Biskilog_Accounting.Server.POSModels; using Biskilog_Accounting.Shared.CustomModels; using Biskilog_Accounting.Shared.Enums; using Biskilog_Accounting.Shared.Interfaces; using Biskilog_Accounting.Shared.POSModels; using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; using MySqlConnector; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Drawing.Drawing2D; namespace Biskilog_Accounting.Server.Services { /// /// Gets the KPIs/ Analysis of operations made with the software /// public class AnalyticalService : IAnalytics { private readonly BiskAcdbContext m_context; private readonly ITokenService m_tokenService; private readonly HttpContext m_httpContext; public AnalyticalService(BiskAcdbContext a_context, ITokenService a_tokenService, IHttpContextAccessor a_httpContextAccessor) { m_context = a_context; m_tokenService = a_tokenService; m_httpContext = a_httpContextAccessor?.HttpContext; } public IEnumerable GetCancelledSales(DateTime a_start, DateTime a_end) { string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; IEnumerable accessiblebranches = m_tokenService.BranchIds(token); 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 && accessiblebranches.Contains(cSale.BranchId) select new CancelledSales { CancelledTransaction = cSale, Value = (from a in activeSale where accessiblebranches.Contains(a.BranchId) select a.Total).Sum(), Customer = !String.IsNullOrEmpty(cc.CustomerId) ? $"{cc.Firstname} {cc.Surname}" : "Walk-IN Purchase" }; } public Dictionary> GetEmployeeSales(DateTime a_start, DateTime a_end) { string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; IEnumerable accessiblebranches = m_tokenService.BranchIds(token); Dictionary> sales = new Dictionary>(); var employeeSales = m_context.Tblcarts.Where(c => c.Date >= a_start && c.Date <= a_end && accessiblebranches.Contains(c.BranchId)).Select(e => e.Cashier).Distinct().ToList(); foreach (var employeeName in employeeSales) { var list = (from a in employeeSales join c in m_context.Tblcarts on a equals c.Cashier into Sales from s in Sales group s by s.Transno into saleItem select new SaleItem { Total = saleItem.Sum(c => c.Total), Transno = saleItem.Key, Cashier = employeeName, Date = saleItem.First().Date, Status = saleItem.First().Status, BranchId = saleItem.First().BranchId }).ToList(); sales.Add(employeeName, list); } return sales; } public IEnumerable GetInDebtCustomers() { string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; IEnumerable accessiblebranches = m_tokenService.BranchIds(token); var listDebts = m_context.Customeraccounts.Where(t => t.Balance < 0 && accessiblebranches.Contains(t.BranchId)).OrderByDescending(d => d.Date).Select(t => t.CustomerId).Distinct().ToList(); foreach (var customerId in listDebts) { yield return new CustomerAccounts { Customer = m_context.Tblcustomers.FirstOrDefault(i => i.CustomerId == customerId), Debt = m_context.Customeraccounts.AsEnumerable().OrderByDescending(d => d.Date).FirstOrDefault(t => t.Balance < 0 && t.CustomerId == customerId).Balance, }; } } public IEnumerable GetMostPurchasedItem(DateTime a_start, DateTime a_end) { 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 GetMostPurchasedItems(@p0, @p1, @p2, @p3)"; command.Parameters.Add(new MySqlParameter("@p0", a_start)); command.Parameters.Add(new MySqlParameter("@p1", a_end)); command.Parameters.Add(new MySqlParameter("@p2", string.Join(", ", accessiblebranches.ToArray()))); command.Parameters.Add(new MySqlParameter("@p3", 50)); m_context.Database.OpenConnection(); using (var reader = command.ExecuteReader()) { List result = new List(); while (reader.Read()) { MostPurchasedItem item = new MostPurchasedItem { ProductId = reader.GetString(0), ProductName = reader.GetString(1), NbrTimesSold = reader.GetInt32(2), Revenue = reader.GetDecimal(3) }; result.Add(item); } return result; } } } return new List(); } public IEnumerable GetOutOfStockItems() { string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; IEnumerable accessiblebranches = m_tokenService.BranchIds(token); return (from item in m_context.Tblinventories join p in m_context.Tblproducts on item.Pcode equals p.Pcode join pu in m_context.Productaltunits on item.Pcode equals pu.Pcode into AltUnit from au in AltUnit.DefaultIfEmpty() join rs in m_context.Restocklevels on item.Pcode equals rs.ProductId join un in m_context.Unitofmeasures on p.BaseUnit equals un.UnitCode orderby item.Quantity where p.Status!.ToLower() != "inactive" && accessiblebranches.Contains(item.BranchId) && ((rs.WarnLevel >= item.Quantity && rs.Unit == p.BaseUnit) || (rs.WarnLevel >= (item.Quantity / au.QuantityUnit) && rs.Unit == au.UnitCode) ) select new ProductItem { Product = p, Stock = item, BaseUnit = un.Unitshort! }); } public IEnumerable GetPriceChanges(DateTime a_start, DateTime a_end) { 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 change.ChangeDate >= a_start && change.ChangeDate <= a_end && accessiblebranches.Contains(change.BranchId) 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 GetProductPriceChangeHistory(int a_limit) { 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 GetProductPriceChangeHistory(@p0,@p1)"; command.Parameters.Add(new MySqlParameter("@p0", string.Join(", ", accessiblebranches.ToArray()))); command.Parameters.Add(new MySqlParameter("@p1", a_limit)); m_context.Database.OpenConnection(); using (var reader = command.ExecuteReader()) { while (reader.Read()) { yield return new ProductPriceChange { Pcode = reader.GetString(0), ProductName = reader.GetString(1), PreviousPrice = reader.GetDecimal(2), CurrentPrice = reader.GetDecimal(3), ChangeDate = reader.GetDateTime(4), BranchId = reader.GetString(5), CountId = reader.GetString(6), }; } } } } } 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); using (var command = m_context.Database.GetDbConnection().CreateCommand()) { command.CommandText = "CALL GetRecentTransactions(@p0,@p1)"; command.Parameters.Add(new MySqlParameter("@p0", string.Join(", ", accessiblebranches.ToArray()))); command.Parameters.Add(new MySqlParameter("@p1", a_limit)); m_context.Database.OpenConnection(); using (var reader = command.ExecuteReader()) { while (reader.Read()) { yield return new SaleItem { Transno = reader.GetString(0), Total = (decimal)reader.GetDouble(1), Date = reader.GetDateTime(2), Cashier = reader.GetString(3), BranchId = reader.GetString(4), Customer = reader.GetString(5), Status = reader.GetString(6), }; } } } } } public IEnumerable GetSalesTransaction(DateTime a_start, DateTime a_end) { string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; IEnumerable accessiblebranches = m_tokenService.BranchIds(token); return m_context.Tblcarts.Where(t => t.Date >= a_start && t.Date <= a_end && accessiblebranches.Contains(t.BranchId)); } public TradeSummary GetTradeSummary() { 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", 2)); m_context.Database.OpenConnection(); using (var reader = command.ExecuteReader()) { int i = 0; TradeSummary result = new TradeSummary(); while (reader.Read()) { if (i == 0) { result.CurrentTradeDate = reader.GetDateTime(0); result.CurrentTradeSales = reader.GetDouble(1); } else if (i == 1) { result.LastTradeDate = reader.GetDateTime(0); result.LastTradeSales = reader.GetDouble(1); } i++; } return result; } } } return new TradeSummary(); } public IEnumerable GetWeeklySalesCategoryTransaction(int a_limit) { 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 GetCategoryTradeSummary(@p0,@p1)"; command.Parameters.Add(new MySqlParameter("@p1", a_limit)); command.Parameters.Add(new MySqlParameter("@p0", string.Join(", ", accessiblebranches.ToArray()))); m_context.Database.OpenConnection(); using (var reader = command.ExecuteReader()) { while (reader.Read()) { yield return new WeeklyCategorySummary { Category = reader.GetString(0), Total = reader.GetDecimal(1), }; } } } } } 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) }; } } } } } } }