public void FileAggregate_RecordFileLineAsRejected_FileLineUpdatedAsRejected()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);
            fileAggregate.AddFileLine(TestData.FileLine);
            fileAggregate.RecordFileLineAsRejected(TestData.LineNumber, TestData.RejectionReason);

            FileDetails fileDetails = fileAggregate.GetFile();

            fileDetails.FileLines.ShouldNotBeNull();
            fileDetails.FileLines.ShouldNotBeEmpty();
            fileDetails.FileLines.ShouldHaveSingleItem();
            fileDetails.FileLines.Single().LineNumber.ShouldBe(1);
            fileDetails.FileLines.Single().LineData.ShouldBe(TestData.FileLine);
            fileDetails.FileLines.Single().ProcessingResult.ShouldBe(ProcessingResult.Rejected);
            fileDetails.FileLines.Single().RejectedReason.ShouldBe(TestData.RejectionReason);
            fileDetails.ProcessingCompleted.ShouldBeTrue();
            fileDetails.ProcessingSummary.ShouldNotBeNull();
            fileDetails.ProcessingSummary.TotalLines.ShouldBe(1);
            fileDetails.ProcessingSummary.NotProcessedLines.ShouldBe(0);
            fileDetails.ProcessingSummary.FailedLines.ShouldBe(0);
            fileDetails.ProcessingSummary.SuccessfullyProcessedLines.ShouldBe(0);
            fileDetails.ProcessingSummary.IgnoredLines.ShouldBe(0);
            fileDetails.ProcessingSummary.RejectedLines.ShouldBe(1);
        }
Пример #2
0
        private void VerifyFile(FileAggregate source, FileDetails fileDetails)
        {
            var fileModel = source.GetFile();

            fileDetails.FileId.ShouldBe(fileModel.FileId);
            fileDetails.FileImportLogId.ShouldBe(fileModel.FileImportLogId);
            fileDetails.FileLocation.ShouldBe(fileModel.FileLocation);
            fileDetails.FileProfileId.ShouldBe(fileModel.FileProfileId);
            fileDetails.MerchantId.ShouldBe(fileModel.MerchantId);
            fileDetails.ProcessingCompleted.ShouldBe(fileModel.ProcessingCompleted);
            fileDetails.UserId.ShouldBe(fileModel.UserId);
            fileDetails.EstateId.ShouldBe(fileModel.EstateId);

            fileDetails.ProcessingSummary.ShouldNotBeNull();
            fileDetails.ProcessingSummary.FailedLines.ShouldBe(fileModel.ProcessingSummary.FailedLines);
            fileDetails.ProcessingSummary.IgnoredLines.ShouldBe(fileModel.ProcessingSummary.IgnoredLines);
            fileDetails.ProcessingSummary.NotProcessedLines.ShouldBe(fileModel.ProcessingSummary.NotProcessedLines);
            fileDetails.ProcessingSummary.SuccessfullyProcessedLines.ShouldBe(fileModel.ProcessingSummary.SuccessfullyProcessedLines);
            fileDetails.ProcessingSummary.TotalLines.ShouldBe(fileModel.ProcessingSummary.TotalLines);

            foreach (FileLine fileModelFileLine in fileModel.FileLines)
            {
                FileLine?fileLineToVerify = fileDetails.FileLines.SingleOrDefault(f => f.LineNumber == fileModelFileLine.LineNumber);
                fileLineToVerify.ShouldNotBeNull();
                fileLineToVerify.LineData.ShouldBe(fileModelFileLine.LineData);
                fileLineToVerify.TransactionId.ShouldBe(fileModelFileLine.TransactionId);
                fileLineToVerify.ProcessingResult.ShouldBe(fileModelFileLine.ProcessingResult);
            }
        }
Пример #3
0
        public static FileAggregate GetCreatedFileAggregate()
        {
            FileAggregate fileAggregate = new FileAggregate();

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FileProfileId, TestData.OriginalFileName, TestData.FileUploadedDateTime);

            return(fileAggregate);
        }
        public void FileAggregate_AddFileLine_FileNotCreated_FileLineAdded()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            Should.Throw <InvalidOperationException>(() =>
            {
                fileAggregate.AddFileLine(TestData.FileLine);
            });
        }
        public void FileAggregate_RecordFileLineAsRejected_FileNotCreated_ErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            Should.Throw <InvalidOperationException>(() =>
            {
                fileAggregate.RecordFileLineAsRejected(TestData.LineNumber, TestData.RejectionReason);
            });
        }
