| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 | using System;using System.Collections.Generic;using System.Linq;using Comal.Classes;using InABox.Clients;using InABox.Core;using InABox.Wpf;using InABox.WPF;namespace PRSDesktop;public static class StockUtils{    public static bool RecalculateHoldingsOfLocations(Guid[] locationIDs, out List<String> report)    {        return RecalculateHoldings(new Filter<IStockHolding>(x => x.Location.ID).InList(locationIDs), out report);    }    public static bool RecalculateHoldingsOfProducts(Guid[] productIDs, out List<String> report)    {        return RecalculateHoldings(new Filter<IStockHolding>(x => x.Product.ID).InList(productIDs), out report);    }    public static bool RecalculateHoldings(Filter<IStockHolding> filter, out List<String> report)    {        bool result = false;        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(                filter.Cast<StockHolding>(),                Columns.Required<StockHolding>().Add(x => x.ID)                    .Add(x => x.Location.ID)                    .Add(x => x.Product.ID)                    .Add(x => x.Job.ID)                    .Add(x => x.Style.ID)                    .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Local)                    .Add(x => x.Units)                    .Add(x => x.AverageValue)                    .Add(x => x.Available)                    .Add(x => x.Qty)                    .Add(x => x.Weight)                    .Add(x => x.Value)            );            query.Add(                filter.Cast<StockMovement>(),                Columns.None<StockMovement>().Add(x => x.ID)                    .Add(x=>x.Location.ID)                    .Add(x => x.Product.ID)                    .Add(x => x.Job.ID)                    .Add(x => x.Style.ID)                    .AddDimensionsColumns(x => x.Dimensions, Dimensions.ColumnsType.Local)                    .Add(x => x.Units)                    .Add(x => x.Cost)                    .Add(x => x.JobRequisitionItem.ID)            );            query.Query();            var holdings = query.Get<StockHolding>();            var toDelete = new List<StockHolding>();            var movements = query.Get<StockMovement>();            double movementcount = (double)movements.Rows.Count;            progress.Report("Processing");            var updates = new List<StockHolding>();                        while (movements.Rows.Any())            {                double percent = ((movementcount - movements.Rows.Count) / movementcount) * 100.0;                progress.Report($"Processing ({percent:F2}% complete)");                var first = movements.Rows.First();                var selected = movements.Rows.Where(x => x.IsEqualTo<StockMovement, StockMovement>(first)).ToList();                var holdingrow = holdings.Rows.FirstOrDefault(x => x.IsEqualTo<StockHolding, StockMovement>(first));                StockHolding holding = null;                if (holdingrow != null)                {                    holdings.Rows.Remove(holdingrow);                    holding = holdingrow.ToObject<StockHolding>();                }                if (holding == null)                {                    var firstmovement = first.ToObject<StockMovement>();                    holding = new StockHolding();                    holding.Location.ID = firstmovement.Location.ID;                    holding.Product.ID = firstmovement.Product.ID;                    holding.Style.ID = firstmovement.Style.ID;                    holding.Job.ID = firstmovement.Job.ID;                    holding.Dimensions.CopyFrom(firstmovement.Dimensions);                }                holding.Recalculate(selected.ToObjects<StockMovement>());                if (holding.Units.IsEffectivelyEqual(0.0) && holding.Available.IsEffectivelyEqual(0.0))                {                    if (holding.ID != Guid.Empty)                        toDelete.Add(holding);                }                else if (holding.IsChanged())                {                    AddMessage(holding.ID != Guid.Empty ? "updated" : "added");                    updates.Add(holding);                }                foreach (var row in selected)                    movements.Rows.Remove(row);            }            toDelete.AddRange(holdings.Rows.ToObjects<StockHolding>());            foreach (var holding in toDelete)                AddMessage("deleted");            if (updates.Any())            {                result = true;                progress.Report($"Updating {updates.Count} Holdings");                new Client<StockHolding>().Save(updates.Where(x => x.IsChanged()), "Updated by Recalculation");            }            if (toDelete.Any())            {                result = true;                progress.Report($"Deleting {toDelete.Count} Holdings");                new Client<StockHolding>().Delete(toDelete, "Removed by Recalculation");            }        });        report = new List<String>();        if (messages.Any())            report.AddRange(messages.Select(x => $"{x.Value} holdings {x.Key}"));        else            report.Add("Nothing to Update");        return result;    }}
 |