using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.Core.Reports; using InABox.Wpf.Reports; using InABox.WPF; using Motorola.Snapi; using Motorola.Snapi.Constants.Enums; using Motorola.Snapi.EventArguments; using BarcodeType = Comal.Classes.BarcodeType; using Color = System.Drawing.Color; using Image = System.Windows.Controls.Image; using InABox.Wpf; using System.ComponentModel; namespace PRSDesktop { /// /// Interaction logic for FactoryPanel.xaml /// public partial class FactoryPanel : IPanel { private readonly BitmapImage barcode = PRSDesktop.Resources.barcode.AsBitmapImage(); private readonly BitmapImage disabled = PRSDesktop.Resources.disabled.AsBitmapImage(); private readonly BitmapImage speechbubble = PRSDesktop.Resources.speechbubble.AsBitmapImage(); private readonly BitmapImage starred = PRSDesktop.Resources.report.AsBitmapImage(48, 48); private readonly BitmapImage grouped = PRSDesktop.Resources.grouped.AsBitmapImage(); private SetoutDocument[] documents = Array.Empty(); private readonly List _scanners = new List(); private readonly string NEARLYDUE_COLOR = "Orange"; private readonly string NOTYETDUE_COLOR = "PaleGreen"; private readonly string OVERDUE_COLOR = "Salmon"; private readonly string PRIORITY_COLOR = "Red"; private readonly string QA_COLOR = "Silver"; private readonly string SELECTED_COLOR = "Yellow"; private readonly string SHARED_COLOR = "Lime"; private readonly string TREATED_COLOR = "DarkOrchid"; private Button? _currentButton; private PDFEditorControl? PDFEditor; private QAGrid? QAGrid; private readonly FactoryFloorLocalSettings _settings; private readonly PanelAction _togglePackPanel; public FactoryPanel() { _settings = new LocalConfiguration().Load(); if (_settings.Section.Equals(CoreUtils.FullGuid) && _settings.Station.Equals(-1)) { var user = new UserConfiguration().Load(); _settings.Section = user.Section; _settings.Station = user.Station; new LocalConfiguration().Save(_settings); } InitializeComponent(); var CanConfigure = Security.IsAllowed(); Section.IsEnabled = CanConfigure; Station.IsEnabled = CanConfigure; PendingVisible = Security.IsAllowed(); Kanbans = new ObservableCollection(); RackContents.ItemsSource = rackcontents; RackPanel.Visibility = _settings.SidePanel == FactorySidePanel.Racks ? Visibility.Visible : Visibility.Collapsed; PackPanel.Visibility = _settings.SidePanel == FactorySidePanel.Packs ? Visibility.Visible : Visibility.Collapsed; } public bool IsReady { get; set; } public void Setup() { var setups = new MultiQuery(); setups.Add(); setups.Add( new Filter(x => x.Hidden).IsEqualTo(false), null, new SortOrder(x => x.Factory.Sequence).ThenBy(x => x.Sequence) ); setups.Add(); setups.Add( LookupFactory.DefineFilter(), new Columns(x => x.ID, x => x.Name, x => x.UserLink.ID), new SortOrder(x => x.Name) ); setups.Add( LookupFactory.DefineFilter(), new Columns(x => x.ID, x => x.Code, x => x.Description, x => x.BarCode) ); if (_settings.AreaID != Guid.Empty) setups.Add( new Filter(x=>x.ID).IsEqualTo(_settings.AreaID), new Columns(x=>x.ID).Add(x=>x.Code).Add(x=>x.Description) ); setups.Query(); Factories = setups.Get().Rows.Select(x => x.ToObject()).ToArray(); Sections = setups.Get().Rows.Select(x => x.ToObject()).ToArray(); Trolleys = setups.Get().Rows.Select(x => x.ToObject()).ToArray(); Shipments = setups.Get(); CurrentSection = Sections.FirstOrDefault(x => x.ID.Equals(_settings.Section)) ?? Sections.FirstOrDefault(); var iSection = 0; var iCount = 0; foreach (var section in Sections) { if (section == CurrentSection) { iSection = Section.Items.Count; iCount = section.Stations; //Sections[id].Item2; } Section.Items.Add($"{section.Factory.Name}: {section.Name}"); } Section.SelectedIndex = iSection; Station.Items.Clear(); for (var i = 1; i <= (CurrentSection?.Stations ?? 0); i++) Station.Items.Add($"Station #{i}"); CurrentStation = _settings.Station + 1; if (CurrentStation < 1) CurrentStation = 1; if (CurrentStation > iCount) CurrentStation = iCount; Station.SelectedIndex = CurrentStation - 1; if (_settings.AreaID != Guid.Empty) { var area = setups.Get().ToObjects().FirstOrDefault(); if (area != null) { _packGrid.Area = area; _areaDescription.Text = $"{area.Code}"; _addPack.IsEnabled = true; } else { _packGrid.Area = null; _areaDescription.Text = "Set\r\nArea"; _settings.AreaID = Guid.Empty; new LocalConfiguration().Save(_settings); _addPack.IsEnabled = false; } } else { _packGrid.Area = null; _areaDescription.Text = "Set\r\nArea"; } _packGrid.Refresh(true,true); SetupScanner(); } public void Shutdown(CancelEventArgs? cancel) { ShutdownScanner(); //UpdateTimeTracking(true); LoadDrawing(null); } public void CreateToolbarButtons(IPanelHost host) { ManufacturingSetupActions.Standard(host); //if (Security.IsAllowed()) // host.CreatePanelAction(new PanelAction() { Caption = "Self Assessment", Image = PRSDesktop.Resources.star, OnExecute = DoSelfAssessment }); host.CreatePanelAction(new PanelAction { Caption = "Lost Time", Image = PRSDesktop.Resources.smiley, OnExecute = DoSelectLostTime }); host.CreatePanelAction(new PanelAction { Caption = "Treament PO", Image = PRSDesktop.Resources.purchase, OnExecute = DoCreatePurchaseOrder }); host.CreatePanelAction(new PanelAction { Caption = "Treatment Delivery", Image = PRSDesktop.Resources.barcode, OnExecute = DoScanDeliveryItems }); host.CreatePanelAction(new PanelAction { Caption = "Select Rack", Image = PRSDesktop.Resources.forklift, OnExecute = DoSelectRack }); host.CreatePanelAction(new PanelAction { Caption = "Close Rack", Image = PRSDesktop.Resources.forklift, OnExecute = DoCloseRack }); host.CreatePanelAction(new PanelAction { Caption = "Scan Barcode", Image = PRSDesktop.Resources.product, OnExecute = DoScanBarcode }); host.CreatePanelAction(new PanelAction { Caption = _settings.SidePanel == FactorySidePanel.Packs ? "Hide Stock" : "Show Stock", Image = PRSDesktop.Resources.trolley, OnExecute = TogglePackPanel}); } private void TogglePackPanel(PanelAction pa) { RackPanel.Visibility = Visibility.Collapsed; PackPanel.Visibility = _settings.SidePanel == FactorySidePanel.Packs ? Visibility.Collapsed : Visibility.Visible; _settings.SidePanel = PackPanel.Visibility == Visibility.Visible ? FactorySidePanel.Packs : FactorySidePanel.None; new LocalConfiguration().Save(_settings); pa.Caption = _settings.SidePanel == FactorySidePanel.Packs ? "Hide Stock" : "Show Stock"; _addPack.IsEnabled = _settings.AreaID != Guid.Empty; } public Dictionary Selected() { var rows = Packets.Rows.Where(p => Kanbans.Any(k => k.Checked && p.Get(c => c.ID).ToString().Equals(k.ID))); var pkts = rows.ToArray().Select(r => r.ToObject()); return new Dictionary { { typeof(ManufacturingPacket).EntityName(), pkts.ToArray() } }; } public string SectionName => "Factory"; public DataModel DataModel(Selection selection) { var rows = (Packets == null) || (selection == Selection.None) ? new CoreRow[] { } : selection == Selection.Selected ? Packets.Rows.Where(p => Kanbans.Any(k => k.Checked && p.Get(c => c.ID).ToString().Equals(k.ID))) : Packets.Rows; var ids = rows.Any() ? rows.Select(r => r.Get(x => x.ID)).ToArray() : new[] { CoreUtils.FullGuid }; return new ManufacturingPacketDataModel(new Filter(x => x.ID).InList(ids)); } public event DataModelUpdateEvent? OnUpdateDataModel; public void Heartbeat(TimeSpan time) { // Security Descriptor should be disabled for non-manufacturing staff if (!Security.IsAllowed() || CurrentSection == null) return; // If Lost Time is Active, let's record that if (LostTime != null) { var history = new ManufacturingHistory(); history.Date = DateTime.Today; history.Employee.ID = App.EmployeeID; history.Packet.ID = Guid.Empty; history.LostTime.ID = LostTime.ID; history.Description = LostTime.Description; //history.Setout.ID = CheckedPackets[id].Item3; //history.Job.ID = CheckedPackets[id].Item4; history.Section.ID = CurrentSection.ID; history.Station = CurrentStation; history.Activity.ID = LostTime.Activity.ID; history.WorkDuration = new TimeSpan(time.Ticks); history.QACompleted = 0; history.WorkCompleted = 0; history.Window = time; new Client().Save(history, "", (o, e) => { }); } else { var CheckedPackets = new Dictionary>(); foreach (var kanban in Kanbans.Where(x => x.Checked)) { var packet = KanbanToPacket(kanban); if (packet != null) { var stagerow = Stages.Rows.FirstOrDefault(r => r.Get(c => c.Parent.ID).Equals(packet.ID) && r.Get(c => c.ManufacturingSectionLink.ID) .Equals(_settings.Section)); if (stagerow != null) { var stage = stagerow.ToObject(); if (stage.Station != 0) CheckedPackets[packet.ID] = new Tuple(stage.Started, stage.Completed, packet.SetoutLink.ID, packet.SetoutLink.JobLink.ID, packet.Serial); } } } if (!CheckedPackets.Any()) CheckedPackets[Guid.Empty] = new Tuple(DateTime.MinValue, DateTime.MinValue, Guid.Empty, Guid.Empty, "No Packet"); var updates = new List(); var slice = time.Ticks / CheckedPackets.Count; foreach (var id in CheckedPackets.Keys) { var history = new ManufacturingHistory(); history.Date = DateTime.Today; history.Employee.ID = App.EmployeeID; history.Packet.ID = id; history.Description = CheckedPackets[id].Item5; //history.Setout.ID = CheckedPackets[id].Item3; //history.Job.ID = CheckedPackets[id].Item4; history.Section.ID = CurrentSection.ID; history.Activity.ID = CurrentSection.Activity.ID; history.Station = CurrentStation; if (CheckedPackets[id].Item1.Equals(DateTime.MinValue)) history.QADuration = new TimeSpan(slice); else history.WorkDuration = new TimeSpan(slice); history.QACompleted = CheckedPackets[id].Item1.Equals(DateTime.MinValue) ? 0 : 0; history.WorkCompleted = CheckedPackets[id].Item2.Equals(DateTime.MinValue) ? 0 : 1; history.Window = time; updates.Add(history); } if (updates.Any()) new Client().Save(updates, "", (o, e) => { }); } } 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 isGuid = Guid.TryParse(code, out var guid); if (isGuid) { if (Sections.Any(x => x.ID.Equals(guid))) { IsReady = false; CurrentSection = Sections.First(x => x.ID.Equals(guid)); Section.SelectedIndex = Array.IndexOf(Sections, CurrentSection); IsReady = true; Progress.Show("Changing Sections"); DoRefresh(true); Progress.Close(); scanner?.Actions.SoundBeeper(BeepPattern.FastWarble); } else if (Trolleys.Any(x => x.ID.Equals(guid))) { var trolley = Trolleys.First().Code; var updates = new List(); foreach (var kanban in Kanbans.Where(x => x.Checked)) { var packet = KanbanToPacket(kanban); packet.Trolleys = trolley; updates.Add(packet); var pktrow = Packets.Rows.FirstOrDefault(r => r.Get(c => c.ID).Equals(Guid.Parse(kanban.ID))); var stagerow = Stages.Rows.FirstOrDefault(r => r.Get(c => c.Parent.ID).Equals(packet.ID) && r.Get( c => c.ManufacturingSectionLink.ID) .Equals(_settings.Section)); pktrow.Set(x => x.Trolleys, packet.Trolleys); LoadModel(kanban, pktrow, stagerow, true); UpdateSelectedKanban(false); } if (updates.Any()) new Client().Save(updates, "Set Trolley to " + trolley, (o, e) => { }); scanner?.Actions.SoundBeeper(BeepPattern.LowHigh); } else { scanner?.Actions.SoundBeeper(BeepPattern.FourLowShort); } } else { var shiprow = Shipments.Rows.FirstOrDefault(r => r.Get(c => c.BarCode).Equals(code)); if (shiprow != null) { if (string.Equals(code, rackbarcode)) { RackPanel.Visibility = Visibility.Collapsed; _settings.SidePanel = FactorySidePanel.None; new LocalConfiguration().Save(_settings); RackContents.ItemsSource = null; rackid = Guid.Empty; rackbarcode = ""; scanner?.Actions.SoundBeeper(BeepPattern.ThreeLowShort); } else { RackContents.ItemsSource = null; rackid = shiprow.Get(c => c.ID); rackbarcode = code; var rows = DeliveryItems.Rows.Where(r => r.Get(c => c.ShipmentLink.ID).Equals(rackid)).ToArray(); rackcontents.Clear(); rackcontents.AddRange(rows.Select(x => x.ToObject())); RackContents.ItemsSource = rackcontents; RackName.Content = $"Rack {shiprow.Get(c => c.Code)}"; RackCount.Content = rows.Length.ToString(); PackPanel.Visibility = Visibility.Collapsed; RackPanel.Visibility = Visibility.Visible; _settings.SidePanel = FactorySidePanel.Racks; new LocalConfiguration().Save(_settings); scanner?.Actions.SoundBeeper(BeepPattern.ThreeHighShort); } } else { if (RackPanel.Visibility == Visibility.Visible) { var row = DeliveryItems.Rows.FirstOrDefault(r => r.Get(c => c.Barcode).Equals(code)); if (row != null) { var delitem = rackcontents.FirstOrDefault(x => string.Equals(x.Barcode, code)); if (delitem != null) { rackcontents.Remove(delitem); delitem.ShipmentLink.ID = Guid.Empty; new Client().Save(delitem, "Item Removed From Rack", (o, e) => { }); row.Set(x => x.ShipmentLink.ID, Guid.Empty); scanner?.Actions.SoundBeeper(BeepPattern.HighLow); } else { delitem = row.ToObject(); delitem.ShipmentLink.ID = rackid; rackcontents.Add(delitem); new Client().Save(delitem, "Item Added to " + RackName.Content, (o, e) => { }); row.Set(x => x.ShipmentLink.ID, rackid); if (Kanbans.Any(x => string.Equals(x.ID, delitem.ManufacturingPacketLink.ID.ToString()))) ReloadPackets(true); scanner?.Actions.SoundBeeper(BeepPattern.LowHigh); } RackContents.ItemsSource = null; RackContents.ItemsSource = rackcontents; RackCount.Content = rackcontents.Count.ToString(); } } else { var id = new Client().Query( new Filter(x => x.Barcode).IsEqualTo(code), new Columns(x => x.ManufacturingPacketLink.ID) ).Rows.FirstOrDefault()?.Get(x => x.ManufacturingPacketLink.ID); if (!id.HasValue) { scanner?.Actions.SoundBeeper(BeepPattern.FourLowShort); return; } var kanban = Kanbans.FirstOrDefault(x => string.Equals(x.ID, id.Value.ToString())); if (kanban == null) { // Error - packet not visible from this station scanner?.Actions.SoundBeeper(BeepPattern.FourLowShort); return; } var stage = Stages.Rows.FirstOrDefault(r => r.Get(c => c.Parent.ID).Equals(id) && r.Get(c => c.ManufacturingSectionLink.ID) .Equals(_settings.Section))?.ToObject(); if (stage == null) scanner?.Actions.SoundBeeper(BeepPattern.FourHighShort); if (stage.Station == 0) AddPacketToCurrentWorkload(stage); if (kanban != CurrentKanban) { CurrentKanban = kanban; UpdateSelectedKanban(false); } scanner?.Actions.SoundBeeper(BeepPattern.LowHigh); } } } } catch (Exception) { scanner?.Actions.SoundBeeper(BeepPattern.FourLowShort); } } private void LoadDrawing(Guid? id) { if (PDFEditor != null) { PDFEditor.Document = null; // Unload PDF Annotations PDFEditor = null; } else if (QAGrid != null) { Editor.Content = null; // Unload QA Answers QAGrid = null; } if (id.HasValue) { var pktid = CurrentKanban != null ? Guid.Parse(CurrentKanban.ID) : Guid.Empty; var row = Packets.Rows.FirstOrDefault(r => r.Get(c => c.ID).Equals(pktid)); var stagerow = Stages.Rows.FirstOrDefault(r => r.Get(c => c.Parent.ID).Equals(pktid) && r.Get(c => c.ManufacturingSectionLink.ID) .Equals(_settings.Section)); var packet = row.ToObject(); if (id.Value == Guid.Empty) { QAGrid = new QAGrid(); var qadata = stagerow != null ? stagerow.Get(c => c.FormData) : ""; var values = string.IsNullOrWhiteSpace(qadata) ? new Dictionary() : Serialization.Deserialize>(qadata); if (CurrentSection != null && row != null) { var genquestions = LoadQAQuestions(packet, true, false); QAGrid.LoadChecks("Global Checks for " + CurrentSection.Name, genquestions, values); //var specquestions = LoadQAQuestions(packet, false, true); //QAGrid.LoadChecks(String.Format("Specific Checks for {0} [{1}] template", packet.ManufacturingTemplateLink.Name, packet.ManufacturingTemplateLink.Code), specquestions, values); } QAGrid.OnChanged += QAGridChanged; Editor.Content = QAGrid; } else { PDFEditor = new PDFEditorControl(); PDFEditor.LineColor = _settings.LineColor; PDFEditor.TextSize = _settings.FontSize; //PDFEditor.PrintAllowed = Security.IsAllowed(); PDFEditor.SaveAllowed = Security.IsAllowed(); var document = documents.FirstOrDefault(x => x.DocumentLink.ID.Equals(id)); PDFEditor.Watermark = packet.WaterMark; PDFEditor.Document = document; PDFEditor.PDFSettingsChanged += PDFEditorSettingsChanged; Editor.Content = PDFEditor; } } } private void DoSelectRack(PanelAction obj) { var dlg = new MultiSelectDialog( null, new Columns(x => x.ID, x => x.Code, x => x.Description, x => x.BarCode), false ); if (dlg.ShowDialog()) { var id = dlg.IDs().FirstOrDefault(); var barcode = dlg.Data().Rows.FirstOrDefault(r => r.Get(c => c.ID).Equals(id))?.Get(x => x.BarCode); ProcessCode(_scanners.FirstOrDefault(), barcode); } } private void DoCloseRack(PanelAction obj) { if (!string.IsNullOrWhiteSpace(rackbarcode)) ProcessCode(_scanners.FirstOrDefault(), rackbarcode); } private void DoScanBarcode(PanelAction obj) { var dlg = new MultiSelectDialog( new Filter(x => x.DeliveredDate).IsEqualTo(DateTime.MinValue) .And(x => x.ManufacturingPacketLink).LinkValid(), new Columns(x => x.ID, x => x.Barcode, x => x.Description), false ); if (dlg.ShowDialog()) { var id = dlg.IDs().FirstOrDefault(); var barcode = dlg.Data().Rows.FirstOrDefault(r => r.Get(c => c.ID).Equals(id)) ?.Get(x => x.Barcode); ProcessCode(_scanners.FirstOrDefault(), barcode); } } private void DoScanDeliveryItems(PanelAction obj) { new DeliveryBuilder(Guid.Empty, Guid.Empty).ShowDialog(); } private void DoCreatePurchaseOrder(PanelAction obj) { //Guid section = CurrentSection != null ? CurrentSection.ID : CoreUtils.FullGuid; //var stages = Stages.Rows.Where(row => row.Get(col => col.ManufacturingSectionLink.ID).Equals(section) && row.Get(col => col.Station).Equals(CurrentStation)); //var ids = stages.Select(row => row.Get(col => col.ManufacturingPacketLink.ID)).ToArray(); var ids = Kanbans.Where(x => !x.ColorKey.Equals(QA_COLOR)).Select(x => Guid.Parse(x.ID)).ToArray(); var treatments = new Client().Query(new Filter(x => x.Packet.ID).InList(ids)); var window = new ManufacturingTreatmentWindow(treatments); if (window.ShowDialog() != true) return; Progress.Show("Creating Purchase Order"); var order = new PurchaseOrder(); //Supplier supplier = new Client().Query( // new Filter(x => x.ID).IsEqualTo(window.SupplierID), // new Columns(x=>x.ID //).Rows.FirstOrDefault()?.ToObject()); order.SupplierLink.ID = window.SupplierID; order.SupplierLink.Name = window.SupplierName; //supplier != null ? supplier.Name : "Unknown Supplier"; order.Description = string.Format("Materials Processing Request raised by {0} from Factory Floor", App.EmployeeName); order.RaisedBy.ID = App.EmployeeID; order.IssuedBy.ID = App.EmployeeID; order.IssuedDate = DateTime.Today; order.DueDate = DateTime.Today.AddDays(7); new Client().Save(order, "Created Treatment Purchase Order"); Progress.SetMessage("Processing Order"); var orderitems = new List(); var packetupdates = new List(); var query = new MultiQuery(); query.Add( new Filter(x => x.Product.ID).IsEqualTo(window.ProductID).And(x => x.SupplierLink.ID) .IsEqualTo(window.SupplierID), new Columns(x => x.Job.ID).Add(x => x.CostPrice).Add(x => x.Product.NettCost) ); query.Add( new Filter(x => x.ID).IsEqualTo(window.ProductID), LookupFactory.DefineLookupColumns(x => x.Product).Add(x => x.NettCost) ); query.Query(); var supprods = query.Get().Rows.Select(x => x.ToObject()).ToArray(); var supprice = supprods.FirstOrDefault(x => Equals(x.Job.ID, Guid.Empty)); var product = query.Get().Rows.FirstOrDefault()?.ToObject(); var stdcost = supprice != null ? supprice.CostPrice : product != null ? product.NettCost : 0.0F; foreach (var row in window.Selected) { var treatment = row.ToObject(); var packet = Packets.Rows.First(p => p.Get(c => c.ID).Equals(treatment.Packet.ID)) .ToObject(); packetupdates.Add(packet); var item = new PurchaseOrderItem(); item.PurchaseOrderLink.ID = order.ID; item.Job.ID = treatment.Packet.SetoutLink.JobLink.ID; item.Packet.ID = packet.ID; item.Product.ID = window.ProductID; if(product is not null) { item.Product.Synchronise(product); } item.Qty = packet.BarcodeQty; item.Dimensions.Length = treatment.Parameter == 0.0F ? 1.0F : treatment.Parameter; var jobprice = supprods.FirstOrDefault(x => x.Job.ID.Equals(item.Job.ID)); item.Cost = (jobprice != null ? jobprice.CostPrice : stdcost) * treatment.Parameter; var description = new List(); description.Add(string.Format("{0} x {1} - {2}", packet.BarcodeQty, packet.Serial, packet.Title)); var dimensions = new List(); if (packet.Height > 0.0F) dimensions.Add(string.Format("H:{0:F2}mm", packet.Height)); if (packet.Width > 0.0F) dimensions.Add(string.Format("W:{0:F2}mm", packet.Width)); if (packet.Length > 0.0F) dimensions.Add(string.Format("L:{0:F2}mm", packet.Length)); dimensions.Add(string.Format("Param:{0:F4}", treatment.Parameter)); if (dimensions.Any()) description.Add(string.Format("Dimensions: {0}", string.Join(" ", dimensions))); item.Description = string.Join("\n", description); orderitems.Add(item); } new Client().Save(orderitems, "Created by Factory Floor Purchase"); Progress.SetMessage("Updating Packets"); foreach (var orderitem in orderitems) { var packet = packetupdates.FirstOrDefault(x => x.ID.Equals(orderitem.Packet.ID)); if (packet != null) packet.OrderItem.ID = orderitem.ID; } new Client().Save(packetupdates.Where(x => x.IsChanged()), ""); Progress.SetMessage("Creating Delivery"); var delivery = new Delivery(); delivery.Date = DateTime.Today; delivery.Due = DateTime.Today; delivery.Employee.ID = App.EmployeeID; var sb = new StringBuilder(); sb.Append("Serial # "); sb.AppendLine(); sb.AppendLine(); delivery.Notes = string.Format("Delivery of Items for processing to {0}\nOrder #{1} (raised on {2:dd MMM yy} by {3})\nItems: {4}", order.SupplierLink.Name, order.PONumber, delivery.Date, App.EmployeeName, string.Join(", ", orderitems.Select(x => string.Format("{0}{1}", x.Description.Split('\n').FirstOrDefault(), x.Qty > 1 ? " (x" + x.Qty.ToString("F0") + ")" : ""))) ); new Client().Save(delivery, "Created by Factory Floor Purchase"); Progress.Close(); PrintDeliveryBarcode(delivery, order); PrintOrderItemBarcodes(delivery, order); SendPurchaseNotification(order.PONumber); MessageBox.Show("All Done"); new DeliveryBuilder(delivery.ID, order.ID).ShowDialog(); Refresh(); } private void SendPurchaseNotification(string PONumber) { var updates = new List(); var roles = new Client().Query(new Filter(x => x.RoleLink.Code).IsEqualTo("PURCHASES")); foreach (var role in roles.Rows) { var notification = new Notification { Title = string.Format("Treatment PO #{0} has been raised", PONumber), Description = "The above Purchase Order has been created, and is ready to be checked and issued to the relevant supplier." }; notification.Sender.ID = App.EmployeeID; notification.Employee.ID = role.Get(x => x.EmployeeLink.ID); updates.Add(notification); } new Client().Save(updates, "Sent Notification"); } private void PrintDeliveryBarcode(Delivery delivery, PurchaseOrder order) { var model = new ManufacturingTreatmentDataModel(order, delivery); var templatename = "Print Treatment Delivery Bar Code"; var sectionName = "Treatment Delivery Bar Code"; var template = new Client() .Load( new Filter(x => x.Name).IsEqualTo(templatename) .And(x => x.DataModel).IsEqualTo(model.Name) .And(x => x.Section).IsEqualTo(sectionName) ).FirstOrDefault(); if (template == null) { template = new ReportTemplate { DataModel = model.Name, Section = sectionName, Name = templatename }; new Client().Save(template, "Auto Created Report Template"); } ReportUtils.PreviewReport(template, model, !Security.IsAllowed(), Security.IsAllowed()); } private void PrintOrderItemBarcodes(Delivery delivery, PurchaseOrder order) { var model = new ManufacturingTreatmentDataModel(order, delivery); var templatename = "Print Treatment Item Bar Codes"; var sectionName = "Treatment Item Bar Code"; var template = new Client() .Load( new Filter(x => x.Name).IsEqualTo(templatename) .And(x => x.DataModel).IsEqualTo(model.Name) .And(x => x.Section).IsEqualTo(sectionName) ).FirstOrDefault(); if (template == null) { template = new ReportTemplate { DataModel = model.Name, Section = sectionName, Name = templatename }; new Client().Save(template, "Auto Created Report Template"); } ReportUtils.PreviewReport(template, model, !Security.IsAllowed(), Security.IsAllowed()); } private CoreTable POItemTable(IEnumerable items) { var result = new CoreTable(); result.LoadColumns(typeof(PurchaseOrderItem)); result.LoadRows(items); return result; } private void DoSelectLostTime(PanelAction obj) { var chooser = new FactoryLostTimeChooser(); if (chooser.ShowDialog() == true) { LostTime = chooser.SelectedLostTime; LostTimeDescription.Content = LostTime.Description; LostTimeActive.Visibility = Visibility.Visible; } } private void CancelLostTime_Click(object sender, RoutedEventArgs e) { LostTime = null; LostTimeActive.Visibility = Visibility.Collapsed; } //private void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) //{ // MessageBox.Show("Exception!\n\n" + e.Exception.Message + "\n\n" + e.Exception.StackTrace); // e.Handled = true; //} private void Section_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!IsReady) return; CurrentSection = Sections[Section.SelectedIndex]; //Kanban.Columns.Clear(); //Kanban.Columns.Add(new KanbanColumn() { Title = CurrentSection, Categories = CurrentSection.ID.ToString() }); //Kanban.Columns[0].AllowDrag = false; //Kanban.Columns[0].PreviewMouseWheel += CardBorder_PreviewMouseWheel; IsReady = false; Station.Items.Clear(); for (var i = 1; i <= CurrentSection.Stations; i++) Station.Items.Add(string.Format("Station #{0}", i)); IsReady = true; Station.SelectedIndex = 0; } private void Station_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!IsReady) return; SelectSectionAndStation(CurrentSection.ID, Station.SelectedIndex + 1); } private void SelectSectionAndStation(Guid section, int station) { CurrentKanban = null; CurrentStation = station; _settings.Section = section; _settings.Station = CurrentStation - 1; new LocalConfiguration().Save(_settings); DoRefresh(true); } private void LoadKanban() { using (new WaitCursor()) { if (CurrentKanban == null) { ButtonStack.Children.Clear(); LoadDrawing(null); _packGrid.CurrentPacket = null; } else if (true) // Kanban has changed - how do we figure this out { var packet = KanbanToPacket(CurrentKanban); _packGrid.CurrentPacket = packet; //SetoutStage stage = packet.GetCurrentStage(); var row = Stages.Rows.FirstOrDefault(r => r.Get(c => c.Parent.ID).Equals(packet.ID) && r.Get(c => c.ManufacturingSectionLink.ID) .Equals(_settings.Section)); var station = row != null ? row.Get(c => c.Station) : 0; var quality = row != null ? row.Get(c => c.QualityStatus) : QualityStatus.NotChecked; var percentage = row != null ? row.Get(c => c.PercentageComplete) : 0.00F; var Pending = station == 0; //packet.StageLink.Station == 0; // Set the Proper Button Set for this type of Packet MfgRow.Height = Pending ? new GridLength(00) : new GridLength(50); foreach (var btn in ButtonGrid.FindVisualChildren