using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows; using System.Windows.Controls; using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Motorola.Snapi; using Motorola.Snapi.Constants.Enums; using Motorola.Snapi.EventArguments; //using RestSharp; namespace PRSDesktop { /// /// Interaction logic for RequisitionPanel.xaml /// public partial class RequisitionPanel : UserControl, IPanel { private Requisition _requisition; public List Scanners = new(); public RequisitionPanel() { InitializeComponent(); PickImage.Source = PRSDesktop.Resources.tick.AsBitmapImage(Color.White); StockImage.Source = PRSDesktop.Resources.forklift.AsBitmapImage(Color.White); TruckImage.Source = PRSDesktop.Resources.truck.AsBitmapImage(); } //DateTime lastselection = DateTime.MaxValue; //DispatcherTimer timer = new DispatcherTimer(); public event DataModelUpdateEvent OnUpdateDataModel; public bool IsReady { get; set; } public Dictionary Selected() { return new Dictionary { { typeof(Requisition).EntityName(), Requisitions.SelectedRows }, { typeof(RequisitionItem).EntityName(), Items.SelectedRows } }; } public void Setup() { //Requisitions.OnSelectItem += Requisitions_OnSelectItem; //Requisitions.OnRequisitionFillStateChanged += Requisitions_OnRequisitionFillStateChanged; //Requisitions.OnRequisitionBoxesChanged += Requisitions_OnRequisitionBoxesChanged; SetupScanner(); Requisitions.Refresh(true, false); Items.Refresh(true, false); UpdateLayout(); } public void Shutdown() { ShutdownScanner(); } public void CreateToolbarButtons(IPanelHost host) { //host.CreatePanelAction(new PanelAction() { Caption = "Archive Requisition", Image = PRSDesktop.Resources.delete, OnExecute = ArchiveRequisition }); } public string SectionName => "Requisitions"; public DataModel DataModel(Selection selection) { var ids = Requisitions.ExtractValues(x => x.ID, selection).ToArray(); return new BaseDataModel(new Filter(x => x.ID).InList(ids)); } public void Refresh() { Requisitions.Refresh(false, true); //lastselection = DateTime.MinValue; //Items.Refresh(true, false); } public void Heartbeat(TimeSpan time) { // Nothing to do here } private void ShutdownScanner() { try { foreach (var scanner in Scanners) scanner.Actions.ToggleLed(LedMode.GreenOff); BarcodeScannerManager.Instance.DataReceived -= Instance_DataReceived; BarcodeScannerManager.Instance.Close(); } catch (Exception e) { MessageBox.Show("Error Shutting down Scanner!\n\n" + e.Message); } } private void SetupScanner() { Scanners.Clear(); BarcodeScannerManager.Instance.Open(); BarcodeScannerManager.Instance.RegisterForEvents(EventType.Barcode, EventType.Pnp, EventType.Image, EventType.Other, EventType.Rmd); BarcodeScannerManager.Instance.GetDevices(); foreach (var scanner in BarcodeScannerManager.Instance.GetDevices()) { Scanners.Add(scanner); scanner.Actions.ToggleLed(LedMode.RedOn); scanner.Actions.SoundBeeper(BeepPattern.FastWarble); } BarcodeScannerManager.Instance.DataReceived += Instance_DataReceived; } private void Instance_DataReceived(object sender, BarcodeScanEventArgs e) { Dispatcher.Invoke(() => { ProcessCode(Scanners[(int)e.ScannerId], e.Data); }); } private void ProcessCode(IMotorolaBarcodeScanner scanner, string code) { try { var iRow = Requisitions.SelectedRows.First().Index; if (iRow == -1) throw new Exception("Please select a Requsition First"); var row = Requisitions.Data.Rows[iRow]; var filled = row.Get(x => x.Filled); if (!filled.IsEmpty()) throw new Exception("Cannot Add Items to a completed Requisition"); var reqid = row.Get(x => x.ID); var boxes = row.Get(x => x.Boxes); var sCode = code; var iQty = 1; if (sCode.Contains("*")) { var comps = sCode.Split('*'); sCode = comps[0]; iQty = int.Parse(comps[1].Trim()); } RequisitionItem item = null; CoreRow itemrow = null; try { itemrow = Items.Data.Rows.FirstOrDefault(r => /* r.Get(x => x.BoxNumber).Equals(boxes) && */ r.Get(x => x.BarCode).Equals(sCode)); //itemrow = Items.Data.Rows.FirstOrDefault(r => r.Get(x => x.BarCode).Equals(sCode)); } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } if (itemrow != null) item = new Client() .Load(new Filter(x => x.ID).IsEqualTo(itemrow.Get(x => x.ID))).FirstOrDefault(); if (item != null) { item.Quantity += iQty; new Client().Save(item, "Quantity Updated by Barcode Scanner"); if (scanner != null) scanner.Actions.SoundBeeper(BeepPattern.LowHigh); Refresh(); } else { var product = new Client().Load(new Filter(x => x.Code).IsEqualTo(sCode)).FirstOrDefault(); if (product != null) { item = new RequisitionItem { RequisitionLink = new RequisitionLink { ID = reqid }, //BoxNumber = boxes, Code = product.Code, Description = product.Name, BarCode = sCode, Quantity = iQty }; new Client().Save(item, "Scanned by Barcode Reader"); if (scanner != null) scanner.Actions.SoundBeeper(BeepPattern.LowHigh); Refresh(); } else { if (scanner != null) scanner.Actions.SoundBeeper(BeepPattern.FourLowLong); } } } catch (Exception e) { if (scanner != null) scanner.Actions.SoundBeeper(BeepPattern.FourLowShort); } } private void ArchiveRequisition(PanelAction obj) { var bClosed = false; var iRow = Requisitions.SelectedRows.First().Index; if (iRow > -1) { var row = Requisitions.Data.Rows[iRow]; var id = row.Get(x => x.ID); var filled = row.Get(x => x.Filled); if (filled.IsEmpty()) { MessageBox.Show("Please complete this requisition before Archiving it!"); } else { var req = new Client().Load(new Filter(x => x.ID).IsEqualTo(id)).FirstOrDefault(); if (req != null) { req.Archived = DateTime.Now; new Client().Save(req, "Requisition Archived"); bClosed = true; } } } else { MessageBox.Show("Please select a requisition first!"); } if (bClosed) Refresh(); } public Dictionary DataEnvironment() { var env = new Dictionary(); env[typeof(Requisition)] = Requisitions.Data; env[typeof(RequisitionItem)] = Items.Data; return env; } //private void Timer_Tick(object sender, EventArgs e) //{ // if (lastselection < DateTime.Now.AddMilliseconds(-500)) // { // lastselection = DateTime.MaxValue; // LoadRequisition(); // } //} private void LoadRequisition() { foreach (var scanner in Scanners) scanner.Actions.ToggleLed(_requisition != null ? LedMode.GreenOn : LedMode.RedOn); Title.Text = _requisition != null ? _requisition.Title : ""; RequestedBy.Content = _requisition != null ? _requisition.RequestedBy.Name : ""; DueDate.Content = _requisition != null ? string.Format("{0:dddd, dd MMM yyyy}", _requisition.Due) : ""; var notes = _requisition != null ? _requisition.Notes : new string[] { }; var request = _requisition != null ? CoreUtils.StripHTML(_requisition.Request) : ""; Request.Text = string.Join("\n===============================\n", Utility.ProcessNotes(notes, request)); MarkAsFilled.IsEnabled = _requisition != null && _requisition.Archived.IsEmpty() && _requisition.StockUpdated.IsEmpty(); MarkAsFilledDescription.Content = _requisition == null || _requisition.Filled.IsEmpty() ? "Mark As Filled" : "Clear Filled Flag"; Items.Options.BeginUpdate(); if (_requisition != null) { if (_requisition.Filled.IsEmpty()) { Items.Options.Add(DynamicGridOption.AddRows); Items.Options.Add(DynamicGridOption.DeleteRows); } else { Items.Options.Remove(DynamicGridOption.AddRows); Items.Options.Remove(DynamicGridOption.DeleteRows); } } Items.Options.EndUpdate(); UpdateStock.IsEnabled = Security.IsAllowed() && _requisition != null && !_requisition.Filled.IsEmpty(); UpdateStockDescription.Content = _requisition == null || _requisition.StockUpdated.IsEmpty() ? "Update Stock Holdings" : "Clear Stock Movements"; TakenBy.IsEnabled = _requisition != null && !_requisition.Filled.IsEmpty() && _requisition.Archived.IsEmpty() && !_requisition.Delivery.IsValid(); TakenByDescription.Content = _requisition == null ? "Select Employee" : _requisition.Delivery.IsValid() ? _requisition.Delivery.Completed.IsEmpty() ? string.Format("Booked On Delivery #{0}", _requisition.Delivery.Number) : string.Format("Delivered on {0:dd MMM yy} (#{1})", _requisition.Delivery.Completed, _requisition.Delivery.Number) : _requisition.TakenBy.IsValid() ? string.Format("{0} ({1:dd MMM yy})", _requisition.TakenBy.Name, _requisition.Archived) : "Select Employee"; } private void Requisitions_OnSelectItem(object sender, DynamicGridSelectionEventArgs e) { _requisition = e.Rows?.FirstOrDefault()?.ToObject(); LoadRequisition(); Items.Requisition = _requisition; Items.Refresh(false, true); //lastselection = DateTime.Now; //Dispatcher.Invoke(() => { LoadRequisition(); }); } private void TakenBy_Click(object sender, RoutedEventArgs e) { if (_requisition == null || _requisition.ID == Guid.Empty) return; var dlg = new MultiSelectDialog( LookupFactory.DefineFilter(), LookupFactory.DefineColumns(), false); if (!dlg.ShowDialog()) return; if (!_requisition.Filled.IsEmpty() && !_requisition.StockUpdated.IsEmpty()) if (MessageBox.Show("This will remove this requisition from this list.\nAre you sure you wish to continue?", "Close Requisition?", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) return; if (_requisition.Archived.IsEmpty()) _requisition.Archived = DateTime.Now; var emp = dlg.Data()?.Rows.FirstOrDefault(); _requisition.TakenBy.ID = emp != null ? emp.Get(x => x.ID) : Guid.Empty; _requisition.TakenBy.Name = emp != null ? emp.Get(x => x.Name) : ""; Progress.Show("Updating Requisition Delivery Status"); new Client().Save(_requisition, "Updated [TakenBy] Flag"); if (!_requisition.Filled.IsEmpty() && !_requisition.StockUpdated.IsEmpty() && !_requisition.Archived.IsEmpty()) { Refresh(); } else { Requisitions.UpdateRow(Requisitions.SelectedRows.First(), x => x.TakenBy.ID, _requisition.TakenBy.ID, false); Requisitions.UpdateRow(Requisitions.SelectedRows.First(), x => x.TakenBy.Name, _requisition.TakenBy.Name, false); Requisitions.UpdateRow(Requisitions.SelectedRows.First(), x => x.Archived, _requisition.Archived); LoadRequisition(); } Progress.Close(); } private void MarkAsFilled_Click(object sender, RoutedEventArgs e) { if (_requisition == null) { MessageBox.Show("Please select a Requisition first!"); return; } DateTime filltime = DateTime.Now; var unpickeditems = Items.Data.Rows.Where(r => _requisition.Filled.IsEmpty() && (r.Get(x => x.Product.ID) != Guid.Empty) && (r.Get(x => x.Product.NonStock) != true) && (r.Get(x => x.Picked).IsEmpty()) ); if (unpickeditems.Any()) { var confirm = MessageBox.Show("Unpicked items exist on this requisition!\n\nDo you want to mark them as picked now?", "Unpicked Items", MessageBoxButton.YesNoCancel, MessageBoxImage.Question); if (confirm == MessageBoxResult.Cancel) return; filltime = DateTime.Now; if (confirm == MessageBoxResult.Yes) { List updates = new List(); foreach (var row in unpickeditems) { var item = row.ToObject(); item.Picked = filltime; updates.Add(item); } new Client().Save(updates, "Marked as Picked because Requisition was marked as filled"); } } _requisition.Filled = _requisition.Filled.IsEmpty() ? filltime : DateTime.MinValue; Progress.Show(_requisition.Filled.IsEmpty() ? "Clearing Delivery Items" : "Creating Delivery Items"); new Client().Save(_requisition, "Updated Filled Flag"); Requisitions.UpdateRow(Requisitions.SelectedRows.First(), x => x.Filled, _requisition.Filled); LoadRequisition(); Items.Refresh(false, true); Progress.Close(); } private void UpdateStock_Click(object sender, RoutedEventArgs e) { if (_requisition == null) { MessageBox.Show("Please select a Requisition first!"); return; } if (_requisition.StockUpdated.IsEmpty()) { var emptyrows = Items.Data.Rows.Where(r => !Entity.IsEntityLinkValid(x => x.Location, r) && r.Get(c => c.Product.NonStock).Equals(false)); if (emptyrows.Any()) { MessageBox.Show("You must select a Holding for each non-stock Item on this Requisition!", "Missing Holdings", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (!_requisition.Filled.IsEmpty() && !_requisition.Archived.IsEmpty()) { if (MessageBox.Show("This will remove this requisition from this list.\nAre you sure you wish to continue?", "Close Requisition?", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) return; } else { if (MessageBox.Show("Update Stock Movements?", "Confirm", MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; } _requisition.StockUpdated = DateTime.Now; } else { if (MessageBox.Show("Clear Stock Movements?", "Confirm", MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; _requisition.StockUpdated = DateTime.MinValue; } Progress.Show("Updating Stock Holdings"); new Client().Save(_requisition, "Updated Stock Flag"); if (!_requisition.Filled.IsEmpty() && !_requisition.StockUpdated.IsEmpty() && !_requisition.Archived.IsEmpty()) { Refresh(); } else { Requisitions.UpdateRow(Requisitions.SelectedRows.First(), x => x.StockUpdated, _requisition.StockUpdated); LoadRequisition(); } Progress.Close(); } } }