Melhoria do processo de erros definitivos e retry.
Melhoria do processo de estimativa de dados faltantes para atender metodologia da CCEE. Adapatação de modelos para poder inserir dados nulos (faltantes) no banco de dados.
This commit is contained in:
parent
460598c6b5
commit
a8d87addad
@ -1,9 +1,10 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Domain;
|
using Domain;
|
||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using System.Globalization;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace Application
|
namespace Application
|
||||||
{
|
{
|
||||||
@ -36,8 +37,6 @@ namespace Application
|
|||||||
var datas = Enumerable.Range(0, (dataFim - dataIni).Days).Select(i => dataIni.AddDays(i));
|
var datas = Enumerable.Range(0, (dataFim - dataIni).Days).Select(i => dataIni.AddDays(i));
|
||||||
|
|
||||||
await Parallel.ForEachAsync(perfis, async (perfil, ct) =>
|
await Parallel.ForEachAsync(perfis, async (perfil, ct) =>
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.Now}: Iniciado ponto {perfil.CodigoSCDE}");
|
Console.WriteLine($"{DateTime.Now}: Iniciado ponto {perfil.CodigoSCDE}");
|
||||||
if (perfil.Codigo5Minutos == "0" || perfil.Codigo5Minutos == string.Empty)
|
if (perfil.Codigo5Minutos == "0" || perfil.Codigo5Minutos == string.Empty)
|
||||||
@ -47,21 +46,66 @@ namespace Application
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var existentes = (await _postgresRepository.ObterMedicoesAsync(perfil.CodigoSCDE, dataIni, dataFim, ct));
|
var existentes = await ObterMedicoesComRetry(perfil.CodigoSCDE, dataIni, dataFim, ct, errosPersistentes);
|
||||||
|
|
||||||
foreach (DateTime dia in datas)
|
foreach (DateTime dia in datas)
|
||||||
{
|
{
|
||||||
int tentativas = 0;
|
await ProcessarDiaAsync(perfil, dia, existentes, endpoint, errosPersistentes, ct);
|
||||||
bool sucesso = false;
|
}
|
||||||
|
Console.WriteLine($"{DateTime.Now}: Finalizado ponto {perfil.CodigoSCDE}");
|
||||||
|
});
|
||||||
|
|
||||||
while (tentativas < 5 && !sucesso)
|
if (errosPersistentes.Count > 0)
|
||||||
|
{
|
||||||
|
File.WriteAllLines(caminhoLog, new[] { "Perfil;Ponto;Status;Message" }.Concat(errosPersistentes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDictionary<(string, double, int), Medicao>> ObterMedicoesComRetry(
|
||||||
|
string codigoSCDE, DateTime dataIni, DateTime dataFim, CancellationToken ct, ConcurrentBag<string> errosPersistentes)
|
||||||
|
{
|
||||||
|
int tentativas = 0;
|
||||||
|
while (tentativas < 3)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _postgresRepository.ObterMedicoesAsync(codigoSCDE, dataIni, dataFim, ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
tentativas++;
|
||||||
|
if (tentativas >= 3)
|
||||||
|
{
|
||||||
|
errosPersistentes.Add($"{codigoSCDE};Erro;{ex.Message.Replace("\n", "-n-")}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
int backoff = (int)Math.Pow(2, tentativas) * 1000;
|
||||||
|
Console.WriteLine($"Erro ao acessar Postgres ({ex.Message}), tentativa {tentativas}. Aguardando {backoff / 1000}s...");
|
||||||
|
await Task.Delay(backoff, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Dictionary<(string, double, int), Medicao>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessarDiaAsync(
|
||||||
|
Perfil perfil,
|
||||||
|
DateTime dia,
|
||||||
|
IDictionary<(string, double, int), Medicao> existentes,
|
||||||
|
Uri endpoint,
|
||||||
|
ConcurrentBag<string> errosPersistentes,
|
||||||
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
if (perfil.DataDeMigracao > dia)
|
if (perfil.DataDeMigracao > dia)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Pular {perfil.CodigoSCDE} - {dia.ToShortDateString()} (antes da migração)");
|
Console.WriteLine($"Pular {perfil.CodigoSCDE} - {dia.ToShortDateString()} (antes da migração)");
|
||||||
errosPersistentes.Add($"{perfil.Codigo5Minutos};{perfil.CodigoSCDE};Fora da data de migração {perfil.DataDeMigracao} x {dia}");
|
errosPersistentes.Add($"{perfil.Codigo5Minutos};{perfil.CodigoSCDE};Fora da data de migração {perfil.DataDeMigracao} x {dia}");
|
||||||
break; // não tentar antes da data de migração
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tentativas = 0;
|
||||||
|
bool sucesso = false;
|
||||||
|
while (tentativas < 5 && !sucesso)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string payload = Xml_requisicao(dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, 1);
|
string payload = Xml_requisicao(dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, 1);
|
||||||
@ -79,33 +123,24 @@ namespace Application
|
|||||||
}
|
}
|
||||||
catch (SoapFaultException ex)
|
catch (SoapFaultException ex)
|
||||||
{
|
{
|
||||||
if (ex.ErrorCode == "2003") // limite de requisições
|
if (ex.ErrorCode == "2003")
|
||||||
{
|
{
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
var delay = 60000 - (now.Second * 1000 + now.Millisecond);
|
var delay = 60000 - (now.Second * 1000 + now.Millisecond);
|
||||||
Console.WriteLine($"!! Limite de requisições atingido. Aguardando até {DateTime.Now.AddMilliseconds(delay)}");
|
Console.WriteLine($"!! Limite de requisições atingido. Aguardando até {DateTime.Now.AddMilliseconds(delay)}");
|
||||||
await Task.Delay(delay, ct); // tentar de novo sem contar como falha
|
await Task.Delay(delay, ct);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ex.ErrorCode == "4001") // Dados não encontrados
|
if (ex.ErrorCode == "4001" || ex.ErrorCode == "2001")
|
||||||
{
|
{
|
||||||
errosPersistentes.Add($"{perfil.Codigo5Minutos};{perfil.CodigoSCDE};SOAP Fault: {ex.ErrorCode};{ex.ErrorMessage.Replace("\n", "-n-")}");
|
errosPersistentes.Add($"{perfil.Codigo5Minutos};{perfil.CodigoSCDE};SOAP Fault: {ex.ErrorCode};{ex.ErrorMessage.Replace("\n", "-n-")}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ex.ErrorCode == "2001") // Sem acesso
|
|
||||||
{
|
|
||||||
errosPersistentes.Add($"{perfil.Codigo5Minutos};{perfil.CodigoSCDE};SOAP Fault: {ex.ErrorCode};{ex.ErrorMessage.Replace("\n", "-n-")}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
await ProcessarXMLAsync(resposta, dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, existentes, ct, 1);
|
await ProcessarXMLAsync(resposta, dia, perfil.Codigo5Minutos, perfil.CodigoSCDE, existentes, ct, 1);
|
||||||
|
|
||||||
sucesso = true;
|
sucesso = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -117,26 +152,13 @@ namespace Application
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int backoff = (int)Math.Pow(2.4, tentativas) * 1000; // exponencial
|
int backoff = (int)Math.Pow(2.4, tentativas) * 1000;
|
||||||
Console.WriteLine($"Erro na requisição ({ex.Message}), tentativa {tentativas}. Aguardando {backoff / 1000}s...");
|
Console.WriteLine($"Erro na requisição ({ex.Message}), tentativa {tentativas}. Aguardando {backoff / 1000}s...");
|
||||||
await Task.Delay(backoff);
|
await Task.Delay(backoff, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine($"{DateTime.Now}: Finalizado ponto {perfil.CodigoSCDE}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex.ToString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (errosPersistentes.Count > 0)
|
|
||||||
{
|
|
||||||
File.WriteAllLines(caminhoLog, new[] { "Perfil;Ponto;Status;Message" }.Concat(errosPersistentes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async Task ProcessarXMLAsync(
|
private async Task ProcessarXMLAsync(
|
||||||
string xml,
|
string xml,
|
||||||
DateTime dia,
|
DateTime dia,
|
||||||
@ -208,8 +230,7 @@ namespace Application
|
|||||||
{
|
{
|
||||||
var logica = g.FirstOrDefault(x => x.Origem == "Inspeção Lógica");
|
var logica = g.FirstOrDefault(x => x.Origem == "Inspeção Lógica");
|
||||||
return logica ?? g.First();
|
return logica ?? g.First();
|
||||||
});
|
}).ToList();
|
||||||
|
|
||||||
|
|
||||||
var minutosEsperados = new[] { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 };
|
var minutosEsperados = new[] { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 };
|
||||||
|
|
||||||
@ -218,55 +239,53 @@ namespace Application
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var medidasComEstimativa = new List<Medicao>();
|
var medidasComEstimativa = new List<Medicao>();
|
||||||
|
for (int hora = 0; hora < 24; hora++)
|
||||||
foreach (var grupoHora in medidasPorHora)
|
|
||||||
{
|
{
|
||||||
var lista = grupoHora.OrderBy(m => m.Minuto).ToList();
|
var grupoHora = medidasPorHora.Where(h => h.Key.Hora == hora).ToList();
|
||||||
|
var lista = grupoHora.SelectMany(g => g).OrderBy(m => m.Minuto).ToList();
|
||||||
var minutosPresentes = lista.Select(m => m.Minuto).ToHashSet();
|
var minutosPresentes = lista.Select(m => m.Minuto).ToHashSet();
|
||||||
var minutosEsperadosAbsolutos = minutosEsperados.Select(m => m + (60 * grupoHora.Key.Hora)).ToList();
|
var minutosEsperadosAbsolutos = minutosEsperados.Select(m => m + (60 * hora)).ToList();
|
||||||
var faltantes = minutosEsperadosAbsolutos.Except(minutosPresentes).OrderBy(m => m).ToList();
|
var faltantes = minutosEsperadosAbsolutos.Except(minutosPresentes).OrderBy(m => m).ToList();
|
||||||
|
|
||||||
// Use apenas valores reais para interpolação
|
// Use apenas valores reais para interpolação
|
||||||
var reais = lista.ToDictionary(m => m.Minuto, m => m);
|
var reais = lista.ToDictionary(m => m.Minuto, m => m);
|
||||||
|
|
||||||
// Identifique sequências de minutos faltantes consecutivos
|
|
||||||
var sequencias = new List<List<int>>();
|
|
||||||
List<int> atual = null;
|
|
||||||
int? ultimo = null;
|
|
||||||
foreach (var min in faltantes)
|
|
||||||
{
|
|
||||||
if (atual == null || ultimo == null || min != ultimo + 5)
|
|
||||||
{
|
|
||||||
atual = new List<int>();
|
|
||||||
sequencias.Add(atual);
|
|
||||||
}
|
|
||||||
atual.Add(min);
|
|
||||||
ultimo = min;
|
|
||||||
}
|
|
||||||
|
|
||||||
var estimadas = new List<Medicao>();
|
var estimadas = new List<Medicao>();
|
||||||
|
|
||||||
foreach (var seq in sequencias)
|
foreach (var faltante in faltantes)
|
||||||
|
{
|
||||||
|
if (faltantes.Count > 3)
|
||||||
|
{
|
||||||
|
// Se mais de 3 faltantes na hora, não faz estimativa
|
||||||
|
var estimada = new Medicao(
|
||||||
|
ponto + "P",
|
||||||
|
(dia.ToOADate() - dia.ToOADate() % 1),
|
||||||
|
faltante,
|
||||||
|
"Faltante",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
estimadas.Add(estimada);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
int minIni = seq.First();
|
|
||||||
int minFim = seq.Last();
|
|
||||||
|
|
||||||
// Busca anterior real
|
// Busca anterior real
|
||||||
var anterior = reais.Values.Where(m => m.Minuto < minIni).OrderByDescending(m => m.Minuto).FirstOrDefault();
|
var anterior = reais.Values.Where(m => m.Minuto < faltante).OrderByDescending(m => m.Minuto).FirstOrDefault();
|
||||||
// Busca posterior real
|
// Busca posterior real
|
||||||
var posterior = reais.Values.Where(m => m.Minuto > minFim).OrderBy(m => m.Minuto).FirstOrDefault();
|
var posterior = reais.Values.Where(m => m.Minuto > faltante).OrderBy(m => m.Minuto).FirstOrDefault();
|
||||||
|
|
||||||
foreach (var minFaltante in seq)
|
var ativaConsumo = Interpolar(anterior?.Minuto, anterior?.AtivaConsumo, posterior?.Minuto, posterior?.AtivaConsumo, faltante) ?? 0;
|
||||||
{
|
var ativaGeracao = Interpolar(anterior?.Minuto, anterior?.AtivaGeracao, posterior?.Minuto, posterior?.AtivaGeracao, faltante) ?? 0;
|
||||||
var ativaConsumo = Interpolar(anterior?.Minuto, anterior?.AtivaConsumo, posterior?.Minuto, posterior?.AtivaConsumo, minFaltante) ?? 0;
|
var reativaConsumo = Interpolar(anterior?.Minuto, anterior?.ReativaConsumo, posterior?.Minuto, posterior?.ReativaConsumo, faltante) ?? 0;
|
||||||
var ativaGeracao = Interpolar(anterior?.Minuto, anterior?.AtivaGeracao, posterior?.Minuto, posterior?.AtivaGeracao, minFaltante) ?? 0;
|
var reativaGeracao = Interpolar(anterior?.Minuto, anterior?.ReativaGeracao, posterior?.Minuto, posterior?.ReativaGeracao, faltante) ?? 0;
|
||||||
var reativaConsumo = Interpolar(anterior?.Minuto, anterior?.ReativaConsumo, posterior?.Minuto, posterior?.ReativaConsumo, minFaltante) ?? 0;
|
|
||||||
var reativaGeracao = Interpolar(anterior?.Minuto, anterior?.ReativaGeracao, posterior?.Minuto, posterior?.ReativaGeracao, minFaltante) ?? 0;
|
|
||||||
|
|
||||||
var estimada = new Medicao(
|
var estimada = new Medicao(
|
||||||
grupoHora.Key.Ponto,
|
grupoHora.First().Key.Ponto,
|
||||||
grupoHora.Key.DiaNum,
|
grupoHora.First().Key.DiaNum,
|
||||||
minFaltante,
|
faltante,
|
||||||
"Estimado",
|
"Estimado",
|
||||||
ativaConsumo,
|
ativaConsumo,
|
||||||
ativaGeracao,
|
ativaGeracao,
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
double DiaNum,
|
double DiaNum,
|
||||||
int Minuto,
|
int Minuto,
|
||||||
string Origem,
|
string Origem,
|
||||||
double AtivaConsumo,
|
double? AtivaConsumo,
|
||||||
double AtivaGeracao,
|
double? AtivaGeracao,
|
||||||
double ReativaConsumo,
|
double? ReativaConsumo,
|
||||||
double ReativaGeracao
|
double? ReativaGeracao
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,8 @@ namespace Infrastructure
|
|||||||
|
|
||||||
string sql = $"SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 AND Unidade_gerenciada ORDER BY cod_smart_unidade";
|
string sql = $"SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 AND Unidade_gerenciada ORDER BY cod_smart_unidade";
|
||||||
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and (Cliente = 'RMC ALIMENTOS' OR Cliente = 'FERREIRA SUPERMERCADO' OR Cliente = 'VANGUARDA ALIMENTOS') AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and (Cliente = 'RMC ALIMENTOS' OR Cliente = 'FERREIRA SUPERMERCADO' OR Cliente = 'VANGUARDA ALIMENTOS') AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
||||||
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'ALMAVIVA' and Unidade = 'GUARULHOS' AND unidadade_gerenciada ORDER BY PerfilCCEE";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'ABEVÊ' and Unidade = 'ABV LOJA 29 - COXIM' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
||||||
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'aeroflex' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
//string sql = "SELECT Cod_5min, Codigo_SCDE, Data_de_Migracao FROM Dados_cadastrais WHERE LEN(Codigo_SCDE) > 5 and Cliente = 'calvi granitos' AND Unidade_gerenciada ORDER BY PerfilCCEE";
|
||||||
|
|
||||||
using var command = new OleDbCommand(sql, connection);
|
using var command = new OleDbCommand(sql, connection);
|
||||||
using var reader = await command.ExecuteReaderAsync(ct);
|
using var reader = await command.ExecuteReaderAsync(ct);
|
||||||
|
|||||||
@ -36,10 +36,10 @@ namespace Infrastructure
|
|||||||
reader.GetDouble(1),
|
reader.GetDouble(1),
|
||||||
reader.GetInt32(2),
|
reader.GetInt32(2),
|
||||||
reader.GetString(3),
|
reader.GetString(3),
|
||||||
reader.GetDouble(4),
|
reader.IsDBNull(4) ? (double?)null : reader.GetDouble(4),
|
||||||
reader.GetDouble(5),
|
reader.IsDBNull(5) ? (double?)null : reader.GetDouble(5),
|
||||||
reader.GetDouble(6),
|
reader.IsDBNull(6) ? (double?)null : reader.GetDouble(6),
|
||||||
reader.GetDouble(7)
|
reader.IsDBNull(7) ? (double?)null : reader.GetDouble(7)
|
||||||
);
|
);
|
||||||
|
|
||||||
existentes[(medicao.Ponto, medicao.DiaNum, medicao.Minuto)] = medicao;
|
existentes[(medicao.Ponto, medicao.DiaNum, medicao.Minuto)] = medicao;
|
||||||
@ -88,10 +88,10 @@ namespace Infrastructure
|
|||||||
AND minuto = @minuto;");
|
AND minuto = @minuto;");
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("origem", m.Origem);
|
cmd.Parameters.AddWithValue("origem", m.Origem);
|
||||||
cmd.Parameters.AddWithValue("ativa_consumo", m.AtivaConsumo);
|
cmd.Parameters.AddWithValue("ativa_consumo", NpgsqlDbType.Numeric, m.AtivaConsumo ?? (object)DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("ativa_geracao", m.AtivaGeracao);
|
cmd.Parameters.AddWithValue("ativa_geracao", NpgsqlDbType.Numeric, m.AtivaGeracao ?? (object)DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("reativa_consumo", m.ReativaConsumo);
|
cmd.Parameters.AddWithValue("reativa_consumo", NpgsqlDbType.Numeric, m.ReativaConsumo ?? (object)DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("reativa_geracao", m.ReativaGeracao);
|
cmd.Parameters.AddWithValue("reativa_geracao", NpgsqlDbType.Numeric, m.ReativaGeracao ?? (object)DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("ponto", m.Ponto);
|
cmd.Parameters.AddWithValue("ponto", m.Ponto);
|
||||||
cmd.Parameters.AddWithValue("dia_num", m.DiaNum);
|
cmd.Parameters.AddWithValue("dia_num", m.DiaNum);
|
||||||
cmd.Parameters.AddWithValue("minuto", m.Minuto);
|
cmd.Parameters.AddWithValue("minuto", m.Minuto);
|
||||||
|
|||||||
@ -12,8 +12,8 @@ class Program
|
|||||||
string caminhoLog = $@"\\srv-dados\documentos\Back\Carteira x.x\Codigo\Erros\log_erros_{inicio:MM_dd_HH_mm}.csv";
|
string caminhoLog = $@"\\srv-dados\documentos\Back\Carteira x.x\Codigo\Erros\log_erros_{inicio:MM_dd_HH_mm}.csv";
|
||||||
//DateTime dataIni = new DateTime(inicio.Year, inicio.Month, 1);
|
//DateTime dataIni = new DateTime(inicio.Year, inicio.Month, 1);
|
||||||
//DateTime dataFim = new DateTime(inicio.Year, inicio.Month, inicio.Day);
|
//DateTime dataFim = new DateTime(inicio.Year, inicio.Month, inicio.Day);
|
||||||
DateTime dataIni = new DateTime(inicio.Year, 1, 1);
|
DateTime dataIni = new DateTime(inicio.Year, 10, 1);
|
||||||
DateTime dataFim = new DateTime(inicio.Year, 2, 1);
|
DateTime dataFim = new DateTime(inicio.Year, 10, 14);
|
||||||
|
|
||||||
// Configuração de dependências (pode usar um container DI depois)
|
// Configuração de dependências (pode usar um container DI depois)
|
||||||
var postgresRepo = new PostgresRepository(PG_CONN_STRING_PROD);
|
var postgresRepo = new PostgresRepository(PG_CONN_STRING_PROD);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user