Skip to content

Commit 4eb36c6

Browse files
Merge pull request #40 from TransactionProcessing/task/#36_getsinglefiledetails
Added Get File Details
2 parents d2bf2b0 + c5e36fd commit 4eb36c6

27 files changed

Lines changed: 1181 additions & 357 deletions

FIleProcessor.Models/FileDetails.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,5 @@ public class FileDetails
8989
/// The processing summary.
9090
/// </value>
9191
public ProcessingSummary ProcessingSummary { get; set; }
92-
}
93-
94-
public class ProcessingSummary
95-
{
96-
public Int32 TotalLines { get; set; }
97-
public Int32 SuccessfullyProcessedLines { get; set; }
98-
public Int32 FailedLines { get; set; }
99-
public Int32 IgnoredLines { get; set; }
100-
public Int32 NotProcessedLines { get; set; }
101-
10292
}
10393
}

FIleProcessor.Models/FileLine.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class FileLine
3838
/// </summary>
3939
/// <value>
4040
/// The transaction identifier.
41+
/// 1011934
4142
/// </value>
4243
public Guid TransactionId { get; set; }
4344

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
namespace FIleProcessor.Models
2+
{
3+
using System;
4+
5+
/// <summary>
6+
///
7+
/// </summary>
8+
public class ProcessingSummary
9+
{
10+
#region Properties
11+
12+
/// <summary>
13+
/// Gets or sets the failed lines.
14+
/// </summary>
15+
/// <value>
16+
/// The failed lines.
17+
/// </value>
18+
public Int32 FailedLines { get; set; }
19+
20+
/// <summary>
21+
/// Gets or sets the ignored lines.
22+
/// </summary>
23+
/// <value>
24+
/// The ignored lines.
25+
/// </value>
26+
public Int32 IgnoredLines { get; set; }
27+
28+
/// <summary>
29+
/// Gets or sets the not processed lines.
30+
/// </summary>
31+
/// <value>
32+
/// The not processed lines.
33+
/// </value>
34+
public Int32 NotProcessedLines { get; set; }
35+
36+
/// <summary>
37+
/// Gets or sets the successfully processed lines.
38+
/// </summary>
39+
/// <value>
40+
/// The successfully processed lines.
41+
/// </value>
42+
public Int32 SuccessfullyProcessedLines { get; set; }
43+
44+
/// <summary>
45+
/// Gets or sets the total lines.
46+
/// </summary>
47+
/// <value>
48+
/// The total lines.
49+
/// </value>
50+
public Int32 TotalLines { get; set; }
51+
52+
#endregion
53+
}
54+
}

FileProcessor.BusinessLogic.Tests/FileProcessingManagerTests.cs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@ namespace FileProcessor.BusinessLogic.Tests
1010
using Common;
1111
using EstateReporting.Database;
1212
using EstateReporting.Database.Entities;
13+
using FileAggregate;
1314
using FIleProcessor.Models;
1415
using Managers;
1516
using Microsoft.EntityFrameworkCore;
1617
using Microsoft.EntityFrameworkCore.Diagnostics;
1718
using Moq;
19+
using Shared.DomainDrivenDesign.EventSourcing;
1820
using Shared.EntityFramework;
21+
using Shared.EventStore.Aggregate;
22+
using Shared.Exceptions;
1923
using Shouldly;
2024
using Testing;
2125
using Xunit;
2226
using FileImportLog = EstateReporting.Database.Entities.FileImportLog;
27+
using FileLine = FIleProcessor.Models.FileLine;
2328

2429
public class FileProcessingManagerTests
2530
{
@@ -29,7 +34,9 @@ public async Task FileProcessingManager_GetAllFileProfiles_AllFileProfilesReturn
2934
var fileProfiles = TestData.FileProfiles;
3035
var contextFactory = this.CreateMockContextFactory();
3136
Mock<IModelFactory> modelFactory = new Mock<IModelFactory>();
32-
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object,modelFactory.Object);
37+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
38+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
39+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object,modelFactory.Object, fileAggregateRepository.Object);
3340

3441
var allFileProfiles = await manager.GetAllFileProfiles(CancellationToken.None);
3542
allFileProfiles.ShouldNotBeNull();
@@ -42,7 +49,9 @@ public async Task FileProcessingManager_GetFileProfile_FIleProfileReturned()
4249
var fileProfiles = TestData.FileProfiles;
4350
var contextFactory = this.CreateMockContextFactory();
4451
Mock<IModelFactory> modelFactory = new Mock<IModelFactory>();
45-
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory.Object);
52+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
53+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
54+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory.Object, fileAggregateRepository.Object);
4655

