Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit e80c6e1

Browse files
authored
Merge pull request #9 from Kentico/Product-updates
Product updates
2 parents df9bc31 + c63a5e9 commit e80c6e1

12 files changed

+379
-63
lines changed

Kentico.Recombee.Admin.Tests/Kentico.Recombee.Admin.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,8 @@
535535
</ItemGroup>
536536
<ItemGroup>
537537
<Compile Include="ContactMergeProcessorTests.cs" />
538+
<Compile Include="ProductMapperTests.cs" />
539+
<Compile Include="ProductUpdatesProcessorTests.cs" />
538540
<Compile Include="Properties\AssemblyInfo.cs" />
539541
</ItemGroup>
540542
<ItemGroup>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using CMS.Ecommerce;
2+
3+
using Kentico.Recombee.Mappers;
4+
5+
using NUnit.Framework;
6+
using NSubstitute;
7+
8+
namespace Kentico.Recombee.Admin.Tests
9+
{
10+
[TestFixture]
11+
public class ProductMapperTests
12+
{
13+
[Test]
14+
public void Map_ProductIsNull_ThrowsArgumentNullException()
15+
{
16+
Assert.That(() => { ProductMapper.Map(null); }, Throws.ArgumentNullException);
17+
}
18+
19+
20+
[Test]
21+
public void Map_ProductPropertiesMappedToCorrectStructure()
22+
{
23+
var sku = Substitute.For<SKUInfo>();
24+
sku.SKUPrice.Returns(99.9M);
25+
sku.SKUID.Returns(1);
26+
27+
var productPage = Substitute.For<SKUTreeNode>();
28+
productPage.SKU = sku;
29+
productPage.DocumentSKUName.Returns("DocumentSKUName");
30+
productPage.DocumentSKUShortDescription.Returns("DocumentSKUShortDescription");
31+
productPage.DocumentSKUDescription.Returns("DocumentSKUDescription");
32+
productPage.DocumentCulture.Returns("DocumentCulture");
33+
productPage.ClassName.Returns("ClassName");
34+
35+
var result = ProductMapper.Map(productPage);
36+
37+
Assert.Multiple(() => {
38+
Assert.That(result["Name"], Is.EqualTo("DocumentSKUName"));
39+
Assert.That(result["Description"], Is.EqualTo("DocumentSKUShortDescription"));
40+
Assert.That(result["Content"], Is.EqualTo("DocumentSKUDescription"));
41+
Assert.That(result["Culture"], Is.EqualTo("DocumentCulture"));
42+
Assert.That(result["ClassName"], Is.EqualTo("ClassName"));
43+
Assert.That(result["Price"], Is.EqualTo(99.9M));
44+
Assert.That(result["Type"], Is.EqualTo("Product"));
45+
});
46+
}
47+
}
48+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using CMS.Core;
2+
using CMS.Ecommerce;
3+
using CMS.Tests;
4+
5+
using NSubstitute;
6+
using NUnit.Framework;
7+
8+
namespace Kentico.Recombee.Admin.Tests
9+
{
10+
[TestFixture]
11+
public class ProductUpdatesProcessorTests : UnitTests
12+
{
13+
private IProductUpdatesProcessor processor;
14+
private IRecombeeClientService clientService;
15+
16+
17+
[SetUp]
18+
public void SetUp()
19+
{
20+
clientService = Substitute.For<IRecombeeClientService>();
21+
Service.Use<IRecombeeClientService>(clientService);
22+
23+
processor = Service.Resolve<IProductUpdatesProcessor>();
24+
}
25+
26+
27+
[Test]
28+
public void Ctor_NullArgument_ThrowsArgumentNullException()
29+
{
30+
Assert.That(() => { new ProductUpdatesProcessor(null); }, Throws.ArgumentNullException);
31+
}
32+
33+
34+
[Test]
35+
public void Methods_NullArgumentt_ThrowsArgumentNullException()
36+
{
37+
Assert.Multiple(() =>
38+
{
39+
Assert.That(() => { processor.AddProduct(null); }, Throws.ArgumentNullException);
40+
Assert.That(() => { processor.DeleteProduct(null); }, Throws.ArgumentNullException);
41+
});
42+
}
43+
44+
45+
[Test]
46+
public void AddProduct_ProductIsAdded()
47+
{
48+
var productPage = Substitute.For<SKUTreeNode>();
49+
50+
processor.AddProduct(productPage);
51+
52+
clientService.Received().UpdateProduct(Arg.Is(productPage));
53+
}
54+
55+
56+
[Test]
57+
public void DeleteProduct_ProductIsDeleted()
58+
{
59+
var productPage = Substitute.For<SKUTreeNode>();
60+
61+
processor.DeleteProduct(productPage);
62+
63+
clientService.Received().Delete(Arg.Is(productPage));
64+
}
65+
66+
67+
[Test]
68+
public void UpdateProduct_ProductIsUdated()
69+
{
70+
var productPage = Substitute.For<SKUTreeNode>();
71+
72+
processor.UpdateProduct(productPage);
73+
74+
clientService.Received().UpdateProduct(Arg.Is(productPage));
75+
}
76+
}
77+
}

Kentico.Recombee.Admin/DatabaseSetup/HistoryData.cs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -193,25 +193,6 @@ private void PushArticles(IList<TreeNode> articles)
193193
}, true));
194194

