using Comal.Classes; using InABox.Core; using InABox.Database; using System; using System.Linq; namespace Comal.Stores; public class StockHoldingStore : BaseStore { public enum Action { Increase, Decrease } /// /// Maintains the Stock Holding Table when manipulating Stock Movements /// We only accept an ID, because the rest of the movement is pulled from the database /// (slower, but more reliable) /// /// The id of the Stock Movement to query /// The action to perform (increase / decrease) public static void UpdateStockHolding(Guid id, Action action) { var movement = DbFactory.Provider.Query( new Filter(x => x.ID).IsEqualTo(id), new Columns(x => x.ID) .Add(x => x.Location.ID) .Add(x => x.Product.ID) .Add(x => x.Style.ID) .Add(x => x.Job.ID) .Add(x => x.Dimensions.Unit.ID) .Add(x => x.Dimensions.Quantity) .Add(x => x.Dimensions.Height) .Add(x => x.Dimensions.Width) .Add(x => x.Dimensions.Length) .Add(x => x.Dimensions.Weight) .Add(x => x.Dimensions.UnitSize) .Add(x => x.Dimensions.Value) .Add(x => x.JobRequisitionItem.ID) .Add(x => x.Units) .Add(x => x.Cost) ).Rows .FirstOrDefault()? .ToObject(); if (movement == null) return; var holding = DbFactory.Provider.Query(new Filter(x => x.Product.ID).IsEqualTo(movement.Product.ID) .And(x => x.Location.ID).IsEqualTo(movement.Location.ID) .And(x => x.Style.ID).IsEqualTo(movement.Style.ID) .And(x => x.Job.ID).IsEqualTo(movement.Job.ID) .And(x => x.Dimensions.Unit.ID).IsEqualTo(movement.Dimensions.Unit.ID) .And(x => x.Dimensions.UnitSize).IsEqualTo(movement.Dimensions.UnitSize), new Columns(x => x.ID) .Add(x => x.Units) .Add(x => x.Qty) .Add(x => x.Value) .Add(x => x.Available) ).Rows .FirstOrDefault()? .ToObject(); if (holding == null) { holding = new(); holding.Location.ID = movement.Location.ID; holding.Product.ID = movement.Product.ID; holding.Style.ID = movement.Style.ID; holding.Job.ID = movement.Job.ID; holding.Dimensions.CopyFrom(movement.Dimensions); } double multiplier = action == Action.Increase ? 1F : -1F; holding.Units += (multiplier * movement.Units); holding.Qty += (multiplier * movement.Units * movement.Dimensions.Value); holding.Value += (multiplier * movement.Units * movement.Cost); holding.Available += (multiplier * (movement.JobRequisitionItem.ID == Guid.Empty ? movement.Units : 0.0)); holding.Weight = holding.Qty * holding.Dimensions.Weight; holding.AverageValue = holding.Units != 0 ? holding.Value / holding.Units : 0.0F; // Automagically clean up empty holdings if (holding.Units.IsEffectivelyEqual(0.0F)) { if (holding.ID != Guid.Empty) DbFactory.Provider.Delete(holding, ""); } else DbFactory.Provider.Save(holding); } }