using System.Text.Json; using System.Web; using BimAI.Domain.Entities; using BimAI.Infrastructure.Data; using Microsoft.Extensions.Configuration; namespace BimAI.Infrastructure.Sync; public class InvoiceSyncService(HttpClient httpClient, BimAIDbContext db, IConfiguration configuration) { private string DecodeHtmlEntities(string text) { if (string.IsNullOrEmpty(text)) return text; return HttpUtility.HtmlDecode(text); } public async Task RunAsync() { var apiKey = configuration["E5_CRM:ApiKey"]; var syncState = db.SyncStates.FirstOrDefault(x => x.Entity == "Invoice") ?? new SyncState { Entity = "Invoice", LastSynced = 0 }; var url = $"https://crm.twinpol.com/REST/index.php?key={apiKey}&action=bimai.export.ecommerce&since=0"; var response = await httpClient.GetStringAsync(url); var jsonDoc = JsonSerializer.Deserialize(response); if (!jsonDoc.TryGetProperty("data", out var dataElement)) { Console.WriteLine("[SYNC] No 'data' property in response"); return; } var invoices = dataElement.EnumerateArray(); var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); foreach (var invoiceJson in invoices) { try { var e5Id = invoiceJson.GetProperty("e5Id").GetString() ?? ""; var documentNo = DecodeHtmlEntities(invoiceJson.GetProperty("documentNo").GetString() ?? ""); var type = DecodeHtmlEntities(invoiceJson.GetProperty("type").GetString() ?? ""); var registerDateStr = invoiceJson.GetProperty("registerDate").GetString() ?? ""; var sellDateStr = invoiceJson.GetProperty("sellDate").GetString() ?? ""; var clientName = DecodeHtmlEntities(invoiceJson.GetProperty("clientName").GetString() ?? ""); var clientId = DecodeHtmlEntities(invoiceJson.GetProperty("clientId").GetString() ?? ""); var clientNip = DecodeHtmlEntities(invoiceJson.GetProperty("clientNip").GetString() ?? ""); var clientAddress = DecodeHtmlEntities(invoiceJson.GetProperty("clientAddress").GetString() ?? ""); var currency = invoiceJson.GetProperty("currency").GetString() ?? "PLN"; var totalNettoStr = invoiceJson.GetProperty("totalNetto").GetString() ?? "0"; var totalBruttoStr = invoiceJson.GetProperty("totalBrutto").GetString() ?? "0"; var totalVatStr = invoiceJson.GetProperty("totalVat").GetString() ?? "0"; var source = invoiceJson.GetProperty("source").GetString() ?? ""; if (!DateTime.TryParse(registerDateStr, out var registerDate)) { Console.WriteLine($"[SYNC] Invalid registerDate for invoice {documentNo}: {registerDateStr}"); continue; } if (!DateTime.TryParse(sellDateStr, out var sellDate)) { Console.WriteLine($"[SYNC] Invalid sellDate for invoice {documentNo}: {sellDateStr}"); continue; } if (!decimal.TryParse(totalNettoStr, out var totalNetto)) totalNetto = 0; if (!decimal.TryParse(totalBruttoStr, out var totalBrutto)) totalBrutto = 0; if (!decimal.TryParse(totalVatStr, out var totalVat)) totalVat = 0; var existing = db.Invoices.FirstOrDefault(x => x.DocumentNo == documentNo && x.Source == source); if (existing == null) { var invoice = new Invoice { DocumentNo = documentNo, Type = type, RegisterDate = registerDate, SellDate = sellDate, ClientName = clientName, ClientId = string.IsNullOrWhiteSpace(clientId) ? null : clientId, ClientNip = string.IsNullOrWhiteSpace(clientNip) ? null : clientNip, ClientAddress = string.IsNullOrWhiteSpace(clientAddress) ? null : clientAddress, Currency = currency, TotalNetto = totalNetto, TotalBrutto = totalBrutto, TotalVat = totalVat, Source = source, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.Invoices.Add(invoice); Console.WriteLine($"[SYNC] Added invoice: {documentNo} from {source}"); } else { existing.Type = type; existing.RegisterDate = registerDate; existing.SellDate = sellDate; existing.ClientName = clientName; existing.ClientId = string.IsNullOrWhiteSpace(clientId) ? null : clientId; existing.ClientNip = string.IsNullOrWhiteSpace(clientNip) ? null : clientNip; existing.ClientAddress = string.IsNullOrWhiteSpace(clientAddress) ? null : clientAddress; existing.Currency = currency; existing.TotalNetto = totalNetto; existing.TotalBrutto = totalBrutto; existing.TotalVat = totalVat; existing.UpdatedAt = DateTime.UtcNow; Console.WriteLine($"[SYNC] Updated invoice: {documentNo} from {source}"); } } catch (Exception ex) { Console.WriteLine($"[SYNC] Error processing invoice: {ex.Message}"); } } syncState.LastSynced = now; if (db.SyncStates.FirstOrDefault(x => x.Entity == "Invoice") == null) { db.SyncStates.Add(syncState); } else { db.SyncStates.Update(syncState); } await db.SaveChangesAsync(); Console.WriteLine("[SYNC] Invoice sync completed"); } }