440 lines
20 KiB
C#
Raw Blame History

using System.Data.OleDb;
using System.Text;
using System.Text.Json;
using System.Threading.RateLimiting;
using Download_Faturas;
using iText.Layout.Splitting;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace Webhook_4docs
{
public class Program
{
private static readonly RateLimiter connRateLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
{
PermitLimit = 4
});
public static void Main(string[] args)
{
static string IndexedFilename(string stub, string extension)
{
int ix = 0;
string? filename = null;
if (File.Exists(String.Format("{0}.{1}", stub, extension)))
{
do
{
ix++;
filename = String.Format("{0} ({1}).{2}", stub, ix, extension);
} while (File.Exists(filename));
}
else
{
filename = String.Format("{0}.{1}", stub, extension);
}
return filename;
}
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("appsettings.json");
var connectionString = builder.Configuration.GetConnectionString("WebhookDbContext");
string? appFolder = builder.Configuration["PathBase"];
builder.Services.AddDbContext<WebhookDbContext>(options =>
options.UseNpgsql(connectionString)
);
builder.Services.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.AddConsole();
});
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
var logger = app.Services.GetRequiredService<ILogger<Program>>();
using (var scope = app.Services.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<WebhookDbContext>();
dbContext.Database.EnsureCreated();
dbContext.Database.Migrate();
}
string fatura_arquivo;
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UsePathBase(appFolder);
app.UseRouting();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Use((context, next) =>
{
context.Request.PathBase = new PathString(appFolder);
return next(context);
});
// Endpoint para \api
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapPatch("/api", async context =>
{
string requestBody;
using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, true, 1024, true))
{
requestBody = await reader.ReadToEndAsync();
}
var JsonBody = JsonDocument.Parse(requestBody).RootElement;
string CaminhoDB = "X:/Middle/Informativo Setorial/Modelo Word/BD1_dados cadastrais e faturas.accdb";
if (JsonBody.TryGetProperty("requestID", out JsonElement fatura_ID_json))
{
string fatura_ID = fatura_ID_json.ToString();
if (!JsonBody.TryGetProperty("json", out JsonElement root)) { return; }
JsonElement DadosJson = JsonDocument.Parse(root.ToString()).RootElement;
if (root.Get("documentType")?.ToString().ToLower() == "devec") { return; }
Fatura fatura = new(fatura_ID, JsonBody);
bool completed = false;
while (!completed)
{
var connLease = await connRateLimiter.AcquireAsync();
if (connLease.IsAcquired)
{
using (OleDbConnection conn = new(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + CaminhoDB + ";Jet OLEDB:Database Password=gds21"))
{
if (conn != null)
{
if (conn.State == System.Data.ConnectionState.Closed)
{
await conn.OpenAsync();
}
try
{
fatura.Processar(conn);
}
catch (Exception ex)
{
completed = true;
connLease.Dispose();
throw new Exception(ex.Message);
}
}
}
completed = true;
connLease.Dispose();
}
}
string? status = fatura.Status;
int status_id = 0;
switch (status)
{
case ("FATURA DUPLICADA NO BD"):
status_id = 4;
break;
case ("UNIDADE CONSUMIDORA N<>O LOCALIZADA NO BD"):
status_id = 5;
break;
case ("FATURA INCLUIDA NO BD"):
status_id = 6;
break;
case (_):
status = "ERRO";
status_id = 7;
break;
}
try
{
string path = $@"X:\Middle\Carteira {fatura.Gestao![0]}\Carteira {fatura.Gestao}\Faturas fourdocs\{status_id} - {status}";
if (status_id == 6 && fatura.PastaTUSD!.Exists)
{
path = fatura.PastaTUSD!.FullName;
}
fatura_arquivo = IndexedFilename($@"{path}\ID {fatura_ID!} - M<>s {fatura.Mes} - Empresa {fatura.Empresa} - Unidade {fatura.Unidade}", "pdf");
CriarArquivo(fatura_arquivo, JsonBody.GetProperty("pdfFile").ToString());
var DatabaseModel = new ProcessedInvoices
{
InvoiceId = Int32.Parse(fatura_ID),
DateTimeProcessed = DateTime.UtcNow,
Status = status,
InvoicePath = fatura_arquivo
};
logger.LogInformation("Fatura inclu<6C>da no BD");
using (var scope = app.Services.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<WebhookDbContext>();
dbContext.ProcessedInvoices.Add(DatabaseModel);
await dbContext.SaveChangesAsync();
}
logger.LogInformation("Fatura salva na pasta " + fatura_arquivo);
}
catch
{
logger.LogError("Erro no processamento da fatura");
}
}
else if (JsonBody.TryGetProperty("healthy", out _) && JsonBody.TryGetProperty("blame", out _) && JsonBody.TryGetProperty("locationID", out _))
{
double errorID = 0;
switch (JsonBody.GetProperty("healthy").GetBoolean(), JsonBody.GetProperty("blame").ToString().ToLower())
{
case (false, "user"):
logger.LogError("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " Sem acesso");
errorID = 1;
break;
case (false, "system"):
logger.LogError("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " Com erro de sistema");
errorID = 2;
break;
case (false, _):
logger.LogError("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " Com erro " + JsonBody.GetProperty("blame").ToString());
errorID = 3;
break;
case (true, _):
//logger.LogInformation("Loc ID: " + JsonBody.GetProperty("locationID").ToString() + " est<73> saud<75>vel");
break;
}
int test = await UpdateErrorIdStatusAsync(CaminhoDB, JsonBody.GetProperty("locationID").GetInt64(), errorID, JsonBody.GetProperty("systemText").ToString(), logger);
if (test == 0)
{
await InsertErrorIdStatusAsync(CaminhoDB, errorID, requestBody, logger);
}
}
});
});
app.Run();
}
public static async Task InsertErrorIdStatusAsync(string CaminhoDB, double errorID, string requestBody, ILogger logger)
{
var JsonBody = JsonDocument.Parse(requestBody).RootElement;
// Extra<72><61>o dos valores do JSON
double locationID = JsonBody.GetProperty("locationID").GetInt64();
string accountID = JsonBody.GetProperty("accountID").ToString();
string deliveryTimeStamp = JsonBody.GetProperty("deliveryTimestamp").ToString();
string provider = JsonBody.GetProperty("provider").ToString();
string accessPoint = JsonBody.GetProperty("accessPoint").ToString();
string slaStatus = JsonBody.GetProperty("slaStatus").ToString();
string healthy = JsonBody.GetProperty("healthy").ToString();
string blame = JsonBody.GetProperty("blame").ToString();
string lastSuccess = JsonBody.GetProperty("lastSuccess").ToString();
string active = JsonBody.GetProperty("active").ToString();
string blacklistStatus = JsonBody.GetProperty("blacklistStatus").ToString();
string lastActivated = JsonBody.GetProperty("lastActivated").ToString();
string lastDeactivated = JsonBody.GetProperty("lastDeactivated").ToString();
string lastDeactivatedBy = JsonBody.GetProperty("lastDeactivatedBy").ToString();
int maxRetries = 3;
int attempt = 0;
while (attempt < maxRetries)
{
var connLease = await connRateLimiter.AcquireAsync();
if (connLease.IsAcquired)
{
try
{
using (OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + CaminhoDB + ";Jet OLEDB:Database Password=gds21"))
{
await conn.OpenAsync();
using (OleDbCommand cmd = new OleDbCommand(
@"INSERT INTO AgVirtual4DocsErros (
locationID, accountID, errorID, deliveryTimeStamp, provider, accessPoint, slaStatus,
healthy, blame, lastSuccess, active, blacklistStatus, lastActivated, lastDeactivated, lastDeactivatedBy
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn))
{
// Adiciona par<61>metros de forma segura
cmd.Parameters.AddWithValue("@locationID", locationID);
cmd.Parameters.AddWithValue("@accountID", accountID);
cmd.Parameters.AddWithValue("@errorID", errorID);
cmd.Parameters.AddWithValue("@deliveryTimeStamp", deliveryTimeStamp);
cmd.Parameters.AddWithValue("@provider", provider);
cmd.Parameters.AddWithValue("@accessPoint", accessPoint);
cmd.Parameters.AddWithValue("@slaStatus", slaStatus);
cmd.Parameters.AddWithValue("@healthy", healthy);
cmd.Parameters.AddWithValue("@blame", blame);
cmd.Parameters.AddWithValue("@lastSuccess", lastSuccess);
cmd.Parameters.AddWithValue("@active", active);
cmd.Parameters.AddWithValue("@blacklistStatus", blacklistStatus);
cmd.Parameters.AddWithValue("@lastActivated", lastActivated);
cmd.Parameters.AddWithValue("@lastDeactivated", lastDeactivated);
cmd.Parameters.AddWithValue("@lastDeactivatedBy", lastDeactivatedBy);
// Executa o comando
await cmd.ExecuteNonQueryAsync();
}
}
break; // Sai do loop em caso de sucesso
}
catch (OleDbException ex)
{
// Registra o erro
logger.LogInformation($"Erro no OleDb insert: {ex.Message} (Tentativa {attempt + 1} de {maxRetries})");
if (attempt < maxRetries - 1)
{
// Aguarda antes de tentar novamente
await Task.Delay(1000 * (int)Math.Pow(2, attempt)); // Retry com Backoff Exponencial
}
else
{
// Propaga a exce<63><65>o na <20>ltima tentativa
throw;
}
}
finally
{
connLease.Dispose();
}
attempt++; // Incrementa a tentativa ap<61>s adquirir o lease, mesmo que falhe
}
else
{
// Aguarda um curto per<65>odo antes de tentar novamente se n<>o conseguiu adquirir o lease
await Task.Delay(200);
}
}
}
public static async Task<int> UpdateErrorIdStatusAsync(string CaminhoDB, double location_id, double errorID, string systemText, ILogger logger)
{
int test = 0;
int maxRetries = 3;
int attempt = 0;
while (attempt < maxRetries)
{
var connLease = await connRateLimiter.AcquireAsync();
if (connLease.IsAcquired)
{
try
{
using (OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + CaminhoDB + ";Jet OLEDB:Database Password=gds21"))
{
await conn.OpenAsync();
using (OleDbCommand cmd = new OleDbCommand(
@"UPDATE AgVirtual4Docs
SET errorID = ?, status = ?
WHERE location_id = ?", conn))
{
// Adiciona par<61>metros de forma segura
cmd.Parameters.AddWithValue("@errorID", errorID);
cmd.Parameters.AddWithValue("@status", systemText);
cmd.Parameters.AddWithValue("@location_id", location_id);
// Executa o comando e captura o resultado
test = await cmd.ExecuteNonQueryAsync();
}
}
break; // Sai do loop em caso de sucesso
}
catch (OleDbException ex)
{
// Registra o erro
logger.LogInformation($"Erro no OleDb update: {ex.Message} (Tentativa {attempt + 1} de {maxRetries})");
if (attempt < maxRetries - 1)
{
// Aguarda antes de tentar novamente
await Task.Delay(1000 * (int)Math.Pow(2, attempt)); // Retry com Backoff Exponencial
}
else
{
// Propaga a exce<63><65>o na <20>ltima tentativa
throw;
}
}
finally
{
connLease.Dispose();
}
attempt++; // Incrementa a tentativa ap<61>s adquirir o lease, mesmo que falhe
}
else
{
// Aguarda um curto per<65>odo antes de tentar novamente se n<>o conseguiu adquirir o lease
await Task.Delay(200);
}
}
return test;
}
public static void CriarArquivo(string fatura_arquivo, string pdfFile64)
{
//string fatura_arquivo = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.pdf";
if (!File.Exists(fatura_arquivo))
{
byte[] bytes = Convert.FromBase64String(pdfFile64);
System.IO.FileStream stream = new(fatura_arquivo, FileMode.CreateNew);
System.IO.BinaryWriter writer =
new(stream);
writer.Write(bytes, 0, bytes.Length);
writer.Close();
}
}
}
public static partial class JsonExtensions
{
public static JsonElement? Get(this JsonElement element, string name) =>
element.ValueKind != JsonValueKind.Null && element.ValueKind != JsonValueKind.Undefined && element.TryGetProperty(name, out var value)
? value : (JsonElement?)null;
public static JsonElement? Get(this JsonElement element, int index)
{
if (element.ValueKind == JsonValueKind.Null || element.ValueKind == JsonValueKind.Undefined)
return null;
// Throw if index < 0
return index < element.GetArrayLength() ? element[index] : null;
}
}
}