|
@@ -0,0 +1,445 @@
|
|
|
+using Comal.Classes;
|
|
|
+using InABox.Clients;
|
|
|
+using InABox.Core;
|
|
|
+using InABox.DynamicGrid;
|
|
|
+using InABox.WPF;
|
|
|
+using Syncfusion.Data;
|
|
|
+using Syncfusion.UI.Xaml.Grid;
|
|
|
+using Syncfusion.Windows.Shared;
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.ComponentModel;
|
|
|
+using System.Data;
|
|
|
+using System.Linq;
|
|
|
+using System.Runtime.CompilerServices;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using System.Windows;
|
|
|
+using System.Windows.Controls;
|
|
|
+using System.Windows.Data;
|
|
|
+using System.Windows.Media;
|
|
|
+
|
|
|
+namespace PRSDesktop.Panels.Reservation_Management;
|
|
|
+
|
|
|
+public class JobRequisitionItemSelectionItem : BaseObject
|
|
|
+{
|
|
|
+ public double Quantity { get; set; }
|
|
|
+
|
|
|
+ private double _issued;
|
|
|
+ public double Issued
|
|
|
+ {
|
|
|
+ get => _issued;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ var oldValue = _issued;
|
|
|
+ var canMinus = CanMinus;
|
|
|
+ var canPlus = CanPlus;
|
|
|
+
|
|
|
+ _issued = value;
|
|
|
+ if(oldValue != value)
|
|
|
+ {
|
|
|
+ OnPropertyChanged(nameof(Issued), oldValue, value);
|
|
|
+ }
|
|
|
+ if(canMinus != CanMinus)
|
|
|
+ {
|
|
|
+ OnPropertyChanged(nameof(CanMinus), canMinus, CanMinus);
|
|
|
+ }
|
|
|
+ if(canPlus != CanPlus)
|
|
|
+ {
|
|
|
+ OnPropertyChanged(nameof(CanPlus), canPlus, CanPlus);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public double MaxValue { get; set; }
|
|
|
+
|
|
|
+ private bool _editable = true;
|
|
|
+ public bool Editable
|
|
|
+ {
|
|
|
+ get => _editable;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ var oldValue = _editable;
|
|
|
+ var canMinus = CanMinus;
|
|
|
+ var canPlus = CanPlus;
|
|
|
+
|
|
|
+ _editable = value;
|
|
|
+ if(oldValue != value)
|
|
|
+ {
|
|
|
+ OnPropertyChanged(nameof(Editable), oldValue, value);
|
|
|
+ }
|
|
|
+ if(canMinus != CanMinus)
|
|
|
+ {
|
|
|
+ OnPropertyChanged(nameof(CanMinus), canMinus, CanMinus);
|
|
|
+ }
|
|
|
+ if(canPlus != CanPlus)
|
|
|
+ {
|
|
|
+ OnPropertyChanged(nameof(CanPlus), canPlus, CanPlus);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool CanMinus => Editable && Issued > 0;
|
|
|
+
|
|
|
+ public bool CanPlus => Editable && Issued < MaxValue;
|
|
|
+
|
|
|
+ public JobRequisitionItem JRI { get; set; }
|
|
|
+}
|
|
|
+
|
|
|
+public abstract class JobRequisitionItemSelectionGrid<T> : DynamicItemsListGrid<T>, INotifyPropertyChanged
|
|
|
+ where T : JobRequisitionItemSelectionItem, new()
|
|
|
+{
|
|
|
+ private double _totalQuantity;
|
|
|
+ public double TotalQuantity
|
|
|
+ {
|
|
|
+ get => _totalQuantity;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _totalQuantity = value;
|
|
|
+ OnPropertyChanged();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private double _totalIssued;
|
|
|
+ public double TotalIssued
|
|
|
+ {
|
|
|
+ get => _totalIssued;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _totalIssued = value;
|
|
|
+ OnPropertyChanged();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool _observing = true;
|
|
|
+ public void SetObserving(bool observing)
|
|
|
+ {
|
|
|
+ if(_observing != observing)
|
|
|
+ {
|
|
|
+ _observing = observing;
|
|
|
+ if (_observing)
|
|
|
+ {
|
|
|
+ Recalculate();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void Init()
|
|
|
+ {
|
|
|
+ base.Init();
|
|
|
+
|
|
|
+ ActionColumns.Add(new DynamicTemplateColumn(TotalColumn_Template)
|
|
|
+ {
|
|
|
+ HeaderText = "Total",
|
|
|
+ Width = 60,
|
|
|
+ GetSummary = () =>
|
|
|
+ {
|
|
|
+ var summary = new GridSummaryColumn
|
|
|
+ {
|
|
|
+ TemplateSelector = new FuncTemplateSelector((item, o) => TotalQuantity_Template())
|
|
|
+ };
|
|
|
+ return summary;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ ActionColumns.Add(new DynamicTemplateColumn(QuantityColumn_Template)
|
|
|
+ {
|
|
|
+ HeaderText = "Quantity",
|
|
|
+ Width = 230,
|
|
|
+ GetSummary = () =>
|
|
|
+ {
|
|
|
+ var summary = new GridSummaryColumn
|
|
|
+ {
|
|
|
+ TemplateSelector = new FuncTemplateSelector((item, o) => TotalIssued_Template())
|
|
|
+ };
|
|
|
+ return summary;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void DoReconfigure(DynamicGridOptions options)
|
|
|
+ {
|
|
|
+ base.DoReconfigure(options);
|
|
|
+ options.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ private FrameworkElement TotalQuantity_Template()
|
|
|
+ {
|
|
|
+ var quantity = new DoubleTextBox
|
|
|
+ {
|
|
|
+ HorizontalContentAlignment = HorizontalAlignment.Center,
|
|
|
+ VerticalContentAlignment = VerticalAlignment.Center,
|
|
|
+ VerticalAlignment = VerticalAlignment.Stretch,
|
|
|
+ HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
|
+ Background = new SolidColorBrush(Colors.WhiteSmoke),
|
|
|
+ IsReadOnly = true,
|
|
|
+ Margin = new Thickness(0, 5, 0, 5)
|
|
|
+ };
|
|
|
+ quantity.Bind(DoubleTextBox.ValueProperty, this, x => x.TotalQuantity);
|
|
|
+ return quantity;
|
|
|
+ }
|
|
|
+
|
|
|
+ private FrameworkElement TotalIssued_Template()
|
|
|
+ {
|
|
|
+ var quantity = new DoubleTextBox
|
|
|
+ {
|
|
|
+ HorizontalContentAlignment = HorizontalAlignment.Center,
|
|
|
+ VerticalContentAlignment = VerticalAlignment.Center,
|
|
|
+ VerticalAlignment = VerticalAlignment.Stretch,
|
|
|
+ HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
|
+ Background = new SolidColorBrush(Colors.LightGreen),
|
|
|
+ IsReadOnly = true,
|
|
|
+ Margin = new Thickness(50 + 30 + 10, 5, 50 + 30 + 5, 5)
|
|
|
+ };
|
|
|
+ quantity.Bind(DoubleTextBox.ValueProperty, this, x => x.TotalIssued);
|
|
|
+ return quantity;
|
|
|
+ }
|
|
|
+
|
|
|
+ private class TotalAggregate : ISummaryAggregate
|
|
|
+ {
|
|
|
+ public double Sum { get; private set; }
|
|
|
+
|
|
|
+ private JobRequisitionItemSelectionGrid<T> Grid;
|
|
|
+
|
|
|
+ public enum TotalColumn
|
|
|
+ {
|
|
|
+ Quantity,
|
|
|
+ Issued
|
|
|
+ }
|
|
|
+
|
|
|
+ public TotalColumn Type { get; set; }
|
|
|
+
|
|
|
+ public TotalAggregate(TotalColumn type, JobRequisitionItemSelectionGrid<T> grid)
|
|
|
+ {
|
|
|
+ Type = type;
|
|
|
+ Grid = grid;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Action<IEnumerable, string, PropertyDescriptor> CalculateAggregateFunc()
|
|
|
+ {
|
|
|
+ return AggregateFunc;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void AggregateFunc(IEnumerable items, string property, PropertyDescriptor args)
|
|
|
+ {
|
|
|
+ if (items is IEnumerable<DataRowView> rows)
|
|
|
+ {
|
|
|
+ Sum = Type switch
|
|
|
+ {
|
|
|
+ TotalColumn.Quantity => Grid.TotalQuantity,
|
|
|
+ TotalColumn.Issued or _ => Grid.TotalIssued
|
|
|
+ };
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Logger.Send(LogType.Error, "", $"Attempting to calculate aggregate on invalid data type '{items.GetType()}'.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private class UIComponent : DynamicGridGridUIComponent<T>
|
|
|
+ {
|
|
|
+ public UIComponent(JobRequisitionItemSelectionGrid<T> grid)
|
|
|
+ {
|
|
|
+ Parent = grid;
|
|
|
+
|
|
|
+ GridLines = DynamicGridLines.None;
|
|
|
+ RowHeight = 40;
|
|
|
+ HeaderRowHeight = 40;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override Brush? GetCellSelectionBackgroundBrush()
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ protected override Brush? GetCellSelectionForegroundBrush()
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override Brush? GetCellBackground(CoreRow row, DynamicColumnBase column)
|
|
|
+ {
|
|
|
+ return base.GetCellBackground(row, column);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override Style GetHeaderCellStyle(DynamicColumnBase column)
|
|
|
+ {
|
|
|
+ var style = base.GetHeaderCellStyle(column);
|
|
|
+ style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Silver)));
|
|
|
+ style.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.Bold));
|
|
|
+ style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0.0)));
|
|
|
+ style.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0.0)));
|
|
|
+ return style;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override Style GetSummaryRowStyle()
|
|
|
+ {
|
|
|
+ var style = base.GetSummaryRowStyle();
|
|
|
+ style.Setters.Add(new Setter(Control.BorderBrushProperty, new SolidColorBrush(Colors.Silver)));
|
|
|
+ style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(1, 1, 0, 1)));
|
|
|
+ style.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0, 1, 0, 0)));
|
|
|
+ style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.WhiteSmoke)));
|
|
|
+ return style;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override Style GetSummaryCellStyle(DynamicColumnBase column)
|
|
|
+ {
|
|
|
+ var style = base.GetSummaryCellStyle(column);
|
|
|
+
|
|
|
+ style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0)));
|
|
|
+ style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
|
|
|
+ style.Setters.Add(new Setter(GridTableSummaryCell.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
|
|
|
+ style.Setters.Add(new Setter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch));
|
|
|
+ style.Setters.Add(new Setter(Control.PaddingProperty, new Thickness(0)));
|
|
|
+
|
|
|
+ return style;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override IDynamicGridUIComponent<T> CreateUIComponent()
|
|
|
+ {
|
|
|
+ return new UIComponent(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ private FrameworkElement? TotalColumn_Template(CoreRow row)
|
|
|
+ {
|
|
|
+ var item = LoadItem(row);
|
|
|
+
|
|
|
+ var quantity = new DoubleTextBox
|
|
|
+ {
|
|
|
+ HorizontalContentAlignment = HorizontalAlignment.Center,
|
|
|
+ VerticalContentAlignment = VerticalAlignment.Center,
|
|
|
+ VerticalAlignment = VerticalAlignment.Stretch,
|
|
|
+ Background = new SolidColorBrush(Colors.WhiteSmoke),
|
|
|
+ IsReadOnly = true,
|
|
|
+ Margin = new Thickness(0, 5, 0, 5)
|
|
|
+ };
|
|
|
+ quantity.Bind(DoubleTextBox.ValueProperty, item, x => x.Quantity);
|
|
|
+ quantity.Bind(Button.IsEnabledProperty, item, x => x.Editable);
|
|
|
+
|
|
|
+ return quantity;
|
|
|
+ }
|
|
|
+
|
|
|
+ private FrameworkElement? QuantityColumn_Template(CoreRow row)
|
|
|
+ {
|
|
|
+ var item = LoadItem(row);
|
|
|
+
|
|
|
+ var grid = new Grid();
|
|
|
+ grid.Margin = new Thickness(5);
|
|
|
+ grid.AddColumn(50);
|
|
|
+ grid.AddColumn(30);
|
|
|
+ grid.AddColumn(60);
|
|
|
+ grid.AddColumn(30);
|
|
|
+ grid.AddColumn(50);
|
|
|
+
|
|
|
+ var none = new Button
|
|
|
+ {
|
|
|
+ Content = "None",
|
|
|
+ };
|
|
|
+ none.Bind(Button.IsEnabledProperty, item, x => x.Editable);
|
|
|
+ none.Margin = new Thickness(0);
|
|
|
+ none.Click += (o, e) => None_Click(item);
|
|
|
+ grid.AddChild(none, 0, 0);
|
|
|
+
|
|
|
+ var minus = new Button
|
|
|
+ {
|
|
|
+ Content = "-",
|
|
|
+ };
|
|
|
+ minus.Bind(Button.IsEnabledProperty, item, x => x.CanMinus);
|
|
|
+ minus.Margin = new Thickness(5, 0, 0, 0);
|
|
|
+ minus.Click += (o, e) => Minus_Click(item);
|
|
|
+ grid.AddChild(minus, 0, 1);
|
|
|
+
|
|
|
+ var quantity = new DoubleTextBox
|
|
|
+ {
|
|
|
+ HorizontalContentAlignment = HorizontalAlignment.Center,
|
|
|
+ VerticalContentAlignment = VerticalAlignment.Center,
|
|
|
+ VerticalAlignment = VerticalAlignment.Stretch,
|
|
|
+ Background = new SolidColorBrush(Colors.LightYellow),
|
|
|
+ Margin = new Thickness(5, 0, 0, 0)
|
|
|
+ };
|
|
|
+ quantity.Bind(DoubleTextBox.ValueProperty, item, x => x.Issued);
|
|
|
+ quantity.MinValue = 0;
|
|
|
+ quantity.Bind(DoubleTextBox.MaxValueProperty, item, x => x.MaxValue);
|
|
|
+ quantity.Bind(Button.IsEnabledProperty, item, x => x.Editable);
|
|
|
+ grid.AddChild(quantity, 0, 2);
|
|
|
+
|
|
|
+ var plus = new Button
|
|
|
+ {
|
|
|
+ Content = "+",
|
|
|
+ };
|
|
|
+ plus.Bind(Button.IsEnabledProperty, item, x => x.CanPlus);
|
|
|
+ plus.Margin = new Thickness(5, 0, 0, 0);
|
|
|
+ plus.Click += (o, e) => Plus_Click(item);
|
|
|
+ grid.AddChild(plus, 0, 3);
|
|
|
+
|
|
|
+ var all = new Button
|
|
|
+ {
|
|
|
+ Content = "All",
|
|
|
+ };
|
|
|
+ all.Bind(Button.IsEnabledProperty, item, x => x.Editable);
|
|
|
+ all.Margin = new Thickness(5, 0, 0, 0);
|
|
|
+ all.Click += (o, e) => All_Click(item);
|
|
|
+ grid.AddChild(all, 0, 4);
|
|
|
+
|
|
|
+ return grid;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void None_Click(T item)
|
|
|
+ {
|
|
|
+ item.Issued = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Minus_Click(T item)
|
|
|
+ {
|
|
|
+ item.Issued = Math.Max(0, item.Issued - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Plus_Click(T item)
|
|
|
+ {
|
|
|
+ if(item.JRI.ID == Guid.Empty)
|
|
|
+ {
|
|
|
+ item.Issued += 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ item.Issued = Math.Min(item.Issued + 1, item.Quantity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void All_Click(T item)
|
|
|
+ {
|
|
|
+ item.Issued = Math.Max(0, item.Quantity);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void Reload(Filters<T> criteria, Columns<T> columns, ref SortOrder<T>? sort, Action<CoreTable?, Exception?> action)
|
|
|
+ {
|
|
|
+ foreach(var item in Items)
|
|
|
+ {
|
|
|
+ item.PropertyChanged += (o, e) => Recalculate();
|
|
|
+ }
|
|
|
+ Recalculate();
|
|
|
+
|
|
|
+ base.Reload(criteria, columns, ref sort, action);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Dictionary<Guid, double> GetQuantities()
|
|
|
+ {
|
|
|
+ return Items.ToDictionary(x => x.JRI.ID, x => x.Issued);
|
|
|
+ }
|
|
|
+ private void Recalculate()
|
|
|
+ {
|
|
|
+ if (!_observing) return;
|
|
|
+
|
|
|
+ TotalQuantity = Items.Sum(x => x.Quantity);
|
|
|
+ TotalIssued = Items.Sum(x => x.Issued);
|
|
|
+ }
|
|
|
+
|
|
|
+ public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
+
|
|
|
+ protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
|
|
+ {
|
|
|
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
+ }
|
|
|
+}
|