Пример #6
0
        public static FileAggregate GetFileAggregateWithBlankLine()
        {
            FileAggregate fileAggregate = new FileAggregate();

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FileProfileId, TestData.OriginalFileName, TestData.FileUploadedDateTime);
            fileAggregate.AddFileLine(String.Empty);

            return(fileAggregate);
        }
        public void FileAggregate_RecordFileLineAsFailed_FileNotCreated_ErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            Should.Throw <InvalidOperationException>(() =>
            {
                fileAggregate.RecordFileLineAsFailed(TestData.LineNumber, TestData.TransactionId, TestData.ResponseCodeFailed, TestData.ResponseMessageFailed);
            });
        }
        public void FileAggregate_RecordFileLineAsSuccessful_FileNotCreated_ErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            Should.Throw <InvalidOperationException>(() =>
            {
                fileAggregate.RecordFileLineAsSuccessful(TestData.LineNumber, TestData.TransactionId);
            });
        }
Пример #9
0
        public async Task <Unit> Handle(ProcessUploadedFileRequest request, CancellationToken cancellationToken)
        {
            // TODO: Should the file id be generated from the file uploaded to protect against duplicate files???
            FileAggregate fileAggregate = await this.FileAggregateRepository.GetLatestVersion(request.FileId, cancellationToken);

            fileAggregate.CreateFile(request.FileImportLogId, request.EstateId, request.MerchantId, request.UserId, request.FileProfileId, request.FilePath, request.FileUploadedDateTime);

            await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken);

            return(new Unit());
        }
        public void FileAggregate_CanBeCreated_IsCreated()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.ShouldNotBeNull();
            FileDetails fileDetails = fileAggregate.GetFile();

            fileDetails.ShouldNotBeNull();
            fileDetails.FileId.ShouldBe(TestData.FileId);
            fileDetails.ProcessingCompleted.ShouldBeFalse();
        }
        public void FileAggregate_RecordFileLineAsRejected_LineNotFound_ErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);
            fileAggregate.AddFileLine(TestData.FileLine);
            Should.Throw <NotFoundException>(() =>
            {
                fileAggregate.RecordFileLineAsRejected(TestData.NotFoundLineNumber, TestData.RejectionReason);
            });
        }
        public void FileAggregate_RecordFileLineAsFailed_FileHasNoLines_ErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);

            Should.Throw <InvalidOperationException>(() =>
            {
                fileAggregate.RecordFileLineAsFailed(TestData.LineNumber, TestData.TransactionId, TestData.ResponseCodeFailed, TestData.ResponseMessageFailed);
            });
        }
        public void FileAggregate_RecordFileLineAsRejected_FileHasNoLine_ErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);

            Should.Throw <InvalidOperationException>(() =>
            {
                fileAggregate.RecordFileLineAsRejected(TestData.LineNumber, TestData.RejectionReason);
            });
        }
