658 lines
29 KiB
C#

namespace Download_Faturas
{
using System.Data.OleDb;
using System.Globalization;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.Intrinsics.X86;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
using Org.BouncyCastle.Asn1.Cmp;
public class Fatura
{
private const string Token = "UFY4VWzqcHYcGNd0gkBOMFL9G5ZThV6gXBQIJ79F5HSqITzavz4Fe7iXvAbJLvZJ";
private JsonElement faturaParsed;
private string? id;
private string? empresa;
private string? unidade;
private string? pastaMiddle;
private string? uc;
private int mes;
private int? pagina;
public Fatura(string id, string fatura_path, HttpClient httpClient)
{
// Utilizado para gerar novo token
// this.token = Req_token(httpClient).ToString();
HttpResponseMessage fatura_response = this.GetStatus(httpClient, Token, id);
if (fatura_response.IsSuccessStatusCode)
{
this.faturaParsed = JsonDocument.Parse(fatura_response.Content.ReadAsStringAsync().Result).RootElement;
this.Agrupada = this.faturaParsed.TryGetProperty("multiple", out var _);
this.Status = this.faturaParsed.GetProperty("status").GetString();
this.Arquivo = new FileInfo(fatura_path);
this.id = id;
if (this.faturaParsed.GetProperty("external").GetString() is not null)
{
this.pagina = JsonDocument.Parse(this.faturaParsed.GetProperty("external").GetString() !).RootElement.GetProperty("origin")[0].GetProperty("page").GetInt32();
}
if (this.Agrupada)
{
this.Agrupada_children = this.faturaParsed.GetProperty("children").EnumerateArray();
}
}
}
public string? Status { get; private set; }
public FileInfo? Arquivo { get; private set; }
public bool Agrupada { get; private set; }
public JsonElement.ArrayEnumerator Agrupada_children { get; private set; }
public void Processar(OleDbConnection conn)
{
// Variavel para armazenar os dados a serem lancados para a TUSD no BD
RecordSet dadosTusd = new ();
// Resultado da fatura processada
Rootobject parsedResult = JsonSerializer.Deserialize<Rootobject>(this.faturaParsed.GetProperty("result")) !;
dadosTusd.Mes = int.Parse(parsedResult.dates.reading.periodUntil.AddDays(-15).ToString("yMM"));
string uc = new Regex("^0+").Replace(parsedResult.locationNumber, string.Empty).Replace("/", string.Empty).Replace("-", string.Empty).Replace(".", string.Empty);
// Vinculo da fatura com os dados cadastrais
int? unidades;
string sqlQuery = $"SELECT COUNT (Cod_Smart_unidade) FROM Dados_cadastrais WHERE Codigo_Instalacao = @uc";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
cmd.Parameters.AddWithValue("@uc", uc);
unidades = (int?)cmd.ExecuteScalar();
if (unidades == 1)
{
sqlQuery = $"SELECT Cod_Smart_unidade, Cliente, Unidade, PerfilCCEE, Submercado, Status_unidade, Grupo, Perfil, Distribuidora, ICMS_TUSD, Demanda_P, Demanda_FP, Caminho_NFs FROM Dados_cadastrais WHERE Codigo_Instalacao = @uc";
}
else
{
sqlQuery = $"SELECT Cod_Smart_unidade, Cliente, Unidade, PerfilCCEE, Submercado, Status_unidade, Grupo, Perfil, Distribuidora, ICMS_TUSD, Demanda_P, Demanda_FP, Caminho_NFs FROM Dados_cadastrais WHERE (CNPJ_CPF LIKE @cnpj AND Codigo_Instalacao = @uc) OR (Razao_Social LIKE @razao_social AND Codigo_Instalacao = @uc)";
}
}
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
if (unidades == 1)
{
cmd.Parameters.AddWithValue("@uc", uc);
}
else
{
cmd.Parameters.AddWithValue("@cnpj", parsedResult.customer.cnpj?[..8] != null ? parsedResult.customer.cnpj?[..8] + "%" : "NAN");
cmd.Parameters.AddWithValue("@uc", uc);
cmd.Parameters.AddWithValue("@razao_social", parsedResult.customer.name);
}
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// Dados cadastrais
dadosTusd.Cod_Smart_unidade = long.Parse(reader["Cod_Smart_unidade"].ToString() !);
dadosTusd.Perfil_CliqCCEE = reader["PerfilCCEE"].ToString();
dadosTusd.Submercado = reader["Submercado"].ToString();
dadosTusd.Ambiente = reader["Status_unidade"].ToString();
dadosTusd.Grupo = reader["Grupo"].ToString();
dadosTusd.Distribuidora = reader["Distribuidora"].ToString();
dadosTusd.ICMS = float.Parse(reader["ICMS_TUSD"].ToString() !);
dadosTusd.Dem_Cont_P = float.Parse(reader["Demanda_P"].ToString() !);
dadosTusd.Dem_Cont_FP = float.Parse(reader["Demanda_FP"].ToString() !);
dadosTusd.Perfil = reader["Perfil"].ToString();
this.pastaMiddle = reader["Caminho_NFs"].ToString();
this.empresa = reader["Cliente"].ToString();
this.unidade = reader["Unidade"].ToString();
}
}
}
// Verifica se a fatura ja foi lançada
bool tusdLanc;
sqlQuery = $"SELECT Cod_TUSD FROM Dados_TUSD WHERE Cod_TUSD = ?";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
double cod_tusd = double.Parse(dadosTusd.Cod_Smart_unidade.ToString() + dadosTusd.Mes.ToString());
cmd.Parameters.AddWithValue("?", cod_tusd);
using (OleDbDataReader reader = cmd.ExecuteReader())
{
tusdLanc = reader.HasRows;
}
}
if (dadosTusd.Cod_Smart_unidade == 0)
{
this.Status = "UNIDADE CONSUMIDORA NÃO LOCALIZADA NO BD";
this.uc = uc;
this.mes = dadosTusd.Mes;
}
else if (tusdLanc)
{
this.Status = "FATURA DUPLICADA NO BD";
this.uc = uc;
this.mes = dadosTusd.Mes;
}
else
{
// PIS e Cofins
sqlQuery = $"SELECT Distribuidoras_PIS.PIS, Distribuidoras_PIS.COFINS FROM Distribuidoras_geral INNER JOIN Distribuidoras_PIS ON Distribuidoras_geral.ID_dist = Distribuidoras_PIS.ID_dist WHERE Distribuidoras_PIS.Mes = ? AND Distribuidoras_geral.Distribuidora = ?";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
cmd.Parameters.AddWithValue("?", dadosTusd.Mes.ToString());
cmd.Parameters.AddWithValue("?", dadosTusd.Distribuidora);
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// PIS e Cofins
dadosTusd.PIS = float.Parse(reader["PIS"].ToString() !);
dadosTusd.COFINS = float.Parse(reader["COFINS"].ToString() !);
}
}
}
// Dados da fatura processada
dadosTusd.Cod_TUSD = long.Parse(dadosTusd.Cod_Smart_unidade.ToString() + dadosTusd.Mes.ToString());
switch (parsedResult.tariffModality, parsedResult.subgroup)
{
case ("blue", _):
dadosTusd.Perfil = "AZUL";
break;
case ("green", _):
dadosTusd.Perfil = "VERDE";
break;
case ("standart", _):
dadosTusd.Perfil = "CONVENCIONAL";
break;
case (_, "B3"):
dadosTusd.Perfil = "CONVENCIONAL";
break;
default:
break;
}
dadosTusd.Valor = parsedResult.totalCharges;
dadosTusd.Inicio_Leitura = parsedResult.dates.reading.periodFrom;
dadosTusd.Fim_leitura = parsedResult.dates.reading.periodUntil;
DateTime d = DateTime.Now;
dadosTusd.Hora_TUSD = new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second);
dadosTusd.Dem_Reativa_kvar = 0;
dadosTusd.Multa = 0;
dadosTusd.Credito = 0;
dadosTusd.Bandeira_RS_MWh = 0;
dadosTusd.FIC_DIC = 0;
dadosTusd.Enc_conexao = 0;
dadosTusd.Liminar_ICMS = 0;
dadosTusd.Outros = 0;
dadosTusd.Cred_livre = 0;
dadosTusd.Tempo_TUSD = 0;
dadosTusd.Lanc_aut = true;
dadosTusd.Rev_atual = true;
dadosTusd.Revisao = 0;
// Loop entre os dados faturados na fatura
int j = 0;
float? dem_Reg_P = null;
float? dem_Reg_FP = null;
float? consumo_Reg_FP = null;
List<(string, float)> insertOthers = new List<(string, float)>();
foreach (Item item in parsedResult.items)
{
switch (item.type, item.period)
{
// Energia Ponta
case ("energy", "peak"):
dadosTusd.Consumo_P = item.billed / 1000;
break;
// Energia Fora de Ponta
case ("energy", "off-peak"):
if (item.kind == "Gen.")
{
dadosTusd.Consumo_FP = dadosTusd.Consumo_FP + (item.billed / 1000);
}
else
{
dadosTusd.Consumo_FP = item.billed / 1000;
}
break;
// Energia Fora de Ponta
case ("energy", "off-peak inductive"):
dadosTusd.Consumo_FP = dadosTusd.Consumo_FP + (item.billed / 1000);
break;
// Energia Fora de Ponta
case ("energy", "off-peak capacitive"):
dadosTusd.Consumo_FP = dadosTusd.Consumo_FP + (item.billed / 1000);
break;
// Demanda
case ("demand", _):
if (item.contract != 0)
{
if (item.period == "peak")
{
dadosTusd.Dem_Reg_P = item.billed;
dadosTusd.Dem_Cont_P = item.contract;
}
else if (item.period == "off-peak")
{
dadosTusd.Dem_Reg_FP = item.billed;
dadosTusd.Dem_Cont_FP = item.contract;
}
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
if (dadosTusd.Perfil == "AZUL")
{
if (item.period == "peak")
{
sqlQuery = $"UPDATE Dados_cadastrais SET Demanda_P = @demanda WHERE Cod_Smart_unidade = @cod_smart_unidade";
cmd.Parameters.AddWithValue("@demanda", item.contract);
cmd.Parameters.AddWithValue("@cod_smart_unidade", dadosTusd.Cod_Smart_unidade);
}
else if (item.period == "off-peak")
{
sqlQuery = $"UPDATE Dados_cadastrais SET Demanda_FP = @demanda WHERE Cod_Smart_unidade = @cod_smart_unidade";
cmd.Parameters.AddWithValue("@demanda", item.contract);
cmd.Parameters.AddWithValue("@cod_smart_unidade", dadosTusd.Cod_Smart_unidade);
}
}
else if (dadosTusd.Perfil == "VERDE")
{
sqlQuery = $"UPDATE Dados_cadastrais SET Demanda_P = @demanda, Demanda_FP = @demanda WHERE Cod_Smart_unidade = @cod_smart_unidade";
cmd.Parameters.AddWithValue("@demanda", item.contract);
cmd.Parameters.AddWithValue("@cod_smart_unidade", dadosTusd.Cod_Smart_unidade);
}
cmd.ExecuteNonQuery();
}
}
break;
// Ilum. publica
case ("publicLighting", _):
dadosTusd.Ilum_Publica = item.charge;
break;
// Energia Reativa
case ("excessReactiveEnergy", _):
dadosTusd.En_Reativa_Mvarh = (item.billed / 1000) + dadosTusd.En_Reativa_Mvarh;
break;
// Demanda Reativa
case ("excessReactiveDemand", _):
dadosTusd.Dem_Reativa_kvar = item.billed;
break;
// Bandeira Tarifaria
case ("flagSurcharge", _):
dadosTusd.Bandeira_RS_MWh = item.charge;
break;
// Items não classificados
case ("other", _):
j++;
// Exclui os items lançados anteriormente para a fatura e cria a instrução SQL para inserir os novos items
if (j == 1)
{
sqlQuery = $"DELETE FROM Dados_TUSD_aux WHERE Cod_TUSD = @cod_tusd";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
cmd.ExecuteNonQuery();
}
}
insertOthers.Add((item.name, item.charge));
break;
}
}
// Busca a demanda registrada nos itens medidos
foreach (Measureditem measuredItem in parsedResult.measuredItems)
{
switch (measuredItem.type, measuredItem.period)
{
case ("demand", "peak"):
dem_Reg_P = measuredItem.measured;
break;
case ("demand", "off-peak"):
dem_Reg_FP = measuredItem.measured;
break;
case ("energy", "off-peak"):
consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured;
break;
case ("energy", "off-peak inductive"):
consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured;
break;
case ("energy", "off-peak capacitive"):
consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured;
break;
case ("energy", "off-peak capacitive green flag"):
consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured;
break;
case ("energy", "off-peak inductive green flag"):
consumo_Reg_FP = consumo_Reg_FP.GetValueOrDefault() + measuredItem.measured;
break;
}
}
if (dem_Reg_P != null && (Math.Round((decimal)dadosTusd.Consumo_FP, 2) == Math.Round((decimal)(consumo_Reg_FP * 1.025 / 1000) !, 2)))
{
dadosTusd.Dem_Reg_P = (float)(dem_Reg_P * 1.025);
}
else if (dem_Reg_P != null)
{
dadosTusd.Dem_Reg_P = (float)dem_Reg_P;
}
if (dem_Reg_FP != null && (Math.Round((decimal)dadosTusd.Consumo_FP, 2) == Math.Round((decimal)(consumo_Reg_FP * 1.025 / 1000) !, 2)))
{
dadosTusd.Dem_Reg_FP = (float)(dem_Reg_FP * 1.025);
}
else if (dem_Reg_FP != null)
{
dadosTusd.Dem_Reg_FP = dem_Reg_FP ?? 0;
}
var dados = dadosTusd.GetType().GetProperties();
StringBuilder fields = new StringBuilder();
StringBuilder values = new StringBuilder();
// Verifica se já existe a fatura lançada | atualizar fatura ou nova fatura
if (tusdLanc)
{
// Cria o comando para atualização da fatura
sqlQuery = "UPDATE Dados_TUSD SET ";
// Loop por todos os dados ja obtidos
PropertyInfo[] propriedades = typeof(RecordSet).GetProperties();
foreach (PropertyInfo propriedade in propriedades)
{
string nomeColuna = propriedade.Name;
// Adicione a coluna à instrução SQL
sqlQuery += $"{nomeColuna} = @{nomeColuna}, ";
}
// Remova a última vírgula e adicione a cláusula WHERE
sqlQuery = sqlQuery.TrimEnd(',', ' ') + $" WHERE Cod_TUSD = @cod_tusd";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
foreach (PropertyInfo propriedade in propriedades)
{
string nomeColuna = propriedade.Name;
object valorColuna = propriedade.GetValue(dadosTusd) ?? string.Empty;
cmd.Parameters.AddWithValue($"@{nomeColuna}", valorColuna);
}
// Valor do código TUSD na cláusula WHERE
cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
cmd.ExecuteNonQuery();
}
// Inseri os itens classificados como "othes" após criar o registro da TUSD devido as relação entre as tabelas
foreach ((string name, float valor) in insertOthers)
{
j++;
sqlQuery = "INSERT INTO Dados_TUSD_aux (Cod_TUSD,Id,Nome,Valor,Cod_lanc) VALUES (@cod_tusd, @j, @name, @valor,0)";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
cmd.Parameters.AddWithValue("@j", j);
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@valor", valor);
cmd.ExecuteNonQuery();
}
}
}
else
{
// Cria o comando para lançar da fatura
sqlQuery = "INSERT INTO Dados_TUSD (";
PropertyInfo[] propriedades = typeof(RecordSet).GetProperties();
int i = 0;
foreach (PropertyInfo propriedade in propriedades)
{
string nomeColuna = propriedade.Name;
// Adicione a coluna à instrução SQL
sqlQuery += $"{nomeColuna}, ";
}
// Remova a última vírgula e adicione a cláusula VALUES
sqlQuery = sqlQuery.TrimEnd(',', ' ') + ") VALUES (";
foreach (PropertyInfo propriedade in propriedades)
{
// Adicione os parâmetros à instrução SQL
string nomeColuna = propriedade.Name;
sqlQuery += $"@{nomeColuna}, ";
}
// Remova a última vírgula e feche a instrução SQL
sqlQuery = sqlQuery.TrimEnd(',', ' ') + ")";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
foreach (PropertyInfo propriedade in propriedades)
{
string nomeColuna = propriedade.Name;
object valorColuna = propriedade.GetValue(dadosTusd) ?? string.Empty;
cmd.Parameters.AddWithValue($"@{nomeColuna}", valorColuna);
}
cmd.ExecuteNonQuery();
}
// Inseri os itens classificados como "othes" após criar o registro da TUSD devido as relação entre as tabelas
j = 0;
foreach ((string name, float valor) in insertOthers)
{
j++;
sqlQuery = "INSERT INTO Dados_TUSD_aux (Cod_TUSD,Id,Nome,Valor,Cod_lanc) VALUES (@cod_tusd, @j, @name, @valor, 0)";
using (OleDbCommand cmd = new OleDbCommand(sqlQuery, conn))
{
cmd.Parameters.AddWithValue("@cod_tusd", dadosTusd.Cod_TUSD);
cmd.Parameters.AddWithValue("@j", j);
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@valor", valor);
cmd.ExecuteNonQuery();
}
}
}
this.Status = "FATURA INCLUIDA NO BD";
this.uc = uc;
this.mes = dadosTusd.Mes;
}
}
public void Mover(bool separar)
{
string destino = string.Empty;
switch (this.Status, separar)
{
case ("UNIDADE CONSUMIDORA NÃO LOCALIZADA NO BD", _):
destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\5 - {this.Status}\ID {this.id!} - Mês {this.mes} - UC {this.uc}.pdf";
if (separar)
{
new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
this.Arquivo = new FileInfo(destino);
}
else
{
try
{
this.Arquivo!.MoveTo(destino);
}
catch
{
}
}
break;
case ("FATURA DUPLICADA NO BD", _):
destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\4 - {this.Status}\ID {this.id!} - Mês {this.mes} - Empresa {this.empresa} - Unidade {this.unidade}.pdf";
if (separar)
{
new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
this.Arquivo = new FileInfo(destino);
}
else
{
try
{
this.Arquivo!.MoveTo(destino);
}
catch
{
}
}
break;
case ("FATURA INCLUIDA NO BD", _):
destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\6 - {this.Status}\ID {this.id!} - Mês {this.mes} - Empresa {this.empresa} - Unidade {this.unidade}.pdf";
if (separar)
{
new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
this.Arquivo = new FileInfo(destino);
}
else
{
try
{
this.Arquivo!.MoveTo(destino);
}
catch
{
}
}
break;
case ("INVALID", _):
destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\7 - ERRO\ID {this.id!} - {this.Arquivo?.Name}";
if (separar)
{
new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
this.Arquivo = new FileInfo(destino);
}
else
{
try
{
this.Arquivo!.MoveTo(destino);
}
catch
{
throw;
}
}
break;
case (_, true):
destino = this.Arquivo?.Directory?.Parent?.FullName + $@"\3 - PROCESSANDO\ID {this.id!} - {this.Arquivo?.Name}";
new PDFSplitter(this.pagina, this.Arquivo!.ToString(), destino);
this.Arquivo = new FileInfo(destino);
break;
}
}
private HttpResponseMessage GetStatus(HttpClient httpClient, string token, string id)
{
var request = new HttpRequestMessage(new HttpMethod("GET"), $"https://api.4docs.cloud/v2/request/status?id={id}");
request.Headers.TryAddWithoutValidation("Authorization", $"Bearer {token}");
var response = httpClient.Send(request);
return response;
}
private string Req_token(HttpClient httpClient)
{
var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.4docs.cloud/v2/oauth2/token");
var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes("smart:vnqtvmesikjzyipc"));
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");
request.Content = new StringContent("grant_type=client_credentials");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
var response = httpClient.Send(request);
return JsonDocument.Parse(response.Content.ReadAsStringAsync().Result).RootElement.GetProperty("access_token").GetString() !;
}
}
public class PDFSplitter
{
public PDFSplitter(int? pagina, string origem, string destino)
{
FileStream document = new FileStream(origem, FileMode.Open, FileAccess.Read, FileShare.Read);
PdfDocument pdfDocument = new PdfDocument(new PdfReader(document));
var split = new CustomPdfSplitter(pdfDocument, pageRange => new PdfWriter(destino));
PdfDocument result = split.ExtractPageRange(new PageRange(pagina.ToString()));
document.Close();
result.Close();
}
}
public class CustomPdfSplitter : PdfSplitter
{
private Func<PageRange, PdfWriter> nextWriter;
public CustomPdfSplitter(PdfDocument pdfDocument, Func<PageRange, PdfWriter> nextWriter)
: base(pdfDocument)
{
this.nextWriter = nextWriter;
}
protected override PdfWriter GetNextPdfWriter(PageRange documentPageRange)
{
return this.nextWriter.Invoke(documentPageRange);
}
}
}