|
@@ -15,6 +15,8 @@ using System.Windows.Media;
|
|
|
using System.Windows.Media.Imaging;
|
|
|
using PRSDimensionUtils;
|
|
|
using StockMovement = Comal.Classes.StockMovement;
|
|
|
+using Org.BouncyCastle.Asn1.Mozilla;
|
|
|
+using jdk.nashorn.@internal.ir;
|
|
|
|
|
|
namespace PRSDesktop;
|
|
|
|
|
@@ -44,7 +46,9 @@ public class StockForecastItem : BaseObject
|
|
|
public StockDimensions Dimensions => InitializeField(ref _dimensions, nameof(Dimensions));
|
|
|
private StockDimensions? _dimensions;
|
|
|
|
|
|
- public bool IsProductInstance { get; set; }
|
|
|
+ public bool IsProductInstance => ProductInstances.Count > 0;
|
|
|
+
|
|
|
+ public List<ProductInstance> ProductInstances { get; set; } = new(0);
|
|
|
|
|
|
public double MinStock { get; set; }
|
|
|
public double GenStock { get; set; }
|
|
@@ -148,7 +152,8 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
|
|
|
Position = DynamicActionColumnPosition.Start
|
|
|
});
|
|
|
|
|
|
- CreateColumn(GetMinimumStockLevel, ColumnTag.MinimumStockRequired,"Min.","F2");
|
|
|
+ var minStockColumn = CreateColumn(GetMinimumStockLevel, ColumnTag.MinimumStockRequired,"Min.","F2");
|
|
|
+ minStockColumn.ContextMenu = MinimumStock_Menu;
|
|
|
CreateColumn(GetGeneralStockLevel, ColumnTag.GeneralStockHoldings,"Hld.","F2");
|
|
|
CreateColumn(GetGeneralPurchaseOrder, ColumnTag.GeneralPurchaseOrders, "PO.","F2");
|
|
|
CreateColumn(GetBOMBalance, ColumnTag.JobStockRequired, "BOM.","F2");
|
|
@@ -335,7 +340,7 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
|
|
|
|
|
|
#region Column Data and Details
|
|
|
|
|
|
- private void CreateColumn(DynamicTextColumn.GetTextDelegate calculate, ColumnTag tag, string header, string format)
|
|
|
+ private DynamicTextColumn CreateColumn(DynamicTextColumn.GetTextDelegate calculate, ColumnTag tag, string header, string format)
|
|
|
{
|
|
|
var column = new DynamicTextColumn(calculate)
|
|
|
{
|
|
@@ -349,6 +354,7 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
|
|
|
filter => GetColumnFilterItems(filter, tag))
|
|
|
};
|
|
|
ActionColumns.Add(column);
|
|
|
+ return column;
|
|
|
}
|
|
|
|
|
|
private DynamicTextColumn GetColumn(ColumnTag tag) => (ActionColumns.First(x => Equals(x.Tag, tag)) as DynamicTextColumn)!;
|
|
@@ -569,6 +575,102 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private ContextMenu? MinimumStock_Menu(CoreRow[]? rows)
|
|
|
+ {
|
|
|
+ if (rows is null || rows.Length == 0) return null;
|
|
|
+
|
|
|
+ var items = LoadItems(rows);
|
|
|
+
|
|
|
+ var menu = new ContextMenu();
|
|
|
+ if (Security.CanEdit<ProductInstance>())
|
|
|
+ {
|
|
|
+ if(items.Any(x => x.IsProductInstance))
|
|
|
+ {
|
|
|
+ menu.AddItem("Adjust minimum stock", null, items, AdjustMinStock_Click);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(menu.Items.Count > 0)
|
|
|
+ {
|
|
|
+ return menu;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void AdjustMinStock_Click(StockForecastItem[] items)
|
|
|
+ {
|
|
|
+ var productInstances = items.SelectMany(x => x.ProductInstances).ToArray();
|
|
|
+ var grid = new ProductInstanceMinimumStockEditGrid(productInstances.ToArray(x => x.ID));
|
|
|
+ var dlg = new DynamicContentDialog(grid)
|
|
|
+ {
|
|
|
+ Title = "Adjust minimum stock levels",
|
|
|
+ CanSave = true
|
|
|
+ };
|
|
|
+ grid.Refresh(true, true);
|
|
|
+ if(dlg.ShowDialog() == true)
|
|
|
+ {
|
|
|
+ Client.Save(grid.Items, "Min stock adjusted.");
|
|
|
+ Refresh(false, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private class ProductInstanceMinimumStockEditGrid(Guid[] instanceIDs) : DynamicItemsListGrid<ProductInstance>, ISpecificGrid
|
|
|
+ {
|
|
|
+ protected override void DoReconfigure(DynamicGridOptions options)
|
|
|
+ {
|
|
|
+ base.DoReconfigure(options);
|
|
|
+
|
|
|
+ options.Clear();
|
|
|
+ options.DirectEdit = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override DynamicGridColumns GenerateColumns()
|
|
|
+ {
|
|
|
+ return new DynamicGridColumns<ProductInstance>()
|
|
|
+ .AddFluent(x => x.Product.ID)
|
|
|
+ .AddFluent(x => x.Style.ID)
|
|
|
+ .AddFluent(x => x.Dimensions.UnitSize)
|
|
|
+ .AddFluent(x => x.MinimumStockLevel, caption: "Min. Stock", width: 100);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override BaseEditor CustomiseEditor(DynamicGridColumn column, BaseEditor editor)
|
|
|
+ {
|
|
|
+ editor = base.CustomiseEditor(column, editor);
|
|
|
+
|
|
|
+ if(column.ColumnName == nameof(ProductInstance.MinimumStockLevel))
|
|
|
+ {
|
|
|
+ editor.Editable = Editable.Enabled;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ editor.Editable = Editable.Disabled;
|
|
|
+ }
|
|
|
+ return editor;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void Reload(Filters<ProductInstance> criteria, Columns<ProductInstance> columns, ref SortOrder<ProductInstance>? sort, CancellationToken token, Action<CoreTable?, Exception?> action)
|
|
|
+ {
|
|
|
+ criteria.Add(new Filter<ProductInstance>(x => x.ID).InList(instanceIDs));
|
|
|
+ Client.Query<ProductInstance>(criteria.Combine(), columns, sort, null, (t, e) =>
|
|
|
+ {
|
|
|
+ if (t is not null)
|
|
|
+ {
|
|
|
+ Items = t.ToList<ProductInstance>();
|
|
|
+ var table = new CoreTable();
|
|
|
+ table.LoadColumns(typeof(ProductInstance));
|
|
|
+ table.LoadRows(Items);
|
|
|
+ action(table, null);
|
|
|
+ }
|
|
|
+ else if (e is not null)
|
|
|
+ {
|
|
|
+ action(null, e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
#endregion
|
|
|
|
|
|
#region Refresh
|
|
@@ -726,6 +828,7 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
|
|
|
new KeyedQueryDef<ProductInstance>(
|
|
|
new Filter<ProductInstance>(x=>x.MinimumStockLevel).IsNotEqualTo(0.0).And(x => x.Product.Group.ID).InList(GroupIDs),
|
|
|
Columns.None<ProductInstance>()
|
|
|
+ .Add(x => x.ID)
|
|
|
.Add(x => x.Product.ID)
|
|
|
.Add(x => x.Style.ID)
|
|
|
.AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Data)
|
|
@@ -800,12 +903,14 @@ public class StockForecastGrid : DynamicItemsListGrid<StockForecastItem>, IDataM
|
|
|
var productInstances = results.GetArray<ProductInstance>();
|
|
|
foreach(var instance in productInstances)
|
|
|
{
|
|
|
- var minStock = DimensionUtils.ConvertDimensions(instance.Dimensions, instance.MinimumStockLevel, (f,c) => Client.Query(f,c));
|
|
|
+ var dimensions = new StockDimensions();
|
|
|
+ dimensions.CopyFrom(instance.Dimensions);
|
|
|
+ var minStock = DimensionUtils.ConvertDimensions(dimensions, instance.MinimumStockLevel, (f,c) => Client.Query(f,c));
|
|
|
|
|
|
- var item = GetItem(new(instance.Product.ID, instance.Style.ID, instance.Dimensions));
|
|
|
+ var item = GetItem(new(instance.Product.ID, instance.Style.ID, dimensions));
|
|
|
|
|
|
item.MinStock += minStock;
|
|
|
- item.IsProductInstance = true;
|
|
|
+ item.ProductInstances.Add(instance);
|
|
|
}
|
|
|
|
|
|
var holdings = results.Get<StockHolding>();
|