|
@@ -1,18 +1,66 @@
|
|
|
using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
using System.Threading;
|
|
|
+using System.Windows;
|
|
|
+using System.Windows.Controls;
|
|
|
using Comal.Classes;
|
|
|
+using InABox.Clients;
|
|
|
using InABox.Core;
|
|
|
using InABox.DynamicGrid;
|
|
|
+using InABox.Wpf;
|
|
|
+using InABox.WPF;
|
|
|
|
|
|
namespace PRSDesktop;
|
|
|
|
|
|
public class ProductHoldingControl : DynamicDataGrid<StockHolding>, IProductControl
|
|
|
{
|
|
|
+
|
|
|
+ private Button AdjustValueButton;
|
|
|
+
|
|
|
+ private Button RecalculateButton;
|
|
|
+
|
|
|
public ProductHoldingControl()
|
|
|
{
|
|
|
ColumnsTag = "ProductHolding";
|
|
|
+ HiddenColumns.Add(x => x.Product.ID);
|
|
|
+ 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.Style.ID);
|
|
|
+ HiddenColumns.Add(x => x.Style.Code);
|
|
|
HiddenColumns.Add(x => x.Qty);
|
|
|
+ HiddenColumns.Add(x => x.Units);
|
|
|
+ HiddenColumns.Add(x => x.Available);
|
|
|
+ HiddenColumns.Add(x => x.AverageValue);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.ID);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.Description);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.HasHeight);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.HasLength);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.HasWidth);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.HasHeight);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.HasQuantity);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.Format);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Unit.Formula);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Length);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Width);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Height);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Quantity);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.Value);
|
|
|
+ HiddenColumns.Add(x => x.Dimensions.UnitSize);
|
|
|
+
|
|
|
+ AdjustValueButton = AddButton("Adjust Value", PRSDesktop.Resources.receipt.AsBitmapImage(), AdjustValues,
|
|
|
+ DynamicGridButtonPosition.Right);
|
|
|
+ AdjustValueButton.Margin = new Thickness(AdjustValueButton.Margin.Left, AdjustValueButton.Margin.Top, 10, AdjustValueButton.Margin.Bottom);
|
|
|
+
|
|
|
+ RecalculateButton = AddButton("Recalculate", PRSDesktop.Resources.service.AsBitmapImage(), RecalculateHoldings,
|
|
|
+ DynamicGridButtonPosition.Right);
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
protected override void DoReconfigure(DynamicGridOptions options)
|
|
|
{
|
|
|
base.DoReconfigure(options);
|
|
@@ -49,4 +97,170 @@ public class ProductHoldingControl : DynamicDataGrid<StockHolding>, IProductCont
|
|
|
//
|
|
|
// return result;
|
|
|
// }
|
|
|
+
|
|
|
+ protected override void SelectItems(CoreRow[]? rows)
|
|
|
+ {
|
|
|
+ base.SelectItems(rows);
|
|
|
+
|
|
|
+ var _groups = rows?.GroupBy(x => new Tuple<Guid, double>(
|
|
|
+ x.Get<StockHolding, Guid>(c => c.Product.ID),
|
|
|
+ x.Get<StockHolding, double>(c => c.Dimensions.Value))
|
|
|
+ );
|
|
|
+ AdjustValueButton.IsEnabled = (Product?.ID ?? Guid.Empty) != Guid.Empty && _groups?.Count() == 1;
|
|
|
+
|
|
|
+ RecalculateButton.IsEnabled = (Product?.ID ?? Guid.Empty) != Guid.Empty;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private bool AdjustValues(Button arg1, CoreRow[] rows)
|
|
|
+ {
|
|
|
+ if (rows?.Any() != true)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ double _newvalue = 0.0;
|
|
|
+ if (DoubleEdit.Execute("New Average Value", 0, double.MaxValue, ref _newvalue))
|
|
|
+ {
|
|
|
+ Progress.ShowModal("Creating Batch", progress =>
|
|
|
+ {
|
|
|
+ StockMovementBatch _batch = new StockMovementBatch()
|
|
|
+ {
|
|
|
+ Type = StockMovementBatchType.Transfer,
|
|
|
+ Employee = new EmployeeLink() { ID = App.EmployeeID },
|
|
|
+ Notes = "Stock Value Adjustment"
|
|
|
+ };
|
|
|
+ Client.Save(_batch,"Stock value adjusted from Products List");
|
|
|
+
|
|
|
+ progress.Report("Creating Movements");
|
|
|
+ List<StockMovement> _updates = new List<StockMovement>();
|
|
|
+ foreach (var _row in rows)
|
|
|
+ {
|
|
|
+ var _holding = _row.ToObject<StockHolding>();
|
|
|
+ _holding.AverageValue = _newvalue;
|
|
|
+ _holding.Value = _newvalue * _holding.Units;
|
|
|
+ Client.Save(_holding,"Stock value adjusted from Products List");
|
|
|
+ _updates.AddRange(_holding.AdjustValue(_newvalue, _batch));
|
|
|
+ }
|
|
|
+
|
|
|
+ progress.Report("Saving Movements");
|
|
|
+ Client.Save(_updates,"Stock value adjusted from Products List");
|
|
|
+ });
|
|
|
+ MessageBox.Show("All Done");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool RecalculateHoldings(Button arg1, CoreRow[] arg2)
|
|
|
+ {
|
|
|
+ Dictionary<String, int> messages = new();
|
|
|
+ void AddMessage(String type)
|
|
|
+ {
|
|
|
+ messages.TryGetValue(type, out int count);
|
|
|
+ messages[type] = ++count;
|
|
|
+ }
|
|
|
+
|
|
|
+ Progress.ShowModal("Recalculating", progress =>
|
|
|
+ {
|
|
|
+ progress.Report("Loading Data");
|
|
|
+ MultiQuery query = new MultiQuery();
|
|
|
+
|
|
|
+ query.Add(
|
|
|
+ new Filter<StockHolding>(x => x.Product.ID).IsEqualTo(Product.ID),
|
|
|
+ Columns.Required<StockHolding>().Add(x => x.ID)
|
|
|
+ .Add(x => x.Product.ID)
|
|
|
+ .Add(x => x.Job.ID)
|
|
|
+ .Add(x => x.Style.ID)
|
|
|
+ .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Local)
|
|
|
+ .Add(x => x.Units)
|
|
|
+ .Add(x => x.AverageValue)
|
|
|
+ .Add(x => x.Available)
|
|
|
+ .Add(x => x.Qty)
|
|
|
+ .Add(x => x.Weight)
|
|
|
+ .Add(x => x.Value)
|
|
|
+ );
|
|
|
+
|
|
|
+ query.Add(
|
|
|
+ new Filter<StockMovement>(x => x.Product.ID).IsEqualTo(Product.ID),
|
|
|
+ Columns.None<StockMovement>().Add(x => x.ID)
|
|
|
+ .Add(x => x.Product.ID)
|
|
|
+ .Add(x => x.Job.ID)
|
|
|
+ .Add(x => x.Style.ID)
|
|
|
+ .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Local)
|
|
|
+ .Add(x => x.Units)
|
|
|
+ .Add(x => x.Cost)
|
|
|
+ .Add(x => x.JobRequisitionItem.ID)
|
|
|
+ );
|
|
|
+ query.Query();
|
|
|
+ var holdings = query.Get<StockHolding>().ToObjects<StockHolding>().ToList();
|
|
|
+ var toDelete = new List<StockHolding>();
|
|
|
+ var movements = query.Get<StockMovement>().ToObjects<StockMovement>().ToList();
|
|
|
+
|
|
|
+ progress.Report("Processing");
|
|
|
+ var updates = new List<StockHolding>();
|
|
|
+
|
|
|
+ while (movements.Any())
|
|
|
+ {
|
|
|
+ var first = movements.First();
|
|
|
+ var selected = movements.Where(x => x.IsEqualTo(first)).ToList();
|
|
|
+
|
|
|
+ var holding = holdings.FirstOrDefault(x => x.IsEqualTo(first));
|
|
|
+ if (holding == null)
|
|
|
+ {
|
|
|
+ holding = new StockHolding();
|
|
|
+ holding.Location.ID = first.Location.ID;
|
|
|
+ holding.Product.ID = Product.ID;
|
|
|
+ holding.Style.ID = first.Style.ID;
|
|
|
+ holding.Job.ID = first.Job.ID;
|
|
|
+ holding.Dimensions.CopyFrom(first.Dimensions);
|
|
|
+ }
|
|
|
+ holding.Recalculate(selected);
|
|
|
+
|
|
|
+ // Removing from the list so that it is not deleted.
|
|
|
+ if (holdings.Contains(holding))
|
|
|
+ holdings.Remove(holding);
|
|
|
+
|
|
|
+ if (holding.Units.IsEffectivelyEqual(0.0) && holding.Available.IsEffectivelyEqual(0.0))
|
|
|
+ {
|
|
|
+ if(holding.ID != Guid.Empty)
|
|
|
+ {
|
|
|
+ toDelete.Add(holding);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (holding.IsChanged())
|
|
|
+ {
|
|
|
+ AddMessage(holding.ID != Guid.Empty ? "updated" : "added");
|
|
|
+ updates.Add(holding);
|
|
|
+ }
|
|
|
+
|
|
|
+ movements.RemoveAll(x => selected.Any(s => s.ID == x.ID));
|
|
|
+ }
|
|
|
+
|
|
|
+ toDelete.AddRange(holdings);
|
|
|
+ foreach (var holding in toDelete)
|
|
|
+ AddMessage("deleted");
|
|
|
+
|
|
|
+ if (updates.Any())
|
|
|
+ {
|
|
|
+ progress.Report($"Updating {updates.Count} Holdings");
|
|
|
+ new Client<StockHolding>().Save(updates.Where(x => x.IsChanged()), "Updated by Recalculation");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (toDelete.Any())
|
|
|
+ {
|
|
|
+ progress.Report($"Deleting {toDelete.Count} Holdings");
|
|
|
+ new Client<StockHolding>().Delete(toDelete, "Removed by Recalculation");
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ MessageWindow.ShowMessage(
|
|
|
+ messages.Any()
|
|
|
+ ? String.Join("\n", messages.Select(x => $"{x.Value} holdings {x.Key}"))
|
|
|
+ : "Nothing to Update!"
|
|
|
+ ,"Recalculate");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|