using System; using System.Collections.Generic; using System.Linq; using Comal.Classes; using InABox.Core; namespace Comal.Stores { public class BaseProductStore : BaseStore where T : Entity, new() { /// /// Update the ComponentCost and NettCost of any Product that contains this one /// as a component /// /// protected void UpdateProductComponentCost(Product entity) { // Extract all the Products that Contain this one as a component var products = Provider.Query( new Filter(x => x.Component.ID).IsEqualTo(entity.ID), new Columns( x => x.ID, x => x.Product.ID, x => x.Product.PricingStrategy, x => x.Product.BaseCost ) ); if (!products.Rows.Any()) return; // All the info we need, we can extract from the product link, so we don't need to // go back to the database and incur another query penalty var infos = products.Rows.Select(x => new ProdInfo { ProductID = x.Get(c => c.Product.ID), Strategy = x.Get(c => c.Product.PricingStrategy), BaseCost = x.Get(c => c.Product.BaseCost) } ).Distinct().ToArray(); var ids = infos.Select(x => x.ProductID).ToArray(); // Now get all the components that these products contain // We _could_ use the delta NettCost the for the entity (newvalue-oldvalue) // And skip this part, but then it will be hard to fix any errors that might creep in, // and we also will need to do this anyway for new products, etc var components = Provider.Query( new Filter(x => x.Product.ID).InList(ids), new Columns( x => x.Product.ID, x => x.NettCost ) ); // Now construct the required updates var updates = new List(); foreach (var info in infos) { double compcost = 0.0F; components.Rows .Where(r => r.Get(c => c.Product.ID).Equals(info.ProductID)) .Select(r => r.Get(c => c.NettCost)) .ToList() .ForEach(x => compcost += x); if (info.Strategy != ProductPricingStrategy.Assembly) { var update = new Product { ID = info.ProductID, NettCost = Product.CalculateNettCost(info.Strategy, info.BaseCost, compcost) }; updates.Add(update); } } Provider.Save(updates); } /// /// Update the Base Cost of any product that has this supplier price as its default /// /// protected void UpdateDefaultSupplierPricing(SupplierProduct entity) { var product = Provider.Query( new Filter(x => x.Supplier.ID).IsEqualTo(entity.ID).And(x => x.UseDefaultSupplierPricing).IsEqualTo(true), new Columns( x => x.ID, x => x.PricingStrategy, x => x.BaseCost, x => x.ComponentCost, x => x.NettCost ) ).Rows.FirstOrDefault()?.ToObject(); if (product != null) { product.BaseCost = entity.CostPrice; product.NettCost = Product.CalculateNettCost(product.PricingStrategy, product.BaseCost, product.ComponentCost); product.TaxCode.ID = entity.TaxCode.ID; if (product.IsChanged()) { Provider.Save(product); UpdateProductComponentCost(product); } } } private struct ProdInfo { public Guid ProductID; public ProductPricingStrategy Strategy; public double BaseCost; } } }