4756
var fileProfile = await manager.GetFileProfile(TestData.SafaricomFileProfileId, CancellationToken.None);
4857
fileProfile.ShouldNotBeNull();
@@ -63,7 +72,9 @@ public async Task FileProcessingManager_GetFileImportLogs_NoMerchantId_ImportLog
6372
context.FileImportLogFiles.AddRange(TestData.FileImportLog2Files);
6473
context.SaveChanges();
6574

66-
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory);
75+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
76+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
77+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object);
6778

6879
var importLogs = await manager.GetFileImportLogs(TestData.EstateId, TestData.ImportLogStartDate, TestData.ImportLogEndDate, null, CancellationToken.None);
6980

@@ -84,7 +95,9 @@ public async Task FileProcessingManager_GetFileImportLogs_WithMerchantId_ImportL
8495
context.FileImportLogFiles.AddRange(TestData.FileImportLog2Files);
8596
context.SaveChanges();
8697

87-
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory);
98+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
99+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
100+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object);
88101

89102
var importLogs = await manager.GetFileImportLogs(TestData.EstateId, TestData.ImportLogStartDate, TestData.ImportLogEndDate, TestData.MerchantId, CancellationToken.None);
90103

@@ -105,7 +118,9 @@ public async Task FileProcessingManager_GetFileImportLog_NoMerchantId_ImportLogR
105118
context.FileImportLogFiles.AddRange(TestData.FileImportLog2Files);
106119
context.SaveChanges();
107120

108-
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory);
121+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
122+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
123+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object);
109124

110125
var importLog = await manager.GetFileImportLog(TestData.FileImportLogId1, TestData.EstateId, null, CancellationToken.None);
111126

@@ -126,13 +141,85 @@ public async Task FileProcessingManager_GetFileImportLog_WithMerchantId_ImportLo
126141
context.FileImportLogFiles.AddRange(TestData.FileImportLog2Files);
127142
context.SaveChanges();
128143

129-
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory);
144+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
145+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
146+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object);
130147

131148
var importLog = await manager.GetFileImportLog(TestData.FileImportLogId1, TestData.EstateId, TestData.MerchantId, CancellationToken.None);
132149

133150
this.VerifyImportLog(TestData.FileImportLogs.First(),importLog, TestData.MerchantId);
134151
}
135152