195195
client.Send(new Batch(articlesToPush));
196-
}
197-
198-
199-
private void PushProducts(IEnumerable<SKUTreeNode> products)
200-
{
201-
var productsToPush = products.Select(productPage => new SetItemValues(productPage.DocumentGUID.ToString(),
202-
new Dictionary<string, object>
203-
{
204-
{ "Name", productPage.DocumentSKUName },
205-
{ "Description", productPage.DocumentSKUShortDescription },
206-
{ "Content", productPage.DocumentSKUDescription},
207-
{ "Culture", productPage.DocumentCulture},
208-
{ "ClassName", productPage.ClassName},
209-
{ "Price", productPage.SKU.SKUPrice },
210-
{ "Type", "Product"},
211-
212-
}, true));
213-
214-
client.Send(new Batch(productsToPush));
215-
}
196+
}
216197
}
217198
}

Kentico.Recombee.Admin/DatabaseSetup/RecombeeStructure.cs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
using CMS.DataEngine;
77
using CMS.DocumentEngine;
88
using CMS.Ecommerce;
9-
using Kentico.Recombee.Helpers;
109

10+
using Kentico.Recombee.Helpers;
11+
using Kentico.Recombee.Mappers;
1112
using Recombee.ApiClient;
1213
using Recombee.ApiClient.ApiRequests;
1314

@@ -85,18 +86,11 @@ private IList<SKUTreeNode> GetProducts()
8586

8687
private void PushProducts(IEnumerable<SKUTreeNode> products)
8788
{
88-
var productsToPush = products.Select(productPage => new SetItemValues(productPage.DocumentGUID.ToString(),
89-
new Dictionary<string, object>
90-
{
91-
{ "Name", productPage.DocumentSKUName },
92-
{ "Description", productPage.DocumentSKUShortDescription },
93-
{ "Content", productPage.DocumentSKUDescription},
94-
{ "Culture", productPage.DocumentCulture},
95-
{ "ClassName", productPage.ClassName},
96-
{ "Price", productPage.SKU.SKUPrice },
97-
{ "Type", "Product"},
98-
99-
}, true));
89+
var productsToPush = products.Select(productPage => new SetItemValues(
90+
productPage.DocumentGUID.ToString(),
91+
ProductMapper.Map(productPage),
92+
true)
93+
);
10094

10195
client.Send(new Batch(productsToPush));
10296
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using CMS;
2+
using CMS.Ecommerce;
3+
4+
using Kentico.Recombee;
5+
6+
[assembly: RegisterImplementation(typeof(IProductUpdatesProcessor), typeof(ProductUpdatesProcessor))]
7+
8+
namespace Kentico.Recombee
9+
{
10+
/// <summary>
11+
/// The contract for an implementation handling product updates.
12+
/// </summary>
13+
public interface IProductUpdatesProcessor
14+
{
15+
/// <summary>
16+
/// Process added product in Recombee.
17+
/// </summary>
18+
/// <param name="productPage">Product page.</param>
19+
void AddProduct(SKUTreeNode productPage);
20+
21+
22+
/// <summary>
23+
/// Deletes given product from recombee database.
24+
/// </summary>
25+
/// <param name="user">Product to delete.</param>
26+
void DeleteProduct(SKUTreeNode productPage);
27+
28+
29+
/// <summary>
30+
/// Updates given product from recombee database.
31+
/// </summary>
32+
/// <param name="user">Product to update.</param>
33+
void UpdateProduct(SKUTreeNode productPage);
34+
}
35+
}

Kentico.Recombee.Admin/IRecombeeClientService.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using CMS;
44
using CMS.ContactManagement;
5+
using CMS.Ecommerce;
56

67
using Kentico.Recombee;
78

@@ -71,5 +72,19 @@ public interface IRecombeeClientService
7172
/// </summary>
7273
/// <param name="itemsToAdd">Cart additions to add.</param>
7374
void Add(IEnumerable<AddCartAddition> itemsToAdd);
75+
76+
77+
/// <summary>
78+
/// Updates given product <paramref name="productPage"/> in Recombee database.
79+
/// </summary>
80+
/// <param name="productPage">Product to update.</param>
81+
void UpdateProduct(SKUTreeNode productPage);
82+
83+
84+
/// <summary>
85+
/// Deletes given product from recombee database.
86+
/// </summary>
87+
/// <param name="user">Product to delete.</param>
88+
void Delete(SKUTreeNode productPage);
7489
}
7590
}

