|
@@ -28,18 +28,18 @@ namespace PRSDesktop;
|
|
|
|
|
|
public class StockForecastBreakupKey(Guid jobID, Guid requiID)
|
|
|
{
|
|
|
- public Guid JobID { get; set; } = jobID != Guid.Empty ? jobID : throw new ArgumentException("jobID cannot be Guid.Empty!", "jobID");
|
|
|
+ public Guid JobID { get; set; } = jobID != Guid.Empty ? jobID : throw new ArgumentException("Job ID cannot be Empty!", "Job ID");
|
|
|
|
|
|
- public Guid JobRequiItemID { get; set; } = requiID;
|
|
|
+ public Guid RequiID { get; set; } = requiID;
|
|
|
|
|
|
public override bool Equals(object? obj)
|
|
|
{
|
|
|
- return obj is StockForecastBreakupKey key && key.JobID == JobID && key.JobRequiItemID == JobRequiItemID;
|
|
|
+ return obj is StockForecastBreakupKey key && key.JobID == JobID && key.RequiID == RequiID;
|
|
|
}
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
{
|
|
|
- return HashCode.Combine(JobID, JobRequiItemID);
|
|
|
+ return HashCode.Combine(JobID, RequiID);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -84,20 +84,22 @@ public class StockForecastOrderingItemQuantity
|
|
|
{
|
|
|
public event Action? Changed;
|
|
|
|
|
|
- private double _stockTotal;
|
|
|
- public double StockTotal
|
|
|
+ private double orderTotal;
|
|
|
+
|
|
|
+ public double OrderTotal
|
|
|
{
|
|
|
- get => _stockTotal;
|
|
|
+ get => orderTotal;
|
|
|
set
|
|
|
{
|
|
|
- _stockTotal = value;
|
|
|
+ orderTotal = value;
|
|
|
Changed?.Invoke();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public Dictionary<StockForecastBreakupKey, double> JobTotals { get; init; } = [];
|
|
|
+ public Dictionary<StockForecastBreakupKey, double> Breakups { get; init; } = [];
|
|
|
|
|
|
private SupplierProduct? _supplierProduct;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Indicates the Supplier Product that has been selected for this cell. This comes from the combobox column.
|
|
|
/// </summary>
|
|
@@ -116,11 +118,6 @@ public class StockForecastOrderingItemQuantity
|
|
|
Changed?.Invoke();
|
|
|
}
|
|
|
|
|
|
- public double JobTotal => JobTotals.Values.Sum();
|
|
|
-
|
|
|
- public double GetTotal(StockForecastOrderingType type) => type == StockForecastOrderingType.StockOrder
|
|
|
- ? StockTotal
|
|
|
- : JobTotal;
|
|
|
}
|
|
|
|
|
|
public class StockForecastOrderingItem : BaseObject
|
|
@@ -149,6 +146,7 @@ public class StockForecastOrderingItem : BaseObject
|
|
|
{
|
|
|
return JobRequiredQuantities;
|
|
|
}
|
|
|
+
|
|
|
public void SetJobRequiredQuantity(Guid jobID, Guid requiID, double requiredQuantity)
|
|
|
{
|
|
|
JobRequiredQuantities[new(jobID, requiID)] = requiredQuantity;
|
|
@@ -160,9 +158,7 @@ public class StockForecastOrderingItem : BaseObject
|
|
|
|
|
|
public StockForecastOrderingItemQuantity GetQuantity(int i) => Quantities[i];
|
|
|
|
|
|
- public double GetTotalQuantity(StockForecastOrderingType type) => type == StockForecastOrderingType.StockOrder
|
|
|
- ? Quantities.Sum(x => x.StockTotal)
|
|
|
- : Quantities.Sum(x => x.JobTotal);
|
|
|
+ public double GetTotalQuantity(StockForecastOrderingType type) => Quantities.Sum(x => x.OrderTotal);
|
|
|
|
|
|
public void SetQuantities(StockForecastOrderingItemQuantity[] quantities)
|
|
|
{
|
|
@@ -289,22 +285,22 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- if(OrderType == StockForecastOrderingType.StockOrder && qty.StockTotal > 0)
|
|
|
+ if(OrderType == StockForecastOrderingType.StockOrder && qty.OrderTotal > 0)
|
|
|
{
|
|
|
- yield return new(supplier, new(), item, qty.StockTotal, qty.SupplierProduct);
|
|
|
+ yield return new(supplier, new(), item, qty.OrderTotal, qty.SupplierProduct);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var breakups = new List<StockForecastOrderData.QuantityBreakup>();
|
|
|
- foreach(var (key, q) in qty.JobTotals)
|
|
|
+ foreach(var (key, q) in qty.Breakups)
|
|
|
{
|
|
|
// Check JobID because we are to skip the empty job (this is just the difference between all the allocations and the quantity on the PO).
|
|
|
if(q > 0 && key.JobID != Guid.Empty)
|
|
|
{
|
|
|
- breakups.Add(new(key.JobID, key.JobRequiItemID, "", q));
|
|
|
+ breakups.Add(new(key.JobID, key.RequiID, "", q));
|
|
|
}
|
|
|
}
|
|
|
- yield return new(supplier, breakups, item, qty.JobTotal, qty.SupplierProduct);
|
|
|
+ yield return new(supplier, breakups, item, qty.OrderTotal, qty.SupplierProduct);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -449,11 +445,11 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
|
|
|
var qty = item.GetQuantity(supplierIdx);
|
|
|
qty.SupplierProduct = supplierProduct;
|
|
|
- qty.StockTotal = 0;
|
|
|
- qty.JobTotals.Clear();
|
|
|
+ qty.OrderTotal = 0;
|
|
|
+ qty.Breakups.Clear();
|
|
|
foreach(var id in item.GetJobRequiredQuantities().Keys)
|
|
|
{
|
|
|
- qty.JobTotals[id] = 0;
|
|
|
+ qty.Breakups[id] = 0;
|
|
|
}
|
|
|
|
|
|
return supplierProduct;
|
|
@@ -479,18 +475,10 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
if(supplierIdx != -1)
|
|
|
{
|
|
|
var qty = item.GetQuantity(supplierIdx);
|
|
|
- if(OrderType == StockForecastOrderingType.StockOrder)
|
|
|
- {
|
|
|
- qty.StockTotal = GetRequiredQuantity(item, selectedSupplierProduct, item.RequiredQuantity);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- qty.JobTotals.Clear();
|
|
|
- foreach(var (id, q) in item.GetJobRequiredQuantities())
|
|
|
- {
|
|
|
- qty.JobTotals[id] = GetRequiredQuantity(item, selectedSupplierProduct, q);
|
|
|
- }
|
|
|
- }
|
|
|
+ qty.OrderTotal = GetRequiredQuantity(item, selectedSupplierProduct, item.RequiredQuantity);
|
|
|
+ qty.Breakups.Clear();
|
|
|
+ foreach(var (id, q) in item.GetJobRequiredQuantities())
|
|
|
+ qty.Breakups[id] = q;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -576,7 +564,11 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
|
|
|
private double GetRequiredQuantity(StockForecastOrderingItem item, SupplierProduct supplierProduct, double requiredQuantity)
|
|
|
{
|
|
|
- switch (item.OrderStrategy)
|
|
|
+ var _strategy = item.CustomStrategy
|
|
|
+ ? SupplierProductOrderStrategy.LowestOverstock
|
|
|
+ : item.OrderStrategy;
|
|
|
+
|
|
|
+ switch (_strategy)
|
|
|
{
|
|
|
case SupplierProductOrderStrategy.Exact:
|
|
|
return requiredQuantity;
|
|
@@ -724,20 +716,20 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
quantities[newIdx] = newQty;
|
|
|
if(OrderType == StockForecastOrderingType.StockOrder)
|
|
|
{
|
|
|
- newQty.StockTotal = 0;
|
|
|
+ newQty.OrderTotal = 0;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
foreach(var id in item.GetJobRequiredQuantities().Keys)
|
|
|
{
|
|
|
- newQty.JobTotals[id] = 0;
|
|
|
+ newQty.Breakups[id] = 0;
|
|
|
}
|
|
|
}
|
|
|
item.SetQuantities(quantities);
|
|
|
}
|
|
|
|
|
|
Suppliers = newSuppliers;
|
|
|
-
|
|
|
+ _loadedColumns = false;
|
|
|
Refresh(true, true);
|
|
|
}
|
|
|
});
|
|
@@ -833,11 +825,11 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
Background = new SolidColorBrush(Colors.LightYellow),
|
|
|
BorderThickness = new Thickness(0.0),
|
|
|
MinValue = 0.0,
|
|
|
- Value = Item.GetQuantity(SupplierIndex).StockTotal
|
|
|
+ Value = Item.GetQuantity(SupplierIndex).OrderTotal
|
|
|
};
|
|
|
editor.ValueChanged += (o, e) =>
|
|
|
{
|
|
|
- Item.GetQuantity(SupplierIndex).StockTotal = editor.Value ?? default;
|
|
|
+ Item.GetQuantity(SupplierIndex).OrderTotal = editor.Value ?? default;
|
|
|
};
|
|
|
Content = editor;
|
|
|
}
|
|
@@ -856,7 +848,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
Background = new SolidColorBrush(Colors.White),
|
|
|
BorderThickness = new Thickness(0.0),
|
|
|
IsReadOnly = true,
|
|
|
- Text = string.Format("{0:F2}", Item.GetQuantity(SupplierIndex).JobTotal)
|
|
|
+ Text = string.Format("{0:F2}", Item.GetQuantity(SupplierIndex).OrderTotal)
|
|
|
};
|
|
|
Grid.SetColumn(editor, 0);
|
|
|
grid.Children.Add(editor);
|
|
@@ -876,15 +868,15 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
{
|
|
|
var qty = Item.GetQuantity(SupplierIndex);
|
|
|
|
|
|
- Parent.LoadJobData(qty.JobTotals.Keys.Select(x => x.JobID));
|
|
|
- Parent.LoadJobRequiData(qty.JobTotals.Keys.Select(x => x.JobRequiItemID));
|
|
|
+ Parent.LoadJobData(qty.Breakups.Keys.Select(x => x.JobID));
|
|
|
+ Parent.LoadJobRequiData(qty.Breakups.Keys.Select(x => x.RequiID));
|
|
|
|
|
|
- var items = qty.JobTotals.Select(x =>
|
|
|
+ var items = qty.Breakups.Select(x =>
|
|
|
{
|
|
|
var item = new StockForecastOrderingJobItem
|
|
|
{
|
|
|
JobID = x.Key.JobID,
|
|
|
- JobRequiID = x.Key.JobRequiItemID,
|
|
|
+ JobRequiID = x.Key.RequiID,
|
|
|
RequiredQuantity = Item.GetJobRequiredQuantities().GetValueOrDefault(x.Key),
|
|
|
Quantity = x.Value
|
|
|
};
|
|
@@ -912,10 +904,10 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
{
|
|
|
foreach(var item in items)
|
|
|
{
|
|
|
- qty.JobTotals[new(item.JobID, item.JobRequiID)] = item.Quantity;
|
|
|
+ qty.Breakups[new(item.JobID, item.JobRequiID)] = item.Quantity;
|
|
|
}
|
|
|
qty.DoChanged();
|
|
|
- editor.Text = string.Format("{0:F2}", Item.GetQuantity(SupplierIndex).JobTotal);
|
|
|
+ editor.Text = string.Format("{0:F2}", Item.GetQuantity(SupplierIndex).OrderTotal);
|
|
|
}
|
|
|
};
|
|
|
grid.Children.Add(btn);
|
|
@@ -947,7 +939,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
var instance = LoadItem(row);
|
|
|
|
|
|
var comboBox = new ComboBox();
|
|
|
-
|
|
|
+ comboBox.Tag = idx;
|
|
|
var items = SupplierProducts.Where(x => x.SupplierLink.ID == Suppliers[idx].ID && x.Product.ID == instance.Product.ID)
|
|
|
.Select(x => new KeyValuePair<SupplierProduct?, string>(
|
|
|
x,
|
|
@@ -963,7 +955,15 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
comboBox.Bind(ComboBox.SelectedValueProperty, qty, x => x.SupplierProduct);
|
|
|
comboBox.SelectionChanged += (o, e) =>
|
|
|
{
|
|
|
+ var box = o as ComboBox;
|
|
|
instance.CustomStrategy = true;
|
|
|
+ var _item = LoadItem(row);
|
|
|
+ var _product = ((o as ComboBox)?.SelectedValue as SupplierProduct ?? new SupplierProduct());
|
|
|
+ qty.OrderTotal = GetRequiredQuantity(_item, _product, _item.RequiredQuantity);
|
|
|
+ qty.Breakups.Clear();
|
|
|
+ foreach(var (id, q) in _item.GetJobRequiredQuantities())
|
|
|
+ qty.Breakups[id] = q;
|
|
|
+
|
|
|
InvalidateRow(row);
|
|
|
};
|
|
|
|
|
@@ -977,7 +977,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
return comboBox;
|
|
|
})
|
|
|
{
|
|
|
- HeaderText = "Supplier Product.",
|
|
|
+ HeaderText = "U.O.M.",
|
|
|
Width = 80
|
|
|
};
|
|
|
QuantityColumns[idx] = new DynamicTemplateColumn(row =>
|
|
@@ -1003,7 +1003,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
var qty = instance.GetQuantity(idx);
|
|
|
if(qty.SupplierProduct is not null)
|
|
|
{
|
|
|
- return $"{qty.GetTotal(OrderType) * qty.SupplierProduct.CostPrice:C2}";
|
|
|
+ return $"{qty.OrderTotal * qty.SupplierProduct.CostPrice:C2}";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -1084,7 +1084,7 @@ public class StockForecastOrderingGrid : DynamicItemsListGrid<StockForecastOrder
|
|
|
var qty = item.GetQuantity(SupplierIndex);
|
|
|
if(qty.SupplierProduct is not null)
|
|
|
{
|
|
|
- Sum += qty.GetTotal(Grid.OrderType) * qty.SupplierProduct.CostPrice;
|
|
|
+ Sum += qty.OrderTotal * qty.SupplierProduct.CostPrice;
|
|
|
}
|
|
|
}
|
|
|
}
|