123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- 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;
- using PRSDesktop.Panels.Products.Locations;
- using Syncfusion.Windows.Controls.RichTextBoxAdv;
- using Exception = System.Exception;
- namespace PRSDesktop;
- public class StockHoldingGrid : DynamicDataGrid<StockHolding>
- {
- private enum MovementAction
- {
- Receive,
- Issue,
- Transfer
- }
- private MovementAction _action;
- private StockHolding? _holding;
-
- private Button IssueButton;
- private Button ReceiveButton;
- private DynamicDataGrid<StockMovement> smg;
- //Button ReserveButton = null;
- private Button TransferButton;
-
- private Button RecalculateButton;
- public StockHoldingGrid() : base()
- {
- ColumnsTag = "StockHolding";
-
- }
- protected override void Init()
- {
- base.Init();
- ReceiveButton = AddButton("Receive", PRSDesktop.Resources.add.AsBitmapImage(), ReceiveStock);
- ReceiveButton.IsEnabled = false;
- IssueButton = AddButton("Issue", PRSDesktop.Resources.delete.AsBitmapImage(), IssueStock);
- IssueButton.IsEnabled = false;
- //ReserveButton = AddButton("Reserve", PRSDesktop.Resources.project.AsBitmapImage(), ReserveStock);
- //ReserveButton.Margin = new Thickness(20, ReserveButton.Margin.Top, ReserveButton.Margin.Right, ReserveButton.Margin.Bottom);
- //ReserveButton.IsEnabled = false;
- TransferButton = AddButton("Transfer", PRSDesktop.Resources.split.AsBitmapImage(), TransferStock);
- TransferButton.Margin = new Thickness(20, TransferButton.Margin.Top, TransferButton.Margin.Right, TransferButton.Margin.Bottom);
- TransferButton.IsEnabled = false;
- RecalculateButton = AddButton("Recalculate", PRSDesktop.Resources.service.AsBitmapImage(), RecalculateHoldings,
- DynamicGridButtonPosition.Right);
- HiddenColumns.Add(x => x.Product.ID);
- HiddenColumns.Add(x => x.Job.ID);
- HiddenColumns.Add(x => x.Job.JobNumber);
- HiddenColumns.Add(x => x.Location.ID);
- HiddenColumns.Add(x => x.Location.Code);
- 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);
- ActionColumns.Add(new DynamicMenuColumn(BuildMenu) { Position = DynamicActionColumnPosition.End });
- }
- 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.Location.ID).IsEqualTo(Location.ID),
- new Columns<StockHolding>(x => x.ID)
- .Add(x => x.Product.ID)
- .Add(x => x.Job.ID)
- .Add(x => x.Style.ID)
- .Add(x => x.Dimensions.Unit.ID)
- .Add(x => x.Dimensions.Length)
- .Add(x => x.Dimensions.Width)
- .Add(x => x.Dimensions.Height)
- .Add(x => x.Dimensions.Quantity)
- .Add(x => x.Dimensions.Value)
- .Add(x => x.Dimensions.UnitSize)
- .Add(x => x.Units)
- .Add(x => x.AverageValue)
- );
-
- query.Add(
- new Filter<StockMovement>(x => x.Location.ID).IsEqualTo(Location.ID),
- new Columns<StockMovement>(x => x.ID)
- .Add(x => x.Product.ID)
- .Add(x => x.Job.ID)
- .Add(x => x.Style.ID)
- .Add(x => x.Dimensions.Unit.ID)
- .Add(x => x.Dimensions.Length)
- .Add(x => x.Dimensions.Width)
- .Add(x => x.Dimensions.Height)
- .Add(x => x.Dimensions.Quantity)
- .Add(x => x.Dimensions.Value)
- .Add(x => x.Dimensions.UnitSize)
- .Add(x => x.Units)
- .Add(x => x.Cost)
- );
- query.Query();
- var holdings = query.Get<StockHolding>().ToObjects<StockHolding>().ToList();
- 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.Product.ID == first.Product.ID
- && x.Job.ID == first.Job.ID
- && x.Style.ID == first.Style.ID
- && x.Dimensions.Unit.ID == first.Dimensions.Unit.ID
- && x.Dimensions.Length.IsEffectivelyEqual(first.Dimensions.Length)
- && x.Dimensions.Width.IsEffectivelyEqual(first.Dimensions.Width)
- && x.Dimensions.Height.IsEffectivelyEqual(first.Dimensions.Height)
- && x.Dimensions.Quantity.IsEffectivelyEqual(first.Dimensions.Quantity)
- && x.Dimensions.Weight.IsEffectivelyEqual(first.Dimensions.Weight)
- && x.Dimensions.Value.IsEffectivelyEqual(first.Dimensions.Value)
- && String.Equals(x.Dimensions.UnitSize, first.Dimensions.UnitSize)
- );
- var units = selected.Aggregate(0.0d, (t, s) => t += s.Units);
- var cost = selected.Aggregate(0.0d, (t, s) => t += (s.Units * s.Cost));
-
- var holding = holdings.FirstOrDefault(x =>
- x.Product.ID == first.Product.ID
- && x.Job.ID == first.Job.ID
- && x.Style.ID == first.Style.ID
- && x.Dimensions.Unit.ID == first.Dimensions.Unit.ID
- && x.Dimensions.Length.IsEffectivelyEqual(first.Dimensions.Length)
- && x.Dimensions.Width.IsEffectivelyEqual(first.Dimensions.Width)
- && x.Dimensions.Height.IsEffectivelyEqual(first.Dimensions.Height)
- && x.Dimensions.Quantity.IsEffectivelyEqual(first.Dimensions.Quantity)
- && x.Dimensions.Weight.IsEffectivelyEqual(first.Dimensions.Weight)
- && x.Dimensions.Length.IsEffectivelyEqual(first.Dimensions.Length)
- && String.Equals(x.Dimensions.UnitSize, first.Dimensions.UnitSize)
- );
- if (holding == null)
- {
- holding = new StockHolding();
- holding.Location.ID = Location.ID;
- holding.Product.ID = first.Product.ID;
- holding.Style.ID = first.Style.ID;
- holding.Job.ID = first.Job.ID;
- holding.Dimensions.Unit.ID = first.Dimensions.Unit.ID;
- holding.Dimensions.Length = first.Dimensions.Length;
- holding.Dimensions.Width = first.Dimensions.Width;
- holding.Dimensions.Height = first.Dimensions.Height;
- holding.Dimensions.Quantity = first.Dimensions.Quantity;
- holding.Dimensions.Weight = first.Dimensions.Weight;
- holding.Dimensions.Value = first.Dimensions.Value;
- holding.Dimensions.UnitSize = first.Dimensions.UnitSize;
- }
- holding.Units = units;
- holding.AverageValue = units.IsEffectivelyEqual(0.0F) ? 0.0d : cost / units;
- if (holdings.Contains(holding))
- holdings.Remove(holding);
- if (holding.IsChanged() && !holding.Units.IsEffectivelyEqual(0.0f))
- {
- AddMessage(holding.ID != Guid.Empty ? "updated" : "added");
- updates.Add(holding);
- }
- movements.RemoveAll(x => selected.Any(s => s.ID == x.ID));
- }
- foreach (var holding in holdings)
- AddMessage("deleted");
- if (updates.Any())
- {
- progress.Report($"Updating {updates.Count} Holdings");
- new Client<StockHolding>().Save(updates.Where(x => x.IsChanged()), "Updated by Recalculation");
- }
- if (holdings.Any())
- {
- progress.Report($"Deleting {holdings.Count} Holdings");
- new Client<StockHolding>().Delete(holdings, "Removed by Recalculation");
- }
- });
- MessageWindow.ShowMessage(
- messages.Any()
- ? String.Join("\n", messages.Select(x => $"{x.Value} holdings {x.Key}"))
- : "Nothing to Update!"
- ,"Recalculate");
- return true;
- }
- public override DynamicGridColumns GenerateColumns()
- {
- var columns = new DynamicGridColumns<StockHolding>();
- columns.Add(x => x.Product.Code, 120, "Product Code", "", Alignment.MiddleCenter);
- columns.Add(x => x.Product.Name, 0, "Product Name", "", Alignment.MiddleLeft);
- columns.Add(x => x.Job.JobNumber, 50, "Job", "", Alignment.MiddleCenter);
- columns.Add(x => x.Style.Description, 0, "Style", "", Alignment.MiddleLeft);
- columns.Add(x => x.Dimensions.UnitSize, 100, "Size", "", Alignment.MiddleCenter);
- columns.Add(x => x.Units, 70, "Units", "", Alignment.MiddleCenter);
- columns.Add(x => x.Available, 70, "Available", "", Alignment.MiddleCenter);
- return columns;
- }
- protected override void DoReconfigure(FluentList<DynamicGridOption> options)
- {
- base.DoReconfigure(options);
- options
- .BeginUpdate()
- .Remove(DynamicGridOption.AddRows)
- .Remove(DynamicGridOption.EditRows)
- .Remove(DynamicGridOption.DeleteRows)
- .Add(DynamicGridOption.RecordCount)
- .Add(DynamicGridOption.SelectColumns)
- .Add(DynamicGridOption.FilterRows)
- .EndUpdate();
- }
- private IEnumerable<JobRequisitionItem> LoadRequisitionItems(StockHolding holding)
- {
- var items = Client.Query(
- new Filter<JobRequisitionItem>(x => x.ID).InQuery(StockHolding.GetFilter(holding), x => x.JobRequisitionItem.ID),
- new Columns<JobRequisitionItem>(x => x.ID)
- .Add(x => x.Job.JobNumber)
- .Add(x => x.Requisition.Number)
- .Add(x => x.Requisition.Description)
- .Add(x => x.Qty))
- .ToObjects<JobRequisitionItem>();
- if (!holding.Available.IsEffectivelyEqual(0.0F))
- items = CoreUtils.One(new JobRequisitionItem() { Qty = holding.Available }).Concat(items);
- return items;
- }
- private void BuildMenu(DynamicMenuColumn column, CoreRow? row)
- {
- if (row is null) return;
- var holding = row.ToObject<StockHolding>();
- if (holding.Available.IsEffectivelyEqual(holding.Units))
- column.AddItem("(No Requisitions in this Holding", null, null).IsEnabled = false;
- else
- column.AddItem("View Requisition Items", null, ViewRequisitions_Click);
-
- column.AddSeparator();
- var requiitems = LoadRequisitionItems(holding).ToList();
-
- column.AddItem("Relocate Items", null, r => RelocateItems(holding, requiitems.ToArray()));
- }
- private class StockJobSelection : BaseObject
- {
- [EditorSequence(1)]
- public JobLink Job { get; set; }
-
- [EditorSequence(2)]
- public double Qty { get; set; }
- }
-
- private void RelocateItems(StockHolding holding, JobRequisitionItem[] requiitems)
- {
- var win = new StockHoldingRelocationWindow(holding, requiitems);
- if (win.ShowDialog() == true)
- {
- var quantities = win.GetQuantities();
- var target = win.GetTargetLocation();
- List<StockMovement> updates = new List<StockMovement>();
- foreach (var requiitem in requiitems)
- {
- if (!quantities.TryGetValue(requiitem.ID, out var qty)) continue;
- var mout = new StockMovement();
- mout.Location.ID = holding.Location.ID;
- mout.Product.ID = holding.Product.ID;
- mout.Style.ID = holding.Style.ID;
- mout.Dimensions.CopyFrom(holding.Dimensions);
- mout.Job.ID = holding.Job.ID;
- mout.Issued = Math.Min(requiitem.Qty, qty);
- mout.Cost = holding.AverageValue;
- mout.JobRequisitionItem.ID = requiitem.ID;
- mout.Type = StockMovementType.TransferOut;
- mout.Date = DateTime.Now;
- mout.IsTransfer = true;
- mout.Employee.ID = App.EmployeeID;
- mout.Notes = $"Moved to {target.Code} by {App.EmployeeName}";
- updates.Add(mout);
-
- var min = new StockMovement();
- min.Location.ID = target.ID;
- min.Product.ID = holding.Product.ID;
- min.Style.ID = holding.Style.ID;
- min.Dimensions.CopyFrom(holding.Dimensions);
- min.Job.ID = holding.Job.ID;
- min.Received = mout.Issued;
- min.Cost = holding.AverageValue;
- min.JobRequisitionItem.ID = requiitem.ID;
- min.Transaction = mout.Transaction;
- min.Type = StockMovementType.TransferIn;
- min.Date = mout.Date;
- min.IsTransfer = true;
- min.Employee.ID = App.EmployeeID;
- min.Notes = $"Moved From {holding.Location.Code} by {App.EmployeeName}";
- updates.Add(min);
- }
- SaveBatch(StockMovementBatchType.Transfer, updates);
- DoChanged();
- Refresh(false, true);
- }
- }
- private void ViewRequisitions_Click(CoreRow? row)
- {
- if (row is null) return;
- var holding = row.ToObject<StockHolding>();
- var grid = (DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(JobRequisitionItem)) as DynamicDataGrid<JobRequisitionItem>)!;
- grid.OnDefineFilter += (type) =>
- {
- if(type == typeof(JobRequisitionItem))
- {
- return new Filter<JobRequisitionItem>(x => x.ID)
- .InQuery(
- StockHolding.GetFilter(holding),
- x => x.JobRequisitionItem.ID);
- }
- else
- {
- return null;
- }
- };
- DynamicGridUtils.CreateGridWindow("Job Requisition Items for stock holding", grid).ShowDialog();
- }
- private bool ReceiveStock(Button arg1, CoreRow[] rows)
- {
- var movement = new StockMovement();
- movement.Location.ID = Location.ID;
- movement.Location.Code = Location.Code;
- movement.Job.ID = Location.Job.ID;
- movement.Job.JobNumber = Location.Job.JobNumber;
- movement.Job.Name = Location.Job.Name;
- movement.Location.Description = Location.Description;
- movement.Date = DateTime.Now;
- movement.IsTransfer = false;
- movement.Employee.ID = App.EmployeeID;
- movement.Type = StockMovementType.Receive;
- movement.CommitChanges();
- var holding = rows.First().ToObject<StockHolding>();
- var smg = CheckStockMovementGrid(MovementAction.Receive, holding);
- var result = smg.EditItems(new[] { movement });
- if (result)
- {
- DoChanged();
- SaveBatch(StockMovementBatchType.Receipt, new StockMovement[] { movement});
- }
-
- return result;
- }
- private static void SaveBatch(StockMovementBatchType type, IList<StockMovement> movements)
- {
- var batch = new StockMovementBatch();
- batch.Type = type;
- batch.Notes = batch.Type + " batch created from Desktop Stock Location Screen";
- batch.Employee.ID = App.EmployeeID;
- new Client<StockMovementBatch>().Save(batch, "created from Desktop Stock Location Screen");
- foreach (var mvt in movements)
- {
- mvt.Batch.ID = batch.ID;
- }
- new Client<StockMovement>().Save(movements, "Updating batch from Desktop Stock Location Screen");
- }
- private bool IssueStock(Button arg1, CoreRow[] rows)
- {
- if (rows?.Length != 1)
- {
- MessageWindow.ShowMessage("Please select an item to issue", "No selected items");
- return false;
- }
-
- var holding = rows.First().ToObject<StockHolding>();
- var items = LoadRequisitionItems(holding).AsArray();
- DoIssue(holding, items);
- return false;
- }
- private IEnumerable<StockMovement> CreateIssue(StockHolding holding, double qty, Guid jobID, Guid requiID)
- {
- var issue = CreateMovementFromHolding(holding);
- issue.Job.ID = jobID;
- issue.Type = StockMovementType.Issue;
- issue.JobRequisitionItem.ID = requiID;
- issue.Issued = qty;
- issue.Notes = $"Issued by {App.EmployeeName}";
- yield return issue;
- if (holding.Job.ID != issue.Job.ID)
- {
- var xferout = CreateMovementFromHolding(holding);
- xferout.Type = StockMovementType.TransferOut;
- xferout.JobRequisitionItem.ID = requiID;
- xferout.Issued = qty;
- xferout.Transaction = issue.Transaction;
- xferout.IsTransfer = true;
- xferout.Notes = $"Issued by {App.EmployeeName}";
- yield return xferout;
-
- var xferin = CreateMovementFromHolding(holding);
- xferin.Job.ID = issue.Job.ID;
- xferin.Type = StockMovementType.TransferIn;
- xferin.JobRequisitionItem.ID = requiID;
- xferin.Received = qty;
- xferin.Transaction = issue.Transaction;
- xferin.IsTransfer = true;
- xferin.Notes = $"Issued by {App.EmployeeName}";
- yield return xferin;
- }
- }
- private void DoIssue(StockHolding holding, JobRequisitionItem[] requiitems)
- {
- var updates = new List<StockMovement>();
- if(requiitems.Length > 1 || requiitems.Any(x => x.ID != Guid.Empty))
- {
- var win = new StockHoldingRelocationWindow(holding, requiitems)
- {
- IsTargetEditable = false
- };
- if (win.ShowDialog() == true)
- {
- var quantities = win.GetQuantities();
- var target = win.GetTargetLocation();
- foreach(var requi in requiitems)
- {
- if (!quantities.TryGetValue(requi.ID, out var qty)) continue;
- updates.AddRange(CreateIssue(holding, qty, requi.ID != Guid.Empty ? requi.Job.ID : holding.Job.ID, requi.ID));
- }
- DoChanged();
- Refresh(false,true);
- SaveBatch(StockMovementBatchType.Issue, updates.ToArray());
- }
- }
- else
- {
- var sjs = new StockJobSelection();
- sjs.Job.ID = holding.Job.ID;
- sjs.Qty = requiitems[0].Qty;
-
- var sjg = new DynamicItemsListGrid<StockJobSelection>();
- sjg.OnValidate += (sender, items, errors) =>
- {
- if (items[0].Qty > requiitems[0].Qty)
- errors.Add($"Qty must not exceed {requiitems[0].Qty}");
- };
- if (sjg.EditItems(new StockJobSelection[] { sjs }))
- {
- var mvts = CreateIssue(holding, sjs.Qty, sjs.Job.ID, Guid.Empty);
- SaveBatch(StockMovementBatchType.Issue, mvts.AsArray());
- }
- }
- }
-
- private bool TransferStock(Button arg1, CoreRow[] rows)
- {
- if (rows?.Length != 1)
- return false;
-
- var holding = rows.First().ToObject<StockHolding>();
- var items = LoadRequisitionItems(holding).AsArray();
- DoTransfer(holding, items);
- return false;
- }
- private void DoTransfer(StockHolding holding, JobRequisitionItem[] requiitems)
- {
- if (requiitems.Length > 1 || requiitems[0].Requisition.ID != Guid.Empty)
- {
- RelocateItems(holding, requiitems);
- return;
- }
-
- var movement = CreateMovementFromHolding(holding);
- movement.JobRequisitionItem.ID = requiitems[0].ID;
- movement.Received = holding.Units;
- movement.IsTransfer = true;
- movement.Type = StockMovementType.TransferIn;
- var smg = CheckStockMovementGrid(MovementAction.Transfer, holding);
- var result = smg.EditItems(new[] { movement });
- var mvts = new List<StockMovement>
- {
- movement
- };
- if (result)
- {
- var other = CreateMovementFromHolding(holding);
- other.Issued = movement.Received;
- other.Transaction = movement.Transaction;
- other.IsTransfer = true;
- other.Type = StockMovementType.TransferOut;
- other.JobRequisitionItem.ID = requiitems[0].ID;
- var changes = new List<string>();
- if (movement.Location.ID != other.Location.ID)
- changes.Add(movement.Location.Code);
- if (movement.Job.ID != other.Job.ID)
- changes.Add(string.IsNullOrEmpty(movement.Job.JobNumber) ? "General Stock" : movement.Job.JobNumber);
- if (movement.Style.ID != other.Style.ID)
- changes.Add(movement.Style.Code);
- //other.Notes = "Transferred to "+String.Join(" / ",changes);
- other.Notes = string.Format("Transferred to {0}{1}{2}", string.Join(" / ",
- changes.Where(x => !string.IsNullOrWhiteSpace(x))),
- string.IsNullOrWhiteSpace(movement.Notes) ? "" : "\n",
- string.Join("\n", movement.Notes.Split('\n').Where(x => !x.StartsWith("Transferred from ")))
- );
- other.System = true;
- Client.Save(other, "");
- mvts.Add(other);
- }
- if (result)
- {
- DoChanged();
- SaveBatch(StockMovementBatchType.Transfer, mvts.ToArray());
- }
- Refresh(false, true);
- }
- private StockMovement CreateMovementFromHolding(StockHolding holding)
- {
- var movement = new StockMovement();
- movement.Date = DateTime.Now;
- movement.Location.ID = Location.ID;
- movement.Location.Code = Location.Code;
- movement.Location.Description = Location.Description;
- movement.Product.ID = holding.Product.ID;
- movement.Job.ID = holding.Job.ID;
- movement.Job.JobNumber = holding.Job.JobNumber;
- movement.Style.ID = holding.Style.ID;
- movement.Style.Code = holding.Style.Code;
- movement.Employee.ID = App.EmployeeID;
- movement.Dimensions.CopyFrom(holding.Dimensions);
- movement.Cost = holding.AverageValue;
- movement.CommitChanges();
- return movement;
- }
- public IStockLocation Location { get; set; }
- protected override void SelectItems(CoreRow[]? rows)
- {
- base.SelectItems(rows);
- ReceiveButton.IsEnabled = Location != null && Location.ID != Guid.Empty;
- IssueButton.IsEnabled = Location != null && Location.ID != Guid.Empty && rows?.Any() == true;
- TransferButton.IsEnabled = Location != null && Location.ID != Guid.Empty && rows?.Any() == true;
- }
- private DynamicDataGrid<StockMovement> CheckStockMovementGrid(MovementAction action, StockHolding holding)
- {
- _action = action;
- _holding = holding;
- if (smg == null)
- {
- smg = new DynamicDataGrid<StockMovement>();
- smg.OnCustomiseEditor += StockMovementCustomiseEditor;
- smg.OnValidate += StockMovementValidate;
- smg.OnEditorValueChanged += StockMovementValueChanged;
- }
- return smg;
- }
-
- private Dictionary<string, object?> StockMovementValueChanged(IDynamicEditorForm form, string name, object value)
- {
- var result = new Dictionary<string, object?>();
- if (name.Equals("Location.Job.ID"))
- {
- var editor = form.FindEditor("Job.ID");
- if (!value.Equals(Guid.Empty))
- result = DynamicGridUtils.UpdateEditorValue(form.Items, "Job.ID", value);
- else
- foreach (StockMovement item in form.Items)
- result = DynamicGridUtils.UpdateEditorValue(new[] { item }, "Job.ID",
- item.Job.HasOriginalValue("ID") ? item.Job.GetOriginalValue(x => x.ID) : item.Job.ID);
- editor.IsEnabled = value.Equals(Guid.Empty);
- }
- return result;
- }
-
- private void StockMovementValidate(object sender, StockMovement[] items, List<string> errors)
- {
- if (items.Any(x => x.Received == 0 && x.Issued == 0))
- {
- errors.Add("Quantity may not be zero");
- }
- else if(_action == MovementAction.Issue && _holding is not null && items.Any(x => x.Issued > _holding.Available))
- {
- errors.Add($"Quantity may not be greater than available stock ({_holding.Available})");
- }
- if (items.Any(x => x.Product.ID == Guid.Empty))
- errors.Add("Product may not be blank");
- if (items.Any(x => x.Location.ID == Guid.Empty))
- errors.Add("Location may not be blank");
- if (!errors.Any() && _action == MovementAction.Transfer)
- foreach (var item in items)
- {
- var changes = new List<string>();
- if (item.Location.HasOriginalValue(x => x.ID))
- changes.Add(item.Location.GetOriginalValue(x => x.Code));
- if (item.Job.HasOriginalValue(x => x.ID))
- {
- var job = item.Job.GetOriginalValue(x => x.JobNumber);
- if (string.IsNullOrEmpty(job))
- job = "General Stock";
- changes.Add(job);
- }
- if (item.Style.HasOriginalValue(x => x.ID))
- changes.Add(item.Style.GetOriginalValue(x => x.Code));
- if (changes.Any())
- item.Notes = string.Format("Transferred from {0}{1}{2}",
- string.Join(" / ", changes.Where(x => !string.IsNullOrWhiteSpace(x))),
- string.IsNullOrWhiteSpace(item.Notes) ? "" : "\n", item.Notes);
- else
- errors.Add("Transfers must change either Location, Style or Job");
- }
- }
- private void StockMovementCustomiseEditor(IDynamicEditorForm sender, StockMovement[]? items, DynamicGridColumn column, BaseEditor editor)
- {
- if (column.ColumnName.Equals("Location.ID"))
- editor.Editable = _action == MovementAction.Transfer ? Editable.Enabled : Editable.Hidden;
-
- if (column.ColumnName.Equals("Product.ID"))
- editor.Editable = _action == MovementAction.Receive ? Editable.Enabled : Editable.Disabled;
-
- if (column.ColumnName.Equals("Product.NettCost"))
- editor.Editable = Editable.Hidden;
-
- if (column.ColumnName.Equals("Style.ID"))
- editor.Editable = _action == MovementAction.Receive || _action == MovementAction.Transfer ? Editable.Enabled : Editable.Hidden;
- if (column.ColumnName.Equals("UnitSize"))
- editor.Editable = _action == MovementAction.Receive ? Editable.Enabled : Editable.Hidden;
-
- if (column.ColumnName.Equals("Job.ID"))
- editor.Editable = _action == MovementAction.Receive && items?.FirstOrDefault()?.Job.IsValid() == true ? Editable.Disabled : Editable.Enabled;
-
- if (column.ColumnName.Equals(nameof(StockMovement.Received)))
- {
- editor.Editable = _action == MovementAction.Receive || _action == MovementAction.Transfer ? Editable.Enabled : Editable.Hidden;
- editor.Caption = "Quantity";
- }
- if (column.ColumnName.Equals(nameof(StockMovement.Issued)))
- {
- editor.Editable = _action == MovementAction.Issue ? Editable.Enabled : Editable.Hidden;
- editor.Caption = "Quantity";
- }
-
- }
- protected override void Reload(Filters<StockHolding> criteria, Columns<StockHolding> columns, ref SortOrder<StockHolding>? sort, Action<CoreTable?, Exception?> action)
- {
- ReceiveButton.IsEnabled = Location != null && Location.ID != Guid.Empty;
- if (Location == null)
- criteria.Add(new Filter<StockHolding>().None());
- else
- criteria.Add(new Filter<StockHolding>(x => x.Location.ID).IsEqualTo(Location.ID));
- base.Reload(criteria, columns, ref sort, action);
- }
-
- }
|