Skip to content

Commit e125978

Browse files
Merge pull request #110 from StuartFerguson/task/#107_getmerchantbalance
Get merchant balance route added
2 parents d1bfe69 + d18d01b commit e125978

33 files changed

Lines changed: 728 additions & 114 deletions

File tree

EstateManagement.BusinessLogic.Tests/EstateManagement.BusinessLogic.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</PackageReference>
1414
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
1515
<PackageReference Include="Moq" Version="4.14.1" />
16-
<PackageReference Include="Shared.EventStore" Version="0.0.5.1" />
16+
<PackageReference Include="Shared.EventStore" Version="0.0.14" />
1717
<PackageReference Include="Shouldly" Version="3.0.2" />
1818
<PackageReference Include="xunit" Version="2.4.1" />
1919
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">

EstateManagement.BusinessLogic.Tests/Manager/EstateManagementManagerTests.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class EstateManagementManagerTests
2929
private readonly Mock<IAggregateRepository<EstateAggregate>> EstateAggregateRepository;
3030
private readonly Mock<IAggregateRepository<MerchantAggregate>> MerchantAggregateRepository;
3131
private readonly Mock<IEstateManagementRepository> EstateManagementRepository;
32-
32+
private readonly Mock<IEventStoreContextManager> EventStoreContextManager;
3333
private readonly Mock<IModelFactory> ModelFactory;
3434

3535
private readonly EstateManagementManager EstateManagementManager;
@@ -40,14 +40,15 @@ public EstateManagementManagerTests()
4040
this.EstateAggregateRepository = new Mock<IAggregateRepository<EstateAggregate>>();
4141
this.MerchantAggregateRepository = new Mock<IAggregateRepository<MerchantAggregate>>();
4242
this.EstateManagementRepository = new Mock<IEstateManagementRepository>();
43+
this.EventStoreContextManager = new Mock<IEventStoreContextManager>();
4344

4445
this.ModelFactory = new Mock<IModelFactory>();
4546

4647
aggregateRepositoryManager.Setup(x => x.GetAggregateRepository<EstateAggregate>(It.IsAny<Guid>())).Returns(this.EstateAggregateRepository.Object);
4748
aggregateRepositoryManager.Setup(x => x.GetAggregateRepository<MerchantAggregate>(It.IsAny<Guid>())).Returns(this.MerchantAggregateRepository.Object);
4849

4950
this.EstateManagementManager =
50-
new EstateManagementManager(aggregateRepositoryManager.Object, this.EstateManagementRepository.Object, this.ModelFactory.Object);
51+
new EstateManagementManager(aggregateRepositoryManager.Object, this.EstateManagementRepository.Object, this.EventStoreContextManager.Object, this.ModelFactory.Object);
5152
}
5253

5354
[Fact]
@@ -117,6 +118,24 @@ public async Task EstateManagementManager_GetMerchant_WithContact_MerchantIsRetu
117118
merchantModel.Contacts.ShouldHaveSingleItem();
118119
}
119120

