public async Task CreateFileData_Always_CreatesFileData() { // Arrange CustomerFile customerFile = new CustomerFile("WEE", (ulong)12345); var customerFileGeneratorResult = new IbisFileGeneratorResult<CustomerFile>(customerFile, A.Dummy<List<Exception>>()); IIbisCustomerFileGenerator customerFileGenerator = A.Fake<IIbisCustomerFileGenerator>(); A.CallTo(() => customerFileGenerator.CreateAsync(A<ulong>._, A<InvoiceRun>._)) .Returns(customerFileGeneratorResult); TransactionFile transactionFile = new TransactionFile("WEE", (ulong)12345); var ibisFileGeneratorResult = new IbisFileGeneratorResult<TransactionFile>(transactionFile, A.Dummy<List<Exception>>()); IIbisTransactionFileGenerator transactionFileGenerator = A.Fake<IIbisTransactionFileGenerator>(); A.CallTo(() => transactionFileGenerator.CreateAsync(A<ulong>._, A<InvoiceRun>._)) .Returns(ibisFileGeneratorResult); IIbisFileDataErrorTranslator errorTranslator = A.Dummy<IIbisFileDataErrorTranslator>(); IbisFileDataGenerator generator = new IbisFileDataGenerator( customerFileGenerator, transactionFileGenerator, errorTranslator); // Act var result = await generator.CreateFileDataAsync(A.Dummy<ulong>(), A.Dummy<InvoiceRun>()); var ibistFileData = result.IbisFileData; // Assert Assert.NotNull(ibistFileData); Assert.False(string.IsNullOrEmpty(ibistFileData.CustomerFileData)); Assert.False(string.IsNullOrEmpty(ibistFileData.TransactionFileData)); }
public void Write_WithOneInvoiceAndTwoLineItems_GeneratesCorrectOutput() { // Arrange List<InvoiceLineItem> lineItems = new List<InvoiceLineItem>(); lineItems.Add(new InvoiceLineItem(100.00m, "Test item 1")); lineItems.Add(new InvoiceLineItem(123.45m, "Test item 2")); Invoice invoice = new Invoice( "WEE0001", new DateTime(2015, 1, 1), TransactionType.Invoice, "WEE741804H", lineItems); TransactionFile file = new TransactionFile("WEE", 0); file.AddInvoice(invoice); // Act string result = file.Write(); // Assert string expectedDate = DateTime.UtcNow.Date.ToString("dd-MMM-yyyy").ToUpperInvariant(); string expectedOutput = "\"H\",\"0000000\",\"WEE\",\"H\",\"I\",\"00000\",\"\",\"" + expectedDate + "\"" + Environment.NewLine + "\"D\",\"0000001\",\"WEE0001\",\"01-JAN-2015\",\"I\",\"WEE741804H\",\"\",\"GBP\",\"\",\"01-JAN-2015\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"," + "\"10000\",\"\",\"H\",\"Test item 1\",\"W\",\"H\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"1\",\"Each\",\"10000\"" + Environment.NewLine + "\"D\",\"0000002\",\"WEE0001\",\"01-JAN-2015\",\"I\",\"WEE741804H\",\"\",\"GBP\",\"\",\"01-JAN-2015\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"," + "\"12345\",\"\",\"H\",\"Test item 2\",\"W\",\"H\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"1\",\"Each\",\"12345\"" + Environment.NewLine + "\"T\",\"0000003\",\"0000004\",\"22345\",\"0\"" + Environment.NewLine; Assert.Equal(expectedOutput, result); }
public async Task CreateFileData_Always_CreatesFileData() { // Arrange CustomerFile customerFile = new CustomerFile("WEE", (ulong)12345); var customerFileGeneratorResult = new IbisFileGeneratorResult <CustomerFile>(customerFile, A.Dummy <List <Exception> >()); IIbisCustomerFileGenerator customerFileGenerator = A.Fake <IIbisCustomerFileGenerator>(); A.CallTo(() => customerFileGenerator.CreateAsync(A <ulong> ._, A <InvoiceRun> ._)) .Returns(customerFileGeneratorResult); TransactionFile transactionFile = new TransactionFile("WEE", (ulong)12345); var ibisFileGeneratorResult = new IbisFileGeneratorResult <TransactionFile>(transactionFile, A.Dummy <List <Exception> >()); IIbisTransactionFileGenerator transactionFileGenerator = A.Fake <IIbisTransactionFileGenerator>(); A.CallTo(() => transactionFileGenerator.CreateAsync(A <ulong> ._, A <InvoiceRun> ._)) .Returns(ibisFileGeneratorResult); IIbisFileDataErrorTranslator errorTranslator = A.Dummy <IIbisFileDataErrorTranslator>(); IbisFileDataGenerator generator = new IbisFileDataGenerator( customerFileGenerator, transactionFileGenerator, errorTranslator); // Act var result = await generator.CreateFileDataAsync(A.Dummy <ulong>(), A.Dummy <InvoiceRun>()); var ibistFileData = result.IbisFileData; // Assert Assert.NotNull(ibistFileData); Assert.False(string.IsNullOrEmpty(ibistFileData.CustomerFileData)); Assert.False(string.IsNullOrEmpty(ibistFileData.TransactionFileData)); }
public void Write_WithOneInvoiceAndTwoLineItems_GeneratesCorrectOutput() { // Arrange List <InvoiceLineItem> lineItems = new List <InvoiceLineItem>(); lineItems.Add(new InvoiceLineItem(100.00m, "Test item 1")); lineItems.Add(new InvoiceLineItem(123.45m, "Test item 2")); Invoice invoice = new Invoice( "WEE0001", new DateTime(2015, 1, 1), TransactionType.Invoice, "WEE741804H", lineItems); TransactionFile file = new TransactionFile("WEE", 0); file.AddInvoice(invoice); // Act string result = file.Write(); // Assert string expectedDate = DateTime.UtcNow.Date.ToString("dd-MMM-yyyy").ToUpperInvariant(); string expectedOutput = "\"H\",\"0000000\",\"WEE\",\"H\",\"I\",\"00000\",\"\",\"" + expectedDate + "\"" + Environment.NewLine + "\"D\",\"0000001\",\"WEE0001\",\"01-JAN-2015\",\"I\",\"WEE741804H\",\"\",\"GBP\",\"\",\"01-JAN-2015\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"," + "\"10000\",\"\",\"H\",\"Test item 1\",\"W\",\"H\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"1\",\"Each\",\"10000\"" + Environment.NewLine + "\"D\",\"0000002\",\"WEE0001\",\"01-JAN-2015\",\"I\",\"WEE741804H\",\"\",\"GBP\",\"\",\"01-JAN-2015\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"," + "\"12345\",\"\",\"H\",\"Test item 2\",\"W\",\"H\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"1\",\"Each\",\"12345\"" + Environment.NewLine + "\"T\",\"0000003\",\"0000004\",\"22345\",\"0\"" + Environment.NewLine; Assert.Equal(expectedOutput, result); }
public async Task <IActionResult> Edit(int id, [Bind("Id,Content,FileName,Note,Size,UploadDate")] TransactionFile transactionFile) { if (id != transactionFile.Id) { return(NotFound()); } if (ModelState.IsValid) { try { await _transactionFileService.Edit(_context, transactionFile); } catch (DbUpdateConcurrencyException) { if (!TransactionFileExists(transactionFile.Id)) { return(NotFound()); } else { throw; } } return(RedirectToAction(nameof(Index))); } return(View(transactionFile)); }
public async Task CreateFileData_WithFileID_CreatesFilesWithCorrectFileNames() { // Arrange ulong fileID = 123; CustomerFile customerFile = new CustomerFile("WEE", (ulong)12345); var customerFileGeneratorResult = new IbisFileGeneratorResult<CustomerFile>(customerFile, A.Dummy<List<Exception>>()); IIbisCustomerFileGenerator customerFileGenerator = A.Fake<IIbisCustomerFileGenerator>(); A.CallTo(() => customerFileGenerator.CreateAsync(A<ulong>._, A<InvoiceRun>._)) .Returns(customerFileGeneratorResult); TransactionFile transactionFile = new TransactionFile("WEE", (ulong)12345); var ibisFileGeneratorResult = new IbisFileGeneratorResult<TransactionFile>(transactionFile, A.Dummy<List<Exception>>()); IIbisTransactionFileGenerator transactionFileGenerator = A.Fake<IIbisTransactionFileGenerator>(); A.CallTo(() => transactionFileGenerator.CreateAsync(A<ulong>._, A<InvoiceRun>._)) .Returns(ibisFileGeneratorResult); IIbisFileDataErrorTranslator errorTranslator = A.Dummy<IIbisFileDataErrorTranslator>(); IbisFileDataGenerator generator = new IbisFileDataGenerator( customerFileGenerator, transactionFileGenerator, errorTranslator); // Act var result = await generator.CreateFileDataAsync(fileID, A.Dummy<InvoiceRun>()); var ibistFileData = result.IbisFileData; // Assert Assert.NotNull(ibistFileData); Assert.Equal("WEEHC00123.dat", ibistFileData.CustomerFileName); Assert.Equal("WEEHI00123.dat", ibistFileData.TransactionFileName); }
private void CleanUpTransactionFile() { TransactionFile transactionFile = new TransactionFile(); DirectoryBlock directoryBlock = transactionFile.Deserialize(); queue = new Queue <DirectoryBlock>(); queue.Enqueue(directoryBlock); Traverse(); }
public async Task <IActionResult> Create([Bind("Id,Content,FileName,Note,Size,UploadDate")] TransactionFile transactionFile) { if (ModelState.IsValid) { await _transactionFileService.Create(_context, transactionFile); return(RedirectToAction(nameof(Index))); } return(View(transactionFile)); }
public async Task CreateTransactionFile_ProducerSubmissionMarkedAsNotInvoiced_NotIncludedInTransactionFile() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), A.Dummy <decimal>(), complianceYear, scheme, A.Dummy <string>()); var producerSubmission = A.Fake <ProducerSubmission>(); A.CallTo(() => producerSubmission.ChargeThisUpdate) .Returns(123.45m); A.CallTo(() => producerSubmission.Invoiced) .Returns(false); memberUpload.ProducerSubmissions.Add(producerSubmission); memberUpload.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); ByChargeValueTransactionFileGenerator generator = new ByChargeValueTransactionFileGenerator( A.Dummy <ITransactionReferenceGenerator>()); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(0, transactionFile.Invoices.Count); }
public async Task CreateTransactionFile_WithFileID_CreatesFileWithCorrectFileID() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), 123.45m, complianceYear, scheme, A.Dummy <string>()); memberUpload.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); ITransactionReferenceGenerator transactionReferenceGenerator = A.Fake <ITransactionReferenceGenerator>(); A.CallTo(() => transactionReferenceGenerator.GetNextTransactionReferenceAsync()).Returns("WEE800001H"); ByChargeValueTransactionFileGenerator generator = new ByChargeValueTransactionFileGenerator(transactionReferenceGenerator); ulong id = 12345; // Act var result = await generator.CreateAsync(id, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.Equal((ulong)12345, transactionFile.FileID); }
private async Task <TransactionFile> SaveFileAsync(IFormFile file) { var uniqueFileName = GetUniqueFileName(file.FileName); var uploads = Path.Combine(_hostingEnvironment.ContentRootPath, "Uploads"); var filePath = Path.Combine(uploads, uniqueFileName); await file.CopyToAsync(new FileStream(filePath, FileMode.Create)); var transFile = new TransactionFile { FileName = uniqueFileName, UploadedDate = DateTime.UtcNow }; _dbcontext.TransactionFile.Add(transFile); await _dbcontext.SaveChangesAsync(); return(transFile); }
public MigrationResult MigrateToOstor(DirectoryBlock directoryBlock) { MigrationResult result = new MigrationResult(); while (System.IO.File.Exists(TransactionFilePath)) { TransactionFile logFile = new TransactionFile(); DirectoryBlock toDownloadBlock = logFile.Deserialize(); DownloadCloudDirectory downloadDirectory = new DownloadCloudDirectory(toDownloadBlock, "C:\\CloudFiles\\", cloudService); downloadDirectory.DownloadAsync(); CleanUpTransactionFile(); if (DownloadCompleteStatus == true) { System.IO.File.Delete(TransactionFilePath); } } return(result); }
public async Task CreateFileData_WithErrorGeneratingIbisFile_TranslatesError_AndReturnNoIbisFileData() { // Arrange ulong fileID = 123; var customerFile = new CustomerFile("WEE", fileID); var customerFileGeneratorResult = new IbisFileGeneratorResult <CustomerFile>(customerFile, A.Dummy <List <Exception> >()); var customerFileGenerator = A.Fake <IIbisCustomerFileGenerator>(); A.CallTo(() => customerFileGenerator.CreateAsync(A <ulong> ._, A <InvoiceRun> ._)) .Returns(customerFileGeneratorResult); var transactionFile = new TransactionFile("WEE", (ulong)12345); var error = new Exception(); var transactionFileGeneratorResult = new IbisFileGeneratorResult <TransactionFile>(transactionFile, new List <Exception> { error }); var transactionFileGenerator = A.Fake <IIbisTransactionFileGenerator>(); A.CallTo(() => transactionFileGenerator.CreateAsync(A <ulong> ._, A <InvoiceRun> ._)) .Returns(transactionFileGeneratorResult); var errorTranslator = A.Fake <IIbisFileDataErrorTranslator>(); A.CallTo(() => errorTranslator.MakeFriendlyErrorMessages(A <List <Exception> > ._)) .Returns(new List <string> { "error" }); IbisFileDataGenerator generator = new IbisFileDataGenerator( customerFileGenerator, transactionFileGenerator, errorTranslator); // Act var result = await generator.CreateFileDataAsync(fileID, A.Dummy <InvoiceRun>()); // Assert Assert.NotEmpty(result.Errors); Assert.Null(result.IbisFileData); }
private void DownloadFiles(List <FileBlock> files) { List <Task> downloadFilesTask = new List <Task>(); foreach (var file in files) { if (file.DownloadStatus == false) { downloadFilesTask.Add(Task.Run(() => { cloudService.DownloadCloudFile(file, toDownloadDirectoryPath); file.DownloadStatus = true; TransactionFile transactionFile = new TransactionFile(); transactionFile.Create(directory); })); } } Task.WaitAll(downloadFilesTask.ToArray()); }
private void DownloadDirectory(List <DirectoryBlock> subDirectories) { List <Task> downloadDirectoriesTask = new List <Task>(); foreach (var subDirectory in subDirectories) { if (subDirectory.DownloadStatus == false) { downloadDirectoriesTask.Add(Task.Run(() => { System.IO.Directory.CreateDirectory(toDownloadDirectoryPath + subDirectory.path); subDirectory.DownloadStatus = true; queue.Enqueue(subDirectory); TransactionFile transactionFile = new TransactionFile(); transactionFile.Create(directory); })); } } Task.WaitAll(downloadDirectoriesTask.ToArray()); }
public async Task <IbisFileGeneratorResult <TransactionFile> > CreateAsync(ulong fileID, InvoiceRun invoiceRun) { TransactionFile transactionFile = new TransactionFile("WEE", fileID); var errors = new List <Exception>(); foreach (MemberUpload memberUpload in invoiceRun.MemberUploads) { DateTime submittedDate = memberUpload.SubmittedDate.Value; string description = string.Format("Charge for producer registration submission made on {0:dd MMM yyyy}.", submittedDate); try { InvoiceLineItem lineItem = new InvoiceLineItem( memberUpload.TotalCharges, description); string transactionReference = await transactionReferenceGenerator.GetNextTransactionReferenceAsync(); Invoice invoice = new Invoice( memberUpload.Scheme.IbisCustomerReference, invoiceRun.IssuedDate, TransactionType.Invoice, transactionReference, new List <InvoiceLineItem>() { lineItem }); transactionFile.AddInvoice(invoice); } catch (Exception ex) { errors.Add(ex); } } return(new IbisFileGeneratorResult <TransactionFile>(errors.Count == 0 ? transactionFile : null, errors)); }
/// <summary> /// Creates the data representing 1B1S customer and transaction files for the specified list /// of member uploads. /// </summary> /// <param name="fileID">The ID that the 1B1S files will use. This must be unique for every pair of 1B1S files /// and must be in the range of 0 to 99999. To avoid clashes with IDs used by the incumbent system, a seed /// value may need to be used.</param> /// <param name="invoiceRun">The invoice run specifying the list of member uploads to be included.</param> /// <returns>Returns an <see cref="IbisFileDataGeneratorResult"/> which provides the data and file names of the /// generated 1B1S customer and transaction files or a list of error which occurred during the process.</returns> public async Task <IbisFileDataGeneratorResult> CreateFileDataAsync(ulong fileID, InvoiceRun invoiceRun) { var customerFileGeneratorResult = await ibisCustomerFileGenerator.CreateAsync(fileID, invoiceRun); var ibisTransactionFileGeneratorResult = await ibisTransactionFileGenerator.CreateAsync(fileID, invoiceRun); IbisFileData ibisFileData = null; var errors = new List <string>(); if (customerFileGeneratorResult.Errors.Count == 0 && ibisTransactionFileGeneratorResult.Errors.Count == 0) { CustomerFile customerFile = customerFileGeneratorResult.IbisFile; TransactionFile transactionFile = ibisTransactionFileGeneratorResult.IbisFile; string customerFileName = string.Format("WEEHC{0:D5}.dat", fileID); string transactionFileName = string.Format("WEEHI{0:D5}.dat", fileID); string customerFileData = customerFile.Write(); string transactionFileData = transactionFile.Write(); ibisFileData = new IbisFileData( fileID, customerFileName, customerFileData, transactionFileName, transactionFileData); } else { errors = ibisFileDataErrorTranslator .MakeFriendlyErrorMessages(customerFileGeneratorResult .Errors .Union(ibisTransactionFileGeneratorResult.Errors) .ToList()); } return(new IbisFileDataGeneratorResult(ibisFileData, errors)); }
public async Task CreateFileData_WithFileID_CreatesFilesWithCorrectFileNames() { // Arrange ulong fileID = 123; CustomerFile customerFile = new CustomerFile("WEE", (ulong)12345); var customerFileGeneratorResult = new IbisFileGeneratorResult <CustomerFile>(customerFile, A.Dummy <List <Exception> >()); IIbisCustomerFileGenerator customerFileGenerator = A.Fake <IIbisCustomerFileGenerator>(); A.CallTo(() => customerFileGenerator.CreateAsync(A <ulong> ._, A <InvoiceRun> ._)) .Returns(customerFileGeneratorResult); TransactionFile transactionFile = new TransactionFile("WEE", (ulong)12345); var ibisFileGeneratorResult = new IbisFileGeneratorResult <TransactionFile>(transactionFile, A.Dummy <List <Exception> >()); IIbisTransactionFileGenerator transactionFileGenerator = A.Fake <IIbisTransactionFileGenerator>(); A.CallTo(() => transactionFileGenerator.CreateAsync(A <ulong> ._, A <InvoiceRun> ._)) .Returns(ibisFileGeneratorResult); IIbisFileDataErrorTranslator errorTranslator = A.Dummy <IIbisFileDataErrorTranslator>(); IbisFileDataGenerator generator = new IbisFileDataGenerator( customerFileGenerator, transactionFileGenerator, errorTranslator); // Act var result = await generator.CreateFileDataAsync(fileID, A.Dummy <InvoiceRun>()); var ibistFileData = result.IbisFileData; // Assert Assert.NotNull(ibistFileData); Assert.Equal("WEEHC00123.dat", ibistFileData.CustomerFileName); Assert.Equal("WEEHI00123.dat", ibistFileData.TransactionFileName); }
public async Task <IActionResult> UploadFile(IFormFile file) { if (file == null) { return(BadRequest("File required")); } var ext = Path.GetExtension(file.FileName).ToLower(); if (!(ext == ".csv" || ext == ".xml")) { return(BadRequest("Unknown format")); } if (file.Length > (MAX_FILE_SIZE)) { return(BadRequest($"Invalid File Size (Maximum: {MAX_FILE_SIZE / (1024 * 1024)} MB)")); } // Save file into Uploads folder var transFile = new TransactionFile(); string errormsg = ""; try { //throw new Exception(); transFile = await SaveFileAsync(file); Strategy strategy; if (ext == ".csv") { strategy = new CsvExtractor(); } else { strategy = new XmlExtractor(); } var entityExtractor = new TransactionExtractor(strategy); var entities = entityExtractor.ExtractTransaction(file); if (entities.Where(x => !string.IsNullOrWhiteSpace(x.Errors)).Count() == 0) { // Clean records, add to transaction var cleanEntities = entities.Select(x => new TransactionEntity { TransactionId = x.TransactionId, Amount = x.ValidAmount.Value, CurrencyCode = x.CurrencyCode, DateTime = x.ValidTransactionDate.Value.UtcDateTime, Status = x.ValidStatus }); _dbcontext.TransactionEntity.AddRange(cleanEntities); } else { // Dirty records, add to error log var errors = entities.Select(x => new TransactionErrorLog { TransactionId = x.TransactionId, Amount = x.Amount, CurrencyCode = x.CurrencyCode, DateTime = x.TransactionDate, Status = x.Status, Error = x.Errors, FileId = transFile.Id }); _dbcontext.TransactionErrorLog.AddRange(errors); errormsg = "Some records in uploaded file is not valid, please check error log for details."; } await _dbcontext.SaveChangesAsync(); if (string.IsNullOrWhiteSpace(errormsg)) { return(Ok("Success")); } else { return(BadRequest(errormsg)); } } catch (Exception ex) { _logger.LogError(ex, ex.Message); if (System.IO.File.Exists(Path.Combine(_hostingEnvironment.ContentRootPath, "Uploads", transFile.FileName ?? ""))) { GC.Collect(); GC.WaitForPendingFinalizers(); System.IO.File.Delete(Path.Combine(_hostingEnvironment.ContentRootPath, "Uploads", transFile.FileName ?? "")); } // TODO: If db exception in here if (transFile.Id != 0) { _dbcontext.TransactionFile.Remove(transFile); await _dbcontext.SaveChangesAsync(); } return(new StatusCodeResult(500)); } }
public async Task CreateFileData_WithErrorGeneratingCustomerFile_TranslatesError() { // Arrange ulong fileID = 123; var customerFile = new CustomerFile("WEE", fileID); var error = new Exception(); var customerFileGeneratorResult = new IbisFileGeneratorResult<CustomerFile>(customerFile, new List<Exception> { error }); var customerFileGenerator = A.Fake<IIbisCustomerFileGenerator>(); A.CallTo(() => customerFileGenerator.CreateAsync(A<ulong>._, A<InvoiceRun>._)) .Returns(customerFileGeneratorResult); var transactionFile = new TransactionFile("WEE", (ulong)12345); var transactionFileGeneratorResult = new IbisFileGeneratorResult<TransactionFile>(transactionFile, A.Dummy<List<Exception>>()); var transactionFileGenerator = A.Fake<IIbisTransactionFileGenerator>(); A.CallTo(() => transactionFileGenerator.CreateAsync(A<ulong>._, A<InvoiceRun>._)) .Returns(transactionFileGeneratorResult); var errorTranslator = A.Fake<IIbisFileDataErrorTranslator>(); IbisFileDataGenerator generator = new IbisFileDataGenerator( customerFileGenerator, transactionFileGenerator, errorTranslator); // Act await generator.CreateFileDataAsync(fileID, A.Dummy<InvoiceRun>()); // Assert A.CallTo(() => errorTranslator.MakeFriendlyErrorMessages(A<List<Exception>>._)) .MustHaveHappened(); }
public async Task CreateTransactionFile_WithTwoMemberUploads_CreatesTwoInvoices() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload1 = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), 100, complianceYear, scheme, A.Dummy <string>(), A.Dummy <string>(), false); memberUpload1.Submit(A.Dummy <User>()); MemberUpload memberUpload2 = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), 200, complianceYear, scheme, A.Dummy <string>(), A.Dummy <string>(), false); memberUpload2.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload1); memberUploads.Add(memberUpload2); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); ITransactionReferenceGenerator transactionReferenceGenerator = A.Fake <ITransactionReferenceGenerator>(); A.CallTo(() => transactionReferenceGenerator.GetNextTransactionReferenceAsync()).Returns("WEE800001H"); BySubmissionTransactionFileGenerator generator = new BySubmissionTransactionFileGenerator(transactionReferenceGenerator); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(2, transactionFile.Invoices.Count); Invoice invoice1 = transactionFile.Invoices[0]; Assert.NotNull(invoice1); Assert.Equal(100m, invoice1.TransactionTotal); Invoice invoice2 = transactionFile.Invoices[1]; Assert.NotNull(invoice2); Assert.Equal(200m, invoice2.TransactionTotal); }
public async Task <IActionResult> Upload(UploadViewModel viewModel) { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 1)."); // Log error return(BadRequest(ModelState)); } IFormFile file = Request.Form.Files[0]; string fileName = file.FileName; byte[] streamedFileContent = new byte[0]; streamedFileContent = await FileHelper.ProcessStreamedFile(file, ModelState, _permittedExtensions, _fileSizeLimit); if (streamedFileContent.Length == 0) { return(BadRequest(ModelState)); } if (ModelState.IsValid) { List <TransactionImport> imports = new List <TransactionImport>(); FileStatus fileStatus = _transactionFileService.Upload(file, imports); var transactionFile = new TransactionFile() { Content = streamedFileContent, FileName = fileName, Note = viewModel.Note, Size = streamedFileContent.Length, UploadDate = DateTimeOffset.UtcNow, FileStatus = fileStatus }; await _transactionFileService.Create(_context, transactionFile); imports = imports.OrderBy(x => x.Id).Select(x => { x.TransactionFileId = transactionFile.Id; return(x); }).ToList(); try { _context.TransactionImport.AddRange(imports); await _context.SaveChangesAsync(); } catch (Exception e) { } if (fileStatus == FileStatus.Success) { List <Transaction> transactions = new List <Transaction>(); transactions = imports.Where(x => x.ImportStatus == ImportStatus.Success).Select(x => new Transaction { TransactionIdentificator = x.TransactionId, Amount = (decimal)x.Amount, CurrencyCode = x.CurrencyCode, TransactionDate = (DateTimeOffset)x.TransactionDate, Status = x.Status, TransactionImportId = x.Id, }).ToList(); try { foreach (Transaction transaction in transactions) { await _transactionService.Create(_context, transaction); } } catch (Exception e) { } } } return(Created(nameof(TransactionFileController), null)); }
public async Task CreateTransactionFile_WithTwoMemberUploadsForDifferentSchemes_CreatesFileWithTwoInvoices() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); int complianceYear = A.Dummy <int>(); Organisation organisation1 = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme1 = new Scheme(organisation1); scheme1.UpdateScheme( "Test scheme 1", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); MemberUpload memberUpload1 = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), 100, complianceYear, scheme1, A.Dummy <string>(), A.Dummy <string>(), false); memberUpload1.Submit(A.Dummy <User>()); Organisation organisation2 = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme2 = new Scheme(organisation2); scheme2.UpdateScheme( "Test scheme 2", "WEE/BB2222BB/SCH", "WEE00000002", A.Dummy <ObligationType>(), authority); MemberUpload memberUpload2 = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), 200, complianceYear, scheme2, A.Dummy <string>(), A.Dummy <string>(), false); memberUpload2.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload1); memberUploads.Add(memberUpload2); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); A.CallTo(() => transactionReferenceGenerator.GetNextTransactionReferenceAsync()).Returns("WEE800001H"); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(2, transactionFile.Invoices.Count); Invoice invoice1 = transactionFile.Invoices[0]; Assert.NotNull(invoice1); Assert.Equal(100, invoice1.TransactionTotal); Assert.NotNull(invoice1.LineItems); Assert.Equal(1, invoice1.LineItems.Count); InvoiceLineItem lineItem1 = invoice1.LineItems[0]; Assert.NotNull(lineItem1); Assert.Equal(100, lineItem1.AmountExcludingVAT); Invoice invoice2 = transactionFile.Invoices[1]; Assert.NotNull(invoice2); Assert.Equal(200, invoice2.TransactionTotal); Assert.NotNull(invoice2.LineItems); Assert.Equal(1, invoice2.LineItems.Count); InvoiceLineItem lineItem2 = invoice2.LineItems[0]; Assert.NotNull(lineItem2); Assert.Equal(200, lineItem2.AmountExcludingVAT); }
public async Task CreateTransactionFile_WithOneMemberUpload_CreatesFileWithOneInvoiceWithOneLineItemWithCorrectDetails() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), 123.45m, complianceYear, scheme, A.Dummy <string>(), A.Dummy <string>(), false); SystemTime.Freeze(new DateTime(2015, 1, 1)); memberUpload.Submit(A.Dummy <User>()); SystemTime.Unfreeze(); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload); SystemTime.Freeze(new DateTime(2015, 12, 31)); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); SystemTime.Unfreeze(); A.CallTo(() => transactionReferenceGenerator.GetNextTransactionReferenceAsync()).Returns("WEE800001H"); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(1, transactionFile.Invoices.Count); Invoice invoice = transactionFile.Invoices[0]; Assert.NotNull(invoice); Assert.Equal(TransactionType.Invoice, invoice.TransactionType); Assert.Equal("WEE800001H", invoice.TransactionReference); Assert.Equal(123.45m, invoice.TransactionTotal); Assert.Equal(null, invoice.TransactionHeaderNarrative); Assert.Equal(new DateTime(2015, 12, 31), invoice.TransactionDate); Assert.Equal(null, invoice.RelatedTransactionReference); Assert.Equal(CurrencyCode.GBP, invoice.CurrencyCode); Assert.Equal("WEE00000001", invoice.CustomerReference); Assert.NotNull(invoice.LineItems); Assert.Equal(1, invoice.LineItems.Count); InvoiceLineItem lineItem = invoice.LineItems[0]; Assert.NotNull(lineItem); Assert.Equal(123.45m, lineItem.AmountExcludingVAT); Assert.Equal("Charge for producer registration submission made on 01 Jan 2015.", lineItem.Description); Assert.Equal("H", lineItem.AreaCode); Assert.Equal("H", lineItem.ContextCode); Assert.Equal("W", lineItem.IncomeStreamCode); Assert.Equal((ulong)1, lineItem.Quantity); Assert.Equal(UnitOfMeasure.Each, lineItem.UnitOfMeasure); Assert.Equal(null, lineItem.VatCode); }
public async Task <IbisFileGeneratorResult <TransactionFile> > CreateAsync(ulong fileID, InvoiceRun invoiceRun) { TransactionFile transactionFile = new TransactionFile("WEE", fileID); var errors = new List <Exception>(); var groups = invoiceRun.MemberUploads.GroupBy(mu => mu.Scheme); foreach (var group in groups) { List <InvoiceLineItem> lineItems = new List <InvoiceLineItem>(); var lineItemErrors = new List <Exception>(); foreach (MemberUpload memberUpload in group) { var submittedDate = memberUpload.SubmittedDate.Value; var competantAuthorityAnnualChargeAmount = memberUpload.Scheme.CompetentAuthority.AnnualChargeAmount; var description = string.Format("{0}.", CommonMessage(submittedDate)); if (memberUpload.HasAnnualCharge && competantAuthorityAnnualChargeAmount > 0) { description = string.Format("{0} and the {1} annual charge.", CommonMessage(submittedDate), competantAuthorityAnnualChargeAmount.Value.ToString("#,##0.00")); } try { InvoiceLineItem lineItem = new InvoiceLineItem( memberUpload.TotalCharges, description); lineItems.Add(lineItem); } catch (Exception ex) { lineItemErrors.Add(new SchemeFieldException(group.Key, ex)); } } errors.AddRange(lineItemErrors); string transactionReference = await transactionReferenceGenerator.GetNextTransactionReferenceAsync(); if (lineItemErrors.Count == 0) { try { Invoice invoice = new Invoice( group.Key.IbisCustomerReference, invoiceRun.IssuedDate, TransactionType.Invoice, transactionReference, lineItems); transactionFile.AddInvoice(invoice); } catch (Exception ex) { errors.Add(new SchemeFieldException(group.Key, ex)); } } } return(new IbisFileGeneratorResult <TransactionFile>(errors.Count == 0 ? transactionFile : null, errors)); }
public async Task <IbisFileGeneratorResult <TransactionFile> > CreateAsync(ulong fileID, InvoiceRun invoiceRun) { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB"); var errors = new List <Exception>(); TransactionFile transactionFile = new TransactionFile("WEE", fileID); foreach (MemberUpload memberUpload in invoiceRun.MemberUploads) { List <InvoiceLineItem> lineItems = new List <InvoiceLineItem>(); var lineItemGroups = memberUpload.ProducerSubmissions .Where(ps => ps.ChargeThisUpdate != 0) .Where(ps => ps.Invoiced) .GroupBy(ps => ps.ChargeThisUpdate) .OrderBy(g => g.Key) .Select(g => new { Charge = g.Key, Quantity = g.Count() }) .ToList(); if (lineItemGroups.Count > 0) { var lineItemErrors = new List <Exception>(); foreach (var lineItemGroup in lineItemGroups) { decimal amount = lineItemGroup.Charge * lineItemGroup.Quantity; string description = string.Format("{0} producer registration charge{1} at {2:C}.", lineItemGroup.Quantity, lineItemGroup.Quantity != 1 ? "s" : string.Empty, lineItemGroup.Charge); InvoiceLineItem lineItem; try { lineItem = new InvoiceLineItem( amount, description); lineItems.Add(lineItem); } catch (Exception ex) { lineItemErrors.Add(ex); } } errors.AddRange(lineItemErrors); if (lineItemErrors.Count == 0) { string transactionReference = await transactionReferenceGenerator.GetNextTransactionReferenceAsync(); try { Invoice invoice = new Invoice( memberUpload.Scheme.IbisCustomerReference, invoiceRun.IssuedDate, TransactionType.Invoice, transactionReference, lineItems); transactionFile.AddInvoice(invoice); } catch (Exception ex) { errors.Add(ex); } } } } return(new IbisFileGeneratorResult <TransactionFile>(errors.Count == 0 ? transactionFile : null, errors)); }
public async Task CreateTransactionFile_ProducerSubmissionWithNoCharge_NotIncludedInTransactionFile() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), A.Dummy <decimal>(), complianceYear, scheme, A.Dummy <string>()); RegisteredProducer registeredProducer = new RegisteredProducer("WEE/11AAAA11", complianceYear, scheme); ProducerSubmission producerSubmission = new ProducerSubmission( registeredProducer, memberUpload, A.Dummy <ProducerBusiness>(), A.Dummy <AuthorisedRepresentative>(), A.Dummy <DateTime>(), A.Dummy <decimal>(), A.Dummy <bool>(), A.Dummy <DateTime?>(), A.Dummy <string>(), A.Dummy <EEEPlacedOnMarketBandType>(), A.Dummy <SellingTechniqueType>(), A.Dummy <ObligationType>(), A.Dummy <AnnualTurnOverBandType>(), A.Dummy <List <BrandName> >(), A.Dummy <List <SICCode> >(), A.Dummy <Domain.Lookup.ChargeBandAmount>(), 0, A.Dummy <StatusType>()); memberUpload.ProducerSubmissions.Add(producerSubmission); memberUpload.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); ByChargeValueTransactionFileGenerator generator = new ByChargeValueTransactionFileGenerator( A.Dummy <ITransactionReferenceGenerator>()); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(0, transactionFile.Invoices.Count); }
public async Task CreateTransactionFile_WithTwoMemberUploads_CreatesTwoInvoices() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload1 = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), A.Dummy <decimal>(), complianceYear, scheme, A.Dummy <string>(), A.Dummy <string>(), false); RegisteredProducer registeredProducer1 = new RegisteredProducer("WEE/11AAAA11", complianceYear, scheme); ProducerSubmission producerSubmission1 = new ProducerSubmission( registeredProducer1, memberUpload1, A.Dummy <ProducerBusiness>(), A.Dummy <AuthorisedRepresentative>(), A.Dummy <DateTime>(), A.Dummy <decimal>(), A.Dummy <bool>(), A.Dummy <DateTime?>(), A.Dummy <string>(), A.Dummy <EEEPlacedOnMarketBandType>(), A.Dummy <SellingTechniqueType>(), A.Dummy <ObligationType>(), A.Dummy <AnnualTurnOverBandType>(), A.Dummy <List <BrandName> >(), A.Dummy <List <SICCode> >(), A.Dummy <Domain.Lookup.ChargeBandAmount>(), 100m, A.Dummy <StatusType>()); memberUpload1.ProducerSubmissions.Add(producerSubmission1); memberUpload1.Submit(A.Dummy <User>()); MemberUpload memberUpload2 = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), A.Dummy <decimal>(), complianceYear, scheme, A.Dummy <string>(), A.Dummy <string>(), false); RegisteredProducer registeredProducer2 = new RegisteredProducer("WEE/22BBBB22", complianceYear, scheme); ProducerSubmission producerSubmission2 = new ProducerSubmission( registeredProducer2, memberUpload2, A.Dummy <ProducerBusiness>(), A.Dummy <AuthorisedRepresentative>(), A.Dummy <DateTime>(), A.Dummy <decimal>(), A.Dummy <bool>(), A.Dummy <DateTime?>(), A.Dummy <string>(), A.Dummy <EEEPlacedOnMarketBandType>(), A.Dummy <SellingTechniqueType>(), A.Dummy <ObligationType>(), A.Dummy <AnnualTurnOverBandType>(), A.Dummy <List <BrandName> >(), A.Dummy <List <SICCode> >(), A.Dummy <Domain.Lookup.ChargeBandAmount>(), 100m, A.Dummy <StatusType>()); memberUpload2.ProducerSubmissions.Add(producerSubmission2); memberUpload2.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload1); memberUploads.Add(memberUpload2); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); ITransactionReferenceGenerator transactionReferenceGenerator = A.Fake <ITransactionReferenceGenerator>(); A.CallTo(() => transactionReferenceGenerator.GetNextTransactionReferenceAsync()).Returns("WEE800001H"); ByChargeValueTransactionFileGenerator generator = new ByChargeValueTransactionFileGenerator(transactionReferenceGenerator); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(2, transactionFile.Invoices.Count); Invoice invoice1 = transactionFile.Invoices[0]; Assert.NotNull(invoice1); Assert.Equal(100m, invoice1.TransactionTotal); Invoice invoice2 = transactionFile.Invoices[1]; Assert.NotNull(invoice2); Assert.Equal(100m, invoice2.TransactionTotal); }
public async Task CreateTransactionFile_WithOneProducerSubmission_CreatesOneInvoiceWithOneLineItem() { // Arrange UKCompetentAuthority authority = A.Dummy <UKCompetentAuthority>(); Organisation organisation = Organisation.CreateSoleTrader("Test organisation"); Scheme scheme = new Scheme(organisation); scheme.UpdateScheme( "Test scheme", "WEE/AA1111AA/SCH", "WEE00000001", A.Dummy <ObligationType>(), authority); int complianceYear = A.Dummy <int>(); MemberUpload memberUpload = new MemberUpload( A.Dummy <Guid>(), A.Dummy <string>(), A.Dummy <List <MemberUploadError> >(), A.Dummy <decimal>(), complianceYear, scheme, A.Dummy <string>()); RegisteredProducer registeredProducer = new RegisteredProducer("WEE/11AAAA11", complianceYear, scheme); ProducerSubmission producerSubmission = new ProducerSubmission( registeredProducer, memberUpload, A.Dummy <ProducerBusiness>(), A.Dummy <AuthorisedRepresentative>(), A.Dummy <DateTime>(), A.Dummy <decimal>(), A.Dummy <bool>(), A.Dummy <DateTime?>(), A.Dummy <string>(), A.Dummy <EEEPlacedOnMarketBandType>(), A.Dummy <SellingTechniqueType>(), A.Dummy <ObligationType>(), A.Dummy <AnnualTurnOverBandType>(), A.Dummy <List <BrandName> >(), A.Dummy <List <SICCode> >(), A.Dummy <Domain.Lookup.ChargeBandAmount>(), 123.45m, A.Dummy <StatusType>()); memberUpload.ProducerSubmissions.Add(producerSubmission); memberUpload.Submit(A.Dummy <User>()); List <MemberUpload> memberUploads = new List <MemberUpload>(); memberUploads.Add(memberUpload); SystemTime.Freeze(new DateTime(2015, 12, 31)); InvoiceRun invoiceRun = new InvoiceRun(authority, memberUploads, A.Dummy <User>()); SystemTime.Unfreeze(); ITransactionReferenceGenerator transactionReferenceGenerator = A.Fake <ITransactionReferenceGenerator>(); A.CallTo(() => transactionReferenceGenerator.GetNextTransactionReferenceAsync()).Returns("WEE800001H"); ByChargeValueTransactionFileGenerator generator = new ByChargeValueTransactionFileGenerator(transactionReferenceGenerator); // Act var result = await generator.CreateAsync(0, invoiceRun); TransactionFile transactionFile = result.IbisFile; // Assert Assert.NotNull(transactionFile); Assert.Equal(1, transactionFile.Invoices.Count); Invoice invoice = transactionFile.Invoices[0]; Assert.NotNull(invoice); Assert.Equal(TransactionType.Invoice, invoice.TransactionType); Assert.Equal("WEE800001H", invoice.TransactionReference); Assert.Equal(123.45m, invoice.TransactionTotal); Assert.Equal(null, invoice.TransactionHeaderNarrative); Assert.Equal(new DateTime(2015, 12, 31), invoice.TransactionDate); Assert.Equal(null, invoice.RelatedTransactionReference); Assert.Equal(CurrencyCode.GBP, invoice.CurrencyCode); Assert.Equal("WEE00000001", invoice.CustomerReference); Assert.NotNull(invoice.LineItems); Assert.Equal(1, invoice.LineItems.Count); InvoiceLineItem lineItem = invoice.LineItems[0]; Assert.NotNull(lineItem); Assert.Equal(123.45m, lineItem.AmountExcludingVAT); Assert.Equal("1 producer registration charge at £123.45.", lineItem.Description); Assert.Equal("H", lineItem.AreaCode); Assert.Equal("H", lineItem.ContextCode); Assert.Equal("W", lineItem.IncomeStreamCode); Assert.Equal((ulong)1, lineItem.Quantity); Assert.Equal(UnitOfMeasure.Each, lineItem.UnitOfMeasure); Assert.Equal(null, lineItem.VatCode); }