using Comal.Classes;
using InABox.Clients;
using InABox.Core;
using InABox.Wpf;
using InABox.WPF;
using java.sql;
using org.omg.PortableInterceptor;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace PRSDesktop;
public delegate void HoldingsReviewRefresh();
///
/// Interaction logic for JobRequisitionHoldingsReview.xaml
///
public partial class ReservationManagementHoldingsGrid
{
private ProductStyleLink companyDefaultStyle = new ProductStyleLink();
public ProductStyleLink CompanyDefaultStyle
{
get => companyDefaultStyle;
set
{
companyDefaultStyle = value;
DefaultOrNoStyleText.Text = String.IsNullOrWhiteSpace(companyDefaultStyle?.Code)
? "No Style"
: $"{companyDefaultStyle.Code} / None";
}
}
public event HoldingsReviewRefresh? OnHoldingsReviewRefresh;
private JobRequisitionItem? item;
public JobRequisitionItem? Item
{
get
{
return item;
}
set
{
if(item?.ID != value?.ID)
{
item = value;
CalculateHoldings();
SetStyle();
SetProductName();
}
}
}
private void SetProductName()
{
productLbl.Text = Item != null
? Item.Product.Name + " (" + Item.Product.Code + ")"
: "No Product Selected";
}
private void SetStyle()
{
if ((Item != null) && (Item.Style.ID != Guid.Empty))
styleLbl.Text = Item.Style.Description + " (" + Item.Style.Code + ")";
else
styleLbl.Text = "No Style Selected";
}
public ReservationManagementHoldingsGrid()
{
InitializeComponent();
greenList.CollectionChanged += (s, e) =>
{
availableTab.Visibility = greenList.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
};
yellowList.CollectionChanged += (s, e) =>
{
reservedTab.Visibility = yellowList.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
};
redList.CollectionChanged += (s, e) =>
{
requisitionedTab.Visibility = redList.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
};
}
private readonly ObservableCollection greenList = new();
private readonly ObservableCollection yellowList = new();
private readonly ObservableCollection redList = new();
private void DistributeMovements(Dictionary>? movements, Guid selectedStyleID, ReservationManagementHoldingsModel model)
{
if (movements is null) return;
foreach(var (id, mvts) in movements)
{
if(id == Guid.Empty || id == CompanyDefaultStyle.ID)
{
model.StockOfNoStyle.AddRange(mvts);
}
else if (id == selectedStyleID)
{
model.StockOfCurrentStyle.AddRange(mvts);
}
else
{
model.StockOfOtherStyles.AddRange(mvts);
}
}
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));
}
private void CalculateHoldings()
{
if(item is not null)
{
var stockMovements = Client.Query(
new Filter(x => x.Product.ID).IsEqualTo(item.Product.ID)
.And(x => x.Dimensions).DimensionEquals(item.Dimensions)
.And(x => x.Location.ID).IsNotEqualTo(Guid.Empty),
Columns.None().Add(
x => x.ID,
x => x.Style.ID,
x => x.Style.Description,
x => x.Style.Code,
x => x.Units,
x => x.Location.ID,
x => x.Location.Code,
x => x.Location.Description,
x => x.Location.Area.Code,
x => x.Job.ID,
x => x.JobRequisitionItem.ID)
.AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Data))
.ToObjects()
.GroupBy(x => new { JobID = x.Job.ID, Allocated = x.JobRequisitionItem.ID != Guid.Empty })
.ToDictionary(
x => x.Key,
x => x.GroupBy(x => x.Style.ID)
.Select(x =>
{
var mvts = x.ToList();
return new
{
Style = x.Key,
Movements = mvts
};
})
.ToDictionary(
x => x.Style,
x => x.Movements));
var jobs = Client.Query(
new Filter(x => x.ID).InList(stockMovements.Keys.Select(x => x.JobID).ToArray()),
Columns.None().Add(x => x.ID).Add(x => x.JobNumber).Add(x => x.Name))
.ToObjects()
.ToDictionary(x => x.ID, x => x);
if(!stockMovements.ContainsKey(new { JobID = item.Job.ID, Allocated = false }))
{
stockMovements.Add(new { JobID = item.Job.ID, Allocated = false }, new Dictionary>());
}
if (!stockMovements.ContainsKey(new { JobID = Guid.Empty, Allocated = false }))
{
stockMovements.Add(new { JobID = Guid.Empty, Allocated = false }, new Dictionary>());
}
greenList.Clear();
yellowList.Clear();
redList.Clear();
foreach (var (key, movements) in stockMovements)
{
var job = jobs.GetValueOrDefault(key.JobID);
ReservationManagementHoldingsModel holding;
if (key.Allocated)
{
holding = new ReservationManagementHoldingsModel(key.JobID, job?.JobNumber ?? "", job?.Name ?? "")
{
AlreadyAllocated = true
};
DistributeMovements(movements, item.Style.ID, holding);
if (!holding.Empty)
{
redList.Add(holding);
}
}
else if (key.JobID == Guid.Empty)
{
holding = new ReservationManagementHoldingsModel(Guid.Empty, "Free Stock", "Free Stock");
DistributeMovements(movements, item.Style.ID, holding);
greenList.Add(holding);
}
else if(key.JobID == item.Job.ID)
{
holding = new ReservationManagementHoldingsModel(item.Job.ID, item.Job.JobNumber, item.Job.Name);
DistributeMovements(movements, item.Style.ID, holding);
greenList.Add(holding);
}
else
{
holding = new ReservationManagementHoldingsModel(key.JobID, job?.JobNumber ?? "", job?.Name ?? "");
DistributeMovements(movements, item.Style.ID, holding);
if (!holding.Empty)
{
yellowList.Add(holding);
}
}
}
if (greenList.Count == 1)
greenList.Add(new ReservationManagementHoldingsModel());
if (redList.Count == 1)
redList.Add(new ReservationManagementHoldingsModel());
if (yellowList.Count == 1)
yellowList.Add(new ReservationManagementHoldingsModel());
}
else
{
greenList.Clear();
yellowList.Clear();
redList.Clear();
}
listViewGreen.ItemsSource = greenList;
listViewYellow.ItemsSource = yellowList;
listViewRed.ItemsSource = redList;
}
private void Take_RightClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (sender is not FrameworkElement element
|| element.DataContext is not ReservationManagementHoldingsModel model
|| element.Tag is not List mvts) return;
if (model.AlreadyAllocated) return;
if (mvts == model.StockOfCurrentStyle && model.UnitsOfCurrentStyle > 0
|| mvts == model.StockOfNoStyle && model.UnitsOfNoStyle > 0
|| mvts == model.StockOfOtherStyles && model.UnitsOfOtherStyles > 0)
{
return;
}
var menu = new ContextMenu();
menu.AddItem("Take Anyway", null, () => LaunchStockSelectionPage(model, mvts));
menu.IsOpen = true;
}
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 mvts) return;
if (mvts == model.StockOfCurrentStyle && model.UnitsOfCurrentStyle <= 0
|| mvts == model.StockOfNoStyle && model.UnitsOfNoStyle <= 0
|| mvts == model.StockOfOtherStyles && model.UnitsOfOtherStyles <= 0)
{
return;
}
LaunchStockSelectionPage(model, mvts);
}
private void LaunchStockSelectionPage(ReservationManagementHoldingsModel model, List mvts)
{
if (Item is null) return;
var holdings = new Dictionary<(Guid locationID, Guid requiItemID), StockHolding>();
foreach (var mvt in mvts)
{
if(!holdings.TryGetValue(new(mvt.Location.ID, mvt.JobRequisitionItem.ID), out var holding))
{
holding = new StockHolding();
holding.Location.CopyFrom(mvt.Location);
holding.Style.CopyFrom(mvt.Style);
holding.Dimensions.CopyFrom(mvt.Dimensions);
holdings.Add(new(mvt.Location.ID, mvt.JobRequisitionItem.ID), holding);
}
if (mvt.JobRequisitionItem.ID != Guid.Empty && model.AlreadyAllocated)
{
holding.Units += mvt.Units;
}
else if (mvt.JobRequisitionItem.ID == Guid.Empty && !model.AlreadyAllocated)
{
holding.Units += mvt.Units;
}
else
{
// Shouldn't be possible.
}
}
var filteredHoldings = holdings.Where(x => !model.AlreadyAllocated || x.Value.Units.IsEffectivelyGreaterThan(0))
.Select(x => new StockSelectionPage.Holding(x.Value, x.Key.requiItemID));
var page = new StockSelectionPage(
filteredHoldings,
Item,
new Job { ID = model.JobID, Name = model.JobName, JobNumber = model.JobNumber },
model.AlreadyAllocated);
if (page.ShowDialog() == true)
{
//MessageWindow.ShowMessage("Success - stock allocated to requisition line", "Success");
CalculateHoldings();
OnHoldingsReviewRefresh?.Invoke();
}
}
}