using qdr.app.studiou.orders2printpack.Extensions; namespace qdr.app.studiou.orders2printpack.ProductStorage { public class ProductStorage { private IList _rawCollection = new List(); private IList _variants = new List(); private IList _categories = new List(); public IEnumerable Products => _rawCollection.ToArray(); public IEnumerable Variants => GetVariants().ToArray(); public IEnumerable Categories => GetCategories().ToArray(); public void Load(string filePath, string separator) { _rawCollection = CsvParser.Parse(filePath, delimiter: separator).ToList(); CheckProductVariantValidity(); } public void Save(string filePath, string separator) { CsvParser.Save(_rawCollection.OrderBy(x => x.IsVariant).ToArray(), filePath, delimiter: separator); } public void CheckProductVariantValidity() { foreach (var product in _rawCollection.Where(x => x.IsVariant)) { product.IsParentValid = _rawCollection.Any(x => string.Equals(x.Sku, product.ParentName, StringComparison.InvariantCultureIgnoreCase)); } } public ProductDto? GetProductByIdentifier(string? identifier) { if (string.IsNullOrWhiteSpace(identifier)) return null; return _rawCollection.FirstOrDefault(x => string.Equals(x.GetIdentifier(), identifier, StringComparison.InvariantCultureIgnoreCase)); } public ProductDto? GetProductBySku(string sku) { if (string.IsNullOrWhiteSpace(sku)) return null; return _rawCollection.FirstOrDefault(x => !x.IsVariant && string.Equals(x.Sku, sku, StringComparison.InvariantCultureIgnoreCase)); } public ProductDto? GetProductByName(string productName) { if (string.IsNullOrWhiteSpace(productName)) return null; return _rawCollection.FirstOrDefault(x => !x.IsVariant && string.Equals(x.ProductName, productName, StringComparison.InvariantCultureIgnoreCase)); } public VariantDto? GetVariantByIdentifier(string? identifier) { if (identifier == null) return null; return Variants.FirstOrDefault(x => string.Equals(x.GetIdentifier(), identifier, StringComparison.InvariantCultureIgnoreCase)); } public CategoryDto? GetCategoryByIdentifier(string? identifier) { if (identifier == null) return null; return Categories.FirstOrDefault(x => string.Equals(x.GetIdentifier(), identifier, StringComparison.InvariantCultureIgnoreCase)); } public void AppendVariantsFromString(string variantsString) { var variants = variantsString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var variant in variants) { var variantParts = variant.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (variantParts.Length != 2) continue; var variantName = variantParts[0]; var variantValues = variantParts[1].Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); var variantPrice = decimal.Parse(variantValues[0]); var variantMinimal = 0; var variantMaximal = 0; if (variantValues.Length >= 3) { variantMinimal = int.Parse(variantValues[1]); variantMaximal = int.Parse(variantValues[2]); } if (_variants.Any(x => string.Equals(x.Name, variantName, StringComparison.InvariantCultureIgnoreCase))) continue; _variants.Add(new VariantDto() { Name = variantName, Price = variantPrice, QuantityMinimum = variantMinimal, QuantityMaximum = variantMaximal }); } } public void AppendCategoriesFromString(string categoriesString) { var categories = categoriesString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var category in categories) { if (_categories.Any(x => string.Equals(x.Name, categoriesString, StringComparison.InvariantCultureIgnoreCase))) _categories.Add(new CategoryDto() { Name = category }); } } public ProductDto AddNewProduct() { var item = new ProductDto() { Type = ProductDto.CS_ITEM_TYPE_PRODUCT }; _rawCollection.Add(item); return item; } public ProductDto AddNewProductVariant(string? parentSku) { if (!string.IsNullOrWhiteSpace(parentSku)) if (!_rawCollection.Any(x => string.Equals(x.Sku, parentSku, StringComparison.InvariantCultureIgnoreCase))) throw new Exception($"Parent Product SKU '{parentSku}' not found!"); var item = new ProductDto() { Type = ProductDto.CS_ITEM_TYPE_VARIANT, ParentName = parentSku == null ? string.Empty : parentSku }; _rawCollection.Add(item); return item; } public VariantDto AddNewVariant() { var item = new VariantDto() { }; _variants.Add(item); return item; } public CategoryDto AddNewCategory() { var item = new CategoryDto() { }; _categories.Add(item); return item; } public void RemoveProduct(string[]? identifiers) { if (identifiers == null || identifiers.Length == 0) return; foreach (var identifier in identifiers) { var itemToRemove = _rawCollection.FirstOrDefault(x => string.Equals(x.GetIdentifier(), identifier, StringComparison.InvariantCultureIgnoreCase)); if (itemToRemove != null) _rawCollection.Remove(itemToRemove); } } public void RemoveVariants(string[]? identifiers) { if (identifiers == null || identifiers.Length == 0) return; foreach (var identifier in identifiers) { var itemToRemove = _variants.FirstOrDefault(x => string.Equals(x.GetIdentifier(), identifier, StringComparison.InvariantCultureIgnoreCase)); if (itemToRemove != null) _variants.Remove(itemToRemove); } } public void RemoveCategories(string[]? identifiers) { if (identifiers == null || identifiers.Length == 0) return; foreach (var identifier in identifiers) { var itemToRemove = _categories.FirstOrDefault(x => string.Equals(x.GetIdentifier(), identifier, StringComparison.InvariantCultureIgnoreCase)); if (itemToRemove != null) _categories.Remove(itemToRemove); } } public string GetVariantsAsString() { return string.Join(";", _variants.Select(x => x.Name + "=" + x.Price.ToString() + "|" + x.QuantityMinimum.ToString() + "|" + x.QuantityMaximum.ToString())); } public string GetCategoriesAsString() { return string.Join(";", _categories.Select(x => x.Name)); } public IEnumerable GetProductsView(bool includeProduct, bool includeVariants) { return _rawCollection.Where(x => x.IsVariant == includeVariants || !x.IsVariant == includeProduct).ToArray(); } private IEnumerable GetVariants() { var productVariants = _rawCollection.Where(x => x.IsVariant).DistinctBy(x => x.VariantAndPrice).Select(x => new VariantDto() { Name = x.VariantName, Price = x.Price }); foreach (var variant in productVariants) { if (!_variants.Any(x => x.Name == variant.Name)) { _variants.Add(variant); } else { // Keep the existing (e.g. predefined) price when the product variant has // no price set (0). Freshly imported variants default to price 0 and must // not overwrite a price the user already configured. Only sync a real, // non-zero price coming from the products. var existing = _variants.First(x => x.Name == variant.Name); if (variant.Price != 0 && existing.Price != variant.Price) existing.Price = variant.Price; } } return _variants; } private IEnumerable GetCategories() { var productCategories = _rawCollection.Where(x => !x.IsVariant).DistinctBy(x => x.Category).Select(x => new CategoryDto() { Name = x.Category }); foreach (var category in productCategories) { if (!_categories.Any(x => x.Name == category.Name)) { _categories.Add(category); } } return _categories; } } }