153+
[Fact]
154+
public async Task FileProcessingManager_GetFile_FileReturned()
155+
{
156+
var fileProfiles = TestData.FileProfiles;
157+
var context = await this.GetContext(Guid.NewGuid().ToString("N"));
158+
var contextFactory = this.CreateMockContextFactory();
159+
contextFactory.Setup(c => c.GetContext(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(context);
160+
IModelFactory modelFactory = new ModelFactory();
161+
162+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
163+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
164+
fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.GetFileAggregateWithLines);
165+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object);
166+
167+
var fileDetails = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None);
168+
169+
this.VerifyFile(TestData.GetFileAggregateWithLines(), fileDetails);
170+
}
171+
172+
[Fact]
173+
public async Task FileProcessingManager_GetFile_FileNotFound_ErrorThrown()
174+
{
175+
var fileProfiles = TestData.FileProfiles;
176+
var context = await this.GetContext(Guid.NewGuid().ToString("N"));
177+
var contextFactory = this.CreateMockContextFactory();
178+
contextFactory.Setup(c => c.GetContext(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(context);
179+
IModelFactory modelFactory = new ModelFactory();
180+
181+
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
182+
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
183+
fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.GetEmptyFileAggregate);
184+
FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object);
185+
186+
Should.Throw<NotFoundException>(async () =>
187+
{
188+
await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None);
189+
});
190+
}
191+
192+
193+
private void VerifyFile(FileAggregate source, FileDetails fileDetails)
194+
{
195+
var fileModel = source.GetFile();
196+
197+
fileDetails.FileId.ShouldBe(fileModel.FileId);
198+
fileDetails.FileImportLogId.ShouldBe(fileModel.FileImportLogId);
199+
fileDetails.FileLocation.ShouldBe(fileModel.FileLocation);
200+
fileDetails.FileProfileId.ShouldBe(fileModel.FileProfileId);
201+
fileDetails.MerchantId.ShouldBe(fileModel.MerchantId);
202+
fileDetails.ProcessingCompleted.ShouldBe(fileModel.ProcessingCompleted);
203+
fileDetails.UserId.ShouldBe(fileModel.UserId);
204+
fileDetails.EstateId.ShouldBe(fileModel.EstateId);
205+
206+
fileDetails.ProcessingSummary.ShouldNotBeNull();
207+
fileDetails.ProcessingSummary.FailedLines.ShouldBe(fileModel.ProcessingSummary.FailedLines);
208+
fileDetails.ProcessingSummary.IgnoredLines.ShouldBe(fileModel.ProcessingSummary.IgnoredLines);
209+
fileDetails.ProcessingSummary.NotProcessedLines.ShouldBe(fileModel.ProcessingSummary.NotProcessedLines);
210+
fileDetails.ProcessingSummary.SuccessfullyProcessedLines.ShouldBe(fileModel.ProcessingSummary.SuccessfullyProcessedLines);
211+
fileDetails.ProcessingSummary.TotalLines.ShouldBe(fileModel.ProcessingSummary.TotalLines);
212+
213+
foreach (FileLine fileModelFileLine in fileModel.FileLines)
214+
{
215+
FileLine? fileLineToVerify = fileDetails.FileLines.SingleOrDefault(f => f.LineNumber == fileModelFileLine.LineNumber);
216+
fileLineToVerify.ShouldNotBeNull();
217+
fileLineToVerify.LineData.ShouldBe(fileModelFileLine.LineData);
218+
fileLineToVerify.TransactionId.ShouldBe(fileModelFileLine.TransactionId);
219+
fileLineToVerify.ProcessingResult.ShouldBe(fileModelFileLine.ProcessingResult);
220+
}
221+
}
222+
136223
private void VerifyImportLogs(List<FileImportLog> source, List<FIleProcessor.Models.FileImportLog> importLogs, Guid? merchantId = null)
137224
{
138225
importLogs.ShouldNotBeNull();

FileProcessor.BusinessLogic.Tests/FileRequestHandlerTests.cs

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -447,50 +447,7 @@ public async Task FileRequestHandler_SafaricomTopupRequest_NoFileProfiles_Reques
447447
await fileRequestHandler.Handle(safaricomTopupRequest, CancellationToken.None);
448448
});
449449
}
450-
451-
[Fact]
452-
public async Task FileRequestHandler_SafaricomTopupRequest_InProgressDirectoryNotFound_RequestIsHandled()
453-
{
454-
Mock<IFileProcessorManager> fileProcessorManager = new Mock<IFileProcessorManager>();
455-
fileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.FileProfileSafaricom);
456-
Mock<IAggregateRepository<FileImportLogAggregate, DomainEventRecord.DomainEvent>> fileImportLogAggregateRepository =
457-
new Mock<IAggregateRepository<FileImportLogAggregate, DomainEventRecord.DomainEvent>>();
458-
Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>> fileAggregateRepository =
459-
new Mock<IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent>>();
460-
461-
fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(TestData.GetCreatedFileAggregate);
462-
Mock<ITransactionProcessorClient> transactionProcessorClient = new Mock<ITransactionProcessorClient>();
463-
Mock<IEstateClient> estateClient = new Mock<IEstateClient>();
464-
Mock<ISecurityServiceClient> securityServiceClient = new Mock<ISecurityServiceClient>();
465-
Mock<IFileFormatHandler> fileFormatHandler = new Mock<IFileFormatHandler>();
466-
Func<String, IFileFormatHandler> fileFormatHandlerResolver = (format) =>
467-
{
468-
return fileFormatHandler.Object;
469-
};
470-
471-
MockFileSystem fileSystem = new MockFileSystem();
472-
fileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1"));
473-
474-
fileSystem.AddDirectory("home/txnproc/bulkfiles/safaricom/processed");
475-
fileSystem.AddDirectory("home/txnproc/bulkfiles/safaricom/failed");
476-
477-
FileRequestHandler fileRequestHandler = new FileRequestHandler(fileProcessorManager.Object,
478-
fileImportLogAggregateRepository.Object,
479-
fileAggregateRepository.Object,
480-
transactionProcessorClient.Object,
481-
estateClient.Object,
482-
securityServiceClient.Object,
483-
fileFormatHandlerResolver,
484-
fileSystem);
485-
SafaricomTopupRequest safaricomTopupRequest =
486-
new SafaricomTopupRequest(TestData.FileId, TestData.FilePathWithName, TestData.FileProfileId);
487-
488-
Should.Throw<DirectoryNotFoundException>(async () =>
489-
{
490-
await fileRequestHandler.Handle(safaricomTopupRequest, CancellationToken.None);
491-
});
492-
}
493-
450+
494451
[Fact]
495452
public async Task FileRequestHandler_SafaricomTopupRequest_ProcessedDirectoryNotFound_RequestIsHandled()
496453
{

FileProcessor.BusinessLogic/Managers/FileProcessorManager.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
using EstateReporting.Database;
1111
using EstateReporting.Database.Entities;
1212
using EstateReporting.Database.ViewEntities;
13+
using FileAggregate;
1314
using FIleProcessor.Models;
1415
using Microsoft.EntityFrameworkCore;
16+
using Shared.DomainDrivenDesign.EventSourcing;
17+
using Shared.EventStore.Aggregate;
18+
using Shared.Exceptions;
1519
using FileImportLog = FIleProcessor.Models.FileImportLog;
1620
using FileLine = EstateReporting.Database.Entities.FileLine;
1721

@@ -32,6 +36,8 @@ public class FileProcessorManager : IFileProcessorManager
3236

3337
private readonly IModelFactory ModelFactory;
3438

39+
private readonly IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent> FileAggregateRepository;
40+
3541
#endregion
3642

3743
#region Constructors
@@ -44,11 +50,13 @@ public class FileProcessorManager : IFileProcessorManager
4450
/// <param name="modelFactory">The model factory.</param>
4551
public FileProcessorManager(List<FileProfile> fileProfiles,
4652
Shared.EntityFramework.IDbContextFactory<EstateReportingContext> dbContextFactory,
47-
IModelFactory modelFactory)
53+
IModelFactory modelFactory,
54+
IAggregateRepository<FileAggregate, DomainEventRecord.DomainEvent> fileAggregateRepository)
4855
{
4956
this.FileProfiles = fileProfiles;
5057
this.DbContextFactory = dbContextFactory;
5158
this.ModelFactory = modelFactory;
59+
this.FileAggregateRepository = fileAggregateRepository;
5260
}
5361

