using System; using System.Collections.Generic; using System.Linq; using System.Text; using Tanshu.Accounts.Repository; using Tanshu.Accounts.Helpers; using Tanshu.Accounts.Contracts; using System.Windows.Forms; using Tanshu.Common; using Tanshu.Accounts.Entities; using Tanshu.Accounts.Entities.Auth; using Tanshu.Accounts.SqlDAO; using System.Collections.ObjectModel; namespace Tanshu.Accounts.PointOfSale { public class BillController { private Voucher billInfo; private OrderedDictionary bill = new OrderedDictionary(); int? editVoucherID; ISaleForm saleForm; private Customer customer = new CustomerBI().GetCustomer(1); public BillController(int? editVoucherID) { this.editVoucherID = editVoucherID; } 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(); Product 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; decimal discount = frm.Selection(out outList); discount = discount / 100; foreach (var item in bill) { if (item.Key.KotID == -1) continue; var 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 (SelectCustomer selectCustomer = new SelectCustomer(new CustomerBI().GetFilteredCustomers, true)) { selectCustomer.customerEvent += new CustomerEventHandler(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); } } #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, Settled = SettleOption.Unsettled, //Paid = finalBill, TableID = tableID, Waiter = WaiterBI.GetWaiter(waiterID), Printed = finalBill, Void = false, Date = DateTime.Now, Narration = "", User = Session.User }; #endregion #region Inventories var 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); var 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) { var oldKot = billInfo.Kots.Where(x => x.KotID == item.Key.KotID).Single(); var inv = oldKot.Inventories.Where(x => x.Product.ProductID == item.Key.ProductID).Single(); inv.Rate = item.Value.Price; inv.Discount = item.Value.Discount; } else { Inventory 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 (var 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 public void VoidBill() { if (billInfo == null) return; if (!billInfo.Printed) return; if (Session.IsAllowed(RoleConstants.VOID_BILL)) { if (MessageBox.Show("Are you sure you want to void this bill?", "Void Bill", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { SelectVoidReason 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); } } } } Customer selectCustomer_customerEvent(object sender, CustomerEventArgs e) { using (CustomersForm form = new CustomersForm(e.CustomerID, e.Phone)) { form.ShowDialog(); return form.Customer; } } private void PrintBill(int voucherID, int kotID) { if (kotID == 0) Accounts.Print.Thermal.PrintBill(voucherID); else Accounts.Print.Thermal.PrintKot(voucherID, kotID); } private List GetVoidReason(Dictionary filter) { List list = new List(); list.Add(new StringType("Discount")); list.Add(new StringType("Printing Fault")); list.Add(new StringType("Item Changed")); list.Add(new StringType("Quantity Reduced")); list.Add(new StringType("Costing Bill for Party")); list.Add(new StringType("Cashier Mistake")); list.Add(new StringType("Management Freesale")); list.Add(new StringType("Other")); return list.Where(i => i.Description.ToLower().Contains(filter["Name"].ToLower().Trim())).ToList(); } 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; else return item.Value; } } } public BillInventory CurrentKot { get { if (saleForm.BindingSource.Position == -1) return null; else { var item = bill.ElementAt(saleForm.BindingSource.Position); if (item.Key.KotID != -1) return null; else if (item.Key.ProductID == 0) return null; else return item.Value; } } } private void ShowAmount() { //saleForm.BindingSource.CurrencyManager.Position = 1; decimal taxAmount = bill.Values.Sum(b => b.TaxAmount); decimal discountAmount = bill.Values.Sum(b => b.DiscountAmount); decimal grossAmount = bill.Values.Sum(b => b.GrossAmount); decimal valueAmount = bill.Values.Sum(b => b.Value); decimal 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; if (!Session.IsAllowed(role)) return false; return true; } 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.GetSaleVoucher(voucherID); this.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) { BillItemKey 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) { BillItemKey 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); } } BillItemKey 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().GetByName(tableName); if (table != null && table.VoucherID != 0) { LoadBill(table.VoucherID); } } else { InputBoxResult result = InputBox.Show("Table Number", "0", InputBox_Validating); if (result.OK) { string tableID = result.Text.Trim(); if ((tableID != "C") && (tableID != "") && (!tableID.Contains("."))) { var table = new FoodTableBI().GetByName(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(); BillItemKey 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; var option = SettleOption.Unsettled; using (BillSettleForm frm = new BillSettleForm()) { frm.ShowDialog(); option = frm.optionChosen; } if (option != SettleOption.Unsettled) { VoucherBI.SettleVoucher(Session.User, billInfo.VoucherID, option); 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; if (table.VoucherID == 0) LoadBill(MoveTable(table)); else LoadBill(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 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, Settled = SettleOption.Unsettled, TableID = table.Name, Waiter = billInfo.Waiter, Printed = false, Void = false, Date = DateTime.Now, Narration = "", User = Session.User }; VoucherBI.Insert(voucher); } private 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); int 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); } } }