Kentico.Recombee.Admin/Kentico.Recombee.Admin.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,10 @@
550550
<Compile Include="DatabaseSetup\RecombeeStructure.cs" />
551551
<Compile Include="Helpers\RecommendedProductsSettings.cs" />
552552
<Compile Include="IContactMergeProcessor.cs" />
553+
<Compile Include="IProductUpdatesProcessor.cs" />
553554
<Compile Include="IRecombeeClientService.cs" />
555+
<Compile Include="Mappers\ProductMapper.cs" />
556+
<Compile Include="ProductUpdatesProcessor.cs" />
554557
<Compile Include="Properties\AssemblyInfo.cs" />
555558
<Compile Include="RecombeeClientService.cs" />
556559
<Compile Include="RecombeeModule.cs" />
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using CMS.Ecommerce;
5+
6+
namespace Kentico.Recombee.Mappers
7+
{
8+
/// <summary>
9+
/// Encapsulates mapping Kentico objects to Recombee parameters.
10+
/// </summary>
11+
public static class ProductMapper
12+
{
13+
/// <summary>
14+
/// Maps <paramref name="productPage"/> to Recombee structure.
15+
/// </summary>
16+
/// <param name="productPage">Product page.</param>
17+
public static Dictionary<string, object> Map(SKUTreeNode productPage)
18+
{
19+
if (productPage is null)
20+
{
21+
throw new ArgumentNullException(nameof(productPage));
22+
}
23+
24+
return new Dictionary<string, object>
25+
{
26+
{ "Name", productPage.DocumentSKUName },
27+
{ "Description", productPage.DocumentSKUShortDescription },
28+
{ "Content", productPage.DocumentSKUDescription},
29+
{ "Culture", productPage.DocumentCulture},
30+
{ "ClassName", productPage.ClassName},
31+
{ "Price", productPage.SKU.SKUPrice },
32+
{ "Type", "Product"},
33+
};
34+
}
35+
}
36+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using CMS.Ecommerce;
3+
4+
namespace Kentico.Recombee
5+
{
6+
/// <summary>
7+
/// Reflects product actions in Recombee database.
8+
/// </summary>
9+
public class ProductUpdatesProcessor : IProductUpdatesProcessor
10+
{
11+
private readonly IRecombeeClientService recombeeClientService;
12+
13+
/// <summary>
14+
/// Creates an instance of the <see cref="ProductUpdatesProcessor"/> class.
15+
/// </summary>
16+
/// <param name="recombeeClientService">Client service.</param>
17+
public ProductUpdatesProcessor(IRecombeeClientService recombeeClientService)
18+
{
19+
this.recombeeClientService = recombeeClientService ?? throw new ArgumentNullException(nameof(recombeeClientService));
20+
}
21+
22+
23+
/// <summary>
24+
/// Process added product in Recombee.
25+
/// </summary>
26+
/// <param name="productPage">Product page.</param>
27+
public void AddProduct(SKUTreeNode productPage)
28+
{
29+
if (productPage is null)
30+
{
31+
throw new ArgumentNullException(nameof(productPage));
32+
}
33+
34+
UpdateProduct(productPage);
35+
}
36+
37+
38+
/// <summary>
39+
/// Deletes given product from recombee database.
40+
/// </summary>
41+
/// <param name="user">Product to delete.</param>
42+
public void DeleteProduct(SKUTreeNode productPage)
43+
{
44+
if (productPage is null)
45+
{
46+
throw new ArgumentNullException(nameof(productPage));
47+
}
48+
49+
recombeeClientService.Delete(productPage);
50+
}
51+
52+
53+
/// <summary>
54+
/// Updates given product from recombee database.
55+
/// </summary>
56+
/// <param name="user">Product to update.</param>
57+
public void UpdateProduct(SKUTreeNode productPage)
58+
{
59+
if (productPage is null)
60+
{
61+
throw new ArgumentNullException(nameof(productPage));
62+
}
63+
64+
recombeeClientService.UpdateProduct(productPage);
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)