Skip to content

Commit e4430db

Browse files
authored
Merge pull request #16 from dotnetprog/feature/AddSupportForProducts
Add Supports for Product Related Entities
2 parents c49de59 + 933ab41 commit e4430db

18 files changed

+660
-25
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using Dataverse.ConfigurationMigrationTool.Console.Features.Import.Interceptors;
2+
using Microsoft.Xrm.Sdk;
3+
using NSubstitute;
4+
using Shouldly;
5+
6+
namespace Dataverse.ConfigurationMigrationTool.Console.Tests.Features.Import.Interceptors;
7+
public abstract class BaseEntityReferenceFieldInterceptorTests<T> : BaseEntityInterceptorTests<T>
8+
where T : BaseEntityReferenceFieldInterceptor
9+
{
10+
protected string EntityName { get; }
11+
protected string PrimaryKeyName { get; }
12+
protected BaseEntityReferenceFieldInterceptorTests(string EntityName, string PrimaryKeyName)
13+
{
14+
this.EntityName = EntityName;
15+
this.PrimaryKeyName = PrimaryKeyName;
16+
}
17+
protected abstract Task<Entity> GetEntityByIdAsync(Guid Id);
18+
protected abstract Task<Entity> GetEntityByNameAsync(string Name);
19+
[Fact]
20+
public async Task GivenAnEntityWithEntityReferenceField_WhenItsIntercepted_ThenItShouldResolveLookUpByName()
21+
{
22+
//Arrange
23+
var recordName = "Test Team";
24+
var expectedRecord = new Entity(EntityName)
25+
{
26+
Id = Guid.NewGuid(),
27+
["name"] = recordName
28+
};
29+
GetEntityByNameAsync(recordName).Returns(expectedRecord);
30+
31+
var entity = new Entity("account")
32+
{
33+
Id = Guid.NewGuid(),
34+
["name"] = "Test Account",
35+
[PrimaryKeyName] = new EntityReference(EntityName, Guid.NewGuid()) { Name = recordName }
36+
};
37+
38+
//Act
39+
var result = await InterceptAsync(entity);
40+
//Assert
41+
result.GetAttributeValue<EntityReference>(PrimaryKeyName).Id.ShouldBe(expectedRecord.Id);
42+
}
43+
[Fact]
44+
public async Task GivenAnEntityWithEntityReferenceField_WhenItsIntercepted_ThenItShouldResolveLookUpById()
45+
{
46+
//Arrange
47+
var recordName = "Test team";
48+
var expectedRecord = new Entity(EntityName)
49+
{
50+
Id = Guid.NewGuid(),
51+
["name"] = recordName
52+
};
53+
GetEntityByIdAsync(expectedRecord.Id).Returns(expectedRecord);
54+
55+
var entity = new Entity("account")
56+
{
57+
Id = Guid.NewGuid(),
58+
["name"] = "Test Account",
59+
[PrimaryKeyName] = expectedRecord.ToEntityReference()
60+
};
61+
62+
//Act
63+
var result = await InterceptAsync(entity);
64+
//Assert
65+
result.GetAttributeValue<EntityReference>(PrimaryKeyName).Id.ShouldBe(expectedRecord.Id);
66+
}
67+
[Fact]
68+
public async Task GivenAnEntityWithLookUpField_WhenItsInterceptedAndCantBeResolved_ThenItShouldRemoveFieldFromEntity()
69+
{
70+
//Arrange
71+
var recordName = "Test team";
72+
var expectedRecord = new Entity(EntityName)
73+
{
74+
Id = Guid.NewGuid(),
75+
["name"] = recordName
76+
};
77+
78+
var entity = new Entity("account")
79+
{
80+
Id = Guid.NewGuid(),
81+
["name"] = "Test Account",
82+
[PrimaryKeyName] = expectedRecord.ToEntityReference()
83+
};
84+
85+
//Act
86+
var result = await InterceptAsync(entity);
87+
//Assert
88+
result.Attributes.FirstOrDefault(kv => kv.Key == PrimaryKeyName).ShouldBe(default);
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Dataverse.ConfigurationMigrationTool.Console.Features.Import.Interceptors;
2+
using Dataverse.ConfigurationMigrationTool.Console.Services.Dataverse;
3+
using Microsoft.Xrm.Sdk;
4+
using NSubstitute;
5+
6+
namespace Dataverse.ConfigurationMigrationTool.Console.Tests.Features.Import.Interceptors;
7+
public class TargetTransactionCurrencyInterceptorTests : BaseEntityReferenceFieldInterceptorTests<TargetTransactionCurrencyInterceptor>
8+
{
9+
private readonly IProductCatalogService _productCatalogService = Substitute.For<IProductCatalogService>();
10+
11+
public TargetTransactionCurrencyInterceptorTests() : base("transactioncurrency", "transactioncurrencyid")
12+
{
13+
}
14+
15+
protected override TargetTransactionCurrencyInterceptor CreateInterceptor() => new TargetTransactionCurrencyInterceptor(_productCatalogService);
16+
17+
protected override Task<Entity> GetEntityByIdAsync(Guid Id)
18+
{
19+
return _productCatalogService.GetTransacationCurrencyById(Id);
20+
}
21+
22+
protected override Task<Entity> GetEntityByNameAsync(string Name)
23+
{
24+
return _productCatalogService.GetTransacationCurrencyByName(Name);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Dataverse.ConfigurationMigrationTool.Console.Features.Import.Interceptors;
2+
using Dataverse.ConfigurationMigrationTool.Console.Services.Dataverse;
3+
using Microsoft.Xrm.Sdk;
4+
using NSubstitute;
5+
6+
namespace Dataverse.ConfigurationMigrationTool.Console.Tests.Features.Import.Interceptors;
7+
public class TargetUoMInterceptorTests : BaseEntityReferenceFieldInterceptorTests<TargetUoMInterceptor>
8+
{
9+
private readonly IProductCatalogService _productCatalogService = Substitute.For<IProductCatalogService>();
10+
11+
public TargetUoMInterceptorTests() : base("uom", "uomid")
12+
{
13+
}
14+
15+
protected override TargetUoMInterceptor CreateInterceptor() => new TargetUoMInterceptor(_productCatalogService);
16+
17+
protected override Task<Entity> GetEntityByIdAsync(Guid Id)
18+
{
19+
return _productCatalogService.GetUoMById(Id);
20+
}
21+
22+
protected override Task<Entity> GetEntityByNameAsync(string Name)
23+
{
24+
return _productCatalogService.GetUoMByName(Name);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Dataverse.ConfigurationMigrationTool.Console.Features.Import.Interceptors;
2+
using Dataverse.ConfigurationMigrationTool.Console.Services.Dataverse;
3+
using Microsoft.Xrm.Sdk;
4+
using NSubstitute;
5+
6+
namespace Dataverse.ConfigurationMigrationTool.Console.Tests.Features.Import.Interceptors;
7+
public class TargetUoMScheduleInterceptorTests : BaseEntityReferenceFieldInterceptorTests<TargetUoMScheduleInterceptor>
8+
{
9+
private readonly IProductCatalogService _productCatalogService = Substitute.For<IProductCatalogService>();
10+
11+
public TargetUoMScheduleInterceptorTests() : base("uomschedule", "uomscheduleid")
12+
{
13+
}
14+
15+
protected override TargetUoMScheduleInterceptor CreateInterceptor() => new TargetUoMScheduleInterceptor(_productCatalogService);
16+
17+
protected override Task<Entity> GetEntityByIdAsync(Guid Id)
18+
{
19+
return _productCatalogService.GetUoMScheduleById(Id);
20+
}
21+
22+
protected override Task<Entity> GetEntityByNameAsync(string Name)
23+
{
24+
return _productCatalogService.GetUoMScheduleByName(Name);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using Dataverse.ConfigurationMigrationTool.Console.Services.Dataverse;
2+
using FakeXrmEasy.Abstractions;
3+
using FakeXrmEasy.Abstractions.Enums;
4+
using FakeXrmEasy.Middleware;
5+
using FakeXrmEasy.Middleware.Crud;
6+
using Microsoft.Extensions.Caching.Memory;
7+
using Microsoft.Xrm.Sdk;
8+
using NSubstitute;
9+
using Shouldly;
10+
11+
namespace Dataverse.ConfigurationMigrationTool.Console.Tests.Services.Dataverse;
12+
public class DataverseProductCatalogServiceTests
13+
{
14+
private readonly IXrmFakedContext _fakedContext;
15+
private readonly IMemoryCache _memoryCache = Substitute.For<IMemoryCache>();
16+
private readonly DataverseProductCatalogService _repository;
17+
public DataverseProductCatalogServiceTests()
18+
{
19+
// Arrange
20+
_fakedContext = MiddlewareBuilder.New()
21+
.SetLicense(FakeXrmEasyLicense.NonCommercial)
22+
.AddCrud()
23+
.UseCrud()
24+
.Build();
25+
_repository = new DataverseProductCatalogService(_fakedContext.GetAsyncOrganizationService2(), _memoryCache);
26+
}
27+
[Fact]
28+
public async Task GivenAProductCatalogServicey_WhenItFetchesTransactionCurrencyById_ThenItShouldCacheItsResult()
29+
{
30+
//Arrange
31+
var recordname = "Test Team";
32+
33+
var record = new Entity("transactioncurrency")
34+
{
35+
Id = Guid.NewGuid(),
36+
["currencyname"] = recordname
37+
};
38+
var cacheKey = $"product.GetTransacationCurrencyById.{record.Id}";
39+
_fakedContext.Initialize(record);
40+
var CacheEntry = Substitute.For<ICacheEntry>();
41+
_memoryCache.TryGetValue(cacheKey, out Arg.Any<object>()).Returns(false);
42+
_memoryCache.CreateEntry(cacheKey).Returns(CacheEntry);
43+
44+
//Act
45+
46+
var result = await _repository.GetTransacationCurrencyById(record.Id);
47+
48+
//Assert
49+
result.Id.ShouldBe(record.Id);
50+
CacheEntry.Received().SetValue(Arg.Is<Entity>(e => e.Id == record.Id));
51+
52+
}
53+
[Fact]
54+
public async Task GivenAProductCatalogServicey_WhenItFetchesTransactionCurrencyByName_ThenItShouldCacheItsResult()
55+
{
56+
//Arrange
57+
var recordname = "Test Team";
58+
var cacheKey = $"product.GetTransacationCurrencyByName.{recordname}";
59+
var record = new Entity("transactioncurrency")
60+
{
61+
Id = Guid.NewGuid(),
62+
["currencyname"] = recordname
63+
};
64+
_fakedContext.Initialize(record);
65+
var CacheEntry = Substitute.For<ICacheEntry>();
66+
_memoryCache.TryGetValue(cacheKey, out Arg.Any<object>()).Returns(false);
67+
_memoryCache.CreateEntry(cacheKey).Returns(CacheEntry);
68+
69+
//Act
70+
71+
var result = await _repository.GetTransacationCurrencyByName(recordname);
72+
73+
//Assert
74+
result.Id.ShouldBe(record.Id);
75+
CacheEntry.Received().SetValue(Arg.Is<Entity>(e => e.Id == record.Id));
76+
77+
}
78+
[Fact]
79+
public async Task GivenAProductCatalogServicey_WhenItFetchesUoMById_ThenItShouldCacheItsResult()
80+
{
81+
//Arrange
82+
var recordname = "Test Team";
83+
84+
var record = new Entity("uom")
85+
{
86+
Id = Guid.NewGuid(),
87+
["name"] = recordname
88+
};
89+
var cacheKey = $"product.GetUoMById.{record.Id}";
90+
_fakedContext.Initialize(record);
91+
var CacheEntry = Substitute.For<ICacheEntry>();
92+
_memoryCache.TryGetValue(cacheKey, out Arg.Any<object>()).Returns(false);
93+
_memoryCache.CreateEntry(cacheKey).Returns(CacheEntry);
94+
95+
//Act
96+
97+
var result = await _repository.GetUoMById(record.Id);
98+
99+
//Assert
100+
result.Id.ShouldBe(record.Id);
101+
CacheEntry.Received().SetValue(Arg.Is<Entity>(e => e.Id == record.Id));
102+
103+
}
104+
[Fact]
105+
public async Task GivenAProductCatalogServicey_WhenItFetchesUoMByName_ThenItShouldCacheItsResult()
106+
{
107+
//Arrange
108+
var recordname = "Test Team";
109+
var cacheKey = $"product.GetUoMByName.{recordname}";
110+
var record = new Entity("uom")
111+
{
112+
Id = Guid.NewGuid(),
113+
["name"] = recordname
114+
};
115+
_fakedContext.Initialize(record);
116+
var CacheEntry = Substitute.For<ICacheEntry>();
117+
_memoryCache.TryGetValue(cacheKey, out Arg.Any<object>()).Returns(false);
118+
_memoryCache.CreateEntry(cacheKey).Returns(CacheEntry);
119+
120+
//Act
121+
122+
var result = await _repository.GetUoMByName(recordname);
123+
124+
//Assert
125+
result.Id.ShouldBe(record.Id);
126+
CacheEntry.Received().SetValue(Arg.Is<Entity>(e => e.Id == record.Id));
127+
128+
}
129+
[Fact]
130+
public async Task GivenAProductCatalogServicey_WhenItFetchesUoMScheduleById_ThenItShouldCacheItsResult()
131+
{
132+
//Arrange
133+
var recordname = "Test Team";
134+
135+
var record = new Entity("uomschedule")
136+
{
137+
Id = Guid.NewGuid(),
138+
["name"] = recordname
139+
};
140+
var cacheKey = $"product.GetUoMScheduleById.{record.Id}";
141+
_fakedContext.Initialize(record);
142+
var CacheEntry = Substitute.For<ICacheEntry>();
143+
_memoryCache.TryGetValue(cacheKey, out Arg.Any<object>()).Returns(false);
144+
_memoryCache.CreateEntry(cacheKey).Returns(CacheEntry);
145+
146+
//Act
147+
148+
var result = await _repository.GetUoMScheduleById(record.Id);
149+
150+
//Assert
151+
result.Id.ShouldBe(record.Id);
152+
CacheEntry.Received().SetValue(Arg.Is<Entity>(e => e.Id == record.Id));
153+
154+
}
155+
[Fact]
156+
public async Task GivenAProductCatalogServicey_WhenItFetchesUoMScheduleByName_ThenItShouldCacheItsResult()
157+
{
158+
//Arrange
159+
var recordname = "Test Team";
160+
var cacheKey = $"product.GetUoMScheduleByName.{recordname}";
161+
var record = new Entity("uomschedule")
162+
{
163+
Id = Guid.NewGuid(),
164+
["name"] = recordname
165+
};
166+
_fakedContext.Initialize(record);
167+
var CacheEntry = Substitute.For<ICacheEntry>();
168+
_memoryCache.TryGetValue(cacheKey, out Arg.Any<object>()).Returns(false);
169+
_memoryCache.CreateEntry(cacheKey).Returns(CacheEntry);
170+
171+
//Act
172+
173+
var result = await _repository.GetUoMScheduleByName(recordname);
174+
175+
//Assert
176+
result.Id.ShouldBe(record.Id);
177+
CacheEntry.Received().SetValue(Arg.Is<Entity>(e => e.Id == record.Id));
178+
179+
}
180+
}

src/Dataverse.ConfigurationMigrationTool/Dataverse.ConfigurationMigrationTool.Console/Features/Export/Mappers/EntityFieldValueToFieldMapper.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Dataverse.ConfigurationMigrationTool.Console.Features.Shared;
22
using Dataverse.ConfigurationMigrationTool.Console.Features.Shared.Domain;
33
using Microsoft.Xrm.Sdk;
4+
using System.Globalization;
45
using System.Web;
56

67
namespace Dataverse.ConfigurationMigrationTool.Console.Features.Export.Mappers;
@@ -46,17 +47,17 @@ public Field Map((FieldSchema, object) source)
4647
}
4748
if (value is Money moneyValue)
4849
{
49-
fieldResult.Value = moneyValue.Value.ToString();
50+
fieldResult.Value = moneyValue.Value.ToString(CultureInfo.InvariantCulture);
5051
return fieldResult;
5152
}
5253
if (value is decimal decimalValue)
5354
{
54-
fieldResult.Value = decimalValue.ToString();
55+
fieldResult.Value = decimalValue.ToString(CultureInfo.InvariantCulture);
5556
return fieldResult;
5657
}
5758
if (value is double doubleValue)
5859
{
59-
fieldResult.Value = doubleValue.ToString();
60+
fieldResult.Value = doubleValue.ToString(CultureInfo.InvariantCulture);
6061
return fieldResult;
6162
}
6263
var str = value?.ToString() ?? string.Empty;

src/Dataverse.ConfigurationMigrationTool/Dataverse.ConfigurationMigrationTool.Console/Features/IServiceCollectionExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public static IServiceCollection AddSharedServices(this IServiceCollection servi
2525
{
2626
return services.RegisterFromReflection<IFieldSchemaValidationRule>()
2727
.RegisterFromReflection<IRelationshipSchemaValidationRule>()
28-
.AddTransient<IValidator<DataSchema>, SchemaValidator>()
29-
.AddTransient<IValidator<EntitySchema>, EntitySchemaValidator>();
28+
.AddScoped<IValidator<DataSchema>, SchemaValidator>()
29+
.AddScoped<IValidator<EntitySchema>, EntitySchemaValidator>();
3030
}
3131
public static IServiceCollection UseCommands(this IServiceCollection services, params string[] args)
3232
{

0 commit comments

Comments
 (0)