|
|
@@ -1,11 +1,9 @@
|
|
|
-using com.sun.org.apache.xml.@internal.dtm.@ref;
|
|
|
-using Comal.Classes;
|
|
|
+using Comal.Classes;
|
|
|
using InABox.Clients;
|
|
|
using InABox.Core;
|
|
|
using InABox.Wpf;
|
|
|
using InABox.WPF;
|
|
|
-using java.sql;
|
|
|
-using org.omg.PortableInterceptor;
|
|
|
+using PRSDimensionUtils;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
@@ -86,34 +84,40 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
{
|
|
|
requisitionedTab.Visibility = redList.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
};
|
|
|
+ purchasedList.CollectionChanged += (s, e) =>
|
|
|
+ {
|
|
|
+ purchasedTab.Visibility = purchasedList.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
- private readonly ObservableCollection<ReservationManagementHoldingsModel> greenList = new();
|
|
|
- private readonly ObservableCollection<ReservationManagementHoldingsModel> yellowList = new();
|
|
|
- private readonly ObservableCollection<ReservationManagementHoldingsModel> redList = new();
|
|
|
+ private readonly ObservableCollection<ReservationManagementHoldingsModel<StockMovement>> greenList = new();
|
|
|
+ private readonly ObservableCollection<ReservationManagementHoldingsModel<StockMovement>> yellowList = new();
|
|
|
+ private readonly ObservableCollection<ReservationManagementHoldingsModel<StockMovement>> redList = new();
|
|
|
+ private readonly ObservableCollection<ReservationManagementHoldingsModel<PurchaseOrderItem>> purchasedList = new();
|
|
|
|
|
|
- private void DistributeMovements(Dictionary<Guid, List<StockMovement>>? movements, Guid selectedStyleID, ReservationManagementHoldingsModel model)
|
|
|
+ private void DistributeItems<T>(Dictionary<Guid, List<T>>? items, Guid selectedStyleID, ReservationManagementHoldingsModel<T> model,
|
|
|
+ Func<T, double> units)
|
|
|
{
|
|
|
- if (movements is null) return;
|
|
|
+ if (items is null) return;
|
|
|
|
|
|
- foreach(var (id, mvts) in movements)
|
|
|
+ foreach(var (id, styleItems) in items)
|
|
|
{
|
|
|
if(id == Guid.Empty || id == CompanyDefaultStyle.ID)
|
|
|
{
|
|
|
- model.StockOfNoStyle.AddRange(mvts);
|
|
|
+ model.StockOfNoStyle.AddRange(styleItems);
|
|
|
}
|
|
|
else if (id == selectedStyleID)
|
|
|
{
|
|
|
- model.StockOfCurrentStyle.AddRange(mvts);
|
|
|
+ model.StockOfCurrentStyle.AddRange(styleItems);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- model.StockOfOtherStyles.AddRange(mvts);
|
|
|
+ model.StockOfOtherStyles.AddRange(styleItems);
|
|
|
}
|
|
|
}
|
|
|
- model.UnitsOfCurrentStyle = Math.Round(model.StockOfCurrentStyle.Sum(x => x.Units));
|
|
|
- model.UnitsOfNoStyle = Math.Round(model.StockOfNoStyle.Sum(x => x.Units));
|
|
|
- model.UnitsOfOtherStyles = Math.Round(model.StockOfOtherStyles.Sum(x => x.Units));
|
|
|
+ model.UnitsOfCurrentStyle = Math.Round(model.StockOfCurrentStyle.Sum(units));
|
|
|
+ model.UnitsOfNoStyle = Math.Round(model.StockOfNoStyle.Sum(units));
|
|
|
+ model.UnitsOfOtherStyles = Math.Round(model.StockOfOtherStyles.Sum(units));
|
|
|
}
|
|
|
|
|
|
private void CalculateHoldings()
|
|
|
@@ -138,18 +142,67 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
x => x.JobRequisitionItem.ID,
|
|
|
x => x.Cost)
|
|
|
.AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Data))
|
|
|
- .ToArray<StockMovement>();
|
|
|
+ .ToObjects<StockMovement>();
|
|
|
var stockMovements = new Dictionary<(Guid job, bool allocated), Dictionary<Guid, List<StockMovement>>>();
|
|
|
foreach(var mvt in results)
|
|
|
{
|
|
|
- var key = (mvt.Job.ID, mvt.JobRequisitionItem.ID != Guid.Empty);
|
|
|
- var lineDict = stockMovements.GetValueOrAdd(key);
|
|
|
- var mvts = lineDict.GetValueOrAdd(mvt.Style.ID);
|
|
|
- mvts.Add(mvt);
|
|
|
+ stockMovements.GetValueOrAdd((mvt.Job.ID, mvt.JobRequisitionItem.ID != Guid.Empty))
|
|
|
+ .GetValueOrAdd(mvt.Style.ID)
|
|
|
+ .Add(mvt);
|
|
|
+ }
|
|
|
+
|
|
|
+ Filter<PurchaseOrderItem> dimensionsFilter;
|
|
|
+ double jriDimensionsUnitValue;
|
|
|
+ if (item.Dimensions.Unit.Conversion.IsNullOrWhiteSpace())
|
|
|
+ {
|
|
|
+ dimensionsFilter = Filter<PurchaseOrderItem>.Where(x => x.Dimensions).DimensionEquals(item.Dimensions);
|
|
|
+ jriDimensionsUnitValue = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ dimensionsFilter = Filter<PurchaseOrderItem>.Where(x => x.Dimensions.Unit.ID).IsEqualTo(item.Dimensions.Unit.ID);
|
|
|
+ (jriDimensionsUnitValue, _) = DimensionUtils.ConvertDimensions(item.Dimensions.Copy(), 1, 0, Client<ProductDimensionUnit>.Provider);
|
|
|
+ }
|
|
|
+
|
|
|
+ var orderItemsResult = Client.Query(
|
|
|
+ Filter<PurchaseOrderItem>.Where(x => x.Product.ID).IsEqualTo(item.Product.ID)
|
|
|
+ .And(dimensionsFilter)
|
|
|
+ .And(x => x.ReceivedDate).IsEqualTo(DateTime.MinValue),
|
|
|
+ Columns.None<PurchaseOrderItem>()
|
|
|
+ .Add(x => x.ID)
|
|
|
+ .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.All)
|
|
|
+ .Add(x => x.Dimensions.Unit.Conversion)
|
|
|
+ .Add(x => x.Style.ID)
|
|
|
+ .Add(x => x.Style.Description)
|
|
|
+ .Add(x => x.Style.Code)
|
|
|
+ .Add(x => x.Unallocated)
|
|
|
+ .Add(x => x.PurchaseOrderLink.ID)
|
|
|
+ .Add(x => x.PurchaseOrderLink.PONumber)
|
|
|
+ .Add(x => x.Job.ID))
|
|
|
+ .ToObjects<PurchaseOrderItem>();
|
|
|
+ var purchaseOrderItems = new Dictionary<Guid, Dictionary<Guid, List<PurchaseOrderItem>>>();
|
|
|
+ var orderItemQuantities = new Dictionary<Guid, double>();
|
|
|
+ foreach (var orderItem in orderItemsResult)
|
|
|
+ {
|
|
|
+ if (!item.Dimensions.Unit.Conversion.IsNullOrWhiteSpace())
|
|
|
+ {
|
|
|
+ // We need the unallocated quantity to be in terms of the dimensions of the JRI.
|
|
|
+ var (qty, cost) = DimensionUtils.ConvertDimensions(orderItem.Dimensions, orderItem.Unallocated, orderItem.Cost, Client<ProductDimensionUnit>.Provider);
|
|
|
+ orderItemQuantities[orderItem.ID] = qty / jriDimensionsUnitValue;
|
|
|
+ orderItem.Unallocated = qty;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ orderItemQuantities[orderItem.ID] = orderItem.Unallocated;
|
|
|
+ }
|
|
|
+ purchaseOrderItems.GetValueOrAdd(orderItem.Job.ID)
|
|
|
+ .GetValueOrAdd(orderItem.Style.ID)
|
|
|
+ .Add(orderItem);
|
|
|
}
|
|
|
|
|
|
var jobs = Client.Query(
|
|
|
- Filter<Job>.Where(x => x.ID).InList(stockMovements.Keys.Select(x => x.job).ToArray()),
|
|
|
+ Filter<Job>.Where(x => x.ID).InList(
|
|
|
+ stockMovements.Keys.ToArray(x => x.job).Concatenate(purchaseOrderItems.Keys.ToArray())),
|
|
|
Columns.None<Job>().Add(x => x.ID).Add(x => x.JobNumber).Add(x => x.Name))
|
|
|
.ToObjects<Job>()
|
|
|
.ToDictionary(x => x.ID, x => x);
|
|
|
@@ -166,18 +219,20 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
greenList.Clear();
|
|
|
yellowList.Clear();
|
|
|
redList.Clear();
|
|
|
+ purchasedList.Clear();
|
|
|
+
|
|
|
foreach (var (key, movements) in stockMovements)
|
|
|
{
|
|
|
var job = jobs.GetValueOrDefault(key.job);
|
|
|
|
|
|
- ReservationManagementHoldingsModel holding;
|
|
|
+ ReservationManagementHoldingsModel<StockMovement> holding;
|
|
|
if (key.allocated)
|
|
|
{
|
|
|
- holding = new ReservationManagementHoldingsModel(key.job, job?.JobNumber ?? "", job?.Name ?? "")
|
|
|
+ holding = new(key.job, job?.JobNumber ?? "", job?.Name ?? "")
|
|
|
{
|
|
|
AlreadyAllocated = true
|
|
|
};
|
|
|
- DistributeMovements(movements, item.Style.ID, holding);
|
|
|
+ DistributeItems(movements, item.Style.ID, holding, x => x.Units);
|
|
|
if (!holding.Empty)
|
|
|
{
|
|
|
redList.Add(holding);
|
|
|
@@ -185,20 +240,20 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
}
|
|
|
else if (key.job == Guid.Empty)
|
|
|
{
|
|
|
- holding = new ReservationManagementHoldingsModel(Guid.Empty, "Free Stock", "Free Stock");
|
|
|
- DistributeMovements(movements, item.Style.ID, holding);
|
|
|
+ holding = new(Guid.Empty, "Free Stock", "Free Stock");
|
|
|
+ DistributeItems(movements, item.Style.ID, holding, x => x.Units);
|
|
|
greenList.Add(holding);
|
|
|
}
|
|
|
else if(key.job == item.Job.ID)
|
|
|
{
|
|
|
- holding = new ReservationManagementHoldingsModel(item.Job.ID, item.Job.JobNumber, item.Job.Name);
|
|
|
- DistributeMovements(movements, item.Style.ID, holding);
|
|
|
+ holding = new(item.Job.ID, item.Job.JobNumber, item.Job.Name);
|
|
|
+ DistributeItems(movements, item.Style.ID, holding, x => x.Units);
|
|
|
greenList.Add(holding);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- holding = new ReservationManagementHoldingsModel(key.job, job?.JobNumber ?? "", job?.Name ?? "");
|
|
|
- DistributeMovements(movements, item.Style.ID, holding);
|
|
|
+ holding = new(key.job, job?.JobNumber ?? "", job?.Name ?? "");
|
|
|
+ DistributeItems(movements, item.Style.ID, holding, x => x.Units);
|
|
|
if (!holding.Empty)
|
|
|
{
|
|
|
yellowList.Add(holding);
|
|
|
@@ -206,25 +261,50 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ foreach (var (key, orderItems) in purchaseOrderItems)
|
|
|
+ {
|
|
|
+ var job = jobs.GetValueOrDefault(key);
|
|
|
+
|
|
|
+ ReservationManagementHoldingsModel<PurchaseOrderItem> holding;
|
|
|
+ if(key == Guid.Empty)
|
|
|
+ {
|
|
|
+ holding = new(Guid.Empty, "Free Stock", "Free Stock");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ holding = new ReservationManagementHoldingsModel<PurchaseOrderItem>(key, job?.JobNumber ?? "", job?.Name ?? "");
|
|
|
+ }
|
|
|
+ DistributeItems(orderItems, item.Style.ID, holding, x => orderItemQuantities.GetValueOrDefault(x.ID));
|
|
|
+ if (!holding.Empty)
|
|
|
+ {
|
|
|
+ purchasedList.Add(holding);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (greenList.Count == 1)
|
|
|
- greenList.Add(new ReservationManagementHoldingsModel());
|
|
|
+ greenList.Add(new());
|
|
|
|
|
|
if (redList.Count == 1)
|
|
|
- redList.Add(new ReservationManagementHoldingsModel());
|
|
|
+ redList.Add(new());
|
|
|
|
|
|
if (yellowList.Count == 1)
|
|
|
- yellowList.Add(new ReservationManagementHoldingsModel());
|
|
|
+ yellowList.Add(new());
|
|
|
+
|
|
|
+ if (purchasedList.Count == 1)
|
|
|
+ purchasedList.Add(new());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
greenList.Clear();
|
|
|
yellowList.Clear();
|
|
|
redList.Clear();
|
|
|
+ purchasedList.Clear();
|
|
|
}
|
|
|
|
|
|
listViewGreen.ItemsSource = greenList;
|
|
|
listViewYellow.ItemsSource = yellowList;
|
|
|
listViewRed.ItemsSource = redList;
|
|
|
+ listViewPurchased.ItemsSource = purchasedList;
|
|
|
}
|
|
|
|
|
|
//private void Take_RightClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
|
|
@@ -249,28 +329,53 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
private void Take_Click(object sender, RoutedEventArgs e)
|
|
|
{
|
|
|
if (sender is not FrameworkElement element
|
|
|
- || element.DataContext is not ReservationManagementHoldingsModel model
|
|
|
- || element.Tag is not List<StockMovement> mvts) return;
|
|
|
+ || element.DataContext is not ReservationManagementHoldingsModel model) return;
|
|
|
+ var thisList = element.Tag;
|
|
|
|
|
|
- if (mvts == model.StockOfCurrentStyle && model.UnitsOfCurrentStyle.IsEffectivelyEqual(0.0)
|
|
|
- || mvts == model.StockOfNoStyle && model.UnitsOfNoStyle.IsEffectivelyEqual(0.0)
|
|
|
- || mvts == model.StockOfOtherStyles && model.UnitsOfOtherStyles.IsEffectivelyEqual(0.0))
|
|
|
+ if (thisList == model.BaseStockOfCurrentStyle && model.UnitsOfCurrentStyle.IsEffectivelyEqual(0.0)
|
|
|
+ || thisList == model.BaseStockOfNoStyle && model.UnitsOfNoStyle.IsEffectivelyEqual(0.0)
|
|
|
+ || thisList == model.BaseStockOfOtherStyles && model.UnitsOfOtherStyles.IsEffectivelyEqual(0.0))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- LaunchStockSelectionPage(model, mvts);
|
|
|
+ if(model is ReservationManagementHoldingsModel<StockMovement> movementModel
|
|
|
+ && thisList is List<StockMovement> mvts)
|
|
|
+ {
|
|
|
+ LaunchStockSelectionPage(movementModel, mvts);
|
|
|
+ }
|
|
|
+ else if(model is ReservationManagementHoldingsModel<PurchaseOrderItem> orderItemModel
|
|
|
+ && thisList is List<PurchaseOrderItem> orderItems)
|
|
|
+ {
|
|
|
+ LaunchPurchaseOrderSelectionPage(orderItemModel, orderItems);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void LaunchStockSelectionPage(ReservationManagementHoldingsModel model, List<StockMovement> mvts)
|
|
|
+ private void LaunchPurchaseOrderSelectionPage(ReservationManagementHoldingsModel<PurchaseOrderItem> model, List<PurchaseOrderItem> mvts)
|
|
|
+ {
|
|
|
+ if (Item is null) return;
|
|
|
+
|
|
|
+ var page = new PurchaseOrderItemSelectionPage(
|
|
|
+ mvts.Where(x => !x.Unallocated.IsEffectivelyEqual(0.0)),
|
|
|
+ Item,
|
|
|
+ new Job { ID = model.JobID, Name = model.JobName, JobNumber = model.JobNumber });
|
|
|
+
|
|
|
+ if (page.ShowDialog() == true)
|
|
|
+ {
|
|
|
+ //MessageWindow.ShowMessage("Success - stock allocated to requisition line", "Success");
|
|
|
+ CalculateHoldings();
|
|
|
+ OnHoldingsReviewRefresh?.Invoke();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private void LaunchStockSelectionPage(ReservationManagementHoldingsModel<StockMovement> model, List<StockMovement> mvts)
|
|
|
{
|
|
|
if (Item is null) return;
|
|
|
|
|
|
- var holdings = new Dictionary<(Guid locationID, Guid requiItemID), StockHolding>();
|
|
|
+ var holdings = new Dictionary<(Guid locationID, Guid styleID, Guid requiItemID), StockHolding>();
|
|
|
|
|
|
foreach (var mvt in mvts)
|
|
|
{
|
|
|
- if(!holdings.TryGetValue(new(mvt.Location.ID, mvt.JobRequisitionItem.ID), out var holding))
|
|
|
+ if(!holdings.TryGetValue(new(mvt.Location.ID, mvt.Style.ID, mvt.JobRequisitionItem.ID), out var holding))
|
|
|
{
|
|
|
holding = new StockHolding();
|
|
|
|
|
|
@@ -278,7 +383,7 @@ public partial class ReservationManagementHoldingsGrid
|
|
|
holding.Style.CopyFrom(mvt.Style);
|
|
|
holding.Dimensions.CopyFrom(mvt.Dimensions);
|
|
|
|
|
|
- holdings.Add(new(mvt.Location.ID, mvt.JobRequisitionItem.ID), holding);
|
|
|
+ holdings.Add(new(mvt.Location.ID, mvt.Style.ID, mvt.JobRequisitionItem.ID), holding);
|
|
|
}
|
|
|
if (mvt.JobRequisitionItem.ID != Guid.Empty && model.AlreadyAllocated)
|
|
|
{
|