123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Core;
- using InABox.DynamicGrid;
- using Microsoft.CodeAnalysis.VisualBasic.Syntax;
- using Org.BouncyCastle.Asn1.Mozilla;
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Shapes;
- namespace PRSDesktop.Panels.Products.Locations;
- /// <summary>
- /// Interaction logic for StockHoldingRelocationWindow.xaml
- /// </summary>
- public partial class StockHoldingRelocationWindow : Window, INotifyPropertyChanged
- {
- public StockHolding From { get; private init; }
- public enum RelocationMode
- {
- Issue,
- Transfer,
- ReleaseAllocations
- }
- private RelocationMode _mode;
- public RelocationMode Mode
- {
- get => _mode;
- set
- {
- _mode = value;
- UpdateMode();
- }
- }
- public bool ShowHeader => ShowFrom || IsTargetEditable || IsJobEditable;
- private bool _showFrom = true;
- public bool ShowFrom
- {
- get => _showFrom;
- set
- {
- _showFrom = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(ShowHeader));
- }
- }
- private bool _isTargetEditable = true;
- public bool IsTargetEditable
- {
- get => _isTargetEditable;
- set
- {
- _isTargetEditable = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(ShowHeader));
- }
- }
- private bool _isJobEditable = false;
- public bool IsJobEditable
- {
- get => _isJobEditable;
- set
- {
- _isJobEditable = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(ShowHeader));
- }
- }
- private StockLocation? _originalTarget;
- public StockLocation? OriginalTarget
- {
- get => _originalTarget;
- set
- {
- _originalTarget = value;
- To = value;
- }
- }
- private Job? _originalJob;
- public Job? OriginalJob
- {
- get => _originalJob;
- set
- {
- _originalJob = value;
- Job = value;
- }
- }
- private Job? _job;
- public Job? Job
- {
- get => _job;
- set
- {
- _job = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(CanSave));
- OnPropertyChanged($"{nameof(Job)}.{nameof(Job.JobNumber)}");
- OnPropertyChanged($"{nameof(Job)}.{nameof(Job.Name)}");
- UpdateMode();
- }
- }
- private StockLocation? _to;
- public StockLocation? To
- {
- get => _to;
- set
- {
- _to = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(CanSave));
- OnPropertyChanged($"{nameof(To)}.{nameof(To.Code)}");
- OnPropertyChanged($"{nameof(To)}.{nameof(To.Description)}");
- }
- }
- private bool _requireChangeTarget = false;
- /// <summary>
- /// Require that the target location be changed before allowing the "Save" button to be clicked.
- /// </summary>
- public bool RequireChangeTarget
- {
- get => _requireChangeTarget;
- set
- {
- _requireChangeTarget = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(CanSave));
- }
- }
- public bool CanSave
- {
- get
- {
- if(Grid.TotalIssued <= 0)
- {
- return false;
- }
- if(IsTargetEditable && (To?.ID ?? Guid.Empty) == Guid.Empty)
- {
- return false;
- }
- if (RequireChangeTarget)
- {
- if(IsTargetEditable && IsJobEditable)
- {
- return (To?.ID ?? Guid.Empty) != (OriginalTarget?.ID ?? Guid.Empty)
- || (Job?.ID ?? Guid.Empty) != (OriginalJob?.ID ?? Guid.Empty);
- }
- else if (IsTargetEditable)
- {
- return (To?.ID ?? Guid.Empty) != (OriginalTarget?.ID ?? Guid.Empty);
- }
- else if (IsJobEditable)
- {
- return (Job?.ID ?? Guid.Empty) != (OriginalJob?.ID ?? Guid.Empty);
- }
- }
- return true;
- }
- }
- public StockHoldingRelocationWindow(StockHolding from, IEnumerable<JobRequisitionItem> items, RelocationMode mode)
- {
- Client.EnsureColumns(from, Columns.None<StockHolding>().Add(x => x.Location.Code));
- From = from;
- InitializeComponent();
- SetRequisitionItems(items);
- Mode = mode;
- }
- private void UpdateMode()
- {
- if(Mode == RelocationMode.Issue)
- {
- var jobID = Job?.ID ?? Guid.Empty;
- foreach(var item in Grid.Items)
- {
- if(item.JRI.ID != Guid.Empty && item.JRI.Job.ID != jobID)
- {
- item.Editable = false;
- item.Issued = 0;
- }
- else
- {
- item.Editable = true;
- }
- }
- Title = "Issue Items";
- IsJobEditable = true;
- IsTargetEditable = false;
- ShowFrom = true;
- }
- else if(Mode == RelocationMode.Transfer)
- {
- foreach(var item in Grid.Items)
- {
- item.Editable = item.JRI.ID == Guid.Empty || Security.IsAllowed<CanEditAllocatedJobRequisitions>();
- }
- IsJobEditable = true;
- IsTargetEditable = true;
- ShowFrom = false;
- RequireChangeTarget = true;
- Title = "Transfer Stock";
- }
- else if(Mode == RelocationMode.ReleaseAllocations)
- {
- ShowFrom = false;
- IsTargetEditable = false;
- IsJobEditable = false;
- Title = "Release Stock";
- }
- }
- private void Grid_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if(e.PropertyName == nameof(Grid.TotalIssued))
- {
- OnPropertyChanged(nameof(CanSave));
- }
- }
- public void SetRequisitionItems(IEnumerable<JobRequisitionItem> items)
- {
- var rItems = items.AsIList();
- var rIDs = rItems.Select(x => x.ID).Where(x => x != Guid.Empty).ToArray();
- var quantities = Client.Query(
- StockHolding.GetFilter(From)
- .Combine(new Filter<StockMovement>(x => x.JobRequisitionItem.ID).InList(rIDs)),
- Columns.None<StockMovement>().Add(x => x.Units).Add(x => x.JobRequisitionItem.ID))
- .ToObjects<StockMovement>().GroupBy(x => x.JobRequisitionItem.ID).ToDictionary(x => x.Key, x => x.Sum(x => x.Units));
- var requidItems = new List<StockHoldingRelocationItem>();
- var newItems = new List<StockHoldingRelocationItem>();
- foreach(var item in rItems)
- {
- var qty = item.ID != Guid.Empty ? quantities.GetValueOrDefault(item.ID) : item.Qty;
- if(item.ID != Guid.Empty && qty <= 0)
- {
- // We can't do anything with this; it shouldn't be shown.
- continue;
- }
- var newItem = new StockHoldingRelocationItem
- {
- Issued = 0,
- Quantity = qty,
- MaxValue = item.ID == Guid.Empty ? double.MaxValue : qty,
- Text = item.ID == Guid.Empty
- ? "Unrequisitioned Items"
- : $"{item.Job.JobNumber}: #{item.Requisition.Number} ({item.Requisition.Description})",
- JRI = item
- };
- if(item.ID == Guid.Empty)
- {
- newItems.Add(newItem);
- }
- else
- {
- requidItems.Add(newItem);
- }
- }
- int i = 1;
- foreach(var item in requidItems)
- {
- item.ItemNumber = $"{i}. ";
- newItems.Add(item);
- ++i;
- }
- Grid.Items = newItems;
- Grid.Refresh(true, true);
- }
- public Dictionary<Guid, double> GetQuantities()
- {
- return Grid.Items.ToDictionary(x => x.JRI.ID, x => x.Issued);
- }
- public StockLocation GetTargetLocation()
- {
- return To ?? new StockLocation();
- }
- public event PropertyChangedEventHandler? PropertyChanged;
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- #region Target Location
- public static StockLocation? LookupLocation(string? column = null, string? value = null)
- {
- var grid = new MultiSelectDialog<StockLocation>(
- LookupFactory.DefineFilter<StockLocation>(),
- Columns.None<StockLocation>().Add(x => x.ID).Add(x => x.Code).Add(x => x.Description),
- multiselect: false);
- if (grid.ShowDialog(column, value))
- {
- return grid.Data().Rows.First().ToObject<StockLocation>();
- }
- else
- {
- return null;
- }
- }
- private bool DoLookupLocation(string? column, string? value)
- {
- if(LookupLocation(column, value) is StockLocation location)
- {
- To = location;
- return true;
- }
- else
- {
- return false;
- }
- }
- private void ToBox_LostFocus(object sender, RoutedEventArgs e)
- {
- DoSearchLocation();
- }
- private void ToButton_Click(object sender, RoutedEventArgs e)
- {
- DoLookupLocation(null, null);
- }
- private void DoSearchLocation()
- {
- if (ToBox.Text.IsNullOrWhiteSpace() || ToBox.Text == To?.Code)
- {
- To = null;
- return;
- }
- var location = Client.Query(
- new Filter<StockLocation>(x => x.Code).IsEqualTo(ToBox.Text),
- Columns.None<StockLocation>().Add(x => x.ID).Add(x => x.Code).Add(x => x.Description))
- .ToObjects<StockLocation>().FirstOrDefault();
- if(location is not null)
- {
- To = location;
- }
- else
- {
- if(!DoLookupLocation(nameof(To.Code), ToBox.Text))
- {
- To = null;
- }
- }
- }
- private void ToBox_OnKeyUp(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Enter)
- DoSearchLocation();
- }
- #endregion
- #region Job
- private bool DoLookupJob(string? column, string? value)
- {
- var grid = new MultiSelectDialog<Job>(
- LookupFactory.DefineFilter<Job>(),
- Columns.None<Job>().Add(x => x.ID).Add(x => x.JobNumber).Add(x => x.Name),
- multiselect: false);
- if (grid.ShowDialog(column, value))
- {
- Job = grid.Data().Rows.First().ToObject<Job>();
- return true;
- }
- else
- {
- return false;
- }
- }
- private void JobBox_LostFocus(object sender, RoutedEventArgs e)
- {
- DoSearchJob();
- }
- private void JobButton_Click(object sender, RoutedEventArgs e)
- {
- DoLookupJob(null, null);
- }
- private void DoSearchJob()
- {
- if (JobBox.Text.IsNullOrWhiteSpace() || JobBox.Text == To?.Code)
- {
- Job = null;
- return;
- }
- var job = Client.Query(
- new Filter<Job>(x => x.JobNumber).IsEqualTo(JobBox.Text),
- Columns.None<Job>().Add(x => x.ID).Add(x => x.JobNumber).Add(x => x.Name))
- .ToObjects<Job>().FirstOrDefault();
- if(job is not null)
- {
- Job = job;
- }
- else
- {
- if(!DoLookupJob(nameof(Job.JobNumber), JobBox.Text))
- {
- Job = null;
- }
- }
- }
- private void JobBox_OnKeyUp(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Enter)
- DoSearchJob();
- }
- #endregion
- private void OKButton_Click(object sender, RoutedEventArgs e)
- {
- DialogResult = true;
- Close();
- }
- private void CancelButton_Click(object sender, RoutedEventArgs e)
- {
- DialogResult = false;
- Close();
- }
- }
|