using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using Centron.BusinessLogic; using Centron.BusinessLogic.EDI.SupplierEDI; using Centron.Data.Entities.Administration.Logins; using Centron.Data.Entities.EDI; using Centron.Tests.EndToEnd.Infrastructure; using CentronSoftware.Centron.WebServices.Entities.EDI; using Xunit; using Xunit.Abstractions; namespace Centron.Tests.EndToEnd.Tests.EDI { /// /// End-to-end test for diagnosing issues with EDI import functionality /// specifically focusing on why some invoices in a ZIP file might not be processed. /// public class EdiImportTests : EndToEndTest { private const int SupplierI3D = 70003; public EdiImportTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { // Set to true only when you need to update expected files // Verifier.OverrideExpectedFiles = true; } public override void Execute() { using (var session = new BLSession()) { // Execute the EDI import test ImportEdiZipFile_ShouldProcessAllInvoices(session, GetLoggedInUser()); } } /// /// Tests the EDI import functionality by directly loading a local ZIP file /// and passing it to the import process, then verifies all invoices are processed. /// private void ImportEdiZipFile_ShouldProcessAllInvoices(BLSession session, LoggedInUser user) { // Load the test ZIP file from embedded resources byte[] zipFileBytes; var assembly = typeof(EdiImportTests).Assembly; string resourceName = $"{typeof(EdiImportTests).Namespace}.ExampleData.IN_419872_250626.zip"; using (Stream stream = assembly.GetManifestResourceStream(resourceName)) { if (stream == null) { throw new InvalidOperationException($"Embedded resource not found: {resourceName}"); } using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); zipFileBytes = memoryStream.ToArray(); } } TestOutputHelper.WriteLine($"Loaded ZIP file from embedded resource: {zipFileBytes.Length} bytes"); // Create supplier EDI business logic var supplierEdiBL = session.GetBL(); // Get all configurations to identify which one is relevant for our test file var configs = GetRelevantEdiConfigurations(session, supplierEdiBL); TestOutputHelper.WriteLine($"Found {configs.Count} relevant EDI configurations"); // Process the file with each configuration until we find the one that works var importResults = ProcessFileWithConfigurations(zipFileBytes, configs, supplierEdiBL); // Verify the results Verifier.Verify("EdiImport_ZipFileContents", importResults.ZipContents); Verifier.Verify("EdiImport_ProcessedFiles", importResults.ProcessedFiles); Verifier.VerifySql("EdiImport_EDIInvoiceHead_Data", @"SELECT [I3D],[SupplierI3D],[OrigFileName],[SupplierFileName],[SourceOrderNumber],[SourceOrderDate],[SupplierInvoiceNumber],[SupplierInvoiceDate] ,[DeliveryDateStart],[DeliveryDateEnd],[CentronOrderNumber],[BuyerName],[BuyerName2],[BuyerName3],[BuyerStreet],[BuyerZip],[BuyerCity] ,[BuyerCountry],[DeliveryName],[DeliveryName2],[DeliveryName3],[DeliveryStreet],[DeliveryZip],[DeliveryCity],[DeliveryCountry],[BuyerPartyID] ,[DeliveryPartyID],[NeedsUserValidation],[SupplierNetto],[SupplierBrutto],[Currency],[Multidistributor],[Comment],[CentronDeliveryListI3D] ,[CentronOrderI3D],[State],[DeliveryNumber],[IsDeliveryAccept],[EDIConfigurationI3D],[AddField1],[AddField2],[OrderResponseNumber] FROM [dbo].[EDIInvoiceHead]"); // Check that all 4 invoices were processed Assert.Equal(4, importResults.ZipContents.Count); Assert.True(importResults.ProcessedFiles.First().Success); Assert.Equal(4, importResults.ProcessedFiles.First().FileCount); Assert.Equal(4, session.DAOSession.GetSession().Query().Count()); // Log detailed information about processed and unprocessed files LogProcessingResults(importResults); } private List GetRelevantEdiConfigurations( BLSession session, SupplierEdiBL supplierEdiBL) { return new List() { new SupplierEdiConfigurations() { SupplierI3D = SupplierI3D, ExportKind = 1, ObjectKind = 3, EdiDataType = 1, DeleteAfterUpload = false, SupplierCustomerNumber = "44-470896" } }; } private (List ZipContents, List ProcessedFiles) ProcessFileWithConfigurations( byte[] zipFileBytes, List configs, SupplierEdiBL supplierEdiBL) { // Extract file names from zip to log what should be processed var zipContents = GetZipContents(zipFileBytes); TestOutputHelper.WriteLine($"ZIP file contains {zipContents.Count} files"); // Track processing results var processedFiles = new List(); // Prepare memory stream for ZIP file using (var zipStream = new MemoryStream(zipFileBytes)) { // Process the ZIP file var processResult = ProcessEdiZipFile(zipStream, configs, supplierEdiBL); processedFiles.AddRange(processResult); } return (zipContents, processedFiles); } private List GetZipContents(byte[] zipFileBytes) { var fileNames = new List(); using (var zipStream = new MemoryStream(zipFileBytes)) using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Read)) { foreach (var entry in archive.Entries) { fileNames.Add(entry.FullName); TestOutputHelper.WriteLine($"ZIP contains file: {entry.FullName}, Size: {entry.Length} bytes"); } } return fileNames; } private List ProcessEdiZipFile( MemoryStream zipStream, List configs, SupplierEdiBL supplierEdiBL) { var processedFiles = new List(); // Extract the contents of the ZIP file to EDIDistriFile objects var distriFiles = new List(); distriFiles.Add(new EDIDistriFile { DistriName = "IN_419872_250626.zip" }); supplierEdiBL.ZipExtract(zipStream, distriFiles); TestOutputHelper.WriteLine($"Extracted {distriFiles.Count} files from ZIP"); // Try each configuration until we find one that works foreach (var config in configs) { try { TestOutputHelper.WriteLine($"Trying configuration: {config.SupplierI3D}, EDI Type: {config.EdiDataType}, Object Kind: {config.ObjectKind}"); // Create a local copy of distriFiles for each attempt to avoid side effects var filesToProcess = new List(distriFiles); // Call ApplyDistriToCentron bool result = supplierEdiBL.ApplyDistriToCentron(filesToProcess, config, null).Result; // Record the processing result processedFiles.Add(new EDIProcessResult { ConfigurationId = config.I3D, SupplierI3D = config.SupplierI3D, EdiDataType = config.EdiDataType, Success = result, FileCount = distriFiles.Count }); // If successful, no need to try other configurations if (result) { TestOutputHelper.WriteLine($"Successfully processed files with configuration {config.I3D}"); break; } } catch (Exception ex) { TestOutputHelper.WriteLine($"Error processing with configuration {config.I3D}: {ex.Message}"); // Continue with next configuration } } // If no configuration succeeded, check EDI logs for errors if (!processedFiles.Any(r => r.Success)) { TestOutputHelper.WriteLine("No configuration successfully processed the files"); CheckEdiLogs(supplierEdiBL); } return processedFiles; } private void CheckEdiLogs(SupplierEdiBL supplierEdiBL) { var ediLogBL = supplierEdiBL.GetEDILogBL(0); // Get logs for the test file var logFilter = new EDIManagementLogFilter { SupplierI3D = SupplierI3D, // StartDate = DateTime.Now.AddDays(-1), // EndDate = DateTime.Now.AddDays(1) }; // Use reflection to get logs var getLogsMethod = ediLogBL.GetType().GetMethod("GetEDILogs"); var logs = getLogsMethod?.Invoke(ediLogBL, new object[] { logFilter }); if (logs != null) { Verifier.Verify("EdiImport_Logs", logs); TestOutputHelper.WriteLine("Retrieved EDI logs for analysis"); } } private void LogProcessingResults((List ZipContents, List ProcessedFiles) results) { TestOutputHelper.WriteLine("=== EDI Processing Results ==="); TestOutputHelper.WriteLine($"Files in ZIP: {results.ZipContents.Count}"); TestOutputHelper.WriteLine($"Files processed: {results.ProcessedFiles.Count(r => r.Success)}"); foreach (var file in results.ZipContents) { TestOutputHelper.WriteLine($"File: {file}"); } foreach (var result in results.ProcessedFiles) { TestOutputHelper.WriteLine($"Config {result.ConfigurationId} (Supplier {result.SupplierI3D}, Type {result.EdiDataType}): {(result.Success ? "Success" : "Failed")}"); } } } /// /// Helper class to track EDI processing results /// public class EDIProcessResult { public int ConfigurationId { get; set; } public int SupplierI3D { get; set; } public int EdiDataType { get; set; } public bool Success { get; set; } public int FileCount { get; set; } } }