using Biskilog_Accounting.Server.POSModels; using Biskilog_Accounting.Shared.CustomModels; using Biskilog_Accounting.Shared.Interfaces; using Biskilog_Accounting.Shared.POSModels; using Microsoft.Net.Http.Headers; using System.Data.Entity; 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 InDebtCustomers { Customer = m_context.Tblcustomers.FirstOrDefault(i => i.CustomerId == customerId), Debt = m_context.Customeraccounts.OrderByDescending(d => d.Date).FirstOrDefault(t => t.Balance < 0 && t.CustomerId == customerId).Balance, }; } } public IEnumerable GetMostPurchasedItem(DateTime a_start, DateTime a_end) { //TODO either rewrite query or increase memory on server to deal with comparison mode performance issue string token = m_httpContext.Request.Headers[HeaderNames.Authorization]!; IEnumerable accessiblebranches = m_tokenService.BranchIds(token); var items = (from s in m_context.Tblcarts join p in m_context.Tblproducts on s.Id equals p.Pcode where s.Date >= a_start && s.Date <= a_end && s.BranchId == accessiblebranches.First() group s by p into g orderby g.Count() descending select new MostPurchasedItem { ProductId = g.Key.Pcode, ProductName = g.Key.ProductName, NbrTimesSold = g.Count(), Revenue = g.Sum(s => s.Price) }).Take(50).ToList(); return items; } 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 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 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)); } } }