|
@@ -1,17 +1,25 @@
|
|
|
using System;
|
|
|
+using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
+using System.Linq.Expressions;
|
|
|
using System.Reflection;
|
|
|
using System.Windows;
|
|
|
+using System.Windows.Controls;
|
|
|
using Comal.Classes;
|
|
|
using InABox.Clients;
|
|
|
using InABox.Core;
|
|
|
using InABox.DynamicGrid;
|
|
|
-using Microsoft.Exchange.WebServices.Data;
|
|
|
+
|
|
|
|
|
|
namespace PRSDesktop
|
|
|
{
|
|
|
internal class JobSummaryGrid : DynamicDataGrid<JobMaterial>, IJobControl, IDataModelSource
|
|
|
{
|
|
|
+
|
|
|
+ private bool _stylecolumnVisible;
|
|
|
+
|
|
|
+ private bool _includeReserves;
|
|
|
+
|
|
|
public JobSummaryGrid() : base()
|
|
|
{
|
|
|
Options.AddRange(
|
|
@@ -27,74 +35,232 @@ namespace PRSDesktop
|
|
|
HiddenColumns.Add(x => x.Dimensions.UnitSize);
|
|
|
|
|
|
HiddenColumns.Add(x => x.BillOfMaterials);
|
|
|
- HiddenColumns.Add(x => x.TotalRequired);
|
|
|
- HiddenColumns.Add(x => x.BalanceRequired);
|
|
|
+ HiddenColumns.Add(x => x.Requisitions);
|
|
|
+ HiddenColumns.Add(x => x.PickingLists);
|
|
|
+ HiddenColumns.Add(x => x.Issued);
|
|
|
+
|
|
|
HiddenColumns.Add(x => x.ReservedStock);
|
|
|
HiddenColumns.Add(x => x.OnOrder);
|
|
|
- HiddenColumns.Add(x => x.Issued);
|
|
|
- HiddenColumns.Add(x => x.Received);
|
|
|
|
|
|
+ HiddenColumns.Add(x => x.JobShortage);
|
|
|
+
|
|
|
+ HiddenColumns.Add(x => x.FreeOnHand);
|
|
|
+ HiddenColumns.Add(x => x.FreeOnOrder);
|
|
|
+ HiddenColumns.Add(x => x.FreeStockTotal);
|
|
|
+ HiddenColumns.Add(x => x.FreeStockShortage);
|
|
|
+
|
|
|
HiddenColumns.Add(x => x.Product.Image.ID);
|
|
|
HiddenColumns.Add(x => x.Product.Image.FileName);
|
|
|
ActionColumns.Add(new DynamicImageManagerColumn<JobMaterial>(this, x => x.Product.Image, false)
|
|
|
{ Position = DynamicActionColumnPosition.Start });
|
|
|
+
|
|
|
+ AddButton("Include Reserves", null, ToggleIncludeReserves);
|
|
|
|
|
|
OnCellDoubleClick += JobSummaryGrid_OnCellDoubleClick;
|
|
|
}
|
|
|
|
|
|
- private void JobSummaryGrid_OnCellDoubleClick(object sender, DynamicGridCellClickEventArgs args)
|
|
|
+ private bool ToggleIncludeReserves(Button sender, CoreRow[] arg2)
|
|
|
{
|
|
|
- if(args.Column.ColumnName == "BillOfMaterials"
|
|
|
- || args.Column.ColumnName == "TotalRequired"
|
|
|
- || args.Column.ColumnName == "ReservedStock"
|
|
|
- || args.Column.ColumnName == "OnOrder"
|
|
|
- || args.Column.ColumnName == "Issued"
|
|
|
- || args.Column.ColumnName == "Received"
|
|
|
- || args.Column.ColumnName == "FreeStock")
|
|
|
+ _includeReserves = !_includeReserves;
|
|
|
+ UpdateButton(sender, null, _includeReserves ? "Free Stock Only" : "Include Reserves");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void GenerateColumns(DynamicGridColumns columns)
|
|
|
+ {
|
|
|
+ columns.Add<JobMaterial, string>(x => x.Product.Group.Code, 120, "Group Code", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, string>(x => x.Product.Code, 200, "Product Code", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, string>(x => x.Product.Name, 0, "Product Name", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, string>(x => x.Dimensions.UnitSize, 120, "UOM", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.BillOfMaterials, 80, "BOM", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.Requisitions, 80, "Req.", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.PickingLists, 80, "P/L", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.Issued, 80, "Issued", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.ReservedStock, 80, "Reserved", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.OnOrder, 80, "Ordered", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.JobShortage, 80, "Shortage", "", Alignment.MiddleCenter);
|
|
|
+ columns.Add<JobMaterial, double>(x => x.FreeStockTotal, 80, "Free Stock", "", 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)
|
|
|
{
|
|
|
- if(DatabaseSchema.Property(typeof(JobMaterial), args.Column.ColumnName) is StandardProperty property)
|
|
|
- {
|
|
|
- var aggregate = property.Property.GetCustomAttribute<AggregateAttribute>();
|
|
|
- if(aggregate is not null)
|
|
|
- {
|
|
|
- var entityType = aggregate.Source;
|
|
|
- var filter = Filter.Create(entityType).All();
|
|
|
-
|
|
|
- var aggFilter = aggregate.Filter;
|
|
|
- if (aggFilter is not null)
|
|
|
- filter.And(aggFilter);
|
|
|
-
|
|
|
- var links = aggregate.Links;
|
|
|
-
|
|
|
- foreach (var (pLeft, pJobMaterial) in aggregate.Links)
|
|
|
- {
|
|
|
- var value = pJobMaterial == "Job.ID"
|
|
|
- ? ParentID
|
|
|
- : args.Row[pJobMaterial];
|
|
|
-
|
|
|
- filter.And(pLeft).IsEqualTo(value);
|
|
|
- }
|
|
|
-
|
|
|
- var grid = (Activator.CreateInstance(typeof(DynamicDataGrid<>).MakeGenericType(entityType)) as IDynamicDataGrid)!;
|
|
|
- grid.ColumnsTag = $"JobSummaryAggregate.{args.Column.ColumnName}";
|
|
|
- //DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), entityType);
|
|
|
- grid.Options.BeginUpdate().Clear().AddRange(DynamicGridOption.FilterRows, DynamicGridOption.SelectColumns).EndUpdate();
|
|
|
- grid.OnDefineFilter += t =>
|
|
|
- {
|
|
|
- return filter;
|
|
|
- };
|
|
|
+ MessageBox.Show($"Cannot create Grid for [{typeof(TEntity).Name}]");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ grid.ColumnsTag = $"{ColumnsTag}.{columnname}";
|
|
|
+ grid.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).IsEqualTo(ParentID);
|
|
|
+
|
|
|
+ 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 JobSummaryGrid_OnCellDoubleClick(object sender, DynamicGridCellClickEventArgs args)
|
|
|
+ {
|
|
|
+ Guid productid = args.Row.Get<StockSummary, Guid>(c => c.Product.ID);
|
|
|
+ Guid? styleid = _stylecolumnVisible ? args.Row.Get<StockSummary, Guid>(c => c.Style.ID) : null;
|
|
|
+ String unitsize = args.Row.Get<StockSummary, String>(c => c.Dimensions.UnitSize);
|
|
|
|
|
|
- var window = DynamicGridUtils.CreateGridWindow($"Viewing {CoreUtils.Neatify(args.Column.ColumnName)} Calculation", (grid as BaseDynamicGrid)!);
|
|
|
- window.ShowDialog();
|
|
|
- }
|
|
|
- }
|
|
|
+ if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, 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(args.Column.ColumnName == "BalanceRequired")
|
|
|
+
|
|
|
+ else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.Requisitions, ".")))
|
|
|
+ {
|
|
|
+ ShowDetailGrid<JobRequisitionItem>(
|
|
|
+ args.Column.ColumnName,
|
|
|
+ x => x.Product.ID,
|
|
|
+ productid,
|
|
|
+ x => x.Style.ID,
|
|
|
+ styleid,
|
|
|
+ x=>x.Dimensions.UnitSize,
|
|
|
+ unitsize,
|
|
|
+ x => x.Job.ID,
|
|
|
+ new Filter<JobRequisitionItem>(x=>x.Requisition.Approved).IsNotEqualTo(DateTime.MinValue),
|
|
|
+ null
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.PickingLists, ".")))
|
|
|
+ {
|
|
|
+ ShowDetailGrid<RequisitionItem>(
|
|
|
+ args.Column.ColumnName,
|
|
|
+ x => x.Product.ID,
|
|
|
+ productid,
|
|
|
+ x => x.Style.ID,
|
|
|
+ styleid,
|
|
|
+ x=>x.Dimensions.UnitSize,
|
|
|
+ unitsize,
|
|
|
+ x => x.Job.ID,
|
|
|
+ new Filter<RequisitionItem>(x=>x.RequisitionLink.Filled).IsEqualTo(DateTime.MinValue),
|
|
|
+ null
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.Issued, ".")))
|
|
|
{
|
|
|
- var totalRequired = (double)(args.Row["TotalRequired"] ?? 0.0);
|
|
|
- var issued = (double)(args.Row["Issued"] ?? 0.0);
|
|
|
- var balance = (double)(args.Row["BalanceRequired"] ?? 0.0);
|
|
|
- MessageBox.Show($"BalanceRequired\n = TotalRequired - Issued\n = {totalRequired:F2} - {issued:F2} = {balance:F2}");
|
|
|
+ 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<JobMaterial, double>(x => x.ReservedStock, ".")))
|
|
|
+ {
|
|
|
+ ShowDetailGrid<StockHolding>(
|
|
|
+ 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<JobMaterial, double>(x => x.OnOrder, ".")))
|
|
|
+ {
|
|
|
+ ShowDetailGrid<PurchaseOrderItem>(
|
|
|
+ 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<JobMaterial, double>(x => x.FreeOnHand, ".")))
|
|
|
+ {
|
|
|
+ ShowDetailGrid<StockHolding>(
|
|
|
+ args.Column.ColumnName,
|
|
|
+ x => x.Product.ID,
|
|
|
+ productid,
|
|
|
+ x => x.Style.ID,
|
|
|
+ styleid,
|
|
|
+ x=>x.Dimensions.UnitSize,
|
|
|
+ unitsize,
|
|
|
+ null,
|
|
|
+ new Filter<StockHolding>(x=>x.Units).IsNotEqualTo(0.0F)
|
|
|
+ .And(
|
|
|
+ _includeReserves
|
|
|
+ ? new Filter<StockHolding>(x=>x.Job.ID).IsNotEqualTo(ParentID)
|
|
|
+ : new Filter<StockHolding>(x=>x.Job.JobStatus.Active).IsEqualTo(false)
|
|
|
+ ),
|
|
|
+ null
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else if (String.Equals(args.Column.ColumnName, CoreUtils.GetFullPropertyName<JobMaterial, double>(x => x.FreeOnOrder, ".")))
|
|
|
+ {
|
|
|
+ ShowDetailGrid<PurchaseOrderItem>(
|
|
|
+ args.Column.ColumnName,
|
|
|
+ x => x.Product.ID,
|
|
|
+ productid,
|
|
|
+ x => x.Style.ID,
|
|
|
+ styleid,
|
|
|
+ x=>x.Dimensions.UnitSize,
|
|
|
+ unitsize,
|
|
|
+ null,
|
|
|
+
|
|
|
+ _includeReserves
|
|
|
+ ? new Filter<PurchaseOrderItem>(x=>x.Job.ID).IsNotEqualTo(ParentID)
|
|
|
+ : new Filter<PurchaseOrderItem>(x=>x.Job.JobStatus.Active).IsEqualTo(false),
|
|
|
+ null
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -117,7 +283,55 @@ namespace PRSDesktop
|
|
|
result.Job.ID = ParentID;
|
|
|
return result;
|
|
|
}
|
|
|
+
|
|
|
+ private Tuple<Guid,Guid,Guid?,String>[] GetKeys(IEnumerable<CoreRow> rows, Columns<JobMaterial> columns, bool hasstyle)
|
|
|
+ {
|
|
|
+ int jobcol = columns.IndexOf(x => x.Job.ID);
|
|
|
+ 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, Guid?, String>(
|
|
|
+ (Guid)(r.Values[jobcol] ?? Guid.Empty),
|
|
|
+ (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? jobid, Guid productid, Guid? styleid, String unitsize) where TSource : IJobMaterial
|
|
|
+ {
|
|
|
+ int jobcol = columns.IndexOf(x => x.Job.ID);
|
|
|
+ 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=>
|
|
|
+ (!jobid.HasValue || Guid.Equals(r.Values[jobcol], jobid))
|
|
|
+ && 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<JobMaterial, 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));
|
|
|
+
|
|
|
+ target.Set(aggregate, total);
|
|
|
+ return total;
|
|
|
+ }
|
|
|
+
|
|
|
protected override void Reload(Filters<JobMaterial> criteria, Columns<JobMaterial> columns, ref SortOrder<JobMaterial>? sort,
|
|
|
Action<CoreTable?, Exception?> action)
|
|
|
{
|
|
@@ -129,73 +343,94 @@ namespace PRSDesktop
|
|
|
|
|
|
var orderby = sort != null ? Serialization.Deserialize<SortOrder<JobMaterial>>(Serialization.Serialize(sort)) : null;
|
|
|
|
|
|
- bool bHasStyle = columns.ColumnNames().Any(x => x.StartsWith("Style.") && !x.Equals("Style.ID"));
|
|
|
-
|
|
|
new Client<JobMaterial>().Query(filter,columns,orderby, (o,e) =>
|
|
|
{
|
|
|
|
|
|
- void UpdateColumn(CoreRow srcrow, CoreRow tgtrow, int colno)
|
|
|
- {
|
|
|
- if (colno != -1)
|
|
|
- tgtrow.Set(colno, tgtrow.Get<double>(colno) + (double)(srcrow.Values[colno] ?? default(double)));
|
|
|
- }
|
|
|
+ var pids = o.ExtractValues<JobMaterial, Guid>(x => x.Product.ID).ToArray();
|
|
|
+
|
|
|
+ MultiQuery query = new MultiQuery();
|
|
|
+
|
|
|
+ query.Add<StockHolding>(
|
|
|
+ new Filter<StockHolding>(x => x.Product.ID).InList(pids)
|
|
|
+ .And(x=>x.Units).IsNotEqualTo(0.0F)
|
|
|
+ .And(
|
|
|
+ _includeReserves
|
|
|
+ ? new Filter<StockHolding>(x => x.Job.ID).IsNotEqualTo(ParentID)
|
|
|
+ : new Filter<StockHolding>(x => x.Job.JobStatus.Active).IsEqualTo(false)
|
|
|
+ ),
|
|
|
+ new Columns<StockHolding>(x => x.Product.ID)
|
|
|
+ .Add(x => x.Style.ID)
|
|
|
+ .Add(x => x.Dimensions.UnitSize)
|
|
|
+ .Add(x => x.Units)
|
|
|
+ .Add(x=>x.Job.ID)
|
|
|
+ );
|
|
|
+
|
|
|
+ query.Add<PurchaseOrderItem>(
|
|
|
+ new Filter<PurchaseOrderItem>(x => x.ReceivedDate).IsEqualTo(DateTime.MinValue)
|
|
|
+ .And(x => x.Product.ID).InList(pids)
|
|
|
+ .And(
|
|
|
+ _includeReserves
|
|
|
+ ? new Filter<PurchaseOrderItem>(x => x.Job.ID).IsNotEqualTo(ParentID)
|
|
|
+ : new Filter<PurchaseOrderItem>(x => x.Job.JobStatus.Active).IsEqualTo(false)
|
|
|
+ ),
|
|
|
+ new Columns<PurchaseOrderItem>(x => x.Product.ID)
|
|
|
+ .Add(x => x.Style.ID)
|
|
|
+ .Add(x => x.Dimensions.UnitSize)
|
|
|
+ .Add(x => x.Qty)
|
|
|
+ );
|
|
|
+
|
|
|
+ query.Query();
|
|
|
+
|
|
|
+ var freestock = query.Get<StockHolding>();
|
|
|
+ Columns<StockHolding> freestockcolumns = new Columns<StockHolding>(freestock.Columns.Select(x => x.ColumnName));
|
|
|
+
|
|
|
+ var freeorders = query.Get<PurchaseOrderItem>();
|
|
|
+ Columns<PurchaseOrderItem> freeordercolumns = new Columns<PurchaseOrderItem>(freeorders.Columns.Select(x => x.ColumnName));
|
|
|
|
|
|
CoreTable table = new CoreTable();
|
|
|
table.LoadColumns(columns);
|
|
|
|
|
|
if (o != null)
|
|
|
{
|
|
|
-
|
|
|
- int productcol = columns.IndexOf(x => x.Product.ID);
|
|
|
- int stylecol = columns.IndexOf(x => x.Style.ID);
|
|
|
- int unitcol = columns.IndexOf(x => x.Dimensions.UnitSize);
|
|
|
|
|
|
- int bomcol = columns.IndexOf(x => x.BillOfMaterials);
|
|
|
- int requiredcol = columns.IndexOf(x => x.TotalRequired);
|
|
|
- int reservedcol = columns.IndexOf(x => x.ReservedStock);
|
|
|
- int orderedcol = columns.IndexOf(x => x.OnOrder);
|
|
|
- int receivedcol = columns.IndexOf(x => x.Received);
|
|
|
- int issuedcol = columns.IndexOf(x => x.Issued);
|
|
|
- int balancecol = columns.IndexOf(x => x.BalanceRequired);
|
|
|
-
|
|
|
-
|
|
|
- Tuple<Guid, Guid, String>[] keys = o.Rows
|
|
|
- .Select(r => new Tuple<Guid, Guid, String>(
|
|
|
- (Guid)(r.Values[productcol] ?? Guid.Empty),
|
|
|
- bHasStyle ? (Guid)(r.Values[stylecol] ?? Guid.Empty) : Guid.Empty,
|
|
|
- (String)(r.Values[unitcol] ?? ""))
|
|
|
- ).Distinct().ToArray();
|
|
|
+
|
|
|
+ var keys = GetKeys(o.Rows, columns, _stylecolumnVisible);
|
|
|
|
|
|
foreach (var key in keys)
|
|
|
{
|
|
|
- var rows = o.Rows.Where(r =>
|
|
|
- Guid.Equals(r.Values[productcol], key.Item1)
|
|
|
- && (bHasStyle ? Guid.Equals(r.Values[stylecol], key.Item2) : true)
|
|
|
- && String.Equals(r.Values[unitcol], key.Item3)
|
|
|
- ).ToArray();
|
|
|
|
|
|
- CoreRow newrow = null;
|
|
|
- foreach (var row in rows)
|
|
|
+ var rows = GetRows(o.Rows, columns, key.Item1, key.Item2, key.Item3, key.Item4);
|
|
|
+ if (rows.Any())
|
|
|
{
|
|
|
- if (newrow == null)
|
|
|
- {
|
|
|
- newrow = table.NewRow();
|
|
|
- newrow.LoadValues(row.Values);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- UpdateColumn(row, newrow, bomcol);
|
|
|
- UpdateColumn(row, newrow, requiredcol);
|
|
|
- UpdateColumn(row, newrow, orderedcol);
|
|
|
- UpdateColumn(row, newrow, receivedcol);
|
|
|
- UpdateColumn(row, newrow, issuedcol);
|
|
|
- UpdateColumn(row, newrow, balancecol);
|
|
|
- UpdateColumn(row, newrow, reservedcol);
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
+ CoreRow newrow = table.NewRow();
|
|
|
+ newrow.LoadValues(rows.First().Values);
|
|
|
+
|
|
|
+ var bom = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.BillOfMaterials, newrow, x => x.BillOfMaterials);
|
|
|
+ var requi = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.Requisitions, newrow, x => x.Requisitions);
|
|
|
+ var picklist = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.PickingLists, newrow, x => x.PickingLists);
|
|
|
+ var issued = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.Issued, newrow, x => x.Issued);
|
|
|
+
|
|
|
+ var reserved = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.ReservedStock, newrow, x => x.ReservedStock);
|
|
|
+ var ordered = Aggregate(rows, columns, _stylecolumnVisible, true, x => x.OnOrder, newrow, x => x.OnOrder);
|
|
|
|
|
|
- if (newrow != null)
|
|
|
+ var shortage = Math.Max(0, Math.Max(0,(requi - issued)) - (reserved + ordered));
|
|
|
+ newrow.Set<JobMaterial, double>(x => x.JobShortage, shortage);
|
|
|
+
|
|
|
+ var freestockrows = GetRows(freestock.Rows, freestockcolumns, null, key.Item2, key.Item3, key.Item4);
|
|
|
+ var freeonhand = Aggregate(freestockrows, freestockcolumns, _stylecolumnVisible, false, x => x.Units, newrow, x => x.FreeOnHand);
|
|
|
+ newrow.Set<JobMaterial, double>(x => x.FreeOnHand, freeonhand);
|
|
|
+
|
|
|
+ var freeorderrows = GetRows(freeorders.Rows, freeordercolumns, null, key.Item2, key.Item3, key.Item4);
|
|
|
+ var freeonorder = Aggregate(freeorderrows, freeordercolumns, _stylecolumnVisible, false, x => x.Qty, newrow, x => x.FreeOnOrder);
|
|
|
+ newrow.Set<JobMaterial, double>(x => x.FreeOnOrder, freeonorder);
|
|
|
+
|
|
|
+ newrow.Set<JobMaterial, double>(x => x.FreeStockTotal, freeonhand+freeonorder);
|
|
|
+ newrow.Set<JobMaterial, double>(x => x.FreeStockShortage, Math.Max(0,shortage-(freeonhand+freeonorder)));
|
|
|
table.Rows.Add(newrow);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
|
|
|
}
|
|
|
}
|
|
@@ -205,15 +440,15 @@ namespace PRSDesktop
|
|
|
|
|
|
protected override bool FilterRecord(CoreRow row)
|
|
|
{
|
|
|
- var result = base.FilterRecord(row);
|
|
|
- if (result)
|
|
|
- result = (result && row.Get<JobMaterial, double>(x => x.BillOfMaterials) != 0.0F) ||
|
|
|
- row.Get<JobMaterial, double>(x => x.TotalRequired) != 0.0F ||
|
|
|
- row.Get<JobMaterial, double>(x => x.BalanceRequired) != 0.0F ||
|
|
|
- row.Get<JobMaterial, double>(x => x.OnOrder) != 0.0F ||
|
|
|
- row.Get<JobMaterial, double>(x => x.Issued) != 0.0F ||
|
|
|
- row.Get<JobMaterial, double>(x => x.Received) != 0.0F ||
|
|
|
- row.Get<JobMaterial, double>(x => x.ReservedStock) != 0.0F;
|
|
|
+ var result = base.FilterRecord(row)
|
|
|
+ && (
|
|
|
+ row.Get<JobMaterial, double>(x => x.BillOfMaterials) != 0.0F ||
|
|
|
+ row.Get<JobMaterial, double>(x => x.Requisitions) != 0.0F ||
|
|
|
+ row.Get<JobMaterial, double>(x => x.PickingLists) != 0.0F ||
|
|
|
+ row.Get<JobMaterial, double>(x => x.Issued) != 0.0F ||
|
|
|
+ row.Get<JobMaterial, double>(x => x.ReservedStock) != 0.0F ||
|
|
|
+ row.Get<JobMaterial, double>(x => x.OnOrder) != 0.0F
|
|
|
+ );
|
|
|
return result;
|
|
|
}
|
|
|
}
|