From 6ffad126b16f2be169d89687863e3fa6687ca393 Mon Sep 17 00:00:00 2001 From: SvenvanMuiden Date: Fri, 7 Feb 2025 16:18:32 +0100 Subject: [PATCH] csv file report testen --- .../Controllers/MonthlyReportController.cs | 78 ++++----- CargoHub/Services/MontlyReportService.cs | 144 ++++++++--------- UnitTest/CSVfileTest.cs | 152 ++++++++++++++++++ 3 files changed, 262 insertions(+), 112 deletions(-) create mode 100644 UnitTest/CSVfileTest.cs diff --git a/CargoHub/Controllers/MonthlyReportController.cs b/CargoHub/Controllers/MonthlyReportController.cs index 890926c..1b7b2aa 100644 --- a/CargoHub/Controllers/MonthlyReportController.cs +++ b/CargoHub/Controllers/MonthlyReportController.cs @@ -1,45 +1,45 @@ -// using Microsoft.AspNetCore.Mvc; -// using System.IO; -// using System.Text; -// using System.Threading.Tasks; -// using CargoHub.Services; +using Microsoft.AspNetCore.Mvc; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using CargoHub.Services; -// namespace CargoHub.Controllers -// { -// [Route("api/v2/reports")] -// [ApiController] -// [AuthorizationFilter] -// public class ReportsController : ControllerBase -// { -// private readonly ReportService _reportService; +namespace CargoHub.Controllers +{ + [Route("api/v2/reports")] + [ApiController] + [AuthorizationFilter] + public class ReportsController : ControllerBase + { + private readonly ReportService _reportService; -// public ReportsController(ReportService reportService) -// { -// _reportService = reportService; -// } + public ReportsController(ReportService reportService) + { + _reportService = reportService; + } -// [HttpGet("monthly-report")] -// public async Task GenerateMonthlyReport(int year, int month) -// { -// if (year <= 0 || month <= 0 || month > 12) -// { -// return BadRequest(new { message = "Invalid year or month. Please provide valid values." }); -// } + [HttpGet("monthly-report")] + public async Task GenerateMonthlyReport(int year, int month) + { + if (year <= 0 || month <= 0 || month > 12) + { + return BadRequest(new { message = "Invalid year or month. Please provide valid values." }); + } -// // Generate the report and get the CSV content -// string csvContent = await _reportService.GenerateMonthlyCsvReport(year, month); + // Generate the report and get the CSV content + string csvContent = await _reportService.GenerateMonthlyCsvReport(year, month); -// if (!string.IsNullOrEmpty(csvContent)) -// { -// byte[] csvBytes = Encoding.UTF8.GetBytes(csvContent); -// string fileName = $"MonthlyReport_{year}_{month:D2}.csv"; + if (!string.IsNullOrEmpty(csvContent)) + { + byte[] csvBytes = Encoding.UTF8.GetBytes(csvContent); + string fileName = $"MonthlyReport_{year}_{month:D2}.csv"; -// return File(csvBytes, "text/csv", fileName); -// } -// else -// { -// return NotFound(new { message = "No data available for the specified month and year." }); -// } -// } -// } -// } \ No newline at end of file + return File(csvBytes, "text/csv", fileName); + } + else + { + return NotFound(new { message = "No data available for the specified month and year." }); + } + } + } +} \ No newline at end of file diff --git a/CargoHub/Services/MontlyReportService.cs b/CargoHub/Services/MontlyReportService.cs index 340661e..510e981 100644 --- a/CargoHub/Services/MontlyReportService.cs +++ b/CargoHub/Services/MontlyReportService.cs @@ -1,86 +1,84 @@ -// using CargoHub.Models; -// using Microsoft.EntityFrameworkCore; -// using System; -// using System.Linq; -// using System.Text; -// using System.Threading.Tasks; +using CargoHub.Models; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Text; +using System.Threading.Tasks; -// namespace CargoHub.Services -// { -// public class ReportService -// { -// private readonly AppDbContext _context; +namespace CargoHub.Services +{ + public class ReportService + { + private readonly AppDbContext _context; -// public ReportService(AppDbContext context) -// { -// _context = context; -// } + public ReportService(AppDbContext context) + { + _context = context; + } -// public async Task GenerateMonthlyCsvReport(int year, int month) -// { -// // Orders created in the specified month -// var orders = await _context.Orders -// .Where(o => o.CreatedAt.Year == year && o.CreatedAt.Month == month) -// .Include(o => o.OrderItems) -// .ToListAsync(); + public async Task GenerateMonthlyCsvReport(int year, int month) + { + // Orders created in the specified month + var orders = await _context.Orders + .Where(o => o.CreatedAt.Year == year && o.CreatedAt.Month == month) + .Include(o => o.Items) // Correct navigation property + .ToListAsync(); -// // Shipments created in the specified month -// var shipments = await _context.Shipments -// .Where(s => s.CreatedAt.Year == year && s.CreatedAt.Month == month) -// .ToListAsync(); + // Shipments created in the specified month + var shipments = await _context.Shipments + .Where(s => s.CreatedAt.Year == year && s.CreatedAt.Month == month) + .ToListAsync(); -// if (!orders.Any() && !shipments.Any()) -// { -// return null; -// } + if (!orders.Any() && !shipments.Any()) + { + return null; + } -// // Analyze data for the report -// var CalculateAverageOrderProcessingTime = orders -// .Where(o => o.OrderDate.HasValue && o.OrderDate > o.CreatedAt) -// .Select(o => (o.OrderDate.Value - o.CreatedAt).TotalDays) -// .DefaultIfEmpty(0) -// .Average(); + // Analyze data for the report + var CalculateAverageOrderProcessingTime = orders + .Where(o => o.OrderDate > o.CreatedAt) + .Select(o => (o.OrderDate - o.CreatedAt).TotalDays) + .DefaultIfEmpty(0) + .Average(); -// var CalculateAverageShipmentTransitProcessingTime = shipments -// .Where(s => s.ShipmentDate > s.CreatedAt) -// .Select(s => (s.ShipmentDate - s.CreatedAt).TotalDays) -// .DefaultIfEmpty(0) -// .Average(); + var CalculateAverageShipmentTransitProcessingTime = shipments + .Where(s => s.ShipmentDate > s.CreatedAt) + .Select(s => (s.ShipmentDate - s.CreatedAt).TotalDays) + .DefaultIfEmpty(0) + .Average(); -// var totalItems = orders.Sum(o => o.OrderItems.Count()); + var totalItems = orders.Sum(o => o.Items.Count); -// var topWarehouse = orders -// .GroupBy(o => o.WarehouseId) -// .OrderByDescending(g => g.Count()) -// .Select(g => new -// { -// WarehouseId = g.Key, -// OrderCount = g.Count() -// }) -// .FirstOrDefault(); + var topWarehouse = orders + .GroupBy(o => o.WarehouseId) + .OrderByDescending(g => g.Count()) + .Select(g => new + { + WarehouseId = g.Key, + OrderCount = g.Count() + }) + .FirstOrDefault(); -// // Create CSV content -// var csvBuilder = new StringBuilder(); + // Create CSV content + var csvBuilder = new StringBuilder(); -// // Gebruik puntkomma als scheidingsteken voor betere compatibiliteit -// csvBuilder.AppendLine("Jaar;Maand;Totaal Bestellingen;Totale Waarde (€);Gem. Orderverwerkingstijd (dagen);Totaal Zendingen;Gem. Transittijd (dagen);Totaal Items;Top Magazijn ID;Top Magazijn Bestellingen"); + // Use semicolon as a separator for better compatibility + csvBuilder.AppendLine("Year;Month;Total Orders;Total Value (€);Avg. Order Processing Time (days);Total Shipments;Avg. Transit Time (days);Total Items;Top Warehouse ID;Top Warehouse Orders"); -// // Voeg data toe met nette formatting -// csvBuilder.AppendLine( -// $"{year};" + -// $"{month};" + -// $"{orders.Count};" + -// $"{orders.Sum(o => o.TotalAmount):0.00};" + // 2 decimalen voor geldwaarde -// $"{CalculateAverageOrderProcessingTime:0.0};" + // 1 decimaal voor gemiddelden -// $"{shipments.Count};" + -// $"{CalculateAverageShipmentTransitProcessingTime:0.0};" + -// $"{totalItems};" + -// $"{(topWarehouse?.WarehouseId.HasValue == true ? topWarehouse.WarehouseId.ToString() : "N/A")};" + -// $"{(topWarehouse?.OrderCount ?? 0)}" -// ); + // Add data with proper formatting + csvBuilder.AppendLine( + $"{year};" + + $"{month};" + + $"{orders.Count};" + + $"{orders.Sum(o => o.TotalAmount):0.00};" + // 2 decimals for monetary values + $"{CalculateAverageOrderProcessingTime:0.0};" + // 1 decimal for averages + $"{shipments.Count};" + + $"{CalculateAverageShipmentTransitProcessingTime:0.0};" + + $"{totalItems};" + + $"{(topWarehouse != null ? topWarehouse.WarehouseId.ToString() : "N/A")};" + + $"{(topWarehouse?.OrderCount ?? 0)}" + ); -// return csvBuilder.ToString(); - -// } -// } -// } + return csvBuilder.ToString(); + } + } +} diff --git a/UnitTest/CSVfileTest.cs b/UnitTest/CSVfileTest.cs new file mode 100644 index 0000000..4577ced --- /dev/null +++ b/UnitTest/CSVfileTest.cs @@ -0,0 +1,152 @@ +using CargoHub.Models; +using CargoHub.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +[TestClass] +public class ReportServiceTests +{ + private AppDbContext _dbContext; + private ReportService _reportService; + + [TestInitialize] + public void SetUp() + { + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) + .Options; + + _dbContext = new AppDbContext(options); + _reportService = new ReportService(_dbContext); + + // Seed data for Orders + _dbContext.Orders.AddRange(new List + { + new Order + { + Id = 1, + SourceId = 1, + OrderDate = new DateTime(2023, 1, 15), + RequestDate = new DateTime(2023, 1, 17), + CreatedAt = new DateTime(2023, 1, 10), + UpdatedAt = new DateTime(2023, 1, 15), + Reference = "ORD001", + ReferenceExtra = "Extra details", + OrderStatus = "Pending", + Notes = "Order 1 notes", + ShippingNotes = "Shipping notes 1", + PickingNotes = "Picking notes 1", + WarehouseId = 1, + ShipToId = 1, + BillToId = 1, + TotalAmount = 200.00m, + TotalDiscount = 20.00m, + TotalTax = 10.00m, + TotalSurcharge = 5.00m, + Items = new List + { + new OrderItem { ItemId = "P001", Amount = 2 }, + new OrderItem { ItemId = "P002", Amount = 3 } + } + }, + new Order + { + Id = 2, + SourceId = 1, + OrderDate = new DateTime(2023, 1, 20), + RequestDate = new DateTime(2023, 1, 22), + CreatedAt = new DateTime(2023, 1, 12), + UpdatedAt = new DateTime(2023, 1, 20), + Reference = "ORD002", + ReferenceExtra = "Extra details", + OrderStatus = "Pending", + Notes = "Order 2 notes", + ShippingNotes = "Shipping notes 2", + PickingNotes = "Picking notes 2", + WarehouseId = 1, + ShipToId = 2, + BillToId = 2, + TotalAmount = 300.00m, + TotalDiscount = 30.00m, + TotalTax = 15.00m, + TotalSurcharge = 7.50m, + Items = new List + { + new OrderItem { ItemId = "P003", Amount = 1 }, + new OrderItem { ItemId = "P004", Amount = 4 } + } + } + }); + + // Seed data for Shipments + _dbContext.Shipments.Add(new Shipment + { + Id = 1, + SourceId = 1, + OrderDate = new DateTime(2023, 1, 15), + RequestDate = new DateTime(2023, 1, 17), + ShipmentDate = new DateTime(2023, 1, 18), + CreatedAt = new DateTime(2023, 1, 10), + UpdatedAt = new DateTime(2023, 1, 18), + ShipmentType = "O", + ShipmentStatus = "Delivered", + Notes = "Shipment 1 notes", + CarrierCode = "CARR001", + CarrierDescription = "Fast Delivery", + ServiceCode = "NextDay", + PaymentType = "Manual", + TransferMode = "Air", + TotalPackageCount = 5, + TotalPackageWeight = 50.5m, + OrderIds = new List { 1, 2 } + }); + + _dbContext.SaveChanges(); + } + + [TestCleanup] + public void Cleanup() + { + _dbContext.Database.EnsureDeleted(); + _dbContext.Dispose(); + } + + [TestMethod] + public async Task GenerateMonthlyCsvReport_Should_ReturnCorrectReport() + { + // Arrange + var year = 2023; + var month = 1; + + // Act + var csvReport = await _reportService.GenerateMonthlyCsvReport(year, month); + + // Assert + Assert.IsNotNull(csvReport, "CSV report should not be null"); + + // Use the regional formatting expected in the CSV + StringAssert.Contains( + csvReport, + "2023;1;2;500,00;6,5;1;8,0;4;1;2" + ); + } + + + [TestMethod] + public async Task GenerateMonthlyCsvReport_Should_ReturnNull_WhenNoDataExists() + { + // Arrange + var year = 2024; // No data for this year + var month = 1; + + // Act + var csvReport = await _reportService.GenerateMonthlyCsvReport(year, month); + + // Assert + Assert.IsNull(csvReport, "CSV report should be null when no data exists for the specified month"); + } +}