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.
298 lines
12 KiB
C#
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;", "&").Replace("&", "&");
|
|
RS_Vendedor = Vendedor.XNome.Replace("&amp;", "&").Replace("&", "&");
|
|
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;
|
|
}
|
|
} |