5462
#endregion
@@ -139,6 +147,27 @@ public async Task<FileImportLog> GetFileImportLog(Guid fileImportLogId,
139147
return this.ModelFactory.ConvertFrom(importLogQuery, importLogFileQuery);
140148
}
141149

150+
/// <summary>
151+
/// Gets the file.
152+
/// </summary>
153+
/// <param name="fileId">The file identifier.</param>
154+
/// <param name="estateId">The estate identifier.</param>
155+
/// <param name="cancellationToken">The cancellation token.</param>
156+
/// <returns></returns>
157+
public async Task<FileDetails> GetFile(Guid fileId,
158+
Guid estateId,
159+
CancellationToken cancellationToken)
160+
{
161+
FileAggregate fileAggregate = await this.FileAggregateRepository.GetLatestVersion(fileId, cancellationToken);
162+
163+
if (fileAggregate.IsCreated == false)
164+
{
165+
throw new NotFoundException($"File with Id [{fileId}] not found");
166+
}
167+
168+
return fileAggregate.GetFile();
169+
}
170+
142171
#endregion
143172
}
144173
}

FileProcessor.BusinessLogic/Managers/IFileProcessorManager.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ Task<FileProfile> GetFileProfile(Guid fileProfileId,
5151
/// <returns></returns>
5252
Task<FileImportLog> GetFileImportLog(Guid fileImportLogId, Guid estateId, Guid? merchantId, CancellationToken cancellationToken);
5353

54+
/// <summary>
55+
/// Gets the file.
56+
/// </summary>
57+
/// <param name="fileId">The file identifier.</param>
58+
/// <param name="estateId">The estate identifier.</param>
59+
/// <param name="cancellationToken">The cancellation token.</param>
60+
/// <returns></returns>
61+
Task<FileDetails> GetFile(Guid fileId,
62+
Guid estateId,
63+
CancellationToken cancellationToken);
64+
5465
#endregion
5566
}
5667
}

0 commit comments

Comments
 (0)