using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using Tanshu.Accounts.Contracts; using Tanshu.Accounts.Entities; using Tanshu.Accounts.Helpers; using Tanshu.Accounts.PointOfSale.Sales; using Tanshu.Accounts.Print; using Tanshu.Accounts.Repository; using Tanshu.Common; namespace Tanshu.Accounts.PointOfSale { public class BillController { private readonly OrderedDictionary bill = new OrderedDictionary(); private Voucher _billInfo; private Customer _customer = new CustomerBI().GetCustomer(1); private int? _editVoucherID; private ISaleForm _saleForm; public BillController(int? editVoucherID) { this._editVoucherID = editVoucherID; } public BillInventory CurrentProduct { get { if (_saleForm.BindingSource.Position == -1) return null; else { var item = bill.ElementAt(_saleForm.BindingSource.Position); if (item.Key.KotID == -1) return null; return item.Value; } } } public BillInventory CurrentKot { get { if (_saleForm.BindingSource.Position == -1) return null; else { KeyValuePair item = bill.ElementAt(_saleForm.BindingSource.Position); if (item.Key.KotID != -1) return null; if (item.Key.ProductID == 0) return null; return item.Value; } } } public void InitGui(ISaleForm saleForm) { this._saleForm = saleForm; this._saleForm.SetCustomerDisplay(_customer.Name); this._saleForm.SetUserName(Session.User.Name); } private void InitComponents() { InitModel(); InitView(); } private void InitView() { throw new NotImplementedException(); } private void InitModel() { throw new NotImplementedException(); } public void AddProductToGrid(int productID) { new BillHelperFunctions(_saleForm.BindingSource, bill, productID).AddProduct(); var product = ProductBI.GetProduct(productID); if (ProductGroupModifierBI.HasCompulsoryModifier(product.ProductGroup.ProductGroupID)) { var item = CurrentProduct; ShowModifiers(product.ProductGroup.ProductGroupID, item); } ShowAmount(); } public void ShowModifiers(int productGroupID, BillInventory item) { if (item.Printed) return; var list = ProductGroupModifierBI.GetProductGroupModifiers(productGroupID); using (var frm = new ModifierForm(list, item.Modifiers)) { frm.ShowDialog(); item.Modifiers = frm.Selection; } ShowAmount(); } public void ShowDiscount() { if (!Session.IsAllowed(RoleConstants.DISCOUNT)) return; var list = new ProductGroupBI().GetProductGroupTypes(); using (var frm = new DiscountForm(list)) { if (frm.ShowDialog() == DialogResult.OK) { HashSet outList; var discount = frm.Selection(out outList); discount = discount / 100; foreach (var item in bill) { if (item.Key.KotID == -1) continue; ProductGroup pg = new ProductGroupBI().GetProductGroupOfProduct(item.Value.ProductID); if (outList.Contains(pg.GroupType)) new BillHelperFunctions(_saleForm.BindingSource, bill, item.Value.ProductID).SetDiscount( item.Value.Name, discount); } } } ShowAmount(); } public void ShowCustomerList(bool reset) { if ((_customer.CustomerID == 1) && (!reset)) { using (var selectCustomer = new SelectCustomer(new CustomerBI().GetFilteredCustomers, true)) { selectCustomer.customerEvent += selectCustomer_customerEvent; selectCustomer.ShowDialog(); if (selectCustomer.SelectedItem != null) { _customer = selectCustomer.SelectedItem; _saleForm.SetCustomerDisplay(_customer.Name); } else { _customer = new CustomerBI().GetCustomer(1); } } } else { _customer = new CustomerBI().GetCustomer(1); _saleForm.SetCustomerDisplay(_customer.Name); } } public void VoidBill() { if (_billInfo == null) return; if (!_billInfo.Printed) return; if (!Session.IsAllowed(RoleConstants.VOID_BILL)) return; if (MessageBox.Show("Are you sure you want to void this bill?", "Void Bill", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != DialogResult.Yes) return; var voidReason = new SelectVoidReason(GetVoidReason, true); voidReason.ShowDialog(); if (voidReason.SelectedItem != null) { VoucherBI.VoidBill(_billInfo.VoucherID, voidReason.SelectedItem.Description); ClearBill(); } else { MessageBox.Show("Please Select a reason if you want to void the bill", "Bill NOT Voided", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } } private Customer selectCustomer_customerEvent(object sender, CustomerEventArgs e) { using (var form = new CustomersForm(e.CustomerID, e.Phone)) { form.ShowDialog(); return form.Customer; } } private static void PrintBill(int voucherID, int kotID) { if (kotID == 0) Thermal.PrintBill(voucherID); else Thermal.PrintKot(voucherID, kotID); } private static List GetVoidReason(Dictionary filter) { var list = new List { new StringType("Discount"), new StringType("Printing Fault"), new StringType("Item Changed"), new StringType("Quantity Reduced"), new StringType("Costing Bill for Party"), new StringType("Cashier Mistake"), new StringType("Management Freesale"), new StringType("Other") }; return list.Where(i => i.Description.ToLower().Contains(filter["Name"].ToLower().Trim())).ToList(); } private void ShowAmount() { //saleForm.BindingSource.CurrencyManager.Position = 1; var taxAmount = bill.Values.Sum(b => b.TaxAmount); var discountAmount = bill.Values.Sum(b => b.DiscountAmount); var grossAmount = bill.Values.Sum(b => b.GrossAmount); var valueAmount = bill.Values.Sum(b => b.Value); var serviceChargeAmount = bill.Values.Sum(b => b.ServiceChargeAmount); //bill.Values.ToList(); _saleForm.ShowAmount(discountAmount, grossAmount, serviceChargeAmount, taxAmount, valueAmount, bill.Values.ToList()); } public void ProductRemove() { var item = CurrentProduct; if (!Allowed(item)) return; if (item.Printed) return; bill.Remove(new BillItemKey(item.ProductID, 0)); bill.ReCompact(); ShowAmount(); } public void SetQuantity(decimal quantity, bool prompt) { var item = CurrentProduct; if (!Allowed(item)) return; new BillHelperFunctions(_saleForm.BindingSource, bill, CurrentProduct.ProductID).SetQuantity(item, quantity, prompt); ShowAmount(); } public void ChangeRate() { var item = CurrentProduct; if (!Allowed(item)) return; new BillHelperFunctions(_saleForm.BindingSource, bill, CurrentProduct.ProductID).SetPrice(CurrentProduct); ShowAmount(); } private bool Allowed(BillInventory item, RoleConstants role) { if (item == null) return false; return Session.IsAllowed(role); } private bool Allowed(BillInventory item) { return item != null; } private void InputBox_Validating(object sender, InputBoxValidatingArgs e) { } private void LoadBill(int voucherID) { ClearBill(); bill.Clear(); _billInfo = null; _billInfo = VoucherBI.Get(voucherID); _customer = _billInfo.Customer; _saleForm.ShowInfo(_billInfo.BillID, _billInfo.KotID, _billInfo.CreationDate, _billInfo.Date.Value, _billInfo.LastEditDate, _customer.Name, _billInfo.TableID, _billInfo.Waiter.WaiterID, _billInfo.Waiter.Name); foreach (var kot in _billInfo.Kots) { var kotKey = new BillItemKey(kot.KotID, -1); var kotItem = new BillInventory { ProductID = kot.KotID, Discount = 0, Name = string.Format("Kot No.: {0} / KotID {1}", kot.KotID, kot.Code), Price = 0, Printed = true, Quantity = 0, Tax = -1, ServiceCharge = 0, }; bill.Add(kotKey, kotItem); foreach (var inv in kot.Inventories) { var key = new BillItemKey(inv.Product.ProductID, kot.KotID); var item = new BillInventory { ProductID = inv.Product.ProductID, Discount = inv.Discount, Name = inv.Product.Units == string.Empty ? inv.Product.Name : inv.Product.Name + " (" + inv.Product.Units + ")", Price = inv.Rate, Printed = true, Quantity = inv.Quantity, Tax = inv.Tax, ServiceCharge = inv.ServiceCharge, }; foreach (var mod in inv.InventoryModifier) item.Modifiers.Add(mod.Modifier); bill.Add(key, item); } } var newKotKey = new BillItemKey(0, -1); var newKotItem = new BillInventory { ProductID = 0, Discount = 0, Name = "== New Kot ==", Price = 0, Printed = true, Quantity = 0, Tax = -1, ServiceCharge = 0, }; bill.Add(newKotKey, newKotItem); ShowAmount(); } public void LoadBillFromTable(string tableName) { if (!string.IsNullOrEmpty(tableName)) { var table = new FoodTableBI().Get(tableName); if (table != null && table.VoucherID != 0) { LoadBill(table.VoucherID); } } else { var result = InputBox.Show("Table Number", "0", InputBox_Validating); if (result.OK) { var tableID = result.Text.Trim(); if ((tableID != "C") && (tableID != "") && (!tableID.Contains("."))) { var table = new FoodTableBI().Get(tableName); if (table != null && table.VoucherID != 0) { LoadBill(table.VoucherID); } } else ClearBill(); } } } public void CancelBillChanges() { if (bill.Count != 0 && bill.Values.Any(i => i.Printed == false)) if ( MessageBox.Show("Abandon Changes?", "Abandon Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) return; ClearBill(); } public void ClearBill() { _billInfo = null; ShowCustomerList(true); bill.Clear(); var newKotKey = new BillItemKey(0, -1); var newKotItem = new BillInventory { ProductID = 0, Discount = 0, Name = "== New Kot ==", Price = 0, Printed = true, Quantity = 0, Tax = -1, ServiceCharge = 0, }; bill.Add(newKotKey, newKotItem); _saleForm.ClearBill(bill); } public void FormLoad() { ClearBill(); if (_editVoucherID.HasValue) { LoadBill(_editVoucherID.Value); } } internal void SettleBill() { if (_billInfo == null) return; if (!_billInfo.Printed) return; if (!Session.IsAllowed(RoleConstants.SETTLE_BILL)) return; IDictionary options; using (var frm = new SettleChoicesForm(_billInfo)) { frm.ShowDialog(); options = frm.OptionsChosen; } if (options.Count == 0) return; VoucherBI.SettleVoucher(Session.User, _billInfo.VoucherID, options); ClearBill(); } internal void MoveTable() { if (_billInfo == null) return; if (VoucherBI.IsBillPrinted(_billInfo.VoucherID) && !Session.IsAllowed(RoleConstants.EDIT_PRINTED_BILL)) return; var table = GetTableForMove(true); if (table == null) return; LoadBill(table.VoucherID == 0 ? MoveTable(table) : MergeTable(table)); } private int MoveTable(FoodTable table) { if (!Session.IsAllowed(RoleConstants.MOVE_TABLE)) return 0; return new FoodTableBI().Move(_billInfo.TableID, table); } private int MergeTable(FoodTable table) { if (!Session.IsAllowed(RoleConstants.MERGE_TABLE)) return 0; var kots = bill.Where(x => x.Key.KotID == -1 && x.Key.ProductID != 0); foreach (var item in kots) MergeKot(item.Value, table); VoucherBI.Delete(_billInfo.VoucherID); return table.VoucherID; } private static int MergeKot(BillInventory kot, FoodTable table) { if (!Session.IsAllowed(RoleConstants.MERGE_KOT)) return 0; return VoucherBI.MoveKot(kot.ProductID, table); } private int MoveKot(BillInventory kot, FoodTable table) { if (!Session.IsAllowed(RoleConstants.MOVE_KOT)) return 0; CreateNewVoucherForKotMove(kot, table); return MergeKot(kot, table); } private void CreateNewVoucherForKotMove(BillInventory kot, FoodTable table) { var voucher = new Voucher { Customer = _billInfo.Customer, TableID = table.Name, Waiter = _billInfo.Waiter, Printed = false, Void = false, Date = DateTime.Now, Narration = "", User = Session.User }; VoucherBI.Insert(voucher); } private static FoodTable GetTableForMove(bool allowMerge) { using (var frm = new frmMoveTable(new FoodTableBI().List(), allowMerge)) { frm.ShowDialog(); if (frm.Selection != null) return frm.Selection; } return null; } internal void MergeKot() { if (_billInfo == null) return; if (VoucherBI.IsBillPrinted(_billInfo.VoucherID) && !Session.IsAllowed(RoleConstants.EDIT_PRINTED_BILL)) return; var kot = CurrentKot; if (kot == null) return; var table = GetTableForMove(true); if (table == null) return; var count = bill.Keys.Count(x => x.KotID == -1 && x.ProductID != 0); var voucherID = 0; if (table.VoucherID == 0 && count > 1) //Move Kot voucherID = MoveKot(kot, table); else if (table.VoucherID == 0 && count == 1) //Move Table voucherID = MoveTable(table); else if (table.VoucherID != 0 && count > 1) //Merge Kot voucherID = MergeKot(kot, table); else if (table.VoucherID != 0 && count == 1) //Merge Table voucherID = MergeTable(table); if (voucherID != 0) LoadBill(voucherID); } #region Save // if (btnWaiter.Tag == null) //btnWaiter.Tag = WaiterBI.GetWaiters()[0].WaiterID; public void Save(bool print, int waiterID, string tableID) { if (print && !Session.IsAllowed(RoleConstants.PRINT_BILL)) return; if (!print && !Session.IsAllowed(RoleConstants.PRINT_KOT)) return; if ((_billInfo != null) && (VoucherBI.IsBillPrinted(_billInfo.VoucherID)) && (!Session.IsAllowed(RoleConstants.EDIT_PRINTED_BILL))) return; if (bill.Count == 1) //new kot only return; if (print) ShowDiscount(); int? saved; if (_billInfo == null) saved = InsertVoucher(print, waiterID, tableID); else saved = UpdateSale(print, waiterID, tableID); if (_editVoucherID.HasValue) _saleForm.CloseWindow(); else { int kotID = 0; if (!print && saved.HasValue) kotID = saved.Value; if (print || kotID != 0) PrintBill(_billInfo.VoucherID, kotID); } ClearBill(); } private int? InsertVoucher(bool finalBill, int waiterID, string tableID) { if (_billInfo != null) { MessageBox.Show("Error in InsertVoucher, there is a previous sale in memory", "Error"); return null; } #region Voucher _billInfo = new Voucher { Customer = _customer, //Paid = finalBill, TableID = tableID, Waiter = WaiterBI.GetWaiter(waiterID), Printed = finalBill, Void = false, Date = DateTime.Now, Narration = "", User = Session.User }; #endregion #region Inventories Kot kot = GetKotForBill(); if (kot != null) _billInfo.Kots.Add(kot); #endregion return VoucherBI.Insert(_billInfo); } private int? UpdateSale(bool finalBill, int waiterID, string tableID) { #region Voucher _billInfo.User = Session.User; _billInfo.Customer = _customer; if (!_billInfo.Printed && finalBill) _billInfo.Date = null; _billInfo.Printed = _billInfo.Printed || finalBill; _billInfo.TableID = tableID; _billInfo.Waiter = WaiterBI.GetWaiter(waiterID); Kot kot = GetKotForBill(); if (kot != null) _billInfo.Kots.Add(kot); #endregion #region Inventory #endregion return VoucherBI.Update(_billInfo); } private Kot GetKotForBill() { var kot = new Kot(); foreach (var item in bill) { if (item.Key.KotID == -1 || item.Value.Quantity == 0) continue; else if (item.Key.KotID != 0) { Kot oldKot = _billInfo.Kots.Where(x => x.KotID == item.Key.KotID).Single(); Inventory inv = oldKot.Inventories.Where(x => x.Product.ProductID == item.Key.ProductID).Single(); inv.Rate = item.Value.Price; inv.Discount = item.Value.Discount; } else { var temp = new Inventory(); temp.Product = ProductBI.GetProduct(item.Key.ProductID); temp.Quantity = item.Value.Quantity; temp.Rate = item.Value.Price; temp.Discount = item.Value.Discount; temp.ServiceCharge = item.Value.ServiceCharge; temp.Tax = item.Value.Tax; foreach (Modifier mod in item.Value.Modifiers) temp.InventoryModifier.Add(new InventoryModifier { Modifier = mod }); kot.Inventories.Add(temp); } } if (kot.Inventories.Count == 0) return null; else return kot; } #endregion } }