Пример #14
0
        public static FileAggregate GetFileAggregateWithLinesAlreadyProcessed()
        {
            FileAggregate fileAggregate = new FileAggregate();

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FileProfileId, TestData.OriginalFileName, TestData.FileUploadedDateTime);
            fileAggregate.AddFileLine("D,1,2");
            fileAggregate.AddFileLine("D,1,2");
            fileAggregate.AddFileLine("D,1,2");
            fileAggregate.AddFileLine("D,1,2");
            fileAggregate.RecordFileLineAsSuccessful(1, TestData.TransactionId);
            fileAggregate.RecordFileLineAsRejected(2, TestData.RejectionReason);
            fileAggregate.RecordFileLineAsFailed(3, TestData.TransactionId, "-1", "Failed");
            fileAggregate.RecordFileLineAsIgnored(4);

            return(fileAggregate);
        }
        public void FileAggregate_CreateFile_FileAlreadyCreated_NoErrorThrown()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);

            Should.NotThrow(() =>
            {
                fileAggregate.CreateFile(TestData.FileImportLogId,
                                         TestData.EstateId,
                                         TestData.MerchantId,
                                         TestData.UserId,
                                         TestData.FileProfileId,
                                         TestData.FileLocation,
                                         TestData.FileUploadedDateTime);
            });
        }
        /// <summary>
        /// Gets the file.
        /// </summary>
        /// <param name="fileId">The file identifier.</param>
        /// <param name="estateId">The estate identifier.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public async Task <FileDetails> GetFile(Guid fileId,
                                                Guid estateId,
                                                CancellationToken cancellationToken)
        {
            FileAggregate fileAggregate =
                await this.FileAggregateRepository.GetLatestVersion(fileId, cancellationToken);

            if (fileAggregate.IsCreated == false)
            {
                throw new NotFoundException($"File with Id [{fileId}] not found");
            }

            FileDetails fileDetails = fileAggregate.GetFile();

            EstateReportingGenericContext context = await this.DbContextFactory.GetContext(estateId, cancellationToken);

            Merchant merchant = await context.Merchants.AsAsyncEnumerable()
                                .SingleOrDefaultAsync(m => m.MerchantId == fileDetails.MerchantId, cancellationToken);

            if (merchant != null)
            {
                fileDetails.MerchantName = merchant.Name;
            }

            EstateSecurityUser userDetails = await context.EstateSecurityUsers.AsAsyncEnumerable()
                                             .SingleOrDefaultAsync(u => u.SecurityUserId == fileDetails.UserId);

            if (userDetails != null)
            {
                fileDetails.UserEmailAddress = userDetails.EmailAddress;
            }

            FileProfile fileProfile = await this.GetFileProfile(fileDetails.FileProfileId, cancellationToken);

            if (fileProfile != null)
            {
                fileDetails.FileProfileName = fileProfile.Name;
            }

            return(fileDetails);
        }
        public void FileAggregate_CreateFile_FileIsCreated()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);

            fileAggregate.IsCreated.ShouldBeTrue();
            FileDetails fileDetails = fileAggregate.GetFile();

            fileDetails.ShouldNotBeNull();
            fileDetails.FileId.ShouldBe(TestData.FileId);
            fileDetails.FileImportLogId.ShouldBe(TestData.FileImportLogId);
            fileDetails.EstateId.ShouldBe(TestData.EstateId);
            fileDetails.MerchantId.ShouldBe(TestData.MerchantId);
            fileDetails.UserId.ShouldBe(TestData.UserId);
            fileDetails.FileProfileId.ShouldBe(TestData.FileProfileId);
            fileDetails.FileLocation.ShouldBe(TestData.FileLocation);
            fileDetails.FileLines.ShouldBeEmpty();
            fileDetails.ProcessingCompleted.ShouldBeFalse();
        }
        public void FileAggregate_AddFileLine_FileLineAdded()
        {
            FileAggregate fileAggregate = FileAggregate.Create(TestData.FileId);

            fileAggregate.CreateFile(TestData.FileImportLogId, TestData.EstateId, TestData.MerchantId, TestData.UserId,
                                     TestData.FileProfileId, TestData.FileLocation, TestData.FileUploadedDateTime);
            fileAggregate.AddFileLine(TestData.FileLine);

            FileDetails fileDetails = fileAggregate.GetFile();

            fileDetails.FileLines.ShouldNotBeNull();
            fileDetails.FileLines.ShouldNotBeEmpty();
            fileDetails.FileLines.ShouldHaveSingleItem();
            fileDetails.FileLines.Single().LineData.ShouldBe(TestData.FileLine);
            fileDetails.ProcessingCompleted.ShouldBeFalse();
            fileDetails.ProcessingSummary.ShouldNotBeNull();
            fileDetails.ProcessingSummary.TotalLines.ShouldBe(1);
            fileDetails.ProcessingSummary.NotProcessedLines.ShouldBe(1);
            fileDetails.ProcessingSummary.FailedLines.ShouldBe(0);
            fileDetails.ProcessingSummary.SuccessfullyProcessedLines.ShouldBe(0);
            fileDetails.ProcessingSummary.IgnoredLines.ShouldBe(0);
        }
 public void FileAggregate_CanBeCreated_InvalidFileId_IsCreated()
 {
     Should.Throw <ArgumentNullException>(() => { FileAggregate fileAggregate = FileAggregate.Create(Guid.Empty); });
 }
