narsil/Tanshu.Accounts.Repository/ManagementBI.cs

960 lines
40 KiB
C#
Raw Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NHibernate;
using Tanshu.Accounts.Entities;
namespace Tanshu.Accounts.Repository
{
public class SaleInfo
{
public int StartBill { get; set; }
public int FinishBill { get; set; }
public decimal Rate { get; set; }
public decimal Net { get; set; }
public decimal Vat { get; set; }
}
public class ExcelInfo
{
public DateTime Date { get; set; }
public string StartBill { get; set; }
public string FinishBill { get; set; }
public IDictionary<decimal, SaleInfo> SaleAndVat { get; set; }
public decimal ServiceTax { get; set; }
}
public class SaleJson
{
IFormatProvider culture = new CultureInfo("en-US", true);
private DateTime? dateStart;
private DateTime? dateFinish;
public string StartDate { get; set; }
public string FinishDate { get; set; }
public IList<SaleDetailJson> Sale { get; set; }
public DateTime? SDate
{
get
{
if (dateStart.HasValue)
return dateStart;
DateTime dStart;
if (!DateTime.TryParseExact(StartDate, "dd-MM-yyyy", culture, DateTimeStyles.NoCurrentDateDefault, out dStart))
dateStart = null;
else
dateStart = dStart;
return dateStart;
}
}
public DateTime? FDate
{
get
{
if (dateFinish.HasValue)
return dateFinish;
DateTime dFinish;
if (!DateTime.TryParseExact(FinishDate, "dd-MM-yyyy", culture, DateTimeStyles.NoCurrentDateDefault, out dFinish))
dateFinish = null;
else
dateFinish = dFinish;
return dateFinish;
}
}
}
public class SaleDetailJson
{
public decimal Rate { get; set; }
public bool IsLiq { get; set; }
public decimal Amount { get; set; }
}
public class BeerJson
{
IFormatProvider culture = new CultureInfo("en-US", true);
private DateTime? date;
public string Date { get; set; }
public IList<BeerDetailJson> Beers { get; set; }
public DateTime? bDate
{
get
{
if (date.HasValue)
return date;
DateTime tDate;
if (!DateTime.TryParseExact(Date, "d MMM yy", culture, DateTimeStyles.NoCurrentDateDefault, out tDate))
date = null;
else
date = tDate;
return tDate;
}
}
public decimal Quantity
{
get
{
decimal amount = 0;
foreach (var item in Beers)
{
amount += item.Quantity;
}
return amount;
}
}
}
public class BeerDetailJson
{
public string Name { get; set; }
public decimal Quantity { get; set; }
}
public class CreditJson
{
IFormatProvider culture = new CultureInfo("en-US", true);
private DateTime? date;
public string Date { get; set; }
public decimal Amount { get; set; }
public DateTime? CDate
{
get
{
if (date.HasValue)
return date;
DateTime tDate;
if (!DateTime.TryParseExact(Date, "dd/MM/yyyy", culture, DateTimeStyles.NoCurrentDateDefault, out tDate))
date = null;
else
date = tDate;
return tDate;
}
}
}
public class ManagementBI : IUnitOfWork
{
protected readonly ISession _session;
private ITransaction _transaction;
public ManagementBI()
{
_session = SessionManager.Session;
_transaction = _session.BeginTransaction();
}
#region Cleanup
public void DeleteVoid(DateTime startDate, DateTime finishDate)
{
var query = @"delete from Reprint r where r.Voucher in (
select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v.Void = :void
)";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("void", true)
.ExecuteUpdate();
query = @"delete from VoucherSettlement vs where vs.Voucher in (
select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v.Void = :void
)";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("void", true)
.ExecuteUpdate();
query = @"delete from InventoryModifier im where im.Inventory in (
select i from Inventory i where i.Kot in (
select k from Kot k where k.Voucher in (
select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v.Void = :void
)))";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("void", true)
.ExecuteUpdate();
query = @"delete from Inventory i where i.Kot in (
select k from Kot k where k.Voucher in (
select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v.Void = :void
))";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("void", true)
.ExecuteUpdate();
query = @"delete from Kot k where k.Voucher in (
select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v.Void = :void
)";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("void", true)
.ExecuteUpdate();
query = @"delete from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v.Void = :void";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("void", true)
.ExecuteUpdate();
}
public void MoveStaffToNc(DateTime startDate, DateTime finishDate)
{
var query = @"update Voucher set VoucherType = :nc where VoucherType = :staff and Date >= :startDate and Date <= :finishDate";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("nc", VoucherType.NoCharge)
.SetParameter("staff", VoucherType.Staff)
.ExecuteUpdate();
}
public void ClearModifiers(DateTime startDate, DateTime finishDate)
{
var query = @"delete from InventoryModifier im where im.Inventory in (
select i from Inventory i where i.Kot in (
select k from Kot k where k.Voucher in (
select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate
)))";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.ExecuteUpdate();
}
public void CombineKots(DateTime startDate, DateTime finishDate)
{
var query = @"
select v.VoucherID, k.KotID, i.InventoryID, i.Product.ProductID, i.Quantity
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate
order by v.Date, k.Date";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.List<object[]>();
Dictionary<Guid, Dictionary<Guid, List<object[]>>> vouchers = new Dictionary<Guid, Dictionary<Guid, List<object[]>>>();
foreach (var item in list)
{
var voucherID = (Guid)item[0];
var kotID = (Guid)item[1];
var inventoryID = (Guid)item[2];
var productID = (Guid)item[3];
var quantity = (decimal)item[4];
if (!vouchers.ContainsKey(voucherID))
vouchers.Add(voucherID, new Dictionary<Guid, List<object[]>>());
if (!vouchers[voucherID].ContainsKey(kotID))
vouchers[voucherID].Add(kotID, new List<object[]>());
vouchers[voucherID][kotID].Add(new object[] { inventoryID, productID, quantity });
}
foreach (var voucher in vouchers)
{
var kots = voucher.Value;
if (kots.Count <= 1)
continue;
Dictionary<Guid, Guid> kotInventories = new Dictionary<Guid, Guid>();
foreach (var item in kots.ElementAt(0).Value)
{
Guid inventoryID = (Guid)item[0];
Guid productID = (Guid)item[1];
kotInventories.Add(productID, inventoryID);
}
for (var i = kots.Count; i > 1; i--)
{
foreach (var item in kots.ElementAt(i - 1).Value)
{
Guid inventoryID = (Guid)item[0];
Guid productID = (Guid)item[1];
decimal quantity = (decimal)item[2];
if (kotInventories.ContainsKey(productID))
{
query = @"update Inventory set Quantity = Quantity + :quantity where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("quantity", quantity).SetParameter("inventoryID", kotInventories[productID]).ExecuteUpdate();
query = @"delete from Inventory where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("inventoryID", inventoryID).ExecuteUpdate();
}
else
{
kotInventories.Add(productID, inventoryID);
query = @"update Inventory set Kot.KotID = :kotID where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("kotID", kots.ElementAt(0).Key).SetParameter("inventoryID", inventoryID).ExecuteUpdate();
}
}
query = @"delete from Kot where KotID = :kotID";
_session.CreateQuery(query).SetParameter("kotID", kots.ElementAt(i - 1).Key).ExecuteUpdate();
}
}
}
public void RemoveBlankKots(DateTime startDate, DateTime finishDate)
{
var query = @"delete from Kot k where
k.Voucher in (select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate)
and k not in (select distinct i.Kot from Inventory i)";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.ExecuteUpdate();
query = @"delete from VoucherSettlement vs where vs.Voucher in (select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v not in (select distinct k.Voucher from Kot k))";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.ExecuteUpdate();
query = @"delete from Reprint r where r.Voucher in (select v from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v not in (select distinct k.Voucher from Kot k))";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.ExecuteUpdate();
query = @"delete from Voucher v where v.Date >= :startDate and v.Date <= :finishDate and v not in (select distinct k.Voucher from Kot k)";
_session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.ExecuteUpdate();
}
public void SetPayments(DateTime startDate, DateTime finishDate)
{
var query = @"select v.VoucherID, v.VoucherType, sum(i.Amount)
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate
group by v.VoucherID, v.VoucherType";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.List<object[]>();
Dictionary<Guid, object[]> vouchers = new Dictionary<Guid, object[]>();
foreach (var item in list)
{
var voucherType = (int)item[1] == 1 || (int)item[1] == 3 ? VoucherType.Regular : (int)item[1] == 2 ? VoucherType.NoCharge : VoucherType.Staff;
vouchers.Add((Guid)item[0], new object[] { voucherType, Math.Round((decimal)item[2], 5) });
}
foreach (var item in vouchers)
{
SettleOption settlementType;
switch ((VoucherType)item.Value[0])
{
case VoucherType.NoCharge:
settlementType = SettleOption.NoCharge;
break;
case VoucherType.Staff:
settlementType = SettleOption.Staff;
break;
default:
settlementType = SettleOption.Cash;
break;
}
var amount = -1 * (decimal)item.Value[1];
var roundoff = Math.Round(amount) - amount;
query = @"delete from VoucherSettlement vs where vs.Voucher.VoucherID = :voucherID";
_session
.CreateQuery(query)
.SetParameter("voucherID", item.Key)
.ExecuteUpdate();
_session.Save(new VoucherSettlement() { Voucher = new Voucher() { VoucherID = item.Key }, Amount = amount, Settled = SettleOption.Amount });
_session.Save(new VoucherSettlement() { Voucher = new Voucher() { VoucherID = item.Key }, Amount = roundoff, Settled = SettleOption.RoundOff });
_session.Save(new VoucherSettlement() { Voucher = new Voucher() { VoucherID = item.Key }, Amount = -1 * (amount + roundoff), Settled = settlementType });
}
}
public void UpdateBillID(DateTime startDate, DateTime finishDate)
{
var query = @"
select MAX(v.BillID)
from Voucher v
where v.Date < :startDate and v.Void = false and v.VoucherType in (:regular, :takeAway)
";
var lastBill = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("regular", VoucherType.Regular)
.SetParameter("takeAway", VoucherType.TakeAway)
.UniqueResult();
var newID = lastBill == null ? 1 : GetNewID((int)lastBill);
var list = _session.QueryOver<Voucher>()
.Where(x => x.Date >= startDate && x.Date <= finishDate && x.Void == false && (x.VoucherType == VoucherType.Regular || x.VoucherType == VoucherType.TakeAway))
.OrderBy(x => x.Date).Asc
.List();
var count = " of" + list.Count.ToString();
var i = 0;
foreach (var voucher in list)
{
i++;
if (i % 20 == 0)
Console.WriteLine("Loop " + i.ToString() + count);
if (voucher.BillID != newID)
{
var update = _session.CreateSQLQuery("exec UpdateBillID ?,?");
update.SetParameter<Guid>(0, voucher.VoucherID);
update.SetParameter<int>(1, newID);
update.ExecuteUpdate();
}
newID = GetNewID(newID);
}
query = @"
select coalesce(v.BillID + 1, 1)
from Voucher v
where v.Date < :startDate and v.Void = false and v.VoucherType = :nc
order by v.Date desc
";
lastBill = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("nc", VoucherType.NoCharge)
.SetMaxResults(1)
.UniqueResult();
newID = (int)lastBill;
list = _session.QueryOver<Voucher>()
.Where(x => x.Date >= startDate && x.Date <= finishDate && x.VoucherType == VoucherType.NoCharge && x.Void == false)
.OrderBy(x => x.Date).Asc
.List();
foreach (var voucher in list)
{
if (voucher.BillID != newID)
{
var update = _session.CreateSQLQuery("exec UpdateBillID ?,?");
update.SetParameter<Guid>(0, voucher.VoucherID);
update.SetParameter<int>(1, newID);
update.ExecuteUpdate();
}
newID += 1;
}
}
private static int GetNewID(int lastBill)
{
lastBill += 1;
if (lastBill % 10000 == 0)
lastBill += 1;
return lastBill;
}
#endregion
public void MoveToNc(DateTime startDate, DateTime finishDate, decimal target)
{
string query = @"
select v.VoucherID, sum(i.Amount)
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate and i.Vat.TaxID = :vatLiquor and v.Void = false and v.VoucherType not in (:nc, :staff)
group by v.VoucherID
order by sum(i.Amount) desc
";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate.AddHours(7))
.SetParameter("finishDate", finishDate.AddDays(1).AddHours(7))
.SetParameter("nc", VoucherType.NoCharge)
.SetParameter("staff", VoucherType.Staff)
.SetParameter("vatLiquor", new Guid("2C8AD8EC-E09A-4194-B348-01243474CF26"))
.List();
var totalAmount = GetSaleAmount(.1575M, startDate, finishDate) + GetSaleAmount(.2625M, startDate, finishDate);
for (int i = 0; i < list.Count / 20; i += 2) // Skip every alternate bill
{
if (totalAmount <= target)
break;
var item = (object[])list[i];
var voucherID = (Guid)item[0];
var amount = (decimal)item[1];
query = @"update Voucher set VoucherType = :nc where VoucherID = :voucherID";
_session
.CreateQuery(query)
.SetParameter("nc", VoucherType.NoCharge)
.SetParameter("voucherID", voucherID)
.ExecuteUpdate();
totalAmount -= amount;
}
}
public IList<SaleInfo> GetSaleAndVat(DateTime startDate, DateTime finishDate)
{
const string query = @"
select i.VatRate as Rate,
sum(i.Quantity * i.Price * (1 - i.Discount) * (1 + case when i.IsScTaxable then i.ServiceCharge else 0 end)) as Net,
sum(i.Quantity * i.Price * (1 - i.Discount) * (1 + case when i.IsScTaxable then i.ServiceCharge else 0 end) * i.VatRate) as Vat
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate and v.Void = false and v.VoucherType in (:regular, :takeAway)
group by i.VatRate
order by i.VatRate
";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("regular", VoucherType.Regular)
.SetParameter("takeAway", VoucherType.TakeAway)
.List<object[]>();
var info = new List<SaleInfo>();
foreach (var item in list)
{
info.Add(new SaleInfo() { Rate = (decimal)item[0], Net = (decimal)item[1], Vat = (decimal)item[2] });
}
return info;
}
public decimal GetServiceTax(DateTime startDate, DateTime finishDate)
{
const string query = @"
select sum(i.Quantity * i.Price * (1 - i.Discount) * (1 + case when i.IsScTaxable then i.ServiceCharge else 0 end) * i.ServiceTaxRate) as Amount
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate and v.Void = false and v.VoucherType not in (:nc, :staff)
";
var qty = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("nc", VoucherType.NoCharge)
.SetParameter("staff", VoucherType.Staff)
.UniqueResult();
return qty == null ? 0 : (decimal)qty;
}
public SaleInfo GetMinMaxBills(DateTime startDate, DateTime finishDate)
{
const string query = @"
select MIN(v.BillID) as StartBill, MAX(v.BillID) as FinishBill
from Voucher v
where v.Date >= :startDate and v.Date <= :finishDate and v.Void = false and v.VoucherType in (:regular, :takeAway)
";
var item = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("regular", VoucherType.Regular)
.SetParameter("takeAway", VoucherType.TakeAway)
.UniqueResult<object[]>();
if (item[0] == null || item[1] == null)
return null;
return new SaleInfo() { StartBill = (int)item[0], FinishBill = (int)item[1] };
}
public int? GetLastBill(DateTime date)
{
const string query = @"
select v.BillID
from Voucher v
where v.Date >= :startDate and v.Date <= :finishDate and v.Void = false and v.VoucherType in (:regular, :takeAway)
order by v.Date desc
";
var qty = _session
.CreateQuery(query)
.SetParameter("startDate", date.AddHours(7))
.SetParameter("finishDate", date.AddDays(1).AddHours(7))
.SetParameter("regular", VoucherType.Regular)
.SetParameter("takeAway", VoucherType.TakeAway)
.SetMaxResults(1)
.UniqueResult();
if (qty == null)
return null;
return (int)qty;
}
public decimal GetSaleAmount(decimal vat, DateTime startDate, DateTime finishDate)
{
const string query = @"
select sum(i.Quantity * i.Price * (1 - i.Discount) * (1 + case when i.IsScTaxable then i.ServiceCharge else 0 end)) as Amount
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate and i.VatRate = :vat and v.Void = false and v.VoucherType not in (:nc, :staff)
";
var qty = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("vat", vat)
.SetParameter("nc", VoucherType.NoCharge)
.SetParameter("staff", VoucherType.Staff)
.UniqueResult();
return qty == null ? 0 : (decimal)qty;
}
public decimal SetSaleQuantity(decimal vat, decimal amount, DateTime startDate, DateTime finishDate)
{
var query = @"
select i.InventoryID, i.Quantity * i.Price * (1 - i.Discount) * (1 + case when i.IsScTaxable then i.ServiceCharge else 0 end)
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate
and i.VatRate = :vat
and v.VoucherType in (:regular, :takeAway)";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("regular", VoucherType.Regular)
.SetParameter("vat", vat)
.SetParameter("takeAway", VoucherType.TakeAway)
.List<object[]>();
Dictionary<Guid, decimal> inventories = new Dictionary<Guid, decimal>();
list = Randomize(list);
foreach (var item in list)
{
inventories.Add((Guid)item[0], Convert.ToDecimal(item[1]));
}
var left = GetSaleAmount(vat, startDate, finishDate) - amount;
foreach (var item in inventories)
{
if (left <= 0)
break;
var inventoryAmount = item.Value;
if (inventoryAmount > left)
{
var ratio = (inventoryAmount - left) / inventoryAmount;
query = @"update Inventory set Quantity = Quantity * :ratio where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("ratio", ratio).SetParameter("inventoryID", item.Key).ExecuteUpdate();
left = 0;
}
else
{
query = @"delete from Inventory where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("inventoryID", item.Key).ExecuteUpdate();
left -= inventoryAmount;
}
}
return GetSaleAmount(vat, startDate, finishDate);
}
public decimal SetSaleDiscount(decimal vat, decimal amount, DateTime startDate, DateTime finishDate)
{
var rand = new Random();
var query = @"
select i.InventoryID, i.Quantity, i.Discount, i.Quantity * i.Price * (1 - i.Discount) * (1 + case when i.IsScTaxable then i.ServiceCharge else 0 end)
from Voucher v
inner join v.Kots k
inner join k.Inventories i
where v.Date >= :startDate and v.Date <= :finishDate
and i.VatRate = :vat and i.Discount < :maxDiscount
and v.VoucherType in (:regular, :takeAway)";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.SetParameter("regular", VoucherType.Regular)
.SetParameter("vat", vat)
.SetParameter("maxDiscount", .9M)
.SetParameter("takeAway", VoucherType.TakeAway)
.List<object[]>();
Dictionary<Guid, object[]> inventories = new Dictionary<Guid, object[]>();
list = Randomize(list);
foreach (var item in list)
{
inventories.Add((Guid)item[0], new object[] { Convert.ToDecimal(item[1]), Convert.ToDecimal(item[2]), Convert.ToDecimal(item[3]) });
}
var left = GetSaleAmount(vat, startDate, finishDate) - amount;
foreach (var item in inventories)
{
if (left <= 0)
break;
var invQuantity = (decimal)item.Value[0];
var invDiscount = (decimal)item.Value[1];
var invNet = (decimal)item.Value[2];
var minimum = invDiscount == 0 ? 10 : Convert.ToInt32(invDiscount * 100);
var discount = Convert.ToDecimal(rand.Next(minimum, 90)) / 100;
if (discount == invDiscount)
continue;
var reduction = invNet * (discount - invDiscount);
if (reduction > left)
{
discount = left / invNet;
query = @"update Inventory set Discount = :discount where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("discount", discount).SetParameter("inventoryID", item.Key).ExecuteUpdate();
left = 0;
}
else
{
query = @"update Inventory set Discount = :discount where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("discount", discount).SetParameter("inventoryID", item.Key).ExecuteUpdate();
left -= reduction;
}
}
return GetSaleAmount(vat, startDate, finishDate);
}
#region Beer
public decimal GetBeer(DateTime startDate, DateTime finishDate)
{
const string query = @"
select sum(i.Quantity * p.Quantity) as Quantity
from Voucher v
inner join v.Kots k
inner join k.Inventories i
inner join i.Product p
where v.Date >= :startDate and v.Date <= :finishDate and v.Void = false and p.Quantity != 0
";
var qty = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.UniqueResult();
return qty == null ? 0 : (decimal)qty;
}
public decimal SetBeer(DateTime startDate, DateTime finishDate, decimal quantity)
{
var query = @"
select i.InventoryID, i.Product.ProductID, i.Quantity, p.Quantity
from Voucher v
inner join v.Kots k
inner join k.Inventories i
inner join i.Product p
where v.Date >= :startDate and v.Date <= :finishDate
and p.Quantity != 0";
var list = _session
.CreateQuery(query)
.SetParameter("startDate", startDate)
.SetParameter("finishDate", finishDate)
.List<object[]>();
list = Randomize(list);
Dictionary<Guid, object[]> inventories = new Dictionary<Guid, object[]>();
foreach (var item in list)
{
var inventoryID = (Guid)item[0];
var productID = (Guid)item[1];
var inventoryQuantity = (decimal)item[2];
var productQuantity = (decimal)item[3];
inventories.Add(inventoryID, new object[] { productID, inventoryQuantity, productQuantity });
}
var left = GetBeer(startDate, finishDate) - quantity;
foreach (var item in inventories)
{
if (left <= 0)
break;
var productID = (Guid)item.Value[0];
var inventoryQuantity = (decimal)item.Value[1];
var productQuantity = (decimal)item.Value[2];
var q = inventoryQuantity * productQuantity;
if (q > left)
{
var newQuantity = inventoryQuantity * (q - left) / q;
query = @"update Inventory set Quantity = :quantity where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("quantity", newQuantity).SetParameter("inventoryID", item.Key).ExecuteUpdate();
left = 0;
}
else
{
query = @"delete from Inventory where InventoryID = :inventoryID";
_session.CreateQuery(query).SetParameter("inventoryID", item.Key).ExecuteUpdate();
left -= q;
}
}
return GetBeer(startDate, finishDate);
}
#endregion
#region Helper and Comments
private static IList<T> Randomize<T>(IEnumerable<T> list)
{
var tList = list.ToArray();
var rand = new Random();
for (var i = tList.Length - 1; i > 0; i--)
{
var swapIndex = rand.Next(i + 1);
var tmp = tList[i];
tList[i] = tList[swapIndex];
tList[swapIndex] = tmp;
}
return tList.ToList();
}
public string FullBillID(int billID, VoucherType voucherType)
{
switch (voucherType)
{
case VoucherType.NoCharge:
return "NC-" + billID.ToString();
case VoucherType.Staff:
return "ST-" + billID.ToString();
case VoucherType.TakeAway:
case VoucherType.Regular:
default:
return (billID / 10000).ToString() + "-" + (billID % 10000).ToString();
}
}
// public decimal GetBeer(int baseCode, DateTime startDate, DateTime finishDate)
// {
// const string query = @"
//select sum(i.Quantity * p.Quantity) as Quantity
//from Voucher v
//inner join v.Kots k
//inner join k.Inventories i
//inner join i.Product p
//where v.Date >= :startDate and v.Date <= :finishDate and v.Void = false and p.BaseCode = :baseCode
// ";
// var qty = Session
// .CreateQuery(query)
// .SetParameter("startDate", startDate)
// .SetParameter("finishDate", finishDate)
// .SetParameter("baseCode", baseCode)
// .UniqueResult();
// return qty == null ? 0 : (decimal)qty;
// }
// public decimal SetQuantity(int baseCode, decimal quantity, DateTime startDate, DateTime finishDate)
// {
// var list = Randomize(new VoucherBI().List(x => x.Date >= startDate && x.Date <= finishDate && x.Void == false));
// var left = GetBeer(baseCode, startDate, finishDate) - quantity;
// foreach (var item in list)
// {
// if (left <= 0)
// break;
// foreach (var kot in item.Kots)
// {
// if (left <= 0)
// break;
// foreach (var inventory in kot.Inventories)
// {
// if (left <= 0)
// break;
// if (inventory.Product.BaseCode == baseCode)
// {
// using (var bi = new InventoryBI())
// {
// var inventoryQuantity = inventory.Quantity * inventory.Product.Quantity;
// if (inventoryQuantity > left)
// {
// var newQuantity = inventory.Quantity * (inventoryQuantity - left) / inventoryQuantity;
// var i = bi.Get(x => x.InventoryID == inventory.InventoryID);
// i.Quantity = newQuantity;
// bi.Update(i);
// left = 0;
// }
// else
// {
// left -= inventoryQuantity;
// bi.Delete(x => x.InventoryID == inventory.InventoryID);
// }
// }
// }
// }
// }
// }
// return GetBeer(baseCode, startDate, finishDate);
// }
//private static int GetNewID(int code, int toBaseCode)
//{
// // Name Mug, Pit, H H
// // Dark 301, 305, 384 // BaseCode = 1
// // Wheat 300, 304, 383 // BaseCode = 2
// // Premium 299, 303, 382 // BaseCode = 3
// // Light 297, 302, 363 // BaseCode = 4
// // Dragon 677, 679, 678 // BaseCode = 5
// // Festivals 762 764, 752 // BaseCode = 6
// // Festivals 751, 753, 763 // BaseCode = 6
// // Festivals 734, 736, 587 // BaseCode = 6
// // Festivals 408, 409, 735 // BaseCode = 6
// // Strong 697, 708, 707 // BaseCode = 7
// var list = new List<int> { 301, 300, 299, 297, 677, 762, 751, 734, 408, 697 };
// if (list.Contains(code))
// {
// if (toBaseCode == 1)
// return 301;
// if (toBaseCode == 2)
// return 300;
// if (toBaseCode == 3)
// return 299;
// if (toBaseCode == 4)
// return 297;
// if (toBaseCode == 5)
// return 677;
// if (toBaseCode == 6)
// return code;
// if (toBaseCode == 7)
// return 697;
// }
// list = new List<int> { 305, 304, 303, 302, 679, 764, 753, 736, 409, 708 };
// if (list.Contains(code))
// {
// if (toBaseCode == 1)
// return 305;
// if (toBaseCode == 2)
// return 304;
// if (toBaseCode == 3)
// return 303;
// if (toBaseCode == 4)
// return 302;
// if (toBaseCode == 5)
// return 679;
// if (toBaseCode == 6)
// return code;
// if (toBaseCode == 7)
// return 708;
// }
// list = new List<int> { 384, 383, 382, 363, 678, 752, 763, 587, 735, 707 };
// if (list.Contains(code))
// {
// if (toBaseCode == 1)
// return 384;
// if (toBaseCode == 2)
// return 383;
// if (toBaseCode == 3)
// return 382;
// if (toBaseCode == 4)
// return 363;
// if (toBaseCode == 5)
// return 678;
// if (toBaseCode == 6)
// return code;
// if (toBaseCode == 7)
// return 707;
// }
// return code;
//}
//public void SetMove(int fromBaseCode, int toBaseCode, DateTime startDate, DateTime finishDate)
//{
// var list = new VoucherBI().List(x => x.Date >= startDate && x.Date <= finishDate);
// using (var bi = new InventoryBI())
// {
// using (var pbi = new ProductBI())
// {
// foreach (var item in list)
// {
// foreach (var kot in item.Kots)
// {
// foreach (var inventory in kot.Inventories)
// {
// if (inventory.Product.BaseCode == fromBaseCode)
// {
// var i = bi.Get(x => x.InventoryID == inventory.InventoryID);
// i.Product = pbi.Get(x => x.ProductID == GetNewID(i.Product.ProductID, toBaseCode));
// GetNewID(i.InventoryID, toBaseCode);
// bi.Update(i);
// }
// }
// }
// }
// }
// }
//}
#endregion
public void Dispose()
{
if (_transaction != null)
_transaction.Rollback();
}
public void SaveChanges()
{
if (_transaction == null)
throw new InvalidOperationException("UnitOfWork have already been saved.");
_transaction.Commit();
_transaction = null;
}
}
}