OldComplianceNFs/Program.cs
Giuliano Paschoalino 3033a2e12a Refatoração e reestruturação geral do projeto
Removidas classes, interfaces e testes obsoletos, incluindo `Application.cs`, `NF.cs`, `TERecord.cs`, `FileHandlerFactory.cs`, entre outros. A lógica de inicialização, manipulação de arquivos, validação de notas fiscais e acesso ao banco de dados foi completamente reestruturada ou substituída.

Adicionada a classe `Arquivo` para encapsular informações de arquivos XML e PDF, com suporte a múltiplos PDFs associados a um único XML. Refatorada a classe `NF` para melhorar a organização e lidar com novos requisitos, como cálculo de valores e suporte a diferentes unidades de medida.

A lógica de processamento de arquivos XML foi otimizada para execução paralela, com melhorias na geração de CSV e associação de arquivos. Configurações antigas, como `appsettings.json`, foram removidas. Dependências e namespaces desnecessários foram excluídos.

Adicionados novos tratamentos de exceções, melhorias na modularidade e na clareza do código, além de suporte a novos padrões de saída e codificação. O projeto foi reorganizado para atender a novos requisitos e padrões.
2025-10-13 14:23:26 -03:00

298 lines
12 KiB
C#

using System.Reflection;
using System.Text;
using Unimake.Business.DFe.Xml.NFe;
using System.Data;
using Emit = Unimake.Business.DFe.Xml.NFe.Emit;
using System.Xml;
using Unimake.Business.DFe.Validator.NFe;
class Program
{
static readonly string agora = DateTime.Now.AddMonths(-1).ToString("yyMM");
static async Task Main()
{
string pasta = @"X:\Back\Controle NFs\NFs";
List<Arquivo> arquivosXML = Directory.GetFiles(pasta, "*.Xml").Select(x => new Arquivo(x)).Where(y => y.processar).ToList();
foreach (var pdf in Directory.GetFiles(pasta, "*.pdf"))
{
if (arquivosXML.Any(x => x.Referencia == Path.GetFileName(pdf).Split(" - ").First()))
{
arquivosXML.First(x => x.Referencia == Path.GetFileName(pdf).Split(" - ").First())?.CaminhoPdf.Add(pdf);
}
}
var arquivos = arquivosXML.OrderBy(x => x.DataDeCriacao);
var tarefas = new List<Task<string>>();
var linhas = new List<string>();
//Processar arquivosXML em paralelo
foreach (var arquivo in arquivos)
{
tarefas.Add(ProcessarXMLAsync(arquivo));
//linhas.Add(await ProcessarXMLAsync(arquivo));
}
linhas.AddRange(await Task.WhenAll(tarefas));
// Gerar CSV
StringBuilder csv = new();
foreach (string linha in linhas)
{
csv.AppendLine(linha);
}
// Escrever CSV no StdOut (VBA vai capturar)
Console.OutputEncoding = Encoding.Latin1;
Console.Write(csv.ToString());
//dados.Dispose();
}
public class Arquivo
{
public string CaminhoArquivo { get; set; }
public List<string> CaminhoPdf { get; set; } = [];
public string NomeArquivo { get; set; }
public string TipoArquivo { get; set; }
public string Referencia { get; set; }
public DateTime DataDeCriacao { get; }
public NF NF;
public bool processar = true;
public Arquivo(string caminhoArquivo)
{
//Console.WriteLine($"Lendo {caminhoArquivo}");
if (caminhoArquivo == "X:\\Back\\Controle NFs\\NFs\\173420 - DANFE 000173420 (1).xml")
{
Thread.Sleep(10); // Simula atraso para testes
}
CaminhoArquivo = caminhoArquivo;
NomeArquivo = Path.GetFileName(caminhoArquivo);
TipoArquivo = Path.GetExtension(caminhoArquivo).TrimStart('.');
Referencia = NomeArquivo.Split(" - ").FirstOrDefault() ?? "";
DataDeCriacao = File.GetCreationTime(caminhoArquivo);
if (TipoArquivo.Equals("xml", StringComparison.CurrentCultureIgnoreCase))
{
try
{
NF = new NF(caminhoArquivo);
}
catch
{
processar = false;
}
}
}
}
static async Task<string> ProcessarXMLAsync(Arquivo arquivo)
{
NFresponse response = new();
string status = "";
try
{
if (arquivo.TipoArquivo.Equals("xml", StringComparison.CurrentCultureIgnoreCase))
{
//if (arquivo == @"X:\Back\Controle NFs\NFs\345425911,145611 - NFe35250603984862000194550010001466521382788552-procNFe.xml")
//{
// Thread.Sleep(1000);
//}
NF Current_NF = new(arquivo.CaminhoArquivo);
InfNFe infNFe = new NfeProc().LoadFromFile(arquivo.CaminhoArquivo).NFe.InfNFe.First();
Dest Comprador = infNFe.Dest;
Emit Vendedor = infNFe.Emit;
List<Det> Produtos = infNFe.Det;
float soma1 = Produtos.Sum(prod => (float?)prod.Prod.QCom ?? 0);
decimal soma2 = Produtos.Sum(prod =>
(
(
prod.Prod.UCom == "KWH" ?
prod.Prod.QCom / 1000M :
prod.Prod.QCom
)
) *
(
(
prod.Prod.UCom == "KWH" ?
prod.Prod.VUnCom * 1000M :
prod.Prod.VUnCom
)
));
if (Current_NF.CNPJ_Vendedor == "06981176000158" || Current_NF.CNPJ_Vendedor == "06981176002100" || Current_NF.CNPJ_Vendedor == "17155730000164")
{
soma1 /= 1000;
}
if (soma1 != 0)
{
decimal Valor_unitário = soma2 / (decimal)soma1;
}
response.CNPJ_Comprador = Current_NF.CNPJ_Comprador;
response.CNPJ_Vendedor = Current_NF.CNPJ_Vendedor;
response.Montante_operação = Current_NF.Montante_operação;
response.Valor_unitário = Current_NF.Valor_unitário;
response.Valor_final_c_impostos = Current_NF.Valor_final_c_impostos;
response.RS_Comprador = Current_NF.RS_Comprador ?? "";
response.RS_Vendedor = Current_NF.RS_Vendedor ?? "";
response.Numero_NF = Current_NF.Numero_NF ?? 0;
response.ICMS_NF = Current_NF.ICMS_NF;
status = Current_NF.UF_NF ?? "";
response.Month = Current_NF.Month ?? agora;
}
}
catch (Exception)
{
status = "XML vazio";
}
return await Task.Run(() =>
{
return $"\"{arquivo.CaminhoArquivo}\";\"{arquivo.NomeArquivo}\";\"{arquivo.TipoArquivo}\";\"{arquivo.Referencia}\";\"{response.CNPJ_Comprador}\";\"{response.CNPJ_Vendedor}\";\"{response.Montante_operação.ToString()?.Replace(',', '.')}\";\"{response.Valor_unitário.ToString()?.Replace(',', '.')}\";\"{response.Valor_final_c_impostos.ToString()?.Replace(',', '.')}\";\"{response.RS_Comprador}\";\"{response.RS_Vendedor}\";\"{response.Numero_NF}\";\"{response.ICMS_NF.ToString()?.Replace(',', '.')}\";\"{status}\";\"{arquivo.CaminhoPdf.Join("***")}\";\"{response.Month}\"";
});
}
public static double GetICMS(ICMS icms)
{
var propICMS = icms.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
// Opcional: filtrar apenas pelas que começam com "ICMS"
.Where(p => p.Name.StartsWith("ICMS"))
.ToList();
var primeiraProp = propICMS
.Select(p => new { Prop = p, Valor = p.GetValue(icms) })
.FirstOrDefault(x => x.Valor != null);
if (primeiraProp == null) { return 0; }
if (primeiraProp.Valor == null) { return 0; }
var tipo = primeiraProp.Valor.GetType();
var valor = Convert.ChangeType(primeiraProp.Valor, tipo);
var ListICMSReal = valor.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.Name.StartsWith("PICMS"))
.Select(p => p.GetValue(valor))
.FirstOrDefault();
double ICMSReal = 0;
if (ListICMSReal != null && double.TryParse(ListICMSReal.ToString(), out ICMSReal))
{
ICMSReal /= 100d; // Convert percentage to decimal
}
return ICMSReal;
}
public class NFresponse
{
public string CNPJ_Comprador { get; set; } = "";
public string CNPJ_Vendedor { get; set; } = "";
public decimal Montante_operação { get; set; } = 0;
public decimal Valor_unitário { get; set; } = 0;
public double Valor_final_c_impostos { get; set; } = 0;
public string RS_Comprador { get; set; } = "";
public string RS_Vendedor { get; set; } = "";
public int Numero_NF { get; set; } = 0;
public double ICMS_NF { get; set; } = 0;
public string Month { get; set; } = "";
}
public class NF
{
public NF(string caminhoArquivo)
{
nfeProc = new NfeProc().LoadFromFile(caminhoArquivo);
nfe = nfeProc.NFe;
infNFe = nfe.InfNFe.FirstOrDefault() ?? throw new InvalidOperationException("InfNFe is null or empty.");
Comprador = infNFe.Dest;
Vendedor = infNFe.Emit;
Detalhes = infNFe.Det.First();
Produtos = infNFe.Det;
Impostos = Detalhes.Imposto;
NomeArquivo = Path.GetFileName(caminhoArquivo);
TipoArquivo = Path.GetExtension(caminhoArquivo).TrimStart('.');
Referencia = NF.NomeArquivo.Split(" - ").FirstOrDefault() ?? "";
CNPJ_Comprador = Convert.ToInt64(Comprador.CNPJ ?? Comprador.CPF).ToString(@"00000000000000");
CNPJ_Vendedor = Convert.ToInt64(Vendedor.CNPJ).ToString(@"00000000000000");
Soma2 =
Produtos.Sum(prod =>
(
(
prod.Prod.UCom == "KWH" ?
prod.Prod.QCom / 1000M :
prod.Prod.QCom
)
) *
(
(
prod.Prod.UCom == "KWH" ?
prod.Prod.VUnCom * 1000M :
prod.Prod.VUnCom
)
));
Montante_operação
=
Produtos.Sum(prod =>
(
prod.Prod.UCom == "KWH" ?
prod.Prod.QCom / 1000M :
prod.Prod.QCom
)
);
Valor_unitário =
(
Comprador.EnderDest.UF.ToString() == "SP" &&
Vendedor.EnderEmit.UF.ToString() == "SP"
)
?
(
Montante_operação == 0
?
0
:
(Soma2 / Montante_operação) * (1 - (decimal)ICMS_NF))
:
(
Montante_operação == 0
?
0
:
(Soma2 / Montante_operação)
);
Valor_final_c_impostos = (infNFe.Pag.DetPag.Sum(pag => (pag.VPag)) != 0 ? infNFe.Pag.DetPag.Sum(pag => (pag.VPag)) : ((infNFe.Cobr == null ? infNFe.Total.ICMSTot.VNF : infNFe.Cobr.Fat.VLiq)));
RS_Comprador = Comprador.XNome.Replace("&amp;amp;", "&").Replace("&amp;", "&");
RS_Vendedor = Vendedor.XNome.Replace("&amp;amp;", "&").Replace("&amp;", "&");
Numero_NF = infNFe.Ide.NNF;
ICMS_NF = (GetICMS(Impostos.ICMS) == 0 && Valor_final_c_impostos != 0) ? 1 - ((double)Soma2 / Valor_final_c_impostos) : GetICMS(Impostos.ICMS);
UF_NF = Comprador.EnderDest.UF.ToString();
UF_Vend = Vendedor.EnderEmit.UF.ToString();
Month = infNFe.Ide.DhEmi.AddMonths(-1).ToString("yyMM");
}
static NfeProc nfeProc;
static NFe nfe;
static InfNFe infNFe;
static Dest Comprador;
static Emit Vendedor;
static Det Detalhes;
static List<Det> Produtos;
static Imposto Impostos;
public static string NomeArquivo;
public static string? TipoArquivo;
public string? Referencia;
public string CNPJ_Comprador;
public string CNPJ_Vendedor;
public decimal Soma2;
public decimal Montante_operação;
public decimal Valor_unitário;
public double Valor_final_c_impostos;
public string? RS_Comprador;
public string? RS_Vendedor;
public int? Numero_NF;
public double ICMS_NF;
public string? UF_NF;
public string? UF_Vend;
public string? Month;
}
}