121+
[Fact]
122+
public async Task EstateManagementManager_GetMerchantBalance_MerchantBalanceIsReturned()
123+
{
124+
Mock<IEventStoreContext> eventStoreContext = new Mock<IEventStoreContext>();
125+
126+
String projectionState = "{\r\n \"merchants\": {\r\n \"" + $"{TestData.MerchantId}" + "\": {\r\n \"MerchantId\": \"b3054488-ccfc-4bfe-9b0c-ad7ac10b16e8\",\r\n \"MerchantName\": \"Test Merchant 2\",\r\n \"AvailableBalance\": 1000.00,\r\n \"Balance\": 1000.00,\r\n \"LastDepositDateTime\": null,\r\n \"LastSaleDateTime\": null,\r\n \"PendingBalanceUpdates\": []\r\n }\r\n },\r\n \"debug\": []\r\n}";
127+
128+
eventStoreContext.Setup(e => e.GetPartitionStateFromProjection(It.IsAny<String>(), It.IsAny<String>())).ReturnsAsync(projectionState);
129+
this.EventStoreContextManager.Setup(m => m.GetEventStoreContext(It.IsAny<String>())).Returns(eventStoreContext.Object);
130+
131+
var merchantBalanceModel = await this.EstateManagementManager.GetMerchantBalance(TestData.EstateId, TestData.MerchantId, CancellationToken.None);
132+
133+
merchantBalanceModel.EstateId.ShouldBe(TestData.EstateId);
134+
merchantBalanceModel.MerchantId.ShouldBe(TestData.MerchantId);
135+
merchantBalanceModel.AvailableBalance.ShouldBe(TestData.AvailableBalance);
136+
merchantBalanceModel.Balance.ShouldBe(TestData.Balance);
137+
}
138+
120139
[Fact]
121140
public async Task EstateManagementManager_GetMerchants_MerchantListIsReturned()
122141
{

EstateManagement.BusinessLogic/EstateManagement.BusinessLogic.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="SecurityService.Client" Version="0.0.5.4" />
9-
<PackageReference Include="Shared.DomainDrivenDesign" Version="0.0.5.1" />
8+
<PackageReference Include="SecurityService.Client" Version="1.0.0" />
9+
<PackageReference Include="Shared.DomainDrivenDesign" Version="0.0.14" />
1010
<PackageReference Include="MediatR" Version="8.0.1" />
1111
</ItemGroup>
1212

EstateManagement.BusinessLogic/Manger/EstateManagementManager.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
{
33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Net;
7+
using System.Reflection;
58
using System.Threading;
69
using System.Threading.Tasks;
710
using EstateAggregate;
@@ -10,10 +13,13 @@
1013
using Models.Estate;
1114
using Models.Factories;
1215
using Models.Merchant;
16+
using Newtonsoft.Json;
17+
using Newtonsoft.Json.Linq;
1318
using Repository;
1419
using Shared.DomainDrivenDesign.EventStore;
1520
using Shared.EventStore.EventStore;
1621
using Shared.Exceptions;
22+
using Shared.Logger;
1723

1824
/// <summary>
1925
///
@@ -30,6 +36,8 @@ public class EstateManagementManager : IEstateManagementManager
3036

3137
private readonly IEstateManagementRepository EstateManagementRepository;
3238

39+
private readonly IEventStoreContextManager EventStoreContextManager;
40+
3341
private readonly IAggregateRepository<MerchantAggregate> MerchantAggregateRepository;
3442

3543
/// <summary>
@@ -49,10 +57,12 @@ public class EstateManagementManager : IEstateManagementManager
4957
/// <param name="modelFactory">The model factory.</param>
5058
public EstateManagementManager(IAggregateRepositoryManager aggregateRepositoryManager,
5159
IEstateManagementRepository estateManagementRepository,
60+
IEventStoreContextManager eventStoreContextManager,
5261
IModelFactory modelFactory)
5362
{
5463
this.AggregateRepositoryManager = aggregateRepositoryManager;
5564
this.EstateManagementRepository = estateManagementRepository;
65+
this.EventStoreContextManager = eventStoreContextManager;
5666
this.ModelFactory = modelFactory;
5767
}
5868

@@ -100,6 +110,33 @@ public async Task<Merchant> GetMerchant(Guid estateId,
100110
return merchantModel;
101111
}
102112

113+
/// <summary>
114+
/// Gets the merchant balance.
115+
/// </summary>
116+
/// <param name="estateId">The estate identifier.</param>
117+
/// <param name="merchantId">The merchant identifier.</param>
118+
/// <param name="cancellationToken">The cancellation token.</param>
119+
/// <returns></returns>
120+
public async Task<MerchantBalance> GetMerchantBalance(Guid estateId,
121+
Guid merchantId,
122+
CancellationToken cancellationToken)
123+
{
124+
IEventStoreContext context = this.EventStoreContextManager.GetEventStoreContext(estateId.ToString());
125+
126+
String projectionState = await context.GetPartitionStateFromProjection("MerchantBalanceCalculator", $"MerchantBalanceHistory-{merchantId:N}");
127+
128+
JObject parsedState = JObject.Parse(projectionState);
129+
JToken? merchantRecord = parsedState["merchants"][$"{merchantId}"];
130+
131+
return new MerchantBalance
132+
{
133+
AvailableBalance = Decimal.Parse(merchantRecord["AvailableBalance"].ToString()),
134+
Balance = Decimal.Parse(merchantRecord["Balance"].ToString()),
135+
EstateId = estateId,
136+
MerchantId = merchantId
137+
};
138+
}
139+
103140
/// <summary>
104141
/// Gets the merchants.
105142
/// </summary>

EstateManagement.BusinessLogic/Manger/IEstateManagementManager.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ Task<Estate> GetEstate(Guid estateId,
3131
Task<Merchant> GetMerchant(Guid estateId, Guid merchantId,
3232
CancellationToken cancellationToken);
3333

34+
/// <summary>
35+
/// Gets the merchant balance.
36+
/// </summary>
37+
/// <param name="estateId">The estate identifier.</param>
38+
/// <param name="merchantId">The merchant identifier.</param>
39+
/// <param name="cancellationToken">The cancellation token.</param>
40+
/// <returns></returns>
41+
Task<MerchantBalance> GetMerchantBalance(Guid estateId, Guid merchantId,
42+
CancellationToken cancellationToken);
43+
3444
/// <summary>
3545
/// Gets the merchants.
3646
/// </summary>

EstateManagement.BusinessLogic/Services/MerchantDomainService.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,22 @@ public async Task AddDeviceToMerchant(Guid estateId,
268268
await merchantAggregateRepository.SaveChanges(merchantAggregate, cancellationToken);
269269
}
270270

271+
/// <summary>
272+
/// Makes the merchant deposit.
273+
/// </summary>
274+
/// <param name="estateId">The estate identifier.</param>
275+
/// <param name="merchantId">The merchant identifier.</param>
276+
/// <param name="source">The source.</param>
277+
/// <param name="reference">The reference.</param>
278+
/// <param name="depositDateTime">The deposit date time.</param>
279+
/// <param name="amount">The amount.</param>
280+
/// <param name="cancellationToken">The cancellation token.</param>
281+
/// <returns></returns>
282+
/// <exception cref="InvalidOperationException">
283+
/// Merchant Id {merchantId} has not been created
284+
/// or
285+
/// Estate Id {estateId} has not been created
286+
/// </exception>
271287
public async Task<Guid> MakeMerchantDeposit(Guid estateId,
272288
Guid merchantId,
273289
Models.MerchantDepositSource source,

EstateManagement.Client/EstateClient.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,48 @@ public async Task<MerchantResponse> GetMerchant(String accessToken,
459459
return response;
460460
}
461461

462+
/// <summary>
463+
/// Gets the merchant balance.
464+
/// </summary>
465+
/// <param name="accessToken">The access token.</param>
466+
/// <param name="estateId">The estate identifier.</param>
467+
/// <param name="merchantId">The merchant identifier.</param>
468+
/// <param name="cancellationToken">The cancellation token.</param>
469+
/// <returns></returns>
470+
public async Task<MerchantBalanceResponse> GetMerchantBalance(String accessToken,
471+
Guid estateId,
472+
Guid merchantId,
473+
CancellationToken cancellationToken)
474+
{
475+
MerchantBalanceResponse response = null;
476+
477+
String requestUri = $"{this.BaseAddress}/api/estates/{estateId}/merchants/{merchantId}/balance";
478+
479+
try
480+
{
481+
// Add the access token to the client headers
482+
this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
483+
484+
// Make the Http Call here
485+
HttpResponseMessage httpResponse = await this.HttpClient.GetAsync(requestUri, cancellationToken);
486+
487+
// Process the response
488+
String content = await this.HandleResponse(httpResponse, cancellationToken);
489+
490+
// call was successful so now deserialise the body to the response object
491+
response = JsonConvert.DeserializeObject<MerchantBalanceResponse>(content);
492+
}
493+
catch (Exception ex)
494+
{
495+
// An exception has occurred, add some additional information to the message
496+
Exception exception = new Exception($"Error getting balance for merchant Id {merchantId} in estate {estateId}.", ex);
497+
498+
throw exception;
499+
}
500+
501+
return response;
502+
}
503+
462504
/// <summary>
463505
/// Gets the merchants.
464506
/// </summary>

EstateManagement.Client/EstateManagement.Client.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="ClientProxyBase" Version="0.0.7" />
10+
<PackageReference Include="ClientProxyBase" Version="0.0.14" />
1111
</ItemGroup>
1212

1313
<ItemGroup>

EstateManagement.Client/IEstateClient.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ Task<MerchantResponse> GetMerchant(String accessToken,
133133
Guid merchantId,
134134
CancellationToken cancellationToken);
135135

136+
/// <summary>
137+
/// Gets the merchant balance.
138+
/// </summary>
139+
/// <param name="accessToken">The access token.</param>
140+
/// <param name="estateId">The estate identifier.</param>
141+
/// <param name="merchantId">The merchant identifier.</param>
142+
/// <param name="cancellationToken">The cancellation token.</param>
143+
/// <returns></returns>
144+
Task<MerchantBalanceResponse> GetMerchantBalance(String accessToken,
145+
Guid estateId,
146+
Guid merchantId,
147+
CancellationToken cancellationToken);
148+
136149
/// <summary>
137150
/// Gets the merchant.
138151
/// </summary>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
namespace EstateManagement.DataTransferObjects.Responses
2+
{
3+
using System;
4+
5+
public class MerchantBalanceResponse
6+
{
7+
/// <summary>
8+
/// Gets or sets the estate identifier.
9+
/// </summary>
10+
/// <value>
11+
/// The estate identifier.
12+
/// </value>
13+
public Guid EstateId { get; set; }
14+
15+
/// <summary>
16+
/// Gets or sets the merchant identifier.
17+
/// </summary>
18+
/// <value>
19+
/// The merchant identifier.
20+
/// </value>
21+
public Guid MerchantId { get; set; }
22+
23+
/// <summary>
24+
/// Gets or sets the available balance.
25+
/// </summary>
26+
/// <value>
27+
/// The available balance.
28+
/// </value>
29+
public Decimal AvailableBalance { get; set; }
30+
31+
/// <summary>
32+
/// Gets or sets the balance.
33+
/// </summary>
34+
/// <value>
35+
/// The balance.
36+
/// </value>
37+
public Decimal Balance { get; set; }
38+
}
39+
}

0 commit comments

Comments
 (0)