using TrafagSalesExporter.Models; using TrafagSalesExporter.Services; using TrafagSalesExporter.Services.DataSources; namespace TrafagSalesExporter.Tests; public class ManualExcelDataSourceAdapterTests { [Fact] public async Task FetchAsync_Uses_Local_File_Directory_As_OutputDirectory() { var filePath = CreateSpainCsv(); try { var adapter = new ManualExcelDataSourceAdapter( new FakeSharePointUploadService(filePath), new ManualExcelImportService(), new NoopAppEventLogService()); var result = await adapter.FetchAsync(CreateContext(filePath)); Assert.Single(result.Records); Assert.Null(result.ReferenceFilePath); Assert.Equal(Path.GetDirectoryName(Path.GetFullPath(filePath)), result.LocalOutputDirectoryOverride); } finally { File.Delete(filePath); } } [Fact] public async Task FetchAsync_Uses_SharePoint_Source_Folder_As_UploadFolder() { var filePath = CreateSpainCsv(); try { var adapter = new ManualExcelDataSourceAdapter( new FakeSharePointUploadService(filePath), new ManualExcelImportService(), new NoopAppEventLogService()); var result = await adapter.FetchAsync(CreateContext("https://trafagag.sharepoint.com/sites/WorldwideBIPlatform/Import/Finance/Spanien/Spain_Sales_2025.csv")); Assert.Single(result.Records); Assert.Null(result.ReferenceFilePath); Assert.Equal("Import/Finance/Spanien", result.SharePointUploadFolderOverride); Assert.Equal(string.Empty, result.SharePointUploadLandOverride); } finally { File.Delete(filePath); } } [Fact] public async Task FetchAsync_Uses_Latest_SharePoint_File_When_Path_Is_Folder() { var filePath = CreateSpainCsv(); var sharePointService = new FakeSharePointUploadService( filePath, latestFileReference: "Import/Finance/UK_B1/010526_TRUK.xlsx"); try { var adapter = new ManualExcelDataSourceAdapter( sharePointService, new ManualExcelImportService(), new NoopAppEventLogService()); var result = await adapter.FetchAsync(CreateContext("https://trafagag.sharepoint.com/sites/WorldwideBIPlatform/Import/Finance/UK_B1", "TRUK", "England")); Assert.Single(result.Records); Assert.Equal("Import/Finance/UK_B1", result.SharePointUploadFolderOverride); Assert.Equal("Import/Finance/UK_B1/010526_TRUK.xlsx", sharePointService.LastDownloadedReference); Assert.Equal("TRUK", sharePointService.LastResolvedTsc); } finally { File.Delete(filePath); } } private static DataSourceFetchContext CreateContext(string manualImportPath, string tsc = "TRES", string land = "Spanien") => new() { Site = new Site { Id = 7, TSC = tsc, Land = land, ManualImportFilePath = manualImportPath }, SourceDefinition = new SourceSystemDefinition { Code = "MANUAL_EXCEL", ConnectionKind = SourceSystemConnectionKinds.ManualExcel }, Settings = new ExportSettings(), SharePointConfig = new SharePointConfig { TenantId = "tenant", ClientId = "client", ClientSecret = "secret", SiteUrl = "https://trafagag.sharepoint.com/sites/WorldwideBIPlatform" } }; private static string CreateSpainCsv() { var filePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.csv"); var csv = string.Join(Environment.NewLine, "\"TSC\";\"Land\";\"InvoiceNumber\";\"PositionOnInvoice\";\"Material\";\"Name\";\"ProductGroup\";\"Quantity\";\"CustomerNumber\";\"CustomerName\";\"CustomerCountry\";\"StandardCost\";\"StandardCostCurrency\";\"PurchaseOrderNumber\";\"SalesPriceValue\";\"SalesCurrency\";\"DocumentCurrency\";\"CompanyCurrency\";\"Incoterms2020\";\"SalesResponsibleEmployee\";\"InvoiceDate\";\"DocumentType\"", "\"TRES\";\"Spanien\";\"20241332\";\"20\";\"52871\";\"ECL1.0AP\";\"TRANS\";\"1.000000\";\"302208\";\"INTRONIK AUTOMATIZACION E INST. SL\";\"ESPANA\";\"160.760000\";\"EUR\";\"PC240330\";\"265.000000\";\"EUR\";\"EUR\";\"EUR\";\"EXW\";\"1\";\"2025-01-02 00:00:00\";\"Invoice\""); File.WriteAllText(filePath, csv); return filePath; } private sealed class FakeSharePointUploadService : ISharePointUploadService { private readonly string _sourceFilePath; private readonly string _latestFileReference; public FakeSharePointUploadService(string sourceFilePath, string? latestFileReference = null) { _sourceFilePath = sourceFilePath; _latestFileReference = latestFileReference ?? "Import/Finance/Spanien/Spain_Sales_2025.csv"; } public string LastDownloadedReference { get; private set; } = string.Empty; public string LastResolvedTsc { get; private set; } = string.Empty; public Task UploadAsync(string tenantId, string clientId, string clientSecret, string siteUrl, string exportFolder, string land, string localFilePath) => Task.CompletedTask; public Task DownloadToTempFileAsync(string tenantId, string clientId, string clientSecret, string siteUrl, string fileReference) { LastDownloadedReference = fileReference; var tempPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.csv"); File.Copy(_sourceFilePath, tempPath); return Task.FromResult(tempPath); } public Task ResolveLatestFileInFolderAsync(string tenantId, string clientId, string clientSecret, string siteUrl, string folderReference, string siteTsc, int? preferredYear = null) { LastResolvedTsc = siteTsc; return Task.FromResult(new SharePointFileReference(_latestFileReference, new DateTimeOffset(2026, 5, 1, 0, 0, 0, TimeSpan.Zero))); } public Task> ResolveManualImportFilesInFolderAsync(string tenantId, string clientId, string clientSecret, string siteUrl, string folderReference, string siteTsc, int? preferredYear = null) { LastResolvedTsc = siteTsc; IReadOnlyList result = [ new(_latestFileReference, new DateTimeOffset(2026, 5, 1, 0, 0, 0, TimeSpan.Zero)) ]; return Task.FromResult(result); } public Task TestConnectionAsync(string tenantId, string clientId, string clientSecret, string siteUrl) => Task.CompletedTask; } private sealed class NoopAppEventLogService : IAppEventLogService { public Task WriteAsync(string category, string message, string level = "Info", int? siteId = null, string? land = null, string? details = null) => Task.CompletedTask; public Task WriteDebugAsync(string category, string message, int? siteId = null, string? land = null, string? details = null) => Task.CompletedTask; } }