refactor: Simplify ArchiveAsync method signatures and update related implementations
This commit is contained in:
parent
e6b2180c94
commit
ad7dc587b2
@ -32,7 +32,7 @@ namespace ComplianceNFs.Core.Application
|
|||||||
// Handles archiving of files
|
// Handles archiving of files
|
||||||
public interface IArchivingService
|
public interface IArchivingService
|
||||||
{
|
{
|
||||||
Task ArchiveAsync(EnergyInvoice invoice, byte[] rawFile);
|
Task ArchiveAsync(EnergyInvoice invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For streaming invoice status updates (for Monitor)
|
// For streaming invoice status updates (for Monitor)
|
||||||
|
|||||||
@ -92,24 +92,15 @@ namespace ComplianceNFs.Core.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handles matching logic for invoices
|
// Handles matching logic for invoices
|
||||||
public class MatchingService : IMatchingService
|
public class MatchingService(IAccessDbRepository accessDbRepository, ILogger<MatchingService> logger) : IMatchingService
|
||||||
{
|
{
|
||||||
private readonly IAccessDbRepository _accessDbRepository;
|
|
||||||
private readonly ILogger<MatchingService> _logger;
|
|
||||||
|
|
||||||
public MatchingService(IAccessDbRepository accessDbRepository, ILogger<MatchingService> logger)
|
|
||||||
{
|
|
||||||
_accessDbRepository = accessDbRepository;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task MatchAsync(EnergyInvoice invoice)
|
public Task MatchAsync(EnergyInvoice invoice)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Matching invoice {InvoiceId}", invoice.InvoiceId);
|
logger.LogInformation("Matching invoice {InvoiceId}", invoice.InvoiceId);
|
||||||
// Example: Primary match logic (simplified)
|
// Example: Primary match logic (simplified)
|
||||||
var records = _accessDbRepository.GetByCnpj(invoice.CnpjComp ?? throw new ArgumentNullException("CnpjComp is required"));
|
var records = accessDbRepository.GetByCnpj(invoice.CnpjComp ?? throw new ArgumentNullException(null, nameof(invoice.CnpjComp)));
|
||||||
if (records == null || records.ToList().Count == 0)
|
if (records == null || records.ToList().Count == 0)
|
||||||
{
|
{
|
||||||
invoice.Status = InvoiceStatus.NotFound;
|
invoice.Status = InvoiceStatus.NotFound;
|
||||||
@ -164,7 +155,7 @@ namespace ComplianceNFs.Core.Application.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error matching invoice {InvoiceId}", invoice.InvoiceId);
|
logger.LogError(ex, "Error matching invoice {InvoiceId}", invoice.InvoiceId);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@ -211,9 +202,10 @@ namespace ComplianceNFs.Core.Application.Services
|
|||||||
{
|
{
|
||||||
private readonly IFileArchiver _fileArchiver = fileArchiver;
|
private readonly IFileArchiver _fileArchiver = fileArchiver;
|
||||||
|
|
||||||
public Task ArchiveAsync(EnergyInvoice invoice, byte[] rawFile)
|
public Task ArchiveAsync(EnergyInvoice invoice)
|
||||||
{
|
{
|
||||||
return _fileArchiver.ArchiveAsync(invoice, rawFile);
|
_fileArchiver.ArchiveAsync(invoice);
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,6 @@ namespace ComplianceNFs.Core.Ports
|
|||||||
|
|
||||||
public interface IFileArchiver
|
public interface IFileArchiver
|
||||||
{
|
{
|
||||||
Task ArchiveAsync(Entities.EnergyInvoice invoice, byte[] rawFile);
|
void ArchiveAsync(Entities.EnergyInvoice invoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expected = new List<BuyingRecord> {
|
var expected = new List<BuyingRecord> {
|
||||||
new BuyingRecord { CodTE = 180310221018240701, CnpjComp = "06272575007403", CnpjVend = "13777004000122", MontLO = 24.72m, PrecLO = 147.29m }
|
new() { CodTE = 180310221018240701, CnpjComp = "06272575007403", CnpjVend = "13777004000122", MontLO = 24.72m, PrecLO = 147.29m }
|
||||||
};
|
};
|
||||||
var mockRepo = new Mock<IAccessDbRepository>();
|
var mockRepo = new Mock<IAccessDbRepository>();
|
||||||
mockRepo.Setup(r => r.GetByCnpj("06272575007403")).Returns(expected);
|
mockRepo.Setup(r => r.GetByCnpj("06272575007403")).Returns(expected);
|
||||||
|
|||||||
@ -29,10 +29,10 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
var fileBytes = new byte[] { 1, 2, 3 };
|
var fileBytes = new byte[] { 1, 2, 3 };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await service.ArchiveAsync(invoice, fileBytes);
|
await service.ArchiveAsync(invoice);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
mockArchiver.Verify(a => a.ArchiveAsync(invoice, fileBytes), Times.Once);
|
mockArchiver.Verify(a => a.ArchiveAsync(invoice), Times.Once);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,9 +46,8 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Expose protected method for test
|
// Expose protected method for test
|
||||||
private class TestableMailListener : MailListener
|
private class TestableMailListener(IConfiguration config, ILogger<MailListener> logger) : MailListener(config, logger)
|
||||||
{
|
{
|
||||||
public TestableMailListener(IConfiguration config, ILogger<MailListener> logger) : base(config, logger) { }
|
|
||||||
public new void RaiseNewMailReceivedForTest(MailMessage mail) => base.RaiseNewMailReceivedForTest(mail);
|
public new void RaiseNewMailReceivedForTest(MailMessage mail) => base.RaiseNewMailReceivedForTest(mail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
Filename = "file.xml",
|
Filename = "file.xml",
|
||||||
Status = InvoiceStatus.Validated
|
Status = InvoiceStatus.Validated
|
||||||
};
|
};
|
||||||
mockStream.Setup(s => s.GetRecent(It.IsAny<int>())).Returns(new[] { testInvoice });
|
mockStream.Setup(s => s.GetRecent(It.IsAny<int>())).Returns([testInvoice]);
|
||||||
var viewModel = new MonitorViewModel(mockStream.Object);
|
var viewModel = new MonitorViewModel(mockStream.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
@ -38,7 +38,7 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var mockStream = new Mock<IInvoiceStatusStream>();
|
var mockStream = new Mock<IInvoiceStatusStream>();
|
||||||
mockStream.Setup(s => s.GetRecent(It.IsAny<int>())).Returns(Array.Empty<EnergyInvoice>());
|
mockStream.Setup(s => s.GetRecent(It.IsAny<int>())).Returns([]);
|
||||||
var viewModel = new MonitorViewModel(mockStream.Object);
|
var viewModel = new MonitorViewModel(mockStream.Object);
|
||||||
var newInvoice = new EnergyInvoice
|
var newInvoice = new EnergyInvoice
|
||||||
{
|
{
|
||||||
|
|||||||
@ -55,8 +55,8 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
var mockLogger = new Mock<ILogger<MatchingService>>();
|
var mockLogger = new Mock<ILogger<MatchingService>>();
|
||||||
var invoice = new EnergyInvoice { CnpjComp = "123", CnpjVend = "456", MontNF = 300, PrecNF = 600, MailId = "m", ConversationId = "c", SupplierEmail = "s", ReceivedDate = DateTime.Now, InvoiceId = 1, Filename = "f.xml" };
|
var invoice = new EnergyInvoice { CnpjComp = "123", CnpjVend = "456", MontNF = 300, PrecNF = 600, MailId = "m", ConversationId = "c", SupplierEmail = "s", ReceivedDate = DateTime.Now, InvoiceId = 1, Filename = "f.xml" };
|
||||||
var records = new List<BuyingRecord> {
|
var records = new List<BuyingRecord> {
|
||||||
new BuyingRecord { CnpjComp = "123", CnpjVend = "456", MontLO = 100, PrecLO = 200, CodTE = 1 },
|
new() { CnpjComp = "123", CnpjVend = "456", MontLO = 100, PrecLO = 200, CodTE = 1 },
|
||||||
new BuyingRecord { CnpjComp = "123", CnpjVend = "456", MontLO = 200, PrecLO = 400, CodTE = 2 }
|
new() { CnpjComp = "123", CnpjVend = "456", MontLO = 200, PrecLO = 400, CodTE = 2 }
|
||||||
};
|
};
|
||||||
mockRepo.Setup(r => r.GetByCnpj("123")).Returns(records);
|
mockRepo.Setup(r => r.GetByCnpj("123")).Returns(records);
|
||||||
var service = new MatchingService(mockRepo.Object, mockLogger.Object);
|
var service = new MatchingService(mockRepo.Object, mockLogger.Object);
|
||||||
@ -87,8 +87,8 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
Filename = "f.xml"
|
Filename = "f.xml"
|
||||||
};
|
};
|
||||||
var records = new List<BuyingRecord> {
|
var records = new List<BuyingRecord> {
|
||||||
new BuyingRecord { CnpjComp = "123", CnpjVend = "456", MontLO = 100, PrecLO = 200, CodTE = 1 },
|
new() { CnpjComp = "123", CnpjVend = "456", MontLO = 100, PrecLO = 200, CodTE = 1 },
|
||||||
new BuyingRecord { CnpjComp = "123", CnpjVend = "456", MontLO = 200, PrecLO = 400, CodTE = 2 }
|
new() { CnpjComp = "123", CnpjVend = "456", MontLO = 200, PrecLO = 400, CodTE = 2 }
|
||||||
};
|
};
|
||||||
mockRepo.Setup(r => r.GetByCnpj("123")).Returns(records);
|
mockRepo.Setup(r => r.GetByCnpj("123")).Returns(records);
|
||||||
var service = new MatchingService(mockRepo.Object, mockLogger.Object);
|
var service = new MatchingService(mockRepo.Object, mockLogger.Object);
|
||||||
|
|||||||
@ -34,7 +34,7 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
};
|
};
|
||||||
var data = new byte[] { 1, 2, 3, 4 };
|
var data = new byte[] { 1, 2, 3, 4 };
|
||||||
|
|
||||||
await archiver.ArchiveAsync(invoice, data);
|
archiver.ArchiveAsync(invoice);
|
||||||
|
|
||||||
var expectedFolder = Path.Combine(_testBasePath, "Validated");
|
var expectedFolder = Path.Combine(_testBasePath, "Validated");
|
||||||
var expectedFile = Path.Combine(expectedFolder, "testfile.txt");
|
var expectedFile = Path.Combine(expectedFolder, "testfile.txt");
|
||||||
@ -59,11 +59,10 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
ReceivedDate = DateTime.Now,
|
ReceivedDate = DateTime.Now,
|
||||||
InvoiceId = 1
|
InvoiceId = 1
|
||||||
};
|
};
|
||||||
var data1 = new byte[] { 1, 2, 3 };
|
|
||||||
var data2 = new byte[] { 9, 8, 7 };
|
var data2 = new byte[] { 9, 8, 7 };
|
||||||
|
|
||||||
await archiver.ArchiveAsync(invoice, data1);
|
archiver.ArchiveAsync(invoice);
|
||||||
await archiver.ArchiveAsync(invoice, data2);
|
archiver.ArchiveAsync(invoice);
|
||||||
|
|
||||||
var expectedFile = Path.Combine(_testBasePath, "Validated", "testfile.txt");
|
var expectedFile = Path.Combine(_testBasePath, "Validated", "testfile.txt");
|
||||||
var fileData = await File.ReadAllBytesAsync(expectedFile);
|
var fileData = await File.ReadAllBytesAsync(expectedFile);
|
||||||
@ -74,6 +73,7 @@ namespace ComplianceNFs.Infrastructure.Tests
|
|||||||
{
|
{
|
||||||
if (Directory.Exists(_testBasePath))
|
if (Directory.Exists(_testBasePath))
|
||||||
Directory.Delete(_testBasePath, true);
|
Directory.Delete(_testBasePath, true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,9 @@ namespace ComplianceNFs.Infrastructure.Archiving
|
|||||||
{
|
{
|
||||||
private readonly string _basePath = basePath;
|
private readonly string _basePath = basePath;
|
||||||
|
|
||||||
public async Task ArchiveAsync(EnergyInvoice invoice, byte[] rawFile)
|
public void ArchiveAsync(EnergyInvoice invoice)
|
||||||
{
|
{
|
||||||
|
var sourceFile = Path.Combine(_basePath, invoice.Filename);
|
||||||
// Create subfolder for invoice.Status
|
// Create subfolder for invoice.Status
|
||||||
var statusFolder = Path.Combine(_basePath, invoice.Status.ToString());
|
var statusFolder = Path.Combine(_basePath, invoice.Status.ToString());
|
||||||
if (!Directory.Exists(statusFolder))
|
if (!Directory.Exists(statusFolder))
|
||||||
@ -23,7 +24,7 @@ namespace ComplianceNFs.Infrastructure.Archiving
|
|||||||
// Build file path
|
// Build file path
|
||||||
var filePath = Path.Combine(statusFolder, invoice.Filename);
|
var filePath = Path.Combine(statusFolder, invoice.Filename);
|
||||||
// Write file (overwrite if exists)
|
// Write file (overwrite if exists)
|
||||||
await File.WriteAllBytesAsync(filePath, rawFile);
|
File.Move(sourceFile, filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,22 +10,13 @@ using Microsoft.Extensions.Logging;
|
|||||||
namespace ComplianceNFs.Infrastructure.Repositories
|
namespace ComplianceNFs.Infrastructure.Repositories
|
||||||
{
|
{
|
||||||
// Placeholder: fill in actual SQL and mapping logic
|
// Placeholder: fill in actual SQL and mapping logic
|
||||||
public class AttachmentRepository : IAttachmentRepository
|
public class AttachmentRepository(string connectionString, ILogger<AttachmentRepository> logger) : IAttachmentRepository
|
||||||
{
|
{
|
||||||
private readonly string _connectionString;
|
|
||||||
private readonly ILogger<AttachmentRepository> _logger;
|
|
||||||
|
|
||||||
public AttachmentRepository(string connectionString, ILogger<AttachmentRepository> logger)
|
|
||||||
{
|
|
||||||
_connectionString = connectionString;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SaveRawAsync(EnergyInvoice invoice)
|
public async Task SaveRawAsync(EnergyInvoice invoice)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var conn = new NpgsqlConnection(_connectionString);
|
using var conn = new NpgsqlConnection(connectionString);
|
||||||
await conn.OpenAsync();
|
await conn.OpenAsync();
|
||||||
var cmd = conn.CreateCommand();
|
var cmd = conn.CreateCommand();
|
||||||
cmd.CommandText = @"INSERT INTO attachments (
|
cmd.CommandText = @"INSERT INTO attachments (
|
||||||
@ -55,11 +46,11 @@ namespace ComplianceNFs.Infrastructure.Repositories
|
|||||||
cmd.Parameters.AddWithValue("@discrepancy", (object?)invoice.DiscrepancyNotes ?? DBNull.Value);
|
cmd.Parameters.AddWithValue("@discrepancy", (object?)invoice.DiscrepancyNotes ?? DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("@metadata", Newtonsoft.Json.JsonConvert.SerializeObject(invoice));
|
cmd.Parameters.AddWithValue("@metadata", Newtonsoft.Json.JsonConvert.SerializeObject(invoice));
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
_logger.LogInformation("Saved raw invoice {InvoiceId} to attachments table.", invoice.InvoiceId);
|
logger.LogInformation("Saved raw invoice {InvoiceId} to attachments table.", invoice.InvoiceId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error saving raw invoice {InvoiceId} to attachments table.", invoice.InvoiceId);
|
logger.LogError(ex, "Error saving raw invoice {InvoiceId} to attachments table.", invoice.InvoiceId);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,7 +59,7 @@ namespace ComplianceNFs.Infrastructure.Repositories
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var conn = new NpgsqlConnection(_connectionString);
|
using var conn = new NpgsqlConnection(connectionString);
|
||||||
await conn.OpenAsync();
|
await conn.OpenAsync();
|
||||||
var cmd = conn.CreateCommand();
|
var cmd = conn.CreateCommand();
|
||||||
cmd.CommandText = @"UPDATE attachments SET matched_cod_te = @matched_cod_te, status = @status, discrepancy = @discrepancy WHERE invoice_id = @invoice_id";
|
cmd.CommandText = @"UPDATE attachments SET matched_cod_te = @matched_cod_te, status = @status, discrepancy = @discrepancy WHERE invoice_id = @invoice_id";
|
||||||
@ -77,11 +68,11 @@ namespace ComplianceNFs.Infrastructure.Repositories
|
|||||||
cmd.Parameters.AddWithValue("@discrepancy", (object?)notes ?? DBNull.Value);
|
cmd.Parameters.AddWithValue("@discrepancy", (object?)notes ?? DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("@invoice_id", invoiceId);
|
cmd.Parameters.AddWithValue("@invoice_id", invoiceId);
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
_logger.LogInformation("Updated match for invoice {InvoiceId}.", invoiceId);
|
logger.LogInformation("Updated match for invoice {InvoiceId}.", invoiceId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error updating match for invoice {InvoiceId}.", invoiceId);
|
logger.LogError(ex, "Error updating match for invoice {InvoiceId}.", invoiceId);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,6 @@ namespace ComplianceNFs.Monitor
|
|||||||
public class DummyStatusStream : IInvoiceStatusStream
|
public class DummyStatusStream : IInvoiceStatusStream
|
||||||
{
|
{
|
||||||
public event Action<Core.Entities.EnergyInvoice>? StatusUpdated { add { } remove { } }
|
public event Action<Core.Entities.EnergyInvoice>? StatusUpdated { add { } remove { } }
|
||||||
public IEnumerable<Core.Entities.EnergyInvoice> GetRecent(int count = 100) => Array.Empty<Core.Entities.EnergyInvoice>();
|
public IEnumerable<Core.Entities.EnergyInvoice> GetRecent(int count = 100) => [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ public class Worker(ILogger<Worker> logger,
|
|||||||
}
|
}
|
||||||
// 4. Archive
|
// 4. Archive
|
||||||
// (Assume raw file is available or can be loaded if needed)
|
// (Assume raw file is available or can be loaded if needed)
|
||||||
// await _archivingService.ArchiveAsync(invoice, rawFile);
|
await _archivingService.ArchiveAsync(invoice);
|
||||||
_logger.LogInformation("Invoice {NumeroNF} processed with status: {Status}", invoice.NumeroNF, invoice.Status);
|
_logger.LogInformation("Invoice {NumeroNF} processed with status: {Status}", invoice.NumeroNF, invoice.Status);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user