using System; using System.Collections; using System.Collections.Generic; using System.Linq; using NHibernate; using Tanshu.Accounts.Entities; namespace Tanshu.Accounts.Repository { public class ManagementBI : FluentBasicBase { public ManagementBI() : base() { } public ManagementBI(bool beginTransaction) : base(beginTransaction) { } public ManagementBI(ISession session) : base(session) { } public ManagementBI(ISession session, bool beginTransaction) : base(session, beginTransaction) { } public decimal GetFood(int vatID, 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 inner join i.Product p where v.Date >= :startDate and v.Date <= :finishDate and p.Vat.TaxID = :vatID and v.Void = false and v.VoucherType not in (:nc, :staff) "; var qty = Session .CreateQuery(query) .SetParameter("startDate", startDate) .SetParameter("finishDate", finishDate) .SetParameter("vatID", vatID) .SetParameter("nc", VoucherType.NoCharge) .SetParameter("staff", VoucherType.Staff) .UniqueResult(); return qty == null ? 0 : (decimal)qty; } public decimal SetFood(int vatID, decimal amount, DateTime startDate, DateTime finishDate) { var list = Randomize(new VoucherBI().List(x => x.Date >= startDate && x.Date <= finishDate && x.Void == false && x.VoucherType != VoucherType.NoCharge && x.VoucherType != VoucherType.Staff)); var left = GetFood(vatID, startDate, finishDate) - amount; 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.Vat.TaxID == vatID) { using (var bi = new InventoryBI()) { var inventoryAmount = inventory.Quantity * inventory.Price * (1 - inventory.Discount) * (1 + (inventory.IsScTaxable ? inventory.ServiceCharge : 0)); if (inventoryAmount > left) { var newQuantity = inventory.Quantity * (inventoryAmount - left) / inventoryAmount; var i = bi.Get(x => x.InventoryID == inventory.InventoryID); i.Quantity = newQuantity; bi.Update(i); left = 0; } else { left -= inventoryAmount; bi.Delete(x => x.InventoryID == inventory.InventoryID); } } } } } } return GetFood(vatID, startDate, finishDate); } public decimal SetAmount(int vatID, decimal amount, DateTime startDate, DateTime finishDate) { var random = new Random(); var list = Randomize(new VoucherBI().List(x => x.Date >= startDate && x.Date <= finishDate && x.Void == false && x.VoucherType != VoucherType.NoCharge && x.VoucherType != VoucherType.Staff)); var left = GetFood(vatID, startDate, finishDate) - amount; foreach (var item in list) { if (left <= 0) break; var discount = Convert.ToDecimal(random.Next(20, 70)); discount -= discount % 5; discount = discount / 100; foreach (var kot in item.Kots) { if (left <= 0) break; foreach (var inventory in kot.Inventories) { if (left <= 0) break; if (inventory.Product.Vat.TaxID == vatID) { using (var bi = new InventoryBI()) { if (discount < inventory.Discount) continue; var inventoryAmount = inventory.Quantity * inventory.Price * (1 - inventory.Discount) * (1 + (inventory.IsScTaxable ? inventory.ServiceCharge : 0)); var reduction = inventory.Quantity * inventory.Price * (discount - inventory.Discount) * (1 + (inventory.IsScTaxable ? inventory.ServiceCharge : 0)); if (reduction > left) { var newDiscount = (1 - inventory.Discount) * left / inventoryAmount; var i = bi.Get(x => x.InventoryID == inventory.InventoryID); i.Discount = newDiscount; bi.Update(i); left = 0; } else { var i = bi.Get(x => x.InventoryID == inventory.InventoryID); i.Discount = discount; bi.Update(i); left -= reduction; } } } } } } return GetFood(vatID, startDate, finishDate); } public IList GetNcable(DateTime startDate, DateTime finishDate) { const string query = @" select v.VoucherID, sum(case when p.TaxID = 1 then i.ServiceCharge else 0 end) , 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 group by p.BaseCode order by p.BaseCode "; var list = Session .CreateQuery(query) .SetParameter("startDate", startDate) .SetParameter("finishDate", finishDate) .List(); return list; } public IList GetMove(DateTime startDate, DateTime finishDate) { const string query = @" select p.BaseCode, 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 != 0 group by p.BaseCode order by p.BaseCode "; var list = Session .CreateQuery(query) .SetParameter("startDate", startDate) .SetParameter("finishDate", finishDate) .List(); return list; } public decimal GetQuantity(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 = GetQuantity(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 GetQuantity(baseCode, startDate, finishDate); } public void SetMove(int fromBaseCode, int toBaseCode, DateTime startDate, DateTime finishDate) { var list = Randomize(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); } } } } } } } 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 // Festival 409 // BaseCode = 6 // Vanilla 408, 587 // BaseCode = 7 // Strong 697, 708, 707 // BaseCode = 8 if (code == 301 || code == 300 || code == 299 || code == 297 || code == 677 || code == 408 || code == 697) { 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 408; if (toBaseCode == 8) return 697; } if (code == 305 || code == 304 || code == 303 || code == 302 || code == 679 || code == 409 || code == 708) { 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 409; if (toBaseCode == 7) return code; if (toBaseCode == 8) return 708; } if (code == 384 || code == 383 || code == 382 || code == 363 || code == 678 || code == 587 || code == 707) { 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 587; if (toBaseCode == 8) return 707; } return code; } private static IList Randomize(IEnumerable 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(); } } }