Add audit CSV central source option
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TrafagSalesExporter.Data;
|
||||
using TrafagSalesExporter.Models;
|
||||
using TrafagSalesExporter.Services;
|
||||
|
||||
namespace TrafagSalesExporter.Tests;
|
||||
|
||||
public sealed class ExportAuditCsvServiceTests : IDisposable
|
||||
{
|
||||
private readonly string _tempDirectory;
|
||||
|
||||
public ExportAuditCsvServiceTests()
|
||||
{
|
||||
_tempDirectory = Path.Combine("C:\\TMP", $"trafag-audit-csv-tests-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(_tempDirectory);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_tempDirectory))
|
||||
Directory.Delete(_tempDirectory, recursive: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteSiteAuditCsvAsync_Roundtrips_Transformed_SalesRecord()
|
||||
{
|
||||
var service = new ExportAuditCsvService();
|
||||
var settings = new ExportSettings
|
||||
{
|
||||
AuditCsvEnabled = true,
|
||||
LocalAuditCsvFolder = _tempDirectory
|
||||
};
|
||||
var site = new Site { TSC = "TRCH", Land = "Schweiz" };
|
||||
var record = new SalesRecord
|
||||
{
|
||||
SourceSystem = "SAP",
|
||||
ExtractionDate = new DateTime(2026, 6, 11, 8, 30, 0, DateTimeKind.Utc),
|
||||
Tsc = "TRCH",
|
||||
SourceLineId = "line-1",
|
||||
DocumentEntry = 42,
|
||||
InvoiceNumber = "INV-1",
|
||||
PositionOnInvoice = 7,
|
||||
Material = "MAT;1",
|
||||
Name = "Artikel \"Audit\"",
|
||||
ProductDivisionCode = "0001",
|
||||
ProductDivisionText = "Pressure",
|
||||
ProductMappingAssigned = "TRUE",
|
||||
Quantity = 2.5m,
|
||||
SalesPriceValue = 1234.56m,
|
||||
SalesCurrency = "CHF",
|
||||
DocumentCurrency = "EUR",
|
||||
DocumentTotalForeignCurrency = 1300m,
|
||||
DocumentTotalLocalCurrency = 1234.56m,
|
||||
VatSumForeignCurrency = 0m,
|
||||
VatSumLocalCurrency = 0m,
|
||||
DocumentRate = 0.95m,
|
||||
CompanyCurrency = "CHF",
|
||||
PostingDate = new DateTime(2026, 6, 10),
|
||||
InvoiceDate = new DateTime(2026, 6, 11),
|
||||
Land = "Schweiz",
|
||||
DocumentType = "INV"
|
||||
};
|
||||
|
||||
var path = await service.WriteSiteAuditCsvAsync(site, settings, "SAP", _tempDirectory, [record]);
|
||||
|
||||
Assert.True(File.Exists(path));
|
||||
var records = await service.ReadLatestSiteAuditCsvRecordsAsync(settings);
|
||||
var roundtrip = Assert.Single(records);
|
||||
Assert.Equal("SAP", roundtrip.SourceSystem);
|
||||
Assert.Equal("TRCH", roundtrip.Tsc);
|
||||
Assert.Equal("line-1", roundtrip.SourceLineId);
|
||||
Assert.Equal("MAT;1", roundtrip.Material);
|
||||
Assert.Equal("Artikel \"Audit\"", roundtrip.Name);
|
||||
Assert.Equal(1234.56m, roundtrip.SalesPriceValue);
|
||||
Assert.Equal("CHF", roundtrip.SalesCurrency);
|
||||
Assert.Equal(new DateTime(2026, 6, 10), roundtrip.PostingDate);
|
||||
Assert.Equal(new DateTime(2026, 6, 11), roundtrip.InvoiceDate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CentralSalesDataProvider_Uses_AuditCsv_When_Configured()
|
||||
{
|
||||
var csvService = new ExportAuditCsvService();
|
||||
await csvService.WriteSiteAuditCsvAsync(
|
||||
new Site { TSC = "TRUK", Land = "England" },
|
||||
new ExportSettings { AuditCsvEnabled = true, LocalAuditCsvFolder = _tempDirectory },
|
||||
"MANUAL_EXCEL",
|
||||
_tempDirectory,
|
||||
[
|
||||
new SalesRecord
|
||||
{
|
||||
SourceSystem = "MANUAL_EXCEL",
|
||||
ExtractionDate = new DateTime(2026, 6, 11),
|
||||
Tsc = "TRUK",
|
||||
Land = "England",
|
||||
InvoiceNumber = "UK-1",
|
||||
SalesPriceValue = 10m,
|
||||
SalesCurrency = "GBP",
|
||||
InvoiceDate = new DateTime(2026, 1, 1)
|
||||
}
|
||||
]);
|
||||
|
||||
await using var connection = new SqliteConnection("DataSource=:memory:");
|
||||
await connection.OpenAsync();
|
||||
var options = new DbContextOptionsBuilder<AppDbContext>()
|
||||
.UseSqlite(connection)
|
||||
.Options;
|
||||
await using (var db = new AppDbContext(options))
|
||||
{
|
||||
await db.Database.EnsureCreatedAsync();
|
||||
db.ExportSettings.Add(new ExportSettings
|
||||
{
|
||||
UseAuditCsvAsCentralSource = true,
|
||||
LocalAuditCsvFolder = _tempDirectory
|
||||
});
|
||||
db.Sites.Add(new Site
|
||||
{
|
||||
Id = 1,
|
||||
Schema = "DB",
|
||||
TSC = "TRDB",
|
||||
Land = "DB",
|
||||
SourceSystem = "DB",
|
||||
IsActive = true
|
||||
});
|
||||
db.CentralSalesRecords.Add(new CentralSalesRecord
|
||||
{
|
||||
StoredAtUtc = DateTime.UtcNow,
|
||||
SiteId = 1,
|
||||
SourceSystem = "DB",
|
||||
ExtractionDate = new DateTime(2026, 6, 11),
|
||||
Tsc = "TRDB",
|
||||
InvoiceNumber = "DB-1",
|
||||
Land = "DB",
|
||||
DocumentType = "INV"
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
var dbFactory = new TestDbContextFactory(options);
|
||||
var centralService = new CentralSalesRecordService(dbFactory, new NullAppEventLogService());
|
||||
var provider = new CentralSalesDataProvider(dbFactory, centralService, csvService);
|
||||
|
||||
var records = await provider.GetRecordsAsync();
|
||||
|
||||
var record = Assert.Single(records);
|
||||
Assert.Equal("TRUK", record.Tsc);
|
||||
Assert.Equal("UK-1", record.InvoiceNumber);
|
||||
Assert.Equal(10m, record.SalesPriceValue);
|
||||
}
|
||||
|
||||
private sealed class NullAppEventLogService : 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;
|
||||
}
|
||||
|
||||
private sealed class TestDbContextFactory : IDbContextFactory<AppDbContext>
|
||||
{
|
||||
private readonly DbContextOptions<AppDbContext> _options;
|
||||
|
||||
public TestDbContextFactory(DbContextOptions<AppDbContext> options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public AppDbContext CreateDbContext() => new(_options);
|
||||
|
||||
public Task<AppDbContext> CreateDbContextAsync(CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new AppDbContext(_options));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user