Пример #20
0
        /// <summary>
        /// Handles the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        /// <exception cref="System.NotSupportedException">File Id [{request.FileId}] has no lines added</exception>
        /// <exception cref="NotFoundException">
        /// File Line Number {request.LineNumber} not found in File Id {request.FileId}
        /// or
        /// No file profile found with Id {fileDetails.FileProfileId}
        /// or
        /// Merchant not found with Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}
        /// or
        /// No contracts found for Merchant Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}
        /// or
        /// No merchant contract for operator Id {fileProfile.OperatorName} found for Merchant Id {merchant.MerchantId}
        /// or
        /// No variable value product found on the merchant contract for operator Id {fileProfile.OperatorName} and Merchant Id {merchant.MerchantId}
        /// </exception>
        public async Task <Unit> Handle(ProcessTransactionForFileLineRequest request,
                                        CancellationToken cancellationToken)
        {
            // Get the file aggregate, this tells us the file profile information
            FileAggregate fileAggregate = await this.FileAggregateRepository.GetLatestVersion(request.FileId, cancellationToken);

            FileDetails fileDetails = fileAggregate.GetFile();

            if (fileDetails.FileLines.Any() == false)
            {
                throw new NotSupportedException($"File Id [{request.FileId}] has no lines added");
            }

            FileLine fileLine = fileDetails.FileLines.SingleOrDefault(f => f.LineNumber == request.LineNumber);

            if (fileLine == null)
            {
                throw new NotFoundException($"File Line Number {request.LineNumber} not found in File Id {request.FileId}");
            }

            if (fileLine.ProcessingResult != ProcessingResult.NotProcessed)
            {
                // Line already processed
                return(new Unit());
            }

            FileProfile fileProfile = await this.FileProcessorManager.GetFileProfile(fileDetails.FileProfileId, cancellationToken);

            if (fileProfile == null)
            {
                throw new NotFoundException($"No file profile found with Id {fileDetails.FileProfileId}");
            }

            // Determine if we need to actually process this file line
            if (this.FileLineCanBeIgnored(fileLine.LineData, fileProfile.FileFormatHandler))
            {
                // Write something to aggregate to say line was explicity ignored
                fileAggregate.RecordFileLineAsIgnored(fileLine.LineNumber);
                await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken);

                return(new Unit());
            }

            // need to now parse the line (based on the file format), this builds the metadata
            Dictionary <String, String> transactionMetadata = this.ParseFileLine(fileLine.LineData, fileProfile.FileFormatHandler);

            if (transactionMetadata == null)
            {
                // Line failed to parse so record this
                fileAggregate.RecordFileLineAsRejected(fileLine.LineNumber, "Invalid Format");
                await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken);

                return(new Unit());
            }

            // Add the file data to the request metadata
            transactionMetadata.Add("FileId", request.FileId.ToString());
            transactionMetadata.Add("FileLineNumber", fileLine.LineNumber.ToString());

            String operatorName = fileProfile.OperatorName;

            if (transactionMetadata.ContainsKey("OperatorName"))
            {
                // extract the value
                operatorName        = transactionMetadata["OperatorName"];
                transactionMetadata = transactionMetadata.Where(x => x.Key != "OperatorName").ToDictionary(x => x.Key, x => x.Value);
            }

            this.TokenResponse = await this.GetToken(cancellationToken);

            Interlocked.Increment(ref FileRequestHandler.TransactionNumber);

            // Get the merchant details
            MerchantResponse merchant = await this.EstateClient.GetMerchant(this.TokenResponse.AccessToken, fileDetails.EstateId, fileDetails.MerchantId, cancellationToken);

            if (merchant == null)
            {
                throw new NotFoundException($"Merchant not found with Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}");
            }
            List <ContractResponse> contracts = await this.EstateClient.GetMerchantContracts(this.TokenResponse.AccessToken, fileDetails.EstateId, fileDetails.MerchantId, cancellationToken);

            if (contracts.Any() == false)
            {
                throw new NotFoundException($"No contracts found for Merchant Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}");
            }

            ContractResponse?contract = null;

            if (fileProfile.OperatorName == "Voucher")
            {
                contract = contracts.SingleOrDefault(c => c.Description.Contains(operatorName));
            }
            else
            {
                contract = contracts.SingleOrDefault(c => c.OperatorName == operatorName);
            }


            if (contract == null)
            {
                throw new NotFoundException($"No merchant contract for operator Id {operatorName} found for Merchant Id {merchant.MerchantId}");
            }

            ContractProduct?product = contract.Products.SingleOrDefault(p => p.Value == null);  // TODO: Is this enough or should the name be used and stored in file profile??

            if (product == null)
            {
                throw new NotFoundException($"No variable value product found on the merchant contract for operator Id {fileProfile.OperatorName} and Merchant Id {merchant.MerchantId}");
            }

            // Build a transaction request message
            SaleTransactionRequest saleTransactionRequest = new SaleTransactionRequest
            {
                EstateId                      = fileDetails.EstateId,
                MerchantId                    = fileDetails.MerchantId,
                TransactionDateTime           = fileDetails.FileReceivedDateTime,
                TransactionNumber             = FileRequestHandler.TransactionNumber.ToString(),
                TransactionType               = "Sale",
                ContractId                    = contract.ContractId,
                DeviceIdentifier              = merchant.Devices.First().Value,
                OperatorIdentifier            = contract.OperatorName,
                ProductId                     = product.ProductId,
                AdditionalTransactionMetadata = transactionMetadata,
            };

            SerialisedMessage serialisedRequestMessage = new SerialisedMessage
            {
                Metadata = new Dictionary <String, String>
                {
                    { "estate_id", fileDetails.EstateId.ToString() },
                    { "merchant_id", fileDetails.MerchantId.ToString() }
                },
                SerialisedData = JsonConvert.SerializeObject(saleTransactionRequest, new JsonSerializerSettings
                {
                    TypeNameHandling = TypeNameHandling.All
                })
            };

            Logger.LogInformation(serialisedRequestMessage.SerialisedData);

            // Send request to transaction processor
            SerialisedMessage serialisedResponseMessage = await this.TransactionProcessorClient.PerformTransaction(this.TokenResponse.AccessToken, serialisedRequestMessage, cancellationToken);

            // Get the sale transaction response
            SaleTransactionResponse saleTransactionResponse = JsonConvert.DeserializeObject <SaleTransactionResponse>(serialisedResponseMessage.SerialisedData);

            if (saleTransactionResponse.ResponseCode == "0000")
            {
                // record response against file line in file aggregate
                fileAggregate.RecordFileLineAsSuccessful(request.LineNumber, saleTransactionResponse.TransactionId);
            }
            else
            {
                fileAggregate.RecordFileLineAsFailed(request.LineNumber, saleTransactionResponse.TransactionId, saleTransactionResponse.ResponseCode, saleTransactionResponse.ResponseMessage);
            }

            // Save changes to file aggregate
            // TODO: Add retry round this save (maybe 3 retries)
            await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken);

            return(new Unit());
        }
