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
{
/// <summary>
/// Gets the KPIs/ Analysis of operations made with the software
/// </summary>
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 < CancelledSales > GetCancelledSales ( DateTime a_start , DateTime a_end )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > 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 < string , List < SaleItem > > GetEmployeeSales ( DateTime a_start , DateTime a_end )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > accessiblebranches = m_tokenService . BranchIds ( token ) ;
Dictionary < string , List < SaleItem > > sales = new Dictionary < string , List < SaleItem > > ( ) ;
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 < CustomerAccounts > GetInDebtCustomers ( )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > 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 < MostPurchasedItem > GetMostPurchasedItem ( DateTime a_start , DateTime a_end )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
if ( AuthEnums . Valid = = m_tokenService . ValidateToken ( token ) )
{
IEnumerable < string > 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" , 5 0 ) ) ;
m_context . Database . OpenConnection ( ) ;
using ( var reader = command . ExecuteReader ( ) )
{
List < MostPurchasedItem > result = new List < MostPurchasedItem > ( ) ;
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 < MostPurchasedItem > ( ) ;
}
public IEnumerable < ProductItem > GetOutOfStockItems ( )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > 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 < ProductPriceChange > GetPriceChanges ( DateTime a_start , DateTime a_end )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > 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 < ProductPriceChange > GetProductPriceChangeHistory ( int a_limit )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
if ( AuthEnums . Valid = = m_tokenService . ValidateToken ( token ) )
{
IEnumerable < string > 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 < ProductPriceChange > GetRecentPriceChanges ( int a_limit )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > 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 < SaleItem > GetRecentSales ( int a_limit )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
if ( AuthEnums . Valid = = m_tokenService . ValidateToken ( token ) )
{
IEnumerable < string > 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 < Tblcart > GetSalesTransaction ( DateTime a_start , DateTime a_end )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
IEnumerable < string > 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 < string > 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 < WeeklyCategorySummary > GetWeeklySalesCategoryTransaction ( int a_limit )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
if ( AuthEnums . Valid = = m_tokenService . ValidateToken ( token ) )
{
IEnumerable < string > 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 < WeeklySaleItem > GetWeeklySalesTransaction ( )
{
string token = m_httpContext . Request . Headers [ HeaderNames . Authorization ] ! ;
if ( AuthEnums . Valid = = m_tokenService . ValidateToken ( token ) )
{
IEnumerable < string > 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 )
} ;
}
}
}
}
}
}
}