diff --git a/BackupPipefy.Application/Services/BackupService.cs b/BackupPipefy.Application/Services/BackupService.cs
new file mode 100644
index 0000000..6fec736
--- /dev/null
+++ b/BackupPipefy.Application/Services/BackupService.cs
@@ -0,0 +1,79 @@
+using BackupPipefy.Domain.Entities;
+using BackupPipefy.Infrastructure.Data;
+using BackupPipefy.Infrastructure.Services;
+using Microsoft.EntityFrameworkCore;
+
+public class BackupService
+{
+ private readonly PipefyClient _client;
+ private readonly BackupContext _context;
+ private readonly int _requestsPerMinute;
+
+ public BackupService(PipefyClient client, BackupContext context, int requestsPerMinute)
+ {
+ _client = client;
+ _context = context;
+ _requestsPerMinute = requestsPerMinute;
+ }
+
+ public async Task RunBackup(int pipeId)
+ {
+ var control = await _context.BackupControls.FirstOrDefaultAsync();
+ if (control == null)
+ {
+ control = new BackupControl { LastBackupTime = DateTime.MinValue };
+ _context.BackupControls.Add(control);
+ await _context.SaveChangesAsync();
+ }
+
+ DateTime startTime = DateTime.Now;
+
+ string json = await _client.GetCardsAsync(pipeId, control.LastBackupTime);
+
+ var doc = System.Text.Json.JsonDocument.Parse(json);
+ var edges = doc.RootElement.GetProperty("data")
+ .GetProperty("allCards")
+ .GetProperty("edges");
+
+ int count = 0;
+ int delayMs = (int)(60000 / _requestsPerMinute);
+
+ foreach (var edge in edges.EnumerateArray())
+ {
+ var node = edge.GetProperty("node");
+ long id = long.Parse(node.GetProperty("id").GetString());
+
+ var card = await _context.PipefyCards.FindAsync(id);
+ if (card != null)
+ {
+ card.JsonData = node.GetRawText();
+ }
+ else
+ {
+ await _context.PipefyCards.AddAsync(new PipefyCard
+ {
+ Id = id,
+ JsonData = node.GetRawText()
+ });
+ }
+
+ count++;
+ await Task.Delay(delayMs);
+ }
+
+ await _context.SaveChangesAsync();
+
+ // Atualiza o controle de backup
+ control.LastBackupTime = startTime;
+ await _context.SaveChangesAsync();
+
+ // Grava log
+ _context.BackupLogs.Add(new BackupLog
+ {
+ ExecutionTime = startTime,
+ Status = "SUCCESS",
+ RecordsProcessed = count
+ });
+ await _context.SaveChangesAsync();
+ }
+}
diff --git a/BackupPipefy.Domain/BackupPipefy.Domain.csproj b/BackupPipefy.Domain/BackupPipefy.Domain.csproj
index 125f4c9..9ba7383 100644
--- a/BackupPipefy.Domain/BackupPipefy.Domain.csproj
+++ b/BackupPipefy.Domain/BackupPipefy.Domain.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/BackupPipefy.Domain/Entities/BackupLog.cs b/BackupPipefy.Domain/Entities/BackupLog.cs
index e8d66e0..27eb61f 100644
--- a/BackupPipefy.Domain/Entities/BackupLog.cs
+++ b/BackupPipefy.Domain/Entities/BackupLog.cs
@@ -1,12 +1,13 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace BackupPipefy.Domain.Entities
{
- internal class BackupLog
+ public class BackupLog
{
+ public int LogId { get; set; }
+ public DateTime ExecutionTime { get; set; } = DateTime.Now;
+ public string Status { get; set; }
+ public int RecordsProcessed { get; set; }
+ public string ErrorMessage { get; set; }
}
}
diff --git a/BackupPipefy.Domain/Entities/PipefyCard.cs b/BackupPipefy.Domain/Entities/PipefyCard.cs
index 36eae0a..148ee7c 100644
--- a/BackupPipefy.Domain/Entities/PipefyCard.cs
+++ b/BackupPipefy.Domain/Entities/PipefyCard.cs
@@ -1,12 +1,10 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace BackupPipefy.Domain.Entities
{
- internal class PipefyCard
+ public class PipefyCard
{
+ public long Id { get; set; } // ID do card
+ public string JsonData { get; set; } // JSON bruto retornado pelo GraphQL
}
}
diff --git a/BackupPipefy.Infrastructure/Data/BackupContext.cs b/BackupPipefy.Infrastructure/Data/BackupContext.cs
index 4a60f97..d725db5 100644
--- a/BackupPipefy.Infrastructure/Data/BackupContext.cs
+++ b/BackupPipefy.Infrastructure/Data/BackupContext.cs
@@ -1,12 +1,26 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using BackupPipefy.Domain.Entities;
namespace BackupPipefy.Infrastructure.Data
{
- internal class BackupContext
+ public class BackupContext : DbContext
{
+ public DbSet PipefyCards { get; set; }
+ public DbSet BackupLogs { get; set; }
+ public DbSet BackupControls { get; set; }
+
+ public BackupContext(DbContextOptions options) : base(options) { }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.Entity()
+ .HasKey(c => c.Id);
+
+ modelBuilder.Entity()
+ .HasKey(l => l.LogId);
+
+ modelBuilder.Entity()
+ .HasKey(c => c.Id);
+ }
}
}
diff --git a/BackupPipefy.Infrastructure/Services/PipefyClient.cs b/BackupPipefy.Infrastructure/Services/PipefyClient.cs
new file mode 100644
index 0000000..e99e4a1
--- /dev/null
+++ b/BackupPipefy.Infrastructure/Services/PipefyClient.cs
@@ -0,0 +1,27 @@
+namespace BackupPipefy.Infrastructure.Services
+{
+ public class PipefyClient
+ {
+ private readonly HttpClient _httpClient;
+
+ public PipefyClient(string apiToken)
+ {
+ _httpClient = new HttpClient();
+ _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiToken}");
+ }
+
+ public async Task GetCardsAsync(int pipeId, DateTime? lastUpdated = null)
+ {
+ // Aqui você vai montar sua query GraphQL real
+ string query = "{ allCards { edges { node { id updated_at } } } }";
+
+ var payload = new { query };
+ var content = new StringContent(System.Text.Json.JsonSerializer.Serialize(payload), System.Text.Encoding.UTF8, "application/json");
+
+ var response = await _httpClient.PostAsync("https://api.pipefy.com/graphql", content);
+ response.EnsureSuccessStatusCode();
+
+ return await response.Content.ReadAsStringAsync();
+ }
+ }
+}
\ No newline at end of file