aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerghei Cebotari <serghei@cebotari.ru>2023-12-08 23:14:56 +0300
committerSerghei Cebotari <serghei@cebotari.ru>2023-12-08 23:14:56 +0300
commitf448cccbebaf9c6cc92f5576cb89e8918b1beec9 (patch)
treee319a8e8e0e4f763d852ae66479f71f67311a9cd
parente6546254baf8130638aa0dee12f247769da4e308 (diff)
Add RhSolutions.ProductSku project
-rw-r--r--RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs4
-rw-r--r--RhSolutions.AddIn/RhSolutions.AddIn.csproj4
-rw-r--r--RhSolutions.ProductSku/Measure.cs3
-rw-r--r--RhSolutions.ProductSku/Product.cs91
-rw-r--r--RhSolutions.ProductSku/ProductSku.cs194
-rw-r--r--RhSolutions.ProductSku/RhSolutions.ProductSku.csproj20
-rw-r--r--RhSolutions.Tests/RhSolutions.Tests.csproj1
-rw-r--r--RhSolutions.Tests/SkuTests.cs171
-rw-r--r--RhSolutions.sln6
9 files changed, 491 insertions, 3 deletions
diff --git a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
index dcb0f7d..f2bdd6f 100644
--- a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
+++ b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
@@ -63,7 +63,7 @@ public sealed class RhSolutionsAddIn : IExcelAddIn
};
if (!isTesting)
{
- IntelliSenseServer.Install();
+ //IntelliSenseServer.Install();
}
ServicePointManager.SecurityProtocol =
@@ -82,7 +82,7 @@ public sealed class RhSolutionsAddIn : IExcelAddIn
};
if (!isTesting)
{
- IntelliSenseServer.Uninstall();
+ //IntelliSenseServer.Uninstall();
}
}
}
diff --git a/RhSolutions.AddIn/RhSolutions.AddIn.csproj b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
index d73b404..a08a8f2 100644
--- a/RhSolutions.AddIn/RhSolutions.AddIn.csproj
+++ b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
@@ -39,8 +39,10 @@
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="netDxf" Version="2022.11.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
- <PackageReference Include="RhSolutions.ProductSku" Version="1.0.2" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\RhSolutions.ProductSku\RhSolutions.ProductSku.csproj" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/RhSolutions.ProductSku/Measure.cs b/RhSolutions.ProductSku/Measure.cs
new file mode 100644
index 0000000..d7911ab
--- /dev/null
+++ b/RhSolutions.ProductSku/Measure.cs
@@ -0,0 +1,3 @@
+namespace RhSolutions.Models;
+
+public enum Measure { Kg, M, M2, P }
diff --git a/RhSolutions.ProductSku/Product.cs b/RhSolutions.ProductSku/Product.cs
new file mode 100644
index 0000000..5a6f5fa
--- /dev/null
+++ b/RhSolutions.ProductSku/Product.cs
@@ -0,0 +1,91 @@
+using Newtonsoft.Json;
+
+namespace RhSolutions.Models;
+public class Product : IDisposable
+{
+ [JsonIgnore]
+ public string Id
+ {
+ get => ProductSku.Id;
+ set
+ {
+ ProductSku = new(value);
+ }
+ }
+ public string Name { get; set; } = string.Empty;
+ public ProductSku ProductSku { get; set; }
+ public List<ProductSku> DeprecatedSkus { get; set; } = new();
+ public List<string> ProductLines { get; set; } = new();
+ public bool IsOnWarehouse { get; set; } = false;
+ public Measure ProductMeasure { get; set; }
+ public double? DeliveryMakeUp { get; set; }
+ public decimal Price { get; set; }
+
+ [JsonConstructor]
+ public Product(string id,
+ string name,
+ ProductSku productSku,
+ ProductSku[] deprecatedSkus,
+ string[] productLines,
+ bool isOnWarehouse,
+ int productMeasure,
+ int deliveryMakeUp,
+ decimal price)
+ {
+ Id = id;
+ Name = name;
+ ProductSku = productSku;
+ DeprecatedSkus = deprecatedSkus.ToList();
+ ProductLines = productLines.ToList();
+ IsOnWarehouse = isOnWarehouse;
+ ProductMeasure = (Measure)productMeasure;
+ DeliveryMakeUp = deliveryMakeUp;
+ Price = price;
+ }
+ public Product(string sku)
+ {
+ ProductSku = new(sku);
+ }
+
+ public Product(ProductSku productSku)
+ {
+ ProductSku = productSku;
+ }
+
+ public override bool Equals(object? obj)
+ {
+ return obj is Product product &&
+ Name == product.Name &&
+ EqualityComparer<ProductSku>.Default.Equals(ProductSku, product.ProductSku) &&
+ DeprecatedSkus.SequenceEqual(product.DeprecatedSkus) &&
+ ProductLines.SequenceEqual(product.ProductLines) &&
+ IsOnWarehouse == product.IsOnWarehouse &&
+ ProductMeasure == product.ProductMeasure &&
+ DeliveryMakeUp == product.DeliveryMakeUp &&
+ Price == product.Price;
+ }
+
+ public override int GetHashCode()
+ {
+ HashCode hash = new HashCode();
+ hash.Add(Name);
+ hash.Add(ProductSku);
+ DeprecatedSkus.ForEach(x => hash.Add(x));
+ ProductLines.ForEach(x => hash.Add(x));
+ hash.Add(IsOnWarehouse);
+ hash.Add(ProductMeasure);
+ hash.Add(DeliveryMakeUp);
+ hash.Add(Price);
+ return hash.ToHashCode();
+ }
+
+ public override string ToString()
+ {
+ return $"({ProductSku}) {Name}";
+ }
+
+ public void Dispose()
+ {
+
+ }
+}
diff --git a/RhSolutions.ProductSku/ProductSku.cs b/RhSolutions.ProductSku/ProductSku.cs
new file mode 100644
index 0000000..7e3e763
--- /dev/null
+++ b/RhSolutions.ProductSku/ProductSku.cs
@@ -0,0 +1,194 @@
+using System.Text.RegularExpressions;
+using Newtonsoft.Json;
+
+namespace RhSolutions.Models;
+public class ProductSku
+{
+ [JsonIgnore]
+ public string Id
+ {
+ get
+ {
+ return $"1{Article}{Delimiter}{Variant}";
+ }
+ set
+ {
+ var matches = GetMatches(value);
+ if (matches.Count == 0)
+ {
+ throw new ArgumentException($"Wrong Id: {value}");
+ }
+ else
+ {
+ var p = GetProducts(matches).First();
+ _article = p.Article;
+ _delimiter = p.Delimiter;
+ _variant = p.Variant;
+ }
+ }
+ }
+ private const string matchPattern = @"(?<Lead>[1\s]|^|\b)(?<Article>\d{6})(?<Delimiter>[\s13-])(?<Variant>\d{3})(\b|$)";
+ private string _article;
+ private string _variant;
+ private char _delimiter = '1';
+
+ [JsonConstructor]
+ public ProductSku(string article, string delimiter, string variant)
+ {
+ _article = article;
+ _delimiter = delimiter[0];
+ _variant = variant;
+ }
+
+ public ProductSku(string article, string variant)
+ {
+ _article = IsCorrectArticle(article) ? article
+ : throw new ArgumentException($"Wrong Article: {article}");
+ _variant = IsCorrectVariant(variant) ? variant
+ : throw new ArgumentException($"Wrong Variant: {variant}");
+ }
+ public ProductSku(string line)
+ {
+ var matches = GetMatches(line);
+ if (matches.Count == 0)
+ {
+ throw new ArgumentException($"Wrong new Sku input {line}");
+ }
+ else
+ {
+ var p = GetProducts(matches).First();
+ _article = p.Article;
+ _delimiter = p.Delimiter;
+ _variant = p.Variant;
+ }
+ }
+
+ private ProductSku(Match match)
+ {
+ _article = match.Groups["Article"].Value;
+ _delimiter = match.Groups["Delimiter"].Value switch
+ {
+ "3" => '3',
+ _ => '1'
+ };
+ _variant = match.Groups["Variant"].Value;
+ }
+ public string Article
+ {
+ get => _article;
+ set
+ {
+ _article = IsCorrectArticle(value) ? value
+ : throw new ArgumentException($"Wrong Article: {value}");
+ }
+ }
+ public string Variant
+ {
+ get => _variant;
+ set
+ {
+ _variant = IsCorrectVariant(value) ? value
+ : throw new ArgumentException($"Wrong Variant: {value}");
+ }
+ }
+
+ public char Delimiter
+ {
+ get => _delimiter;
+ set
+ {
+ if (value != '1' || value != '3')
+ {
+ throw new ArgumentException($"Wrong Delimiter: {value}");
+ }
+ else
+ {
+ _delimiter = value;
+ }
+ }
+ }
+
+ public static IEnumerable<ProductSku> Parse(string line)
+ {
+ MatchCollection matches = GetMatches(line);
+ if (matches.Count == 0)
+ {
+ return Enumerable.Empty<ProductSku>();
+ }
+ else
+ {
+ return GetProducts(matches);
+ }
+ }
+
+ public static bool TryParse(string line, out IEnumerable<ProductSku> skus)
+ {
+ MatchCollection matches = GetMatches(line);
+ if (matches.Count == 0)
+ {
+ skus = Enumerable.Empty<ProductSku>();
+ return false;
+ }
+
+ else
+ {
+ skus = GetProducts(matches);
+ return true;
+ }
+ }
+
+ private static MatchCollection GetMatches(string line)
+ {
+ return Regex.Matches(line, matchPattern);
+ }
+
+ private static IEnumerable<ProductSku> GetProducts(MatchCollection matches)
+ {
+ foreach (Match match in matches)
+ {
+ yield return new ProductSku(match);
+ }
+ }
+
+ private static bool IsCorrectArticle(string line)
+ {
+ return line != null
+ && line.Length == 6
+ && line.All(c => char.IsDigit(c));
+ }
+
+ private static bool IsCorrectVariant(string line)
+ {
+ return line != null
+ && line.Length == 3
+ && line.All(c => char.IsDigit(c));
+ }
+
+ public override string ToString()
+ {
+ return Id;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+
+ ProductSku other = (ProductSku)obj;
+
+ return this.Article == other.Article &&
+ this.Delimiter == other.Delimiter &&
+ this.Variant == other.Variant;
+ }
+
+ public override int GetHashCode()
+ {
+ HashCode hash = new();
+ hash.Add(_article);
+ hash.Add(_variant);
+ hash.Add(_delimiter);
+ return hash.ToHashCode();
+ }
+}
diff --git a/RhSolutions.ProductSku/RhSolutions.ProductSku.csproj b/RhSolutions.ProductSku/RhSolutions.ProductSku.csproj
new file mode 100644
index 0000000..ecf5130
--- /dev/null
+++ b/RhSolutions.ProductSku/RhSolutions.ProductSku.csproj
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFrameworks>net472;net6.0;net7.0;net8.0</TargetFrameworks>
+ <LangVersion>10.0</LangVersion>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ <Version>1.0.3</Version>
+ <Authors>Serghei Cebotari</Authors>
+ <Product>RhSolutions Sku</Product>
+ <Description>Библиотека с классами моделей артикулов для плагинов и приложений RhSolutions</Description>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
+ <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+ <PackageReference Include="System.Net.Http" Version="4.3.4" />
+ </ItemGroup>
+
+</Project>
diff --git a/RhSolutions.Tests/RhSolutions.Tests.csproj b/RhSolutions.Tests/RhSolutions.Tests.csproj
index 8c6b442..b1491cb 100644
--- a/RhSolutions.Tests/RhSolutions.Tests.csproj
+++ b/RhSolutions.Tests/RhSolutions.Tests.csproj
@@ -15,6 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\RhSolutions.AddIn\RhSolutions.AddIn.csproj" />
+ <ProjectReference Include="..\RhSolutions.ProductSku\RhSolutions.ProductSku.csproj" />
</ItemGroup>
</Project>
diff --git a/RhSolutions.Tests/SkuTests.cs b/RhSolutions.Tests/SkuTests.cs
new file mode 100644
index 0000000..ab9a1c2
--- /dev/null
+++ b/RhSolutions.Tests/SkuTests.cs
@@ -0,0 +1,171 @@
+using RhSolutions.Models;
+
+namespace RhSolutions.Tests;
+
+public class SkuTests
+{
+ [Fact]
+ public void EqualityTest()
+ {
+ Product p1 = new("11600011001")
+ {
+ Name = "Test",
+ ProductLines = new List<string>
+ {
+ "TestLine"
+ },
+ IsOnWarehouse = true,
+ ProductMeasure = Measure.Kg,
+ DeliveryMakeUp = 100.0,
+ Price = 1000
+ };
+
+ Product p2 = new("11600011001")
+ {
+ Name = "Test",
+ ProductLines = new List<string>
+ {
+ "TestLine"
+ },
+ IsOnWarehouse = true,
+ ProductMeasure = Measure.Kg,
+ DeliveryMakeUp = 100.0,
+ Price = 1000
+ };
+
+ Product p3 = new("11600013001")
+ {
+ Name = "Test",
+ ProductLines = new List<string>
+ {
+ "TestLine"
+ },
+ IsOnWarehouse = true,
+ ProductMeasure = Measure.Kg,
+ DeliveryMakeUp = 100.0,
+ Price = 1000
+ };
+
+ Assert.True(p1.Equals(p2));
+ Assert.False(p1.Equals(p3));
+ }
+
+ [Fact]
+ public void ProductHashCodeTest()
+ {
+ Product p1 = new("11600011001")
+ {
+ Name = "Test",
+ ProductLines = new List<string>
+ {
+ "TestLine"
+ },
+ IsOnWarehouse = true,
+ ProductMeasure = Measure.Kg,
+ DeliveryMakeUp = 100.0,
+ Price = 1000
+ };
+
+ Product p2 = new("11600011001")
+ {
+ Name = "Test",
+ ProductLines = new List<string>
+ {
+ "TestLine"
+ },
+ IsOnWarehouse = true,
+ ProductMeasure = Measure.Kg,
+ DeliveryMakeUp = 100.0,
+ Price = 1000
+ };
+
+ Product p3 = new("11600013001")
+ {
+ Name = "Test",
+ ProductLines = new List<string>
+ {
+ "TestLine"
+ },
+ IsOnWarehouse = true,
+ ProductMeasure = Measure.Kg,
+ DeliveryMakeUp = 100.0,
+ Price = 1000
+ };
+
+ int hash1 = p1.GetHashCode();
+ int hash2 = p2.GetHashCode();
+ int hash3 = p3.GetHashCode();
+ Assert.True(hash1 == hash2);
+ Assert.False(hash1 == hash3);
+ }
+
+ [Fact]
+ public void SkuEqualityTest()
+ {
+ ProductSku sku1 = new("160001", "001");
+ ProductSku sku2 = new("11600011001");
+ Assert.True(sku1.Equals(sku2));
+ }
+
+ [Fact]
+ public void SkuHashCodeTest()
+ {
+ ProductSku sku1 = new("160001", "001");
+ ProductSku sku2 = new("11600011001");
+ int hash1 = sku1.GetHashCode();
+ int hash2 = sku2.GetHashCode();
+ Assert.True(hash1 == hash2);
+ }
+
+ [Theory]
+ [InlineData("12222221333")]
+ [InlineData("222222-333")]
+ [InlineData("222222 333")]
+ [InlineData("string 12222221333")]
+ [InlineData("12222221333 string")]
+ [InlineData("string 12222221333 string")]
+ [InlineData("string 222222-333")]
+ [InlineData("222222-333 string")]
+ [InlineData("string 222222-333 string")]
+ [InlineData("string 222222 333")]
+ [InlineData("222222 333 string")]
+ [InlineData("string 222222 333 string")]
+ public void StandardSkuParseTest(string line)
+ {
+ Assert.True(ProductSku.TryParse(line, out var skus));
+ Assert.True(skus.First().Article == "222222"
+ && skus.First().Variant == "333"
+ && skus.First().Delimiter == '1');
+ }
+
+ [Theory]
+ [InlineData("12222223444")]
+ [InlineData("string 12222223444")]
+ [InlineData("12222223444 string")]
+ [InlineData("string 12222223444 string")]
+ public void NewSkuParseTest(string line)
+ {
+ Assert.True(ProductSku.TryParse(line, out var skus));
+ Assert.True(skus.First().Article == "222222"
+ && skus.First().Variant == "444"
+ && skus.First().Delimiter == '3');
+ }
+
+ [Theory]
+ [InlineData("160001-001 11384611001 160002 002 11600033003")]
+ public void MultipleParseTest(string line)
+ {
+ Assert.True(ProductSku.TryParse(line, out var skus));
+ Assert.Equal(4, skus.Count());
+ }
+
+ [Theory]
+ [InlineData("160001 001")]
+ [InlineData("160001*001")]
+ [InlineData("160001001")]
+ [InlineData("31600011001")]
+ public void DoesntParse(string line)
+ {
+ Assert.False(ProductSku.TryParse(line, out _));
+ }
+} \ No newline at end of file
diff --git a/RhSolutions.sln b/RhSolutions.sln
index 8d94b9b..610e085 100644
--- a/RhSolutions.sln
+++ b/RhSolutions.sln
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhSolutions.AddIn", "RhSolu
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhSolutions.Tests", "RhSolutions.Tests\RhSolutions.Tests.csproj", "{6EECCDDB-741C-404A-874F-BB8656265162}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhSolutions.ProductSku", "RhSolutions.ProductSku\RhSolutions.ProductSku.csproj", "{59CD05D0-71E0-4027-968A-8BE89A6FDCEF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
{6EECCDDB-741C-404A-874F-BB8656265162}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EECCDDB-741C-404A-874F-BB8656265162}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EECCDDB-741C-404A-874F-BB8656265162}.Release|Any CPU.Build.0 = Release|Any CPU
+ {59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE