using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Document = InABox.Core.Document; namespace PRSDesktop; public class FactoryPackGrid : DynamicDataGrid { public Guid AreaID { get; set; } public ManufacturingPacket? CurrentPacket { get; set; } public String AreaDescription { get => _holding.HeaderText; set { _holding.HeaderText = value; Refresh(true,false); } } private readonly Dictionary _images = new(); private readonly DynamicActionColumn _holding; public FactoryPackGrid() { HiddenColumns.Add(x=>x.ID); HiddenColumns.Add(x=>x.Product.ID); HiddenColumns.Add(x=>x.Product.Code); HiddenColumns.Add(x=>x.Product.Name); HiddenColumns.Add(x=>x.Product.Image.ID); HiddenColumns.Add(x => x.Dimensions.Unit.ID); HiddenColumns.Add(x => x.Dimensions.Unit.Formula); HiddenColumns.Add(x => x.Dimensions.Unit.Format); HiddenColumns.Add(x=>x.Dimensions.Height); HiddenColumns.Add(x=>x.Dimensions.Width); HiddenColumns.Add(x=>x.Dimensions.Length); HiddenColumns.Add(x=>x.Dimensions.Weight); HiddenColumns.Add(x=>x.Dimensions.Quantity); HiddenColumns.Add(x=>x.Dimensions.Value); HiddenColumns.Add(x=>x.Dimensions.UnitSize); HiddenColumns.Add(x=>x.Style.ID); HiddenColumns.Add(x=>x.Style.Code); HiddenColumns.Add(x=>x.Style.Description); HiddenColumns.Add(x => x.Job.ID); HiddenColumns.Add(x=>x.Job.JobNumber); HiddenColumns.Add(x=>x.Job.Name); HiddenColumns.Add(x=>x.Location.ID); HiddenColumns.Add(x=>x.Location.Code); HiddenColumns.Add(x=>x.Location.Description); HiddenColumns.Add(x=>x.Units); HiddenColumns.Add(x => x.Available); _holding = new DynamicTemplateColumn(PackTemplate) { Width = 0 }; ActionColumns.Add(_holding); } public override void Reconfigure() { base.Reconfigure(); RowHeight = 85; Options.Clear(); } protected override DynamicGridColumns LoadColumns() { var columns = new DynamicGridColumns(); return columns; } protected override void Reload(Filters criteria, Columns columns, ref SortOrder? sort, Action action) { Task imagetask = Task.Run(() => { return new Client().Query( new Filter(x => x.ID) .InQuery(new Filter(x => x.Location.Area.ID).IsEqualTo(AreaID), x => x.Product.Image.ID), new Columns(x => x.ID).Add(x => x.Data) ); }); criteria.Add(new Filter(x => x.Location.Area.ID).IsEqualTo(AreaID)); base.Reload(criteria, columns, ref sort, (o,e) => { if (o != null) { Task.WaitAll(imagetask); _images.Clear(); imagetask.Result.LoadDictionary( _images, x => x.ID, x => x.Data ); } action(o,e); }); } private void CreateStackPanel(Grid grid, int row, int column, FontWeight weight, params Expression>[] bindings) { StackPanel result = new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center, }; result.SetValue(Grid.RowProperty,row); result.SetValue(Grid.ColumnProperty,column); foreach (var binding in bindings) { Label label = new Label() { Margin = new Thickness(5,0,0,0), VerticalContentAlignment = VerticalAlignment.Center, FontWeight = weight }; label.Bind(Label.ContentProperty,binding); result.Children.Add(label); } grid.Children.Add(result); } private FrameworkElement PackTemplate() { var grid = new Grid(); grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); grid.ColumnDefinitions.Add(new ColumnDefinition() { Width= new GridLength(28, GridUnitType.Pixel)}); grid.ColumnDefinitions.Add(new ColumnDefinition() { Width= new GridLength(1, GridUnitType.Pixel)}); grid.ColumnDefinitions.Add(new ColumnDefinition() { Width= new GridLength(90, GridUnitType.Pixel)}); grid.ColumnDefinitions.Add(new ColumnDefinition() { Width= new GridLength(1, GridUnitType.Star)}); grid.ColumnDefinitions.Add(new ColumnDefinition() { Width= new GridLength(70, GridUnitType.Pixel)}); Label label = new Label() { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, LayoutTransform = new RotateTransform(-90) }; label.Bind(Label.ContentProperty, x=>x.Location.Code); label.SetValue(Grid.RowProperty,0); label.SetValue(Grid.RowSpanProperty,3); label.SetValue(Grid.ColumnProperty,0); grid.Children.Add(label); Border border = new Border() { BorderThickness = new Thickness(0.75), BorderBrush = new SolidColorBrush(Colors.DarkGray) }; border.SetValue(Grid.RowProperty,0); border.SetValue(Grid.RowSpanProperty,3); border.SetValue(Grid.ColumnProperty,1); grid.Children.Add(border); Image image = new Image() { Stretch = Stretch.Uniform, Margin=new Thickness(5) }; image.Bind(Image.SourceProperty, x => x.Product.Image.ID, new GuidToImageSourceConverter() { Images = _images}); image.SetValue(Grid.RowProperty,0); image.SetValue(Grid.RowSpanProperty,3); image.SetValue(Grid.ColumnProperty,2); grid.Children.Add(image); CreateStackPanel(grid, 0, 3, FontWeights.Bold, x => x.Product.Code, x => x.Product.Name); CreateStackPanel(grid, 1, 3, FontWeights.Normal, x => x.Dimensions.UnitSize, x => x.Style.Code, x=>x.Style.Description); CreateStackPanel(grid, 2, 3, FontWeights.Normal, x => x.Job.JobNumber, x => x.Job.Name); StackPanel buttonContent = new StackPanel() { Orientation = Orientation.Vertical, VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center }; Label qtyLbl = new Label() { FontSize = 16, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center }; qtyLbl.Bind(Label.ContentProperty, x => x.Units, null, BindingMode.Default, "{0:F2}"); buttonContent.Children.Add(qtyLbl); Label useLbl = new Label() { HorizontalAlignment = HorizontalAlignment.Center, Content = "Use" }; buttonContent.Children.Add(useLbl); Button button = new Button() { Margin = new Thickness(5), Content = buttonContent }; button.Bind(Image.SourceProperty, x => x.ID); button.SetValue(Grid.RowProperty,0); button.SetValue(Grid.RowSpanProperty,4); button.SetValue(Grid.ColumnProperty,4); button.Click += UseStock; grid.Children.Add(button); return grid; } private class FactoryFloorIssue : BaseObject { public JobRequisitionItem[]? RequisitionItems { get; init; } [EditorSequence(1)] [ComboLookupEditor(typeof(RequisitionIDGenerator))] public Guid RequisitionID { get; set; } private class RequisitionIDGenerator : LookupGenerator { public RequisitionIDGenerator(FactoryFloorIssue[] items) : base(items) { } protected override void DoGenerateLookups() { var items = Items?.FirstOrDefault()?.RequisitionItems; if (items == null) return; foreach (var item in items) { AddValue(item.ID, item.ID == Guid.Empty ? $"{item.Requisition.Description}" : $"{item.Requisition.Number}: {item.Requisition.Description}"); } } } [EditorSequence(2)] public double Qty { get; set; } } private void UseStock(object sender, RoutedEventArgs e) { if (CurrentPacket == null) { MessageBox.Show("Please select a Manufacturing Packet before proceeding"); return; } var holdingrow = SelectedRows.FirstOrDefault(); if (holdingrow == null) { MessageBox.Show("Please select a Stock Holding before proceeding"); return; } var holding = holdingrow.ToObject(); var requiitems = holding.LoadRequisitionItems().ToArray(); var ffi = new FactoryFloorIssue() { RequisitionItems = requiitems, Qty = 1, RequisitionID = requiitems.FirstOrDefault()?.ID ?? Guid.Empty }; var ffg = new DynamicItemsListGrid(); ffg.OnValidate += (_, _, errors) => { var id = ffi.RequisitionID; var requi = ffi.RequisitionItems.FirstOrDefault(x => x.ID == id); if (requi == null) errors.Add("Please select an allocation!"); else if (ffi.Qty > requi.Qty) errors.Add($"Qty must not exceed {requi.Qty}"); }; if (!ffg.EditItems([ffi])) return; var _settings = new LocalConfiguration().Load(); if (_settings.CurrentBatchDate != DateTime.Today) { StockMovementBatch batch = new StockMovementBatch { Type = StockMovementBatchType.Issue, TimeStamp = DateTime.Now, Notes = "Manufacturing Consumption" }; batch.Employee.ID = App.EmployeeID; new Client().Save(batch,"Created on Factory Floor Screen"); _settings.CurrentBatchDate = DateTime.Today; _settings.CurrentBatchID = batch.ID; new LocalConfiguration().Save(_settings); } List updates = new(); Guid transactionid = Guid.NewGuid(); if (CurrentPacket.SetoutLink.JobLink.ID != holding.Job.ID) { var transferout = holding.CreateMovement(); transferout.JobRequisitionItem.ID = ffi.RequisitionID; transferout.Batch.ID = _settings.CurrentBatchID; transferout.Type = StockMovementType.TransferOut; transferout.Issued = ffi.Qty; transferout.Transaction = transactionid; transferout.System = true; transferout.Date = DateTime.Now; transferout.Employee.ID = App.EmployeeID; updates.Add(transferout); var transferin = holding.CreateMovement(); transferin.JobRequisitionItem.ID = ffi.RequisitionID; transferin.Batch.ID = _settings.CurrentBatchID; transferin.Type = StockMovementType.TransferIn; transferin.Received = ffi.Qty; transferin.Job.ID = CurrentPacket.SetoutLink.JobLink.ID; transferin.Job.Synchronise(CurrentPacket.SetoutLink.JobLink); transferin.Transaction = transactionid; transferin.Date = DateTime.Now; transferin.System = true; transferin.Employee.ID = App.EmployeeID; updates.Add(transferin); } var issue = holding.CreateMovement(); issue.JobRequisitionItem.ID = ffi.RequisitionID; issue.Batch.ID = _settings.CurrentBatchID; issue.Type = StockMovementType.Issue; issue.Issued = ffi.Qty; issue.Job.ID = CurrentPacket.SetoutLink.JobLink.ID; issue.Job.Synchronise(CurrentPacket.SetoutLink.JobLink); issue.Transaction = transactionid; issue.Date = DateTime.Now; issue.Employee.ID = App.EmployeeID; issue.Notes = "Issued to Manufacturing"; updates.Add(issue); new Client().Save(updates,"Issued Stock to Factory Floor", (_,_) => { }); if (issue.JobRequisitionItem.ID == Guid.Empty) UpdateRow(holdingrow, x=>x.Available, holding.Available - ffi.Qty,false); UpdateRow(holdingrow, x => x.Units, holding.Units - ffi.Qty,true); } }