Пример #21
0
        private async Task <Unit> ProcessFile(Guid fileId,
                                              Guid fileProfileId,
                                              String fileName,
                                              CancellationToken cancellationToken)
        {
            IFileInfo   inProgressFile = null;
            FileProfile fileProfile    = null;

            try
            {
                fileProfile = await this.FileProcessorManager.GetFileProfile(fileProfileId, cancellationToken);

                if (fileProfile == null)
                {
                    throw new NotFoundException($"No file profile found with Id {fileProfileId}");
                }

                // Check the processed/failed directories exist
                if (this.FileSystem.Directory.Exists(fileProfile.ProcessedDirectory) == false)
                {
                    Logger.LogWarning($"Creating Directory {fileProfile.ProcessedDirectory} as not found");
                    this.FileSystem.Directory.CreateDirectory(fileProfile.ProcessedDirectory);
                }

                if (this.FileSystem.Directory.Exists(fileProfile.FailedDirectory) == false)
                {
                    Logger.LogWarning($"Creating Directory {fileProfile.FailedDirectory} as not found");
                    this.FileSystem.Directory.CreateDirectory(fileProfile.FailedDirectory);
                }

                inProgressFile = this.FileSystem.FileInfo.FromFileName(fileName);

                if (inProgressFile.Exists == false)
                {
                    throw new FileNotFoundException($"File {inProgressFile.FullName} not found");
                }

                FileAggregate fileAggregate =
                    await this.FileAggregateRepository.GetLatestVersion(fileId, cancellationToken);

                if (fileAggregate.IsCreated == false)
                {
                    throw new InvalidOperationException($"File with Id {fileId} not created");
                }

                String fileContent = null;
                //Open file for Read\Write
                using (Stream fs = inProgressFile.Open(FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read))
                {
                    //Create object of StreamReader by passing FileStream object on which it needs to operates on
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        //Use ReadToEnd method to read all the content from file
                        fileContent = await sr.ReadToEndAsync();
                    }
                }

                if (String.IsNullOrEmpty(fileContent) == false)
                {
                    String[] fileLines = fileContent.Split(fileProfile.LineTerminator);

                    foreach (String fileLine in fileLines)
                    {
                        fileAggregate.AddFileLine(fileLine);
                    }

                    await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken);
                }

                Logger.LogInformation(
                    $"About to move file {inProgressFile.Name} to [{fileProfile.ProcessedDirectory}]");

                // TODO: Move file now
                inProgressFile.MoveTo($"{fileProfile.ProcessedDirectory}/{inProgressFile.Name}");

                return(new Unit());
            }
            catch (Exception e)
            {
                if (inProgressFile != null && fileProfile != null)
                {
                    inProgressFile.MoveTo($"{fileProfile.FailedDirectory}/{inProgressFile.Name}");
                }

                Logger.LogError(e);
                throw;
            }
        }