123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Windows.Media;
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Core;
- using InABox.DynamicGrid;
- using PRSDesktop.Utils;
- using Syncfusion.Data.Extensions;
- using Xceed.Wpf.Toolkit;
- namespace PRSDesktop
- {
- public class StockSummaryGrid : DynamicDataGrid<StockSummary>, IDataModelSource
- {
-
- public Guid[] GroupIDs { get; set; }
- public Guid[] JobIDs { get; set; }
-
- public StockSummaryGrid() : base()
- {
- ColumnsTag = "StockSummaryGrid";
- GroupIDs = new Guid[] { };
- JobIDs = new Guid[] { };
-
- HiddenColumns.Add(x => x.Product.ID);
- HiddenColumns.Add(x => x.Style.ID);
- HiddenColumns.Add(x => x.Job.ID);
- HiddenColumns.Add(x => x.Dimensions.UnitSize);
- HiddenColumns.Add(x => x.Product.MinimumStockLevel);
- HiddenColumns.Add(x => x.Issued);
- HiddenColumns.Add(x => x.TotalRequired);
- HiddenColumns.Add(x => x.NettRequired);
- HiddenColumns.Add(x => x.AllStock);
- HiddenColumns.Add(x => x.OnOrder);
- HiddenColumns.Add(x => x.TotalStock);
- HiddenColumns.Add(x => x.BalanceAvailable);
- HiddenColumns.Add(x => x.Product.Image.ID);
- HiddenColumns.Add(x => x.Product.Image.FileName);
- ActionColumns.Add(new DynamicImagePreviewColumn<StockSummary>(x => x.Product.Image)
- { Position = DynamicActionColumnPosition.Start });
-
- OnCellDoubleClick += StockSummaryGrid_OnCellDoubleClick;
- }
- protected override void DoReconfigure(FluentList<DynamicGridOption> options)
- {
- base.DoReconfigure(options);
- options.AddRange(
- DynamicGridOption.RecordCount,
- DynamicGridOption.SelectColumns,
- DynamicGridOption.FilterRows,
- DynamicGridOption.ExportData,
- DynamicGridOption.MultiSelect
- );
- }
- protected override void GenerateColumns(DynamicGridColumns columns)
- {
- columns.Add<StockSummary, string>(x => x.Product.Code, 120, "Product Code", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, string>(x => x.Style.Code, 120, "Style Code", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, string>(x => x.Dimensions.UnitSize, 120, "Unit Size", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, int>(x => x.Product.MinimumStockLevel, 120, "Minimum Stock Level", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, double>(x => x.BillOfMaterials, 120, "BOM", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, double>(x => x.Issued, 120, "Issued", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, double>(x => x.AllStock, 120, "Stock", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, double>(x => x.OnOrder, 120, "On Order", "", Alignment.MiddleCenter);
- columns.Add<StockSummary, double>(x => x.BalanceAvailable, 120, "Balance Available", "", Alignment.MiddleCenter);
- }
- private void ShowDetailGrid<TEntity>(
- String columnname,
- Expression<Func<TEntity,object?>> productcol,
- Guid productid,
- Expression<Func<TEntity,object?>> stylecol,
- Guid? styleid,
- Expression<Func<TEntity,object?>> unitcol,
- String unitsize,
- Expression<Func<TEntity,object?>>? jobcol,
- Filter<TEntity>? extrafilter,
- Func<CoreRow,bool>? rowfilter
- )
- {
- var grid = (Activator.CreateInstance(typeof(DynamicDataGrid<>).MakeGenericType(typeof(TEntity))) as IDynamicDataGrid);
- if (grid == null)
- {
- MessageBox.Show($"Cannot create Grid for [{typeof(TEntity).Name}]");
- return;
- }
- grid.ColumnsTag = $"{ColumnsTag}.{columnname}";
- grid.Reconfigure(options => { options.BeginUpdate().Clear().AddRange(DynamicGridOption.FilterRows, DynamicGridOption.SelectColumns).EndUpdate(); });
- grid.OnDefineFilter += t =>
- {
- var filter = new Filter<TEntity>(productcol).IsEqualTo(productid)
- .And(unitcol).IsEqualTo(unitsize);
- if (styleid.HasValue)
- filter = filter.And(stylecol).IsEqualTo(styleid);
-
- if (jobcol != null)
- filter = filter.And(jobcol).InList(JobIDs);
-
- if (extrafilter != null)
- filter = filter.And(extrafilter);
- return filter;
- };
- grid.OnFilterRecord += row => rowfilter?.Invoke(row) ?? true;
- var window = DynamicGridUtils.CreateGridWindow($"Viewing {CoreUtils.Neatify(columnname)} Calculation", (grid as BaseDynamicGrid)!);
- window.ShowDialog();
- }
-
- private void StockSummaryGrid_OnCellDoubleClick(object sender, DynamicGridCellClickEventArgs args)
- {
-
-
- Guid productid = args.Row.Get<StockSummary, Guid>(c => c.Product.ID);
- Guid? styleid = HasStyle() ? args.Row.Get<StockSummary, Guid>(c => c.Style.ID) : null;
- String unitsize = args.Row.Get<StockSummary, String>(c => c.Dimensions.UnitSize);
- if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.BillOfMaterials, ".")))
- {
- ShowDetailGrid<JobBillOfMaterialsItem>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- x => x.Job.ID,
- new Filter<JobBillOfMaterialsItem>(x=>x.BillOfMaterials.Approved).IsNotEqualTo(DateTime.MinValue),
- null
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.Issued, ".")))
- {
- ShowDetailGrid<StockMovement>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- x => x.Job.ID,
- new Filter<StockMovement>(x=>x.IsTransfer).IsEqualTo(false).And(x=>x.Issued).IsNotEqualTo(0.0F),
- null
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.TotalRequired, ".")))
- {
- ShowDetailGrid<StockSummary>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- x => x.Job.ID,
- null,
- null
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.NettRequired, ".")))
- {
- ShowDetailGrid<StockSummary>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- x => x.Job.ID,
- null,
- null
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.AllStock, ".")))
- {
- ShowDetailGrid<StockHolding>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- null,
- null,
- (row) => row.Get<StockHolding,double>(x=>x.Units) != 0.0F
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.OnOrder, ".")))
- {
- ShowDetailGrid<PurchaseOrderItem>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- null,
- null,
- null
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.TotalStock, ".")))
- {
- ShowDetailGrid<StockSummary>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- x => x.Job.ID,
- null,
- null
- );
- }
- else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.BalanceAvailable, ".")))
- {
- ShowDetailGrid<StockSummary>(
- args.Column.ColumnName,
- x => x.Product.ID,
- productid,
- x => x.Style.ID,
- styleid,
- x=>x.Dimensions.UnitSize,
- unitsize,
- x => x.Job.ID,
- null,
- null
- );
- }
-
- }
- private bool HasStyle()
- {
- return DataColumns().ColumnNames().Any(x => x.StartsWith("Style.") && !x.Equals("Style.ID"));
- }
- private Filters<StockSummary> GetFilters()
- {
- var filters = new Filters<StockSummary>();
- filters.Add(FilterComponent.GetFilter());
-
- Filter<StockSummary>? _groupfilter = !GroupIDs.Any()
- ? new Filter<StockSummary>().None()
- : !GroupIDs.Contains(CoreUtils.FullGuid)
- ? new Filter<StockSummary>(x => x.Product.Group.ID).InList(GroupIDs)
- : null;
- filters.Add(_groupfilter);
- var jobFilter = !JobIDs.Any()
- ? new Filter<StockSummary>().None()
- : new Filter<StockSummary>(x => x.Job.ID).InList(JobIDs);
- filters.Add(jobFilter);
- //Filter<StockSummary> _productfilter = new Filter<StockSummary>(x => x.Product.ID).IsNotEqualTo(Guid.Empty);
- //filters.Add(_productfilter);
- return filters;
- }
- private Tuple<Guid,Guid?,String>[] GetKeys(IEnumerable<CoreRow> rows, Columns<StockSummary> columns, bool hasstyle)
- {
- int productcol = columns.IndexOf(x => x.Product.ID);
- int stylecol = hasstyle ? columns.IndexOf(x => x.Style.ID) : -1;
- int unitcol = columns.IndexOf(x => x.Dimensions.UnitSize);
-
- var result = rows.Select(r => new Tuple<Guid, Guid?, String>(
- (Guid)(r.Values[productcol] ?? Guid.Empty),
- (stylecol != -1) ? (Guid)(r.Values[stylecol] ?? Guid.Empty) : null,
- (String)(r.Values[unitcol] ?? ""))
- ).Distinct().ToArray();
-
- return result;
- }
- private CoreRow[] GetRows<TSource>(IEnumerable<CoreRow> rows, Columns<TSource> columns, Guid productid, Guid? styleid, String unitsize) where TSource : IJobMaterial
- {
- int productcol = columns.IndexOf(x => x.Product.ID);
- int stylecol = styleid.HasValue ? columns.IndexOf(x => x.Style.ID) : -1;
- int unitcol = columns.IndexOf(x => x.Dimensions.UnitSize);
-
- var subset = rows
- .Where(r=>
- Guid.Equals(r.Values[productcol], productid)
- && (!styleid.HasValue || Guid.Equals(r.Values[stylecol], styleid))
- && String.Equals(r.Values[unitcol], unitsize)
- );
-
- return subset.ToArray();
- }
- private double Aggregate<TSource>(IEnumerable<CoreRow> rows, Columns<TSource> columns, bool hasstyle, bool hasjob, Expression<Func<TSource, object>> source, CoreRow target, Expression<Func<StockSummary, object>> aggregate )
- {
- int srcol = columns.IndexOf(source);
-
- if (srcol == -1)
- return 0.00;
- var total = rows.Aggregate(0d, (value, row) => value + (double)(row.Values[srcol] ?? 0.0d));
-
- // int productcol = columns.IndexOf(x => x.Product.ID);
- // int stylecol = hasstyle ? columns.IndexOf(x => x.Style.ID) : -1;
- // int jobcol = hasjob ? columns.IndexOf(x => x.Job.ID) : -1;
- // int unitcol = columns.IndexOf(x => x.Dimensions.UnitSize);
- //
- // var tuples = rows.Select(r => new Tuple<Guid, Guid?, Guid?, String, double>(
- // (Guid)(r.Values[productcol] ?? Guid.Empty),
- // (hasstyle ? (Guid)(r.Values[stylecol] ?? Guid.Empty) : null),
- // (hasjob ? (Guid)(r.Values[jobcol] ?? Guid.Empty) : null),
- // (String)(r.Values[unitcol] ?? ""),
- // (double)(r.Values[aggcol] ?? 0.0d))
- // ).ToArray();
- //
- // var total = tuples.Aggregate(0d, (value, tuple) => value + tuple.Item5);
- target.Set(aggregate, total);
- return total;
- }
-
- protected override void Reload(Filters<StockSummary> criteria, Columns<StockSummary> columns, ref SortOrder<StockSummary>? sort,
- Action<CoreTable?, Exception?> action)
- {
- var filter = GetFilters().Combine();
-
- new Client<StockSummary>().Query(filter,columns,sort, (o,e) =>
- {
-
- var pids = o.ExtractValues<StockSummary, Guid>(x => x.Product.ID).ToArray();
-
- MultiQuery query = new MultiQuery();
- query.Add<StockHolding>(
- new Filter<StockHolding>(x => x.Product.ID).InList(pids),
- new Columns<StockHolding>(x => x.Product.ID)
- .Add(x => x.Style.ID)
- .Add(x => x.Dimensions.UnitSize)
- .Add(x => x.Units)
- );
- query.Add<PurchaseOrderItem>(
- new Filter<PurchaseOrderItem>(x => x.ReceivedDate).IsEqualTo(DateTime.MinValue)
- .And(x => x.Product.ID).InList(pids),
- new Columns<PurchaseOrderItem>(x => x.Product.ID)
- .Add(x => x.Style.ID)
- .Add(x => x.Dimensions.UnitSize)
- .Add(x => x.Qty)
- );
- query.Query();
- var holdings = query.Get<StockHolding>();
- Columns<StockHolding> holdingcolumns = new Columns<StockHolding>(holdings.Columns.Select(x => x.ColumnName));
-
- var orders = query.Get<PurchaseOrderItem>();
- Columns<PurchaseOrderItem> ordercolumns = new Columns<PurchaseOrderItem>(orders.Columns.Select(x => x.ColumnName));
-
- CoreTable table = new CoreTable();
- table.LoadColumns(columns);
-
- if (o != null)
- {
-
- bool bHasStyle = HasStyle();
- var keys = GetKeys(o.Rows, columns, bHasStyle);
-
- foreach (var key in keys)
- {
-
- var rows = GetRows(o.Rows, columns, key.Item1, key.Item2, key.Item3);
- if (rows.Any())
- {
-
- CoreRow newrow = table.NewRow();
- newrow.LoadValues(rows.First().Values);
- Aggregate(rows, columns, bHasStyle, true, x => x.BillOfMaterials, newrow, x => x.BillOfMaterials);
- Aggregate(rows, columns, bHasStyle, true, x => x.Issued, newrow, x => x.Issued);
- Aggregate(rows, columns, bHasStyle, true, x => x.TotalRequired, newrow, x => x.TotalRequired);
- var nettrequired = Aggregate(rows, columns, bHasStyle, true, x => x.NettRequired, newrow, x => x.NettRequired);
- var holdingrows = GetRows(holdings.Rows, holdingcolumns, key.Item1, key.Item2, key.Item3);
- var allstock = Aggregate(holdingrows, holdingcolumns, bHasStyle, false, x => x.Units, newrow, x => x.AllStock);
- var orderrows = GetRows(orders.Rows, ordercolumns, key.Item1, key.Item2, key.Item3);
- var onorder = Aggregate(orderrows, ordercolumns, bHasStyle, false, x => x.Qty, newrow, x => x.OnOrder);
- newrow.Set<StockSummary, double>(x => x.TotalStock, allstock + onorder);
- newrow.Set<StockSummary, double>(x => x.BalanceAvailable, allstock + onorder - (newrow.Get<StockSummary,double>(c=>c.Product.MinimumStockLevel) + nettrequired));
- table.Rows.Add(newrow);
- }
-
- }
- }
- action?.Invoke(table, e);
- });
-
- }
- protected override bool FilterRecord(CoreRow row)
- {
- var result = base.FilterRecord(row);
- if (result)
- result = (result && (
- row.Get<StockSummary, double>(x => x.BillOfMaterials) != 0.0F
- || row.Get<StockSummary, double>(x => x.Product.MinimumStockLevel) != 0.0F
- || row.Get<StockSummary, double>(x => x.Issued) != 0.0F
- || row.Get<StockSummary, double>(x => x.AllStock) != 0.0F
- || row.Get<StockSummary, double>(x => x.OnOrder) != 0.0F
- )
- );
- return result;
- }
- // private String _minstock = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.Product.MinimumStockLevel, ".");
- // private String _bom = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.BillOfMaterials, ".");
- // private String _issued = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.Issued, ".");
- // private String _nettrequired = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.NettRequired, ".");
- // private String _stock = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.AllStock, ".");
- // private String _ordered = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.OnOrder, ".");
- private String _balance = CoreUtils.GetFullPropertyName<StockSummary, double>(x => x.BalanceAvailable, ".");
- protected override Brush? GetCellBackground(CoreRow row, string columnname)
- {
-
- if (String.Equals(columnname, _balance))
- {
- return row.Get<StockSummary, double>(x => x.BalanceAvailable) < 0.0F
- ? new SolidColorBrush(Colors.LightSalmon) { Opacity = 0.5 }
- : null;
- }
- return null;
- }
- #region IDataModelSource
-
- public event DataModelUpdateEvent? OnUpdateDataModel;
- public string SectionName => "Stock Summary";
- public DataModel DataModel(Selection selection)
- {
- return new AutoDataModel<StockSummary>(null);
- }
-
- #endregion
- }
- }
|