Ajustes para trasmitir expedientes
This commit is contained in:
@@ -20,6 +20,7 @@ namespace EFCDesk.Classes
|
|||||||
|
|
||||||
public class ApiClient : IDisposable
|
public class ApiClient : IDisposable
|
||||||
{
|
{
|
||||||
|
private static readonly HttpClient _sharedHttpClient = new HttpClient();
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly int _maxRetries;
|
private readonly int _maxRetries;
|
||||||
private readonly TimeSpan _retryDelay;
|
private readonly TimeSpan _retryDelay;
|
||||||
@@ -30,12 +31,10 @@ public class ApiClient : IDisposable
|
|||||||
|
|
||||||
public ApiClient(TimeSpan? timeout = null, int maxRetries = 3, TimeSpan? retryDelay = null)
|
public ApiClient(TimeSpan? timeout = null, int maxRetries = 3, TimeSpan? retryDelay = null)
|
||||||
{
|
{
|
||||||
_httpClient = new HttpClient();
|
_httpClient = _sharedHttpClient;
|
||||||
|
|
||||||
if (timeout.HasValue)
|
if (timeout.HasValue && timeout.Value > _httpClient.Timeout)
|
||||||
_httpClient.Timeout = timeout.Value;
|
_httpClient.Timeout = timeout.Value;
|
||||||
else
|
|
||||||
_httpClient.Timeout = TimeSpan.FromSeconds(30);
|
|
||||||
|
|
||||||
_maxRetries = maxRetries >= 0 ? maxRetries : 3;
|
_maxRetries = maxRetries >= 0 ? maxRetries : 3;
|
||||||
_retryDelay = retryDelay ?? TimeSpan.FromSeconds(2);
|
_retryDelay = retryDelay ?? TimeSpan.FromSeconds(2);
|
||||||
@@ -100,9 +99,11 @@ public class ApiClient : IDisposable
|
|||||||
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
// Limpiar headers para esta solicitud
|
// Limpiar headers para esta solicitud
|
||||||
_httpClient.DefaultRequestHeaders.Authorization = null;
|
// _httpClient.DefaultRequestHeaders.Authorization = null;
|
||||||
|
// var response = await _httpClient.PostAsync(refreshUrl, content);
|
||||||
|
|
||||||
var response = await _httpClient.PostAsync(refreshUrl, content);
|
using var request = new HttpRequestMessage(HttpMethod.Post, refreshUrl) { Content = content };
|
||||||
|
var response = await _httpClient.SendAsync(request);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@@ -191,7 +192,7 @@ public class ApiClient : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<string> SendWithRetriesAsync(Func<Task<HttpResponseMessage>> sendFunc, bool requireAuth = true)
|
private async Task<string> SendWithRetriesAsync(Func<HttpRequestMessage> requestFunc, bool requireAuth = true)
|
||||||
{
|
{
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
while (true)
|
while (true)
|
||||||
@@ -199,40 +200,61 @@ public class ApiClient : IDisposable
|
|||||||
attempts++;
|
attempts++;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Asegurar que tenemos token antes de enviar (solo si requiere auth)
|
string? token = null;
|
||||||
if (requireAuth)
|
|
||||||
await EnsureTokenAsync();
|
|
||||||
|
|
||||||
var response = await sendFunc();
|
if (requireAuth)
|
||||||
|
{
|
||||||
|
await EnsureTokenAsync();
|
||||||
|
lock (_tokenLock)
|
||||||
|
{
|
||||||
|
token = _currentToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = requestFunc();
|
||||||
|
|
||||||
|
if (requireAuth && token != null)
|
||||||
|
{
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await _httpClient.SendAsync(request);
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
// Si es 401 Unauthorized y requiere auth, intentar refresh token
|
|
||||||
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized && requireAuth)
|
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized && requireAuth)
|
||||||
{
|
{
|
||||||
bool refreshed = await TryRefreshTokenAsync();
|
bool refreshed = await TryRefreshTokenAsync();
|
||||||
if (refreshed)
|
if (refreshed)
|
||||||
{
|
{
|
||||||
// Reintentar con nuevo token
|
string? newToken = null;
|
||||||
response = await sendFunc();
|
lock (_tokenLock)
|
||||||
|
{
|
||||||
|
newToken = _currentToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newRequest = requestFunc();
|
||||||
|
if (newToken != null)
|
||||||
|
{
|
||||||
|
newRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", newToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
response = await _httpClient.SendAsync(newRequest);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
return await response.Content.ReadAsStringAsync();
|
return await response.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string errorContent = await response.Content.ReadAsStringAsync();
|
string errorContent = await response.Content.ReadAsStringAsync();
|
||||||
// throw new ApiException($"Error {response.StatusCode}: {errorContent}", (int)response.StatusCode);
|
|
||||||
return errorContent;
|
return errorContent;
|
||||||
}
|
}
|
||||||
return await response.Content.ReadAsStringAsync();
|
return await response.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException) when (attempts <= _maxRetries)
|
catch (TaskCanceledException) when (attempts <= _maxRetries)
|
||||||
{
|
{
|
||||||
// Timeout: reintentar
|
|
||||||
await Task.Delay(_retryDelay);
|
await Task.Delay(_retryDelay);
|
||||||
}
|
}
|
||||||
catch (HttpRequestException) when (attempts <= _maxRetries)
|
catch (HttpRequestException) when (attempts <= _maxRetries)
|
||||||
{
|
{
|
||||||
// Error red: reintentar
|
|
||||||
await Task.Delay(_retryDelay);
|
await Task.Delay(_retryDelay);
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
@@ -252,24 +274,24 @@ public class ApiClient : IDisposable
|
|||||||
|
|
||||||
public async Task<string> GetAsync(string url)
|
public async Task<string> GetAsync(string url)
|
||||||
{
|
{
|
||||||
return await SendWithRetriesAsync(() => _httpClient.GetAsync(url));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Get, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> PostJsonAsync(string url, string jsonContent)
|
public async Task<string> PostJsonAsync(string url, string jsonContent)
|
||||||
{
|
{
|
||||||
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
||||||
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, content));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Post, url) { Content = content });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> PutJsonAsync(string url, string jsonContent)
|
public async Task<string> PutJsonAsync(string url, string jsonContent)
|
||||||
{
|
{
|
||||||
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
||||||
return await SendWithRetriesAsync(() => _httpClient.PutAsync(url, content));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Put, url) { Content = content });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> DeleteAsync(string url)
|
public async Task<string> DeleteAsync(string url)
|
||||||
{
|
{
|
||||||
return await SendWithRetriesAsync(() => _httpClient.DeleteAsync(url));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Delete, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Método para enviar archivo y JSON juntos en multipart/form-data
|
// Método para enviar archivo y JSON juntos en multipart/form-data
|
||||||
@@ -290,7 +312,7 @@ public class ApiClient : IDisposable
|
|||||||
var jsonContent = new StringContent(jsonString, System.Text.Encoding.UTF8, "application/json");
|
var jsonContent = new StringContent(jsonString, System.Text.Encoding.UTF8, "application/json");
|
||||||
form.Add(jsonContent, jsonFieldName);
|
form.Add(jsonContent, jsonFieldName);
|
||||||
|
|
||||||
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Post, url) { Content = form });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> PostMultipartAsync(string url, string filePath, string organizacion, string pedimento,
|
public async Task<string> PostMultipartAsync(string url, string filePath, string organizacion, string pedimento,
|
||||||
@@ -316,7 +338,7 @@ public class ApiClient : IDisposable
|
|||||||
form.Add(new StringContent(documentType), "document_type");
|
form.Add(new StringContent(documentType), "document_type");
|
||||||
form.Add(new StringContent(fuente), "fuente");
|
form.Add(new StringContent(fuente), "fuente");
|
||||||
|
|
||||||
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Post, url) { Content = form });
|
||||||
}
|
}
|
||||||
|
|
||||||
//public async Task<string> PostMultipartZipAsync(string url, string token, byte[] zipBytes, string zipFileName, string fileFieldName = "archivos")
|
//public async Task<string> PostMultipartZipAsync(string url, string token, byte[] zipBytes, string zipFileName, string fileFieldName = "archivos")
|
||||||
@@ -369,14 +391,14 @@ public class ApiClient : IDisposable
|
|||||||
//form.Add(new StringContent(documentType), "document_type");
|
//form.Add(new StringContent(documentType), "document_type");
|
||||||
//form.Add(new StringContent(fuente), "fuente");
|
//form.Add(new StringContent(fuente), "fuente");
|
||||||
|
|
||||||
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Post, url) { Content = form });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Método existente que acepta string JSON
|
// Método existente que acepta string JSON
|
||||||
public async Task<string> PostJsonWithoutAuthAsync(string url, string jsonContent)
|
public async Task<string> PostJsonWithoutAuthAsync(string url, string jsonContent)
|
||||||
{
|
{
|
||||||
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
||||||
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, content), requireAuth: false);
|
return await SendWithRetriesAsync(() => new HttpRequestMessage(HttpMethod.Post, url) { Content = content }, requireAuth: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nueva sobrecarga que acepta cualquier objeto
|
// Nueva sobrecarga que acepta cualquier objeto
|
||||||
@@ -460,7 +482,7 @@ public class ApiClient : IDisposable
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_httpClient.Dispose();
|
// No disposing _httpClient because it's a shared singleton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,9 @@ namespace EFCDesk.Classes
|
|||||||
}
|
}
|
||||||
public static string CrearEndpointpedimentoDesk()
|
public static string CrearEndpointpedimentoDesk()
|
||||||
{
|
{
|
||||||
return @"/api/v1/customs/pedimentos/bulk-create-pedimento_desk/";
|
// return @"/api/v1/customs/pedimentos/bulk-create-pedimento_desk/";
|
||||||
|
// return @"/api/v1/customs/pedimentos/bulk-upload-record-zip/";
|
||||||
|
return @"/api/v1/customs/pedimentos/bulk-upload-record-zip-async/";
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Espera hasta que todos los archivos dentro de la carpeta estén libres (no en uso)
|
/// Espera hasta que todos los archivos dentro de la carpeta estén libres (no en uso)
|
||||||
@@ -360,5 +362,53 @@ namespace EFCDesk.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string CrearZipMultipleArchivos(string[] rutasArchivos, string nombreArchivoZip, bool autoLimpiar = false)
|
||||||
|
{
|
||||||
|
string tempRoot = Path.Combine(Path.GetTempPath(), "temp-efc-desk");
|
||||||
|
string tempFolder = Path.Combine(tempRoot, Guid.NewGuid().ToString().ToLower().Replace("-", "").Substring(0, 8));
|
||||||
|
Directory.CreateDirectory(tempFolder);
|
||||||
|
|
||||||
|
string zipPath = Path.Combine(tempFolder, nombreArchivoZip);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
|
||||||
|
{
|
||||||
|
foreach (var rutaArchivo in rutasArchivos)
|
||||||
|
{
|
||||||
|
if (File.Exists(rutaArchivo))
|
||||||
|
{
|
||||||
|
zip.CreateEntryFromFile(rutaArchivo, Path.GetFileName(rutaArchivo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zipPath;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Globales.logger.LogError("Helpers - CrearZipMultipleArchivos", ex);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (autoLimpiar)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Threading.Thread.Sleep(3000);
|
||||||
|
if (Directory.Exists(tempFolder))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempFolder, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Globales.logger.LogError("Helpers - No se pudo limpiar carpeta temporal en CrearZipMultipleArchivos", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace EFCDesk.Classes
|
|||||||
private readonly object _lockProceso = new object();
|
private readonly object _lockProceso = new object();
|
||||||
|
|
||||||
// Parámetros de robustez
|
// Parámetros de robustez
|
||||||
private readonly int _maxConcurrent = 2;
|
private readonly int _maxConcurrent = 1;
|
||||||
private readonly int _perFileTimeoutSeconds = 30;
|
private readonly int _perFileTimeoutSeconds = 30;
|
||||||
private readonly int _maxReintentos = 10; // reintentos de 1 minuto
|
private readonly int _maxReintentos = 10; // reintentos de 1 minuto
|
||||||
private readonly TimeSpan _reintentoDelay = TimeSpan.FromMinutes(1);
|
private readonly TimeSpan _reintentoDelay = TimeSpan.FromMinutes(1);
|
||||||
@@ -225,126 +225,7 @@ namespace EFCDesk.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private async Task ProcesarCarpetaRaizAsync(string carpetaRaiz)
|
private async Task ProcesarCarpetaRaizAsync1(string carpetaRaiz)
|
||||||
//{
|
|
||||||
// if (!Directory.Exists(carpetaRaiz))
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[SKIP] No existe: {carpetaRaiz}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Console.WriteLine($"➡️ Procesando raíz: {carpetaRaiz}");
|
|
||||||
// var nombreRaiz = Path.GetFileName(carpetaRaiz);
|
|
||||||
// var archivos = Directory.GetFiles(carpetaRaiz, "*.*", SearchOption.AllDirectories)
|
|
||||||
// .Where(f => !EsTemporal(f))
|
|
||||||
// .ToArray();
|
|
||||||
|
|
||||||
// if (archivos.Length == 0)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[INFO] Sin archivos en {carpetaRaiz}");
|
|
||||||
// _repo.MarcarCarpetaProcesada(carpetaRaiz);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Reintentos para archivos en uso
|
|
||||||
// int intento = 0;
|
|
||||||
// while (intento <= _maxReintentos)
|
|
||||||
// {
|
|
||||||
// var pendientes = archivos.Where(f => File.Exists(f) && !FileUtil.IsFileReady(f)).ToArray();
|
|
||||||
// if (pendientes.Length == 0) break;
|
|
||||||
|
|
||||||
// if (intento == _maxReintentos)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[WARN] Archivos bloqueados tras {_maxReintentos} intentos. Se omite: {carpetaRaiz}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Console.WriteLine($"[WAIT] {pendientes.Length} archivos bloqueados en {carpetaRaiz}. Reintento {intento + 1}/{_maxReintentos} en {_reintentoDelay.TotalMinutes} min.");
|
|
||||||
// await Task.Delay(_reintentoDelay);
|
|
||||||
// intento++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Filtrar archivos ya procesados (persistente en SQLite)
|
|
||||||
// var archivosAProcesar = new List<string>(archivos.Length);
|
|
||||||
// foreach (var f in archivos)
|
|
||||||
// {
|
|
||||||
// if (_repo.EstaArchivoProcesado(f)) continue;
|
|
||||||
// archivosAProcesar.Add(f);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (archivosAProcesar.Count == 0)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[INFO] Todos los archivos ya fueron procesados en {carpetaRaiz}");
|
|
||||||
// _repo.MarcarCarpetaProcesada(carpetaRaiz);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Crear ZIP aplanado
|
|
||||||
// var rutaZip = Path.Combine(Path.GetDirectoryName(carpetaRaiz)!, $"{nombreRaiz}.zip");
|
|
||||||
// if (File.Exists(rutaZip)) File.Delete(rutaZip);
|
|
||||||
|
|
||||||
// using (var zip = ZipFile.Open(rutaZip, ZipArchiveMode.Create))
|
|
||||||
// {
|
|
||||||
// foreach (var archivo in archivosAProcesar)
|
|
||||||
// {
|
|
||||||
// var nombreArchivo = Path.GetFileName(archivo);
|
|
||||||
|
|
||||||
// // Seguridad adicional: esperar per-file si justo se bloquea
|
|
||||||
// if (!FileUtil.WaitAllFilesReady(new[] { archivo }, _perFileTimeoutSeconds))
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[SKIP] Bloqueado: {archivo}");
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Registrar como procesado antes de subir, para evitar duplicados si se cae después
|
|
||||||
// var sha1 = FileUtil.TryGetSHA1(archivo); // opcional, puede ser null
|
|
||||||
// _repo.RegistrarArchivoProcesado(archivo, nombreArchivo, carpetaRaiz, $"{nombreRaiz}.zip", sha1);
|
|
||||||
|
|
||||||
// // Agregar al zip aplanado (sin directorios)
|
|
||||||
// zip.CreateEntryFromFile(archivo, nombreArchivo, CompressionLevel.Optimal);
|
|
||||||
// Console.WriteLine($" + {nombreArchivo}");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Console.WriteLine($"ZIP creado: {rutaZip}");
|
|
||||||
|
|
||||||
// // 🔌 HOOK: Subir a FTP
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// SubirArchivoFTP(rutaZip);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[FTP ERR] {ex.Message}");
|
|
||||||
// // según tu estrategia, podrías marcar la carpeta como pendiente otra vez
|
|
||||||
// // y retornar aquí para reintentar más tarde.
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 🔌 HOOK: Registrar en API
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// RegistrarArchivoEnAPI(rutaZip);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[API ERR] {ex.Message}");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// File.Delete(rutaZip);
|
|
||||||
// Console.WriteLine($"🧹 ZIP eliminado: {rutaZip}");
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine($"[ZIP DEL ERR] {ex.Message}");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _repo.MarcarCarpetaProcesada(carpetaRaiz);
|
|
||||||
// Console.WriteLine($"✅ Completado: {carpetaRaiz}");
|
|
||||||
//}
|
|
||||||
|
|
||||||
private async Task ProcesarCarpetaRaizAsync(string carpetaRaiz)
|
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(carpetaRaiz))
|
if (!Directory.Exists(carpetaRaiz))
|
||||||
{
|
{
|
||||||
@@ -359,16 +240,6 @@ namespace EFCDesk.Classes
|
|||||||
.Where(f => !EsTemporal(f))
|
.Where(f => !EsTemporal(f))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
// ==== Validar formato de nombre === //
|
|
||||||
//string pattern = @"^\d{2}-\d{2}-\d{4}-\d{7}$";
|
|
||||||
//bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombreRaiz, pattern);
|
|
||||||
//if (!esValido)
|
|
||||||
//{
|
|
||||||
// _repo.MarcarCarpetaProcesada(carpetaRaiz, "Formato Incorrecto");
|
|
||||||
// Console.WriteLine($"[SKIP] Formato Expediente Incorrecto: {nombreRaiz}");
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool esValido = Helpers.EsValidaNomeclaturaCarpeta(nombreRaiz);
|
bool esValido = Helpers.EsValidaNomeclaturaCarpeta(nombreRaiz);
|
||||||
if (!esValido)
|
if (!esValido)
|
||||||
{
|
{
|
||||||
@@ -471,6 +342,7 @@ namespace EFCDesk.Classes
|
|||||||
_dbSemaforo.Release();
|
_dbSemaforo.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crear ZIP aplanado con solo ese archivo
|
||||||
bool respuesa = false;
|
bool respuesa = false;
|
||||||
// 🔌 HOOK: Registrar en API
|
// 🔌 HOOK: Registrar en API
|
||||||
try
|
try
|
||||||
@@ -515,6 +387,319 @@ namespace EFCDesk.Classes
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ProcesarCarpetaRaizAsync(string carpetaRaiz)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(carpetaRaiz))
|
||||||
|
{
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "No existe");
|
||||||
|
Console.WriteLine($"[SKIP] No existe: {carpetaRaiz}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Procesando raíz (ZIP único): {carpetaRaiz}");
|
||||||
|
var nombreRaiz = Path.GetFileName(carpetaRaiz);
|
||||||
|
var archivos = Directory.GetFiles(carpetaRaiz, "*.*", SearchOption.AllDirectories)
|
||||||
|
.Where(f => !EsTemporal(f))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
bool esValido = Helpers.EsValidaNomeclaturaCarpeta(nombreRaiz);
|
||||||
|
if (!esValido)
|
||||||
|
{
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Formato Incorrecto");
|
||||||
|
Console.WriteLine($"[SKIP] Formato Expediente Incorrecto: {nombreRaiz}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archivos.Length == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[INFO] Sin archivos en {carpetaRaiz}");
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Sin Archivos");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intento = 0;
|
||||||
|
while (intento <= _maxReintentos)
|
||||||
|
{
|
||||||
|
var pendientes = archivos.Where(f => File.Exists(f) && !FileUtil.IsFileReady(f)).ToArray();
|
||||||
|
if (pendientes.Length == 0) break;
|
||||||
|
|
||||||
|
if (intento == _maxReintentos)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[WARN] Archivos bloqueados tras {_maxReintentos} intentos. Se omite: {carpetaRaiz}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"[WAIT] {pendientes.Length} archivos bloqueados en {carpetaRaiz}. Reintento {intento + 1}/{_maxReintentos} en {_reintentoDelay.TotalMinutes} min.");
|
||||||
|
await Task.Delay(_reintentoDelay);
|
||||||
|
intento++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var archivosAProcesar = new List<string>(archivos.Length);
|
||||||
|
await _dbSemaforo.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var f in archivos)
|
||||||
|
{
|
||||||
|
if (_repo.EstaArchivoProcesado(f)) continue;
|
||||||
|
archivosAProcesar.Add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_dbSemaforo.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archivosAProcesar.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[INFO] Todos los archivos ya fueron procesados en {carpetaRaiz}");
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesado");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//foreach (var archivo in archivosAProcesar)
|
||||||
|
//{
|
||||||
|
// if (!FileUtil.WaitAllFilesReady(new[] { archivo }, _perFileTimeoutSeconds))
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"[SKIP] Bloqueado: {archivo}");
|
||||||
|
// archivosAProcesar.Remove(archivo);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (Helpers.ObtenerTamanoEnBytes(archivo) <= 0)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"[SKIP] Sin Informacion: {archivo}");
|
||||||
|
// archivosAProcesar.Remove(archivo);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!Helpers.ValidarArchivo(archivo))
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"[SKIP] Extension no valida: {archivo}");
|
||||||
|
// archivosAProcesar.Remove(archivo);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
archivosAProcesar.RemoveAll(archivo =>
|
||||||
|
{
|
||||||
|
if (!FileUtil.WaitAllFilesReady(new[] { archivo }, _perFileTimeoutSeconds))
|
||||||
|
{
|
||||||
|
Globales.logger.LogWarning($"Archivo bloqueado tras múltiples intentos: {archivo}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Helpers.ObtenerTamanoEnBytes(archivo) <= 0)
|
||||||
|
{
|
||||||
|
Globales.logger.LogWarning($"Archivo sin información: {archivo}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Helpers.ValidarArchivo(archivo))
|
||||||
|
{
|
||||||
|
Globales.logger.LogWarning($"Archivo con extensión no válida: {archivo}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (archivosAProcesar.Count == 0)
|
||||||
|
{
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesado");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string sfuente = "";
|
||||||
|
int expedienteLogistico = Properties.Settings.Default.ExpLogistico;
|
||||||
|
int expedienteWinsaai = Properties.Settings.Default.ExpWinsaai;
|
||||||
|
|
||||||
|
if (expedienteWinsaai > 0 && expedienteLogistico > 0)
|
||||||
|
{
|
||||||
|
sfuente = Properties.Settings.Default.ExpLogistico.ToString();
|
||||||
|
}
|
||||||
|
else if (expedienteWinsaai > 0)
|
||||||
|
{
|
||||||
|
sfuente = Properties.Settings.Default.ExpWinsaai.ToString();
|
||||||
|
}
|
||||||
|
else if (expedienteLogistico > 0)
|
||||||
|
{
|
||||||
|
sfuente = Properties.Settings.Default.ExpLogistico.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sfuente = "5";
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, string> metadatos = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "fuente", sfuente },
|
||||||
|
{ "clave_pedimento", "" },
|
||||||
|
{ "pedimento", "" },
|
||||||
|
{ "patente", "" },
|
||||||
|
{ "aduana", "" },
|
||||||
|
{ "tipo_operacion", "" },
|
||||||
|
{ "contribuyente", "" },
|
||||||
|
{ "curp_apoderado", "" },
|
||||||
|
{ "fecha_pago", "" },
|
||||||
|
{ "partidas", "" },
|
||||||
|
};
|
||||||
|
|
||||||
|
bool metadatosCompletos = false;
|
||||||
|
foreach (var archivo in archivosAProcesar)
|
||||||
|
{
|
||||||
|
if (Helpers.EsArchivoXMl(archivo) && !metadatosCompletos)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string xml = File.ReadAllText(archivo);
|
||||||
|
var parser = new PedimentoXmlParser(xml);
|
||||||
|
|
||||||
|
var (tieneError, numeroOperacion) = parser.GetResultadoOperacion();
|
||||||
|
|
||||||
|
string numeroPedimento = parser.GetNumeroPedimento();
|
||||||
|
var encabezado = parser.GetEncabezado();
|
||||||
|
var importador = parser.GetImportador();
|
||||||
|
var fechas = parser.GetFechas();
|
||||||
|
var partidas = parser.GetPartidas();
|
||||||
|
|
||||||
|
if (!tieneError && encabezado.Count > 0)
|
||||||
|
{
|
||||||
|
string[] partes = nombreRaiz.Split("-");
|
||||||
|
|
||||||
|
metadatos["pedimento"] = numeroPedimento;
|
||||||
|
metadatos["clave_pedimento"] = encabezado.ContainsKey("ClavePedimento") ? encabezado["ClavePedimento"] : "";
|
||||||
|
metadatos["patente"] = partes.Length >= 3 ? partes[2] : "";
|
||||||
|
metadatos["aduana"] = encabezado.ContainsKey("AduanaES") ? encabezado["AduanaES"] : "";
|
||||||
|
metadatos["tipo_operacion"] = encabezado.ContainsKey("TipoOperacion") ? encabezado["TipoOperacion"] : "";
|
||||||
|
metadatos["contribuyente"] = importador.ContainsKey("RFC") ? importador["RFC"] : "";
|
||||||
|
metadatos["curp_apoderado"] = encabezado.ContainsKey("CurpApoderado") ? encabezado["CurpApoderado"] : "";
|
||||||
|
metadatos["partidas"] = partidas.Count.ToString();
|
||||||
|
|
||||||
|
foreach (var fecha in fechas)
|
||||||
|
{
|
||||||
|
if (fecha.ContainsKey("TipoClave") && fecha["TipoClave"] == "2" && fecha.ContainsKey("Fecha"))
|
||||||
|
{
|
||||||
|
string[] partesFecha = fecha["Fecha"].Split("-");
|
||||||
|
metadatos["fecha_pago"] = partesFecha[0] + "-" + partesFecha[1] + "-" + partesFecha[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadatosCompletos = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Console.WriteLine($"[WARN] Error al parsear XML {archivo}: {ex.Message}");
|
||||||
|
Globales.logger.LogError($"Error al parsear XML {archivo}", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rutaZip = Path.Combine(Path.GetDirectoryName(carpetaRaiz)!, $"{nombreRaiz}.zip");
|
||||||
|
// if (File.Exists(rutaZip)) File.Delete(rutaZip);
|
||||||
|
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesando");
|
||||||
|
|
||||||
|
string[] archivosParaZip = archivosAProcesar.ToArray();
|
||||||
|
rutaZip = Helpers.CrearZipMultipleArchivos(archivosParaZip, $"{nombreRaiz}.zip");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(rutaZip) || !File.Exists(rutaZip))
|
||||||
|
{
|
||||||
|
Globales.logger.LogError($"No se pudo crear el ZIP para {carpetaRaiz}");
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Pendiente");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool respuesta = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var apiClient = Globales.ApiClientLarge;
|
||||||
|
string UrlPostArchivoZip = DominioEFC + ApiGetPedimentoDesk;
|
||||||
|
|
||||||
|
string respuestaJson = await apiClient.PostMultipartZipAsync(
|
||||||
|
url: UrlPostArchivoZip,
|
||||||
|
filePath: rutaZip,
|
||||||
|
zipFileName: $"{nombreRaiz}.zip",
|
||||||
|
metadatos: metadatos
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!apiClient.IsJson(respuestaJson) || !apiClient.HasJsonData(respuestaJson))
|
||||||
|
{
|
||||||
|
Globales.logger.LogError($"Respuesta inválida de API para {carpetaRaiz}: {respuestaJson}");
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Error API");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JsonHelper.TryParse(respuestaJson, out var root))
|
||||||
|
{
|
||||||
|
var JsonData = JsonHelper.ToDictionary(root);
|
||||||
|
|
||||||
|
if (JsonData != null && JsonData.ContainsKey("tieneError"))
|
||||||
|
{
|
||||||
|
bool tieneError = Convert.ToBoolean(JsonData["tieneError"]);
|
||||||
|
if (tieneError)
|
||||||
|
{
|
||||||
|
string mensaje = Convert.ToString(JsonData["mensaje"]) ?? "Error desconocido";
|
||||||
|
Globales.logger.LogError($"API respondió con error para {carpetaRaiz}: {mensaje}");
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Error API");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string taskId = Convert.ToString(JsonData["task_id"]) ?? "";
|
||||||
|
if (!string.IsNullOrEmpty(taskId))
|
||||||
|
{
|
||||||
|
Globales.logger.LogInfo($"Archivo ZIP enviado a API para {carpetaRaiz}, task_id: {taskId}");
|
||||||
|
_repo.GuardarTaskID(carpetaRaiz, taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
respuesta = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Globales.logger.LogError($"Error al registrar en API para {carpetaRaiz}", ex);
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Error API");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
string tempFolder = Path.GetDirectoryName(rutaZip) ?? "";
|
||||||
|
if (Directory.Exists(tempFolder))
|
||||||
|
{
|
||||||
|
try { Directory.Delete(tempFolder, true); } catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (respuesta)
|
||||||
|
{
|
||||||
|
await _dbSemaforo.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var archivo in archivosAProcesar)
|
||||||
|
{
|
||||||
|
var nombreArchivo = Path.GetFileName(archivo);
|
||||||
|
var sha1 = FileUtil.TryGetSHA1(archivo);
|
||||||
|
_repo.RegistrarArchivoProcesado(archivo, nombreArchivo, carpetaRaiz, $"{nombreRaiz}.zip", sha1);
|
||||||
|
_repo.ActualizarEstadoArchivo(archivo, "Procesado");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_dbSemaforo.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesado");
|
||||||
|
Globales.logger.LogInfo($"Proceso Completado (ZIP único): {carpetaRaiz} - {archivosAProcesar.Count} archivos");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Pendiente");
|
||||||
|
Globales.logger.LogError($"Proceso Fallido (ZIP único) para {carpetaRaiz}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool EsTemporal(string path)
|
private static bool EsTemporal(string path)
|
||||||
{
|
{
|
||||||
var name = Path.GetFileName(path);
|
var name = Path.GetFileName(path);
|
||||||
@@ -529,15 +714,7 @@ namespace EFCDesk.Classes
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> RegistrarArchivoEnAPI(string rutaArchivo, string pedimento, Dictionary<string, string>? metadatosPrecalculados = null)
|
||||||
// Implementa tus integraciones reales aquí
|
|
||||||
private void SubirArchivoFTP(string rutaZip)
|
|
||||||
{
|
|
||||||
// TODO: tu implementación real de FTP
|
|
||||||
Console.WriteLine($"[FTP] Subido: {rutaZip}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> RegistrarArchivoEnAPI(string rutaArchivo, string pedimento)
|
|
||||||
{
|
{
|
||||||
// TODO: tu implementación real de API
|
// TODO: tu implementación real de API
|
||||||
try
|
try
|
||||||
@@ -554,7 +731,197 @@ namespace EFCDesk.Classes
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(Token))
|
if (!string.IsNullOrEmpty(Token))
|
||||||
{
|
{
|
||||||
using var apiClient = new ApiClient(timeout: TimeSpan.FromSeconds(600), maxRetries: 3, retryDelay: TimeSpan.FromSeconds(60));
|
var apiClient = Globales.ApiClientLarge;
|
||||||
|
|
||||||
|
string sfuente = "";
|
||||||
|
int expedienteLogistico = Properties.Settings.Default.ExpLogistico;
|
||||||
|
int expedienteWinsaai = Properties.Settings.Default.ExpWinsaai;
|
||||||
|
|
||||||
|
if (expedienteWinsaai > 0 && expedienteLogistico > 0)
|
||||||
|
{
|
||||||
|
sfuente = Properties.Settings.Default.ExpLogistico.ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (expedienteWinsaai > 0)
|
||||||
|
{
|
||||||
|
sfuente = Properties.Settings.Default.ExpWinsaai.ToString();
|
||||||
|
}
|
||||||
|
else if (expedienteLogistico > 0)
|
||||||
|
{
|
||||||
|
sfuente = Properties.Settings.Default.ExpLogistico.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sfuente = "5";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica que el archivo exista
|
||||||
|
if (!File.Exists(rutaArchivo))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, string> metadatos;
|
||||||
|
|
||||||
|
if (metadatosPrecalculados != null)
|
||||||
|
{
|
||||||
|
metadatos = metadatosPrecalculados;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metadatos = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "fuente", sfuente },
|
||||||
|
{ "clave_pedimento", "" },
|
||||||
|
{ "pedimento", "" },
|
||||||
|
{ "patente", "" },
|
||||||
|
{ "aduana", "" },
|
||||||
|
{ "tipo_operacion", "" },
|
||||||
|
{ "contribuyente", "" },
|
||||||
|
{ "curp_apoderado", "" },
|
||||||
|
{ "fecha_pago", "" },
|
||||||
|
{ "partidas", "" },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Helpers.EsArchivoXMl(rutaArchivo))
|
||||||
|
{
|
||||||
|
string xml = File.ReadAllText(rutaArchivo);
|
||||||
|
var parser = new PedimentoXmlParser(xml);
|
||||||
|
|
||||||
|
var (tieneError, numeroOperacion) = parser.GetResultadoOperacion();
|
||||||
|
|
||||||
|
string numeroPedimento = parser.GetNumeroPedimento();
|
||||||
|
var encabezado = parser.GetEncabezado();
|
||||||
|
var importador = parser.GetImportador();
|
||||||
|
var fechas = parser.GetFechas();
|
||||||
|
var partidas = parser.GetPartidas();
|
||||||
|
|
||||||
|
if (!tieneError && encabezado.Count > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
string[] partes = pedimento.Split("-");
|
||||||
|
|
||||||
|
metadatos["pedimento"] = numeroPedimento;
|
||||||
|
metadatos["clave_pedimento"] = encabezado["ClavePedimento"];
|
||||||
|
metadatos["patente"] = partes[2];
|
||||||
|
metadatos["aduana"] = encabezado["AduanaES"];
|
||||||
|
metadatos["tipo_operacion"] = encabezado["TipoOperacion"];
|
||||||
|
metadatos["contribuyente"] = importador["RFC"];
|
||||||
|
metadatos["curp_apoderado"] = encabezado["CurpApoderado"];
|
||||||
|
metadatos["partidas"] = partidas.Count.ToString();
|
||||||
|
|
||||||
|
foreach (var fecha in fechas)
|
||||||
|
{
|
||||||
|
if (fecha["TipoClave"] == "2")
|
||||||
|
{
|
||||||
|
string[] partesFecha = fecha["Fecha"].Split("-");
|
||||||
|
metadatos["fecha_pago"] = partesFecha[0] + "-" + partesFecha[1] + "-" + partesFecha[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string nombreZip = $"{pedimento}.zip";
|
||||||
|
string rutaZip = Helpers.CrearZipArchivoEnTemp(rutaArchivo, nombreZip);
|
||||||
|
|
||||||
|
string UrlPostArchivoZip = DominioEFC + ApiGetPedimentoDesk;
|
||||||
|
string respuestaJson = await apiClient.PostMultipartZipAsync(
|
||||||
|
url: UrlPostArchivoZip,
|
||||||
|
filePath: rutaZip,
|
||||||
|
zipFileName: nombreZip,
|
||||||
|
metadatos: metadatos
|
||||||
|
);
|
||||||
|
|
||||||
|
string tempFolder = Path.GetDirectoryName(rutaZip) ?? "";
|
||||||
|
|
||||||
|
// Borra toda la carpeta temporal
|
||||||
|
if (Directory.Exists(tempFolder))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempFolder, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!apiClient.IsJson(respuestaJson))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!apiClient.HasJsonData(respuestaJson))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JsonHelper.TryParse(respuestaJson, out var root))
|
||||||
|
{
|
||||||
|
var JsonData = JsonHelper.ToDictionary(root);
|
||||||
|
|
||||||
|
if (JsonData == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (JsonData.ContainsKey("tieneError"))
|
||||||
|
{
|
||||||
|
bool tieneError = Convert.ToBoolean(JsonData["tieneError"]);
|
||||||
|
if (tieneError)
|
||||||
|
{
|
||||||
|
string mensaje = Convert.ToString(JsonData["mensaje"]) ?? "Error desconocido";
|
||||||
|
|
||||||
|
logger.LogError($"Se presentan errores al intentar subir los documentos del pedimento {pedimento}");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogError("Error en la configuracion del Id de Usuario:" + DominioEFC, new Exception("Error Id Usuario"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError("Error inesperado SubirArchivoApiAsync", ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"[API] Registrado: {rutaArchivo}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> RegistrarArchivoEnAPI_Original(string rutaArchivo, string pedimento)
|
||||||
|
{
|
||||||
|
// TODO: tu implementación real de API
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var config = ConfiguracionJSON.LoadFromJson();
|
||||||
|
string Token = Globales.accesToken ?? "";
|
||||||
|
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(DominioEFC))
|
||||||
|
{
|
||||||
|
logger.LogError("No se ha configurado el dominio", null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Token))
|
||||||
|
{
|
||||||
|
var apiClient = Globales.ApiClientLarge;
|
||||||
|
|
||||||
string sfuente = "";
|
string sfuente = "";
|
||||||
int expedienteLogistico = Properties.Settings.Default.ExpLogistico;
|
int expedienteLogistico = Properties.Settings.Default.ExpLogistico;
|
||||||
@@ -598,91 +965,6 @@ namespace EFCDesk.Classes
|
|||||||
{ "partidas", "" },
|
{ "partidas", "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
//if (Helpers.EsValidaNomeclaturaSAAIM3(rutaArchivo))
|
|
||||||
//{
|
|
||||||
// // Validar contenido del archivo SAAI M3
|
|
||||||
|
|
||||||
// var registros = SaaiM3Helper.LeerArchivo(rutaArchivo);
|
|
||||||
// var resultados = SaaiM3Helper.BuscarPorTipo(registros, "501");
|
|
||||||
|
|
||||||
// foreach (var reg in resultados)
|
|
||||||
// {
|
|
||||||
// metadatos["clave_pedimento"] = reg.Campos[5];
|
|
||||||
// metadatos["pedimento"] = reg.Campos[2];
|
|
||||||
// metadatos["patente"] = reg.Campos[1];
|
|
||||||
// metadatos["aduana"] = reg.Campos[3];
|
|
||||||
// metadatos["tipo_operacion"] = reg.Campos[4];
|
|
||||||
// metadatos["contribuyente"] = reg.Campos[8];
|
|
||||||
// metadatos["curp_apoderado"] = reg.Campos[9];
|
|
||||||
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// resultados = SaaiM3Helper.BuscarPorTipo(registros, "506");
|
|
||||||
|
|
||||||
// foreach (var reg in resultados)
|
|
||||||
// {
|
|
||||||
// string tipoFechaPago = reg.Campos[2];
|
|
||||||
// if (tipoFechaPago == "2")
|
|
||||||
// {
|
|
||||||
// string fechaOriginal = reg.Campos[3];
|
|
||||||
// DateTime fecha = DateTime.ParseExact(fechaOriginal, "ddMMyyyy", null);
|
|
||||||
|
|
||||||
// metadatos["fecha_pago"] = fecha.ToString("yyyy-MM-dd");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Numero de partidas
|
|
||||||
// resultados = SaaiM3Helper.BuscarPorTipo(registros, "551");
|
|
||||||
// metadatos["partidas"] = resultados.Count.ToString();
|
|
||||||
//}
|
|
||||||
//else if (Helpers.EsArchivoXMl(rutaArchivo))
|
|
||||||
//{
|
|
||||||
|
|
||||||
// //
|
|
||||||
|
|
||||||
// // Validar contenido del XML Pedimento Completo
|
|
||||||
// string xml = File.ReadAllText(rutaArchivo);
|
|
||||||
// var parser = new PedimentoXmlParser(xml);
|
|
||||||
|
|
||||||
// var (tieneError, numeroOperacion) = parser.GetResultadoOperacion();
|
|
||||||
|
|
||||||
// string numeroPedimento = parser.GetNumeroPedimento();
|
|
||||||
// var encabezado = parser.GetEncabezado();
|
|
||||||
// var importador = parser.GetImportador();
|
|
||||||
// var fechas = parser.GetFechas();
|
|
||||||
// var partidas = parser.GetPartidas();
|
|
||||||
|
|
||||||
// if (!tieneError && encabezado.Count > 0)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// string[] partes = pedimento.Split("-");
|
|
||||||
|
|
||||||
// metadatos["pedimento"] = numeroPedimento;
|
|
||||||
// metadatos["clave_pedimento"] = encabezado["ClavePedimento"];
|
|
||||||
// metadatos["patente"] = partes[2];
|
|
||||||
// metadatos["aduana"] = encabezado["AduanaES"];
|
|
||||||
// metadatos["tipo_operacion"] = encabezado["TipoOperacion"];
|
|
||||||
// metadatos["contribuyente"] = importador["RFC"];
|
|
||||||
// metadatos["curp_apoderado"] = encabezado["CurpApoderado"]; ;
|
|
||||||
// metadatos["partidas"] = partidas.Count.ToString();
|
|
||||||
|
|
||||||
// foreach (var fecha in fechas)
|
|
||||||
// {
|
|
||||||
// if (fecha["TipoClave"] == "2")
|
|
||||||
// {
|
|
||||||
// string[] partesFecha = fecha["Fecha"].Split("-");
|
|
||||||
// metadatos["fecha_pago"] = partesFecha[0] + "-" + partesFecha[1] + "-" + partesFecha[2];
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (Helpers.EsArchivoXMl(rutaArchivo))
|
if (Helpers.EsArchivoXMl(rutaArchivo))
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -770,6 +1052,10 @@ namespace EFCDesk.Classes
|
|||||||
bool tieneError = Convert.ToBoolean(JsonData["tieneError"]);
|
bool tieneError = Convert.ToBoolean(JsonData["tieneError"]);
|
||||||
if (tieneError)
|
if (tieneError)
|
||||||
{
|
{
|
||||||
|
string mensaje = Convert.ToString(JsonData["mensaje"]) ?? "Error desconocido";
|
||||||
|
|
||||||
|
logger.LogError($"Se presentan errores al intentar subir los documentos del pedimento {pedimento}");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ namespace EFCDesk.Classes
|
|||||||
Nombre TEXT NOT NULL,
|
Nombre TEXT NOT NULL,
|
||||||
Tipo TEXT NOT NULL, -- Hijo o Nieto
|
Tipo TEXT NOT NULL, -- Hijo o Nieto
|
||||||
Estado TEXT NOT NULL, -- Nuevo o Procesado
|
Estado TEXT NOT NULL, -- Nuevo o Procesado
|
||||||
FechaCreado DATETIME DEFAULT NULL
|
FechaCreado DATETIME DEFAULT NULL,
|
||||||
|
TaskId TEXT DEFAULT NULL
|
||||||
);";
|
);";
|
||||||
string createIndex = @"
|
string createIndex = @"
|
||||||
CREATE INDEX IF NOT EXISTS IX_Carpetas_Estado ON Carpetas(Estado);
|
CREATE INDEX IF NOT EXISTS IX_Carpetas_Estado ON Carpetas(Estado);
|
||||||
@@ -521,6 +522,29 @@ namespace EFCDesk.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool GuardarTaskID(string rutaArchivo, string taskId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var connection = new SQLiteConnection(_connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
string updateQuery = "UPDATE Carpetas SET TaskId=@t WHERE Ruta=@r";
|
||||||
|
using (var command = new SQLiteCommand(updateQuery, connection))
|
||||||
|
{
|
||||||
|
command.Parameters.AddWithValue("@r", rutaArchivo);
|
||||||
|
command.Parameters.AddWithValue("@t", taskId);
|
||||||
|
return command.ExecuteNonQuery() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool EstaArchivoProcesado(string rutaArchivo)
|
public bool EstaArchivoProcesado(string rutaArchivo)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -788,11 +812,11 @@ namespace EFCDesk.Classes
|
|||||||
|
|
||||||
if (buscarExpediente == "*")
|
if (buscarExpediente == "*")
|
||||||
{
|
{
|
||||||
query = "SELECT Id, Nombre, Estado, FechaCreado, Ruta from Carpetas ORDER BY Nombre DESC LIMIT @pageSize OFFSET @offset;";
|
query = "SELECT Id, Nombre, Estado, FechaCreado, Ruta, TaskId from Carpetas ORDER BY Nombre DESC LIMIT @pageSize OFFSET @offset;";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
query = "SELECT Id, Nombre, Estado, FechaCreado, Ruta from Carpetas WHERE Nombre LIKE '%' || @Expediente || '%' LIMIT @pageSize OFFSET @offset;";
|
query = "SELECT Id, Nombre, Estado, FechaCreado, Ruta, TaskId from Carpetas WHERE Nombre LIKE '%' || @Expediente || '%' LIMIT @pageSize OFFSET @offset;";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,7 +837,8 @@ namespace EFCDesk.Classes
|
|||||||
Expediente = reader.GetString(1),
|
Expediente = reader.GetString(1),
|
||||||
Estado = reader.GetString(2),
|
Estado = reader.GetString(2),
|
||||||
FechaCreacion = reader.GetString(3),
|
FechaCreacion = reader.GetString(3),
|
||||||
Ruta = reader.GetString(4)
|
Ruta = reader.GetString(4),
|
||||||
|
TaskId = reader.IsDBNull(5) ? "" : reader.GetString(5)
|
||||||
};
|
};
|
||||||
|
|
||||||
lista.Add(exp);
|
lista.Add(exp);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<ApplicationIcon>EFC.ico</ApplicationIcon>
|
<ApplicationIcon>EFC.ico</ApplicationIcon>
|
||||||
<ErrorReport>send</ErrorReport>
|
<ErrorReport>send</ErrorReport>
|
||||||
<Copyright>Aduanasoft©2025</Copyright>
|
<Copyright>Aduanasoft©2025</Copyright>
|
||||||
<FileVersion>26.2.2.2</FileVersion>
|
<FileVersion>26.3.1.1</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -15,5 +15,7 @@ namespace EFCDesk.Entidades
|
|||||||
public string FechaCreacion { get; set; } = "";
|
public string FechaCreacion { get; set; } = "";
|
||||||
public string Ruta { get; set; } = "";
|
public string Ruta { get; set; } = "";
|
||||||
public string Ticks { get; set; } = "";
|
public string Ticks { get; set; } = "";
|
||||||
|
public string TaskId { get; set; } = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
Forms/FormConfiguracionExpediente.Designer.cs
generated
22
Forms/FormConfiguracionExpediente.Designer.cs
generated
@@ -63,6 +63,7 @@
|
|||||||
textBoxPasswordFTP = new TextBox();
|
textBoxPasswordFTP = new TextBox();
|
||||||
button4 = new Button();
|
button4 = new Button();
|
||||||
button5 = new Button();
|
button5 = new Button();
|
||||||
|
lblVersion = new Label();
|
||||||
tabControl1.SuspendLayout();
|
tabControl1.SuspendLayout();
|
||||||
tabGeneral.SuspendLayout();
|
tabGeneral.SuspendLayout();
|
||||||
groupBox1.SuspendLayout();
|
groupBox1.SuspendLayout();
|
||||||
@@ -89,6 +90,7 @@
|
|||||||
//
|
//
|
||||||
// tabGeneral
|
// tabGeneral
|
||||||
//
|
//
|
||||||
|
tabGeneral.Controls.Add(lblVersion);
|
||||||
tabGeneral.Controls.Add(groupBox1);
|
tabGeneral.Controls.Add(groupBox1);
|
||||||
tabGeneral.Controls.Add(groupBoxEspacio);
|
tabGeneral.Controls.Add(groupBoxEspacio);
|
||||||
tabGeneral.Location = new Point(4, 26);
|
tabGeneral.Location = new Point(4, 26);
|
||||||
@@ -154,10 +156,10 @@
|
|||||||
//
|
//
|
||||||
tabPage2.Controls.Add(groupBox4);
|
tabPage2.Controls.Add(groupBox4);
|
||||||
tabPage2.Controls.Add(groupBox3);
|
tabPage2.Controls.Add(groupBox3);
|
||||||
tabPage2.Location = new Point(4, 26);
|
tabPage2.Location = new Point(4, 24);
|
||||||
tabPage2.Name = "tabPage2";
|
tabPage2.Name = "tabPage2";
|
||||||
tabPage2.Padding = new Padding(3);
|
tabPage2.Padding = new Padding(3);
|
||||||
tabPage2.Size = new Size(288, 252);
|
tabPage2.Size = new Size(288, 254);
|
||||||
tabPage2.TabIndex = 1;
|
tabPage2.TabIndex = 1;
|
||||||
tabPage2.Text = "Archivos";
|
tabPage2.Text = "Archivos";
|
||||||
tabPage2.UseVisualStyleBackColor = true;
|
tabPage2.UseVisualStyleBackColor = true;
|
||||||
@@ -247,10 +249,10 @@
|
|||||||
tabPage1.Controls.Add(label6);
|
tabPage1.Controls.Add(label6);
|
||||||
tabPage1.Controls.Add(txtDiminioEFC);
|
tabPage1.Controls.Add(txtDiminioEFC);
|
||||||
tabPage1.Controls.Add(groupBox5);
|
tabPage1.Controls.Add(groupBox5);
|
||||||
tabPage1.Location = new Point(4, 26);
|
tabPage1.Location = new Point(4, 24);
|
||||||
tabPage1.Name = "tabPage1";
|
tabPage1.Name = "tabPage1";
|
||||||
tabPage1.Padding = new Padding(3);
|
tabPage1.Padding = new Padding(3);
|
||||||
tabPage1.Size = new Size(288, 252);
|
tabPage1.Size = new Size(288, 254);
|
||||||
tabPage1.TabIndex = 2;
|
tabPage1.TabIndex = 2;
|
||||||
tabPage1.Text = "Avanzados";
|
tabPage1.Text = "Avanzados";
|
||||||
tabPage1.UseVisualStyleBackColor = true;
|
tabPage1.UseVisualStyleBackColor = true;
|
||||||
@@ -416,6 +418,16 @@
|
|||||||
button5.UseVisualStyleBackColor = true;
|
button5.UseVisualStyleBackColor = true;
|
||||||
button5.Click += button5_Click;
|
button5.Click += button5_Click;
|
||||||
//
|
//
|
||||||
|
// lblVersion
|
||||||
|
//
|
||||||
|
lblVersion.AutoSize = true;
|
||||||
|
lblVersion.Font = new Font("Century Gothic", 9F, FontStyle.Bold, GraphicsUnit.Point, 0);
|
||||||
|
lblVersion.Location = new Point(5, 230);
|
||||||
|
lblVersion.Name = "lblVersion";
|
||||||
|
lblVersion.Size = new Size(90, 16);
|
||||||
|
lblVersion.TabIndex = 2;
|
||||||
|
lblVersion.Text = "Versión 1.0.0.0";
|
||||||
|
//
|
||||||
// FormConfiguracionExpediente
|
// FormConfiguracionExpediente
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(7F, 17F);
|
AutoScaleDimensions = new SizeF(7F, 17F);
|
||||||
@@ -437,6 +449,7 @@
|
|||||||
Shown += FormConfiguracionExpediente_Shown;
|
Shown += FormConfiguracionExpediente_Shown;
|
||||||
tabControl1.ResumeLayout(false);
|
tabControl1.ResumeLayout(false);
|
||||||
tabGeneral.ResumeLayout(false);
|
tabGeneral.ResumeLayout(false);
|
||||||
|
tabGeneral.PerformLayout();
|
||||||
groupBox1.ResumeLayout(false);
|
groupBox1.ResumeLayout(false);
|
||||||
groupBox1.PerformLayout();
|
groupBox1.PerformLayout();
|
||||||
groupBoxEspacio.ResumeLayout(false);
|
groupBoxEspacio.ResumeLayout(false);
|
||||||
@@ -491,5 +504,6 @@
|
|||||||
private TextBox textBoxPasswordFTP;
|
private TextBox textBoxPasswordFTP;
|
||||||
private Label label6;
|
private Label label6;
|
||||||
private TextBox txtDiminioEFC;
|
private TextBox txtDiminioEFC;
|
||||||
|
private Label lblVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,6 +236,9 @@ namespace EFCDesk.Forms
|
|||||||
|
|
||||||
private void FormConfiguracionExpediente_Shown(object sender, EventArgs e)
|
private void FormConfiguracionExpediente_Shown(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
lblVersion.Text = "Versión: " + Globales.VersionApp;
|
||||||
|
|
||||||
var configJson = new ConfiguracionJSON();
|
var configJson = new ConfiguracionJSON();
|
||||||
configJson = ConfiguracionJSON.LoadFromJson();
|
configJson = ConfiguracionJSON.LoadFromJson();
|
||||||
|
|
||||||
|
|||||||
1
Forms/FormExpedientes.Designer.cs
generated
1
Forms/FormExpedientes.Designer.cs
generated
@@ -73,6 +73,7 @@
|
|||||||
dgwExpedientes.RowHeadersVisible = false;
|
dgwExpedientes.RowHeadersVisible = false;
|
||||||
dgwExpedientes.Size = new Size(559, 258);
|
dgwExpedientes.Size = new Size(559, 258);
|
||||||
dgwExpedientes.TabIndex = 2;
|
dgwExpedientes.TabIndex = 2;
|
||||||
|
dgwExpedientes.CellClick += dgwExpedientes_CellClick;
|
||||||
//
|
//
|
||||||
// BTN_Buscar
|
// BTN_Buscar
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using EFCDesk.Classes;
|
using EFCDesk.Classes;
|
||||||
|
using FontAwesome.Sharp;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -9,6 +10,7 @@ using System.Globalization;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
@@ -22,12 +24,14 @@ namespace EFCDesk.Forms
|
|||||||
public long _registros;
|
public long _registros;
|
||||||
public long _pagina;
|
public long _pagina;
|
||||||
public long _paginas;
|
public long _paginas;
|
||||||
|
public string? _buscarExpediente;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SQLiteHelper _sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
|
private static SQLiteHelper _sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
|
||||||
private long paginacion = 1000;
|
private long paginacion = 1000;
|
||||||
private bool _clickPorCodigo = false;
|
private bool _clickPorCodigo = false;
|
||||||
private Paginacion _paginacion = new Paginacion();
|
private Paginacion _paginacion = new Paginacion();
|
||||||
|
private string DominioEFC = Helpers.DominioExpedienteElectronico();
|
||||||
|
|
||||||
public FormExpedientes()
|
public FormExpedientes()
|
||||||
{
|
{
|
||||||
@@ -38,7 +42,7 @@ namespace EFCDesk.Forms
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CargarVistaExpedientes(int pagina, string buscarExpediente = "*")
|
private async Task CargarVistaExpedientes(long pagina, string buscarExpediente = "*")
|
||||||
{
|
{
|
||||||
// Limpiar la fuente de datos
|
// Limpiar la fuente de datos
|
||||||
dgwExpedientes.DataSource = null;
|
dgwExpedientes.DataSource = null;
|
||||||
@@ -54,7 +58,26 @@ namespace EFCDesk.Forms
|
|||||||
table.Columns.Add("Expediente", typeof(string));
|
table.Columns.Add("Expediente", typeof(string));
|
||||||
table.Columns.Add("Ruta", typeof(string));
|
table.Columns.Add("Ruta", typeof(string));
|
||||||
table.Columns.Add("Estatus", typeof(string));
|
table.Columns.Add("Estatus", typeof(string));
|
||||||
table.Columns.Add("Fecha Registro", typeof(string));
|
table.Columns.Add("Fecha Registro", typeof(string)); // TaskId
|
||||||
|
table.Columns.Add("TaskId", typeof(string)); // TaskId
|
||||||
|
// Columna de Acciones con botón FontAwesome
|
||||||
|
var columnaAcciones = new DataGridViewImageColumn
|
||||||
|
{
|
||||||
|
Name = "Acciones",
|
||||||
|
HeaderText = "Acciones",
|
||||||
|
Width = 50,
|
||||||
|
ImageLayout = DataGridViewImageCellLayout.Zoom
|
||||||
|
};
|
||||||
|
|
||||||
|
// Columna de acciones
|
||||||
|
//table.Columns.Add("Acciones", typeof(Image));
|
||||||
|
|
||||||
|
// Crear el icono UNA sola vez
|
||||||
|
Bitmap iconoVer = IconChar.Eye.ToBitmap(
|
||||||
|
IconFont.Auto,
|
||||||
|
16,
|
||||||
|
Color.Black
|
||||||
|
);
|
||||||
|
|
||||||
foreach (var exp in listaExpedientes)
|
foreach (var exp in listaExpedientes)
|
||||||
{
|
{
|
||||||
@@ -63,6 +86,8 @@ namespace EFCDesk.Forms
|
|||||||
row["Ruta"] = exp.Ruta;
|
row["Ruta"] = exp.Ruta;
|
||||||
row["Estatus"] = exp.Estado;
|
row["Estatus"] = exp.Estado;
|
||||||
row["Fecha Registro"] = exp.FechaCreacion;
|
row["Fecha Registro"] = exp.FechaCreacion;
|
||||||
|
row["TaskId"] = exp.TaskId;
|
||||||
|
//row["Acciones"] = iconoVer;
|
||||||
table.Rows.Add(row);
|
table.Rows.Add(row);
|
||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
@@ -90,6 +115,10 @@ namespace EFCDesk.Forms
|
|||||||
dgwExpedientes.Columns["Fecha Registro"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
|
dgwExpedientes.Columns["Fecha Registro"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
|
||||||
dgwExpedientes.Columns["Fecha Registro"].Width = 180;
|
dgwExpedientes.Columns["Fecha Registro"].Width = 180;
|
||||||
|
|
||||||
|
//dgwExpedientes.Columns["Acciones"].Width = 40;
|
||||||
|
//dgwExpedientes.Columns["Acciones"].HeaderText = "";
|
||||||
|
//((DataGridViewImageColumn)dgwExpedientes.Columns["Acciones"]).ImageLayout = DataGridViewImageCellLayout.Zoom;
|
||||||
|
|
||||||
_ = Task.Run(() =>
|
_ = Task.Run(() =>
|
||||||
{
|
{
|
||||||
long total = dgwExpedientes.RowCount;
|
long total = dgwExpedientes.RowCount;
|
||||||
@@ -98,6 +127,7 @@ namespace EFCDesk.Forms
|
|||||||
_paginacion._registros = total;
|
_paginacion._registros = total;
|
||||||
_paginacion._pagina = pagina;
|
_paginacion._pagina = pagina;
|
||||||
_paginacion._paginas = totalPaginas;
|
_paginacion._paginas = totalPaginas;
|
||||||
|
_paginacion._buscarExpediente = ((string.IsNullOrEmpty(buscarExpediente) || string.IsNullOrWhiteSpace(buscarExpediente))) ? "*" : buscarExpediente;
|
||||||
|
|
||||||
ActualizarEtiqueta();
|
ActualizarEtiqueta();
|
||||||
});
|
});
|
||||||
@@ -109,6 +139,7 @@ namespace EFCDesk.Forms
|
|||||||
_paginacion._registros = 0;
|
_paginacion._registros = 0;
|
||||||
_paginacion._pagina = 0;
|
_paginacion._pagina = 0;
|
||||||
_paginacion._paginas = 0;
|
_paginacion._paginas = 0;
|
||||||
|
_paginacion._buscarExpediente = "*";
|
||||||
|
|
||||||
ActualizarEtiqueta();
|
ActualizarEtiqueta();
|
||||||
}
|
}
|
||||||
@@ -116,6 +147,85 @@ namespace EFCDesk.Forms
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string> ConsultarEstadoTareaAsync(string taskId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var apiClient = Globales.ApiClient;
|
||||||
|
string url = DominioEFC + $"/api/v1/tasks/status/?task_id={taskId}";
|
||||||
|
return await apiClient.GetAsync(url);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al consultar estado: {ex.Message}", "Error",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcesarRespuestaTareaAsync(string responseJson, string rutaExpediente)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(responseJson)) return;
|
||||||
|
|
||||||
|
var apiClient = Globales.ApiClient;
|
||||||
|
if (!apiClient.IsJson(responseJson)) return;
|
||||||
|
|
||||||
|
var data = apiClient.TryParseJson<Dictionary<string, object>>(responseJson);
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
// Extraer información
|
||||||
|
string status = data.ContainsKey("status") ? data["status"]?.ToString() ?? "" : "";
|
||||||
|
bool successful = data.ContainsKey("successful") && Convert.ToBoolean(data["successful"]);
|
||||||
|
int documentsCreated = 0;
|
||||||
|
bool tieneError = true;
|
||||||
|
|
||||||
|
if (data.ContainsKey("result") && data["result"] is JsonElement resultElement)
|
||||||
|
{
|
||||||
|
var result = JsonSerializer.Deserialize<Dictionary<string, object>>(resultElement.GetRawText());
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
tieneError = result.ContainsKey("tieneError") && Convert.ToBoolean(result["tieneError"]);
|
||||||
|
documentsCreated = result.ContainsKey("documents_created") ? Convert.ToInt32(result["documents_created"]) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determinar nuevo estado basado en respuesta
|
||||||
|
string nuevoEstado = "Error";
|
||||||
|
string mensaje = "";
|
||||||
|
|
||||||
|
if (successful && !tieneError)
|
||||||
|
{
|
||||||
|
nuevoEstado = "Procesado";
|
||||||
|
mensaje = $"Tarea completada. Documentos creados: {documentsCreated}";
|
||||||
|
}
|
||||||
|
else if (status == "PENDING" || status == "STARTED")
|
||||||
|
{
|
||||||
|
nuevoEstado = "Procesando";
|
||||||
|
mensaje = "Tarea en proceso...";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mensaje = $"Error en tarea: {status}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar en SQLite
|
||||||
|
_sqliteHelper.MarcarCarpetaProcesada(rutaExpediente, nuevoEstado);
|
||||||
|
|
||||||
|
// Mostrar resultado
|
||||||
|
MessageBox.Show(mensaje, "Estado de Tarea", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
|
||||||
|
// Recargar la grilla para ver el cambio
|
||||||
|
long pagina = _paginacion._pagina; // 'long' no puede ser null, así que no se necesita el operador '??'
|
||||||
|
string buscarExpediente = _paginacion._buscarExpediente ?? "*"; // Si es null, usar "*"
|
||||||
|
if (!(pagina > 0))
|
||||||
|
{
|
||||||
|
pagina = 1; // Valor predeterminado si 'pagina' no es válido
|
||||||
|
}
|
||||||
|
|
||||||
|
// await Task.Run(() => CargarVistaExpedientes(pagina: pagina, buscarExpediente: buscarExpediente));
|
||||||
|
await CargarVistaExpedientes(pagina: pagina, buscarExpediente: buscarExpediente);
|
||||||
|
}
|
||||||
|
|
||||||
private async void FormExpedientes_Shown(object sender, EventArgs e)
|
private async void FormExpedientes_Shown(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
edt_Pagina.Text = "1";
|
edt_Pagina.Text = "1";
|
||||||
@@ -255,6 +365,42 @@ namespace EFCDesk.Forms
|
|||||||
BTN_Buscar.PerformClick();
|
BTN_Buscar.PerformClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void dgwExpedientes_CellClick(object sender, DataGridViewCellEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.RowIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var column = dgwExpedientes.Columns[e.ColumnIndex];
|
||||||
|
|
||||||
|
if (column.Name == "Acciones")
|
||||||
|
{
|
||||||
|
object? cellValueExp = dgwExpedientes.Rows[e.RowIndex].Cells["Expediente"].Value;
|
||||||
|
object? cellValueTask = dgwExpedientes.Rows[e.RowIndex].Cells["TaskId"].Value;
|
||||||
|
|
||||||
|
string? expediente = cellValueExp?.ToString();
|
||||||
|
string? taskId = cellValueTask?.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(taskId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
//// Ejecutar trabajo pesado en segundo plano
|
||||||
|
//var resultado = await Task.Run(() =>
|
||||||
|
//{
|
||||||
|
// // Simulación de proceso pesado
|
||||||
|
// Thread.Sleep(1000);
|
||||||
|
// return $"Procesado expediente {taskId}";
|
||||||
|
//});
|
||||||
|
|
||||||
|
//MessageBox.Show(resultado);
|
||||||
|
|
||||||
|
string responseJson = await ConsultarEstadoTareaAsync(taskId);
|
||||||
|
|
||||||
|
await ProcesarRespuestaTareaAsync(responseJson, expediente);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -801,96 +801,96 @@ namespace EFCDesk.Forms
|
|||||||
sqliteHelper.AgregarRegistroErrorLog(e, sNombreClase, currentMethod);
|
sqliteHelper.AgregarRegistroErrorLog(e, sNombreClase, currentMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async Task<bool> SubirArchivoApiAsync(string pedimento, string filePath)
|
// private async Task<bool> SubirArchivoApiAsync(string pedimento, string filePath)
|
||||||
{
|
// {
|
||||||
|
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
var config = ConfiguracionJSON.LoadFromJson();
|
// var config = ConfiguracionJSON.LoadFromJson();
|
||||||
string Token = SecureDataHandler.ReadDataAsPlainText() ?? "";
|
// string Token = SecureDataHandler.ReadDataAsPlainText() ?? "";
|
||||||
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(DominioEFC))
|
// if (string.IsNullOrWhiteSpace(DominioEFC))
|
||||||
{
|
// {
|
||||||
logger.LogError("No se ha configurado el dominio", null);
|
// logger.LogError("No se ha configurado el dominio", null);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Token))
|
// if (!string.IsNullOrEmpty(Token))
|
||||||
{
|
// {
|
||||||
using var apiClient = new ApiClient(timeout: TimeSpan.FromSeconds(10), maxRetries: 3, retryDelay: TimeSpan.FromSeconds(2));
|
// var apiClient = Globales.ApiClient;
|
||||||
string UrlGetPedimento = DominioEFC + ApiGetPedimento + pedimento;
|
// string UrlGetPedimento = DominioEFC + ApiGetPedimento + pedimento;
|
||||||
string jsonResponse = await apiClient.GetAsync(url: UrlGetPedimento);
|
// string jsonResponse = await apiClient.GetAsync(url: UrlGetPedimento);
|
||||||
|
|
||||||
if (!apiClient.IsJson(jsonResponse))
|
// if (!apiClient.IsJson(jsonResponse))
|
||||||
{
|
// {
|
||||||
logger.LogError("Error en la respuesta de la peticion de pedimento al intentar subir el archivo al api:" + DominioEFC, new Exception("Error API"));
|
// logger.LogError("Error en la respuesta de la peticion de pedimento al intentar subir el archivo al api:" + DominioEFC, new Exception("Error API"));
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!apiClient.HasJsonData(jsonResponse))
|
// if (!apiClient.HasJsonData(jsonResponse))
|
||||||
{
|
// {
|
||||||
logger.LogError("No se obtuvo informacion del api:" + DominioEFC, null);
|
// logger.LogError("No se obtuvo informacion del api:" + DominioEFC, null);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var pedimentos = apiClient.TryParseJson<List<Pedimentos>>(jsonResponse);
|
// var pedimentos = apiClient.TryParseJson<List<Pedimentos>>(jsonResponse);
|
||||||
|
|
||||||
if (pedimentos != null)
|
// if (pedimentos != null)
|
||||||
{
|
// {
|
||||||
// Obtener el primer pedimento de la lista
|
// // Obtener el primer pedimento de la lista
|
||||||
var primerPedimento = pedimentos.FirstOrDefault();
|
// var primerPedimento = pedimentos.FirstOrDefault();
|
||||||
string guiOrganizacion = primerPedimento.organizacion;
|
// string guiOrganizacion = primerPedimento.organizacion;
|
||||||
string guiPedimento = primerPedimento.id;
|
// string guiPedimento = primerPedimento.id;
|
||||||
|
|
||||||
string UrlPostArchivo = DominioEFC + ApiPostDocuments;
|
// string UrlPostArchivo = DominioEFC + ApiPostDocuments;
|
||||||
|
|
||||||
string respuesta = await apiClient.PostMultipartAsync(
|
//string respuesta = await apiClient.PostMultipartAsync(
|
||||||
url: UrlPostArchivo,
|
// url: UrlPostArchivo,
|
||||||
filePath: filePath,
|
// filePath: filePath,
|
||||||
organizacion: guiOrganizacion,
|
// organizacion: guiOrganizacion,
|
||||||
pedimento: guiPedimento,
|
// pedimento: guiPedimento,
|
||||||
documentType: "9",
|
// documentType: "9",
|
||||||
fuente: "1"
|
// fuente: "1"
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!apiClient.IsJson(jsonResponse))
|
// if (!apiClient.IsJson(jsonResponse))
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
if (!apiClient.HasJsonData(jsonResponse))
|
// if (!apiClient.HasJsonData(jsonResponse))
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var documentos = apiClient.TryParseJson<List<Documentos>>(jsonResponse);
|
// var documentos = apiClient.TryParseJson<List<Documentos>>(jsonResponse);
|
||||||
if (documentos == null)
|
// if (documentos == null)
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
logger.LogInfo("No se encontro el pedimento");
|
// logger.LogInfo("No se encontro el pedimento");
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
logger.LogError("Error en la configuracion del Id de Usuario:" + DominioEFC, new Exception("Error Id Usuario"));
|
// logger.LogError("Error en la configuracion del Id de Usuario:" + DominioEFC, new Exception("Error Id Usuario"));
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
logger.LogError("Error inesperado SubirArchivoApiAsync", ex);
|
// logger.LogError("Error inesperado SubirArchivoApiAsync", ex);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
private void RegistrarArchivoEnAPI(string file)
|
private void RegistrarArchivoEnAPI(string file)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
81
Program.cs
81
Program.cs
@@ -1,6 +1,8 @@
|
|||||||
using EFCDesk.Classes;
|
using EFCDesk.Classes;
|
||||||
using EFCDesk.Forms;
|
using EFCDesk.Forms;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace EFCDesk
|
namespace EFCDesk
|
||||||
{
|
{
|
||||||
@@ -11,6 +13,10 @@ namespace EFCDesk
|
|||||||
public static ConfiguracionJSON configJson = ConfiguracionJSON.LoadFromJson();
|
public static ConfiguracionJSON configJson = ConfiguracionJSON.LoadFromJson();
|
||||||
public static string accesToken = "";
|
public static string accesToken = "";
|
||||||
public static string refresToken = "";
|
public static string refresToken = "";
|
||||||
|
public static string VersionApp = "1.0.0";
|
||||||
|
|
||||||
|
public static ApiClient ApiClientLarge { get; set; } = null!;
|
||||||
|
public static ApiClient ApiClient { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class Program
|
internal static class Program
|
||||||
@@ -19,7 +25,7 @@ namespace EFCDesk
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static async Task Main()
|
static async Task Main()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -27,6 +33,9 @@ namespace EFCDesk
|
|||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
|
var fileVersionInfo = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
|
||||||
|
Globales.VersionApp = fileVersionInfo.FileVersion ?? "1.0.0";
|
||||||
|
|
||||||
string carpetaBase = @"C:\EFC";
|
string carpetaBase = @"C:\EFC";
|
||||||
if (!Directory.Exists(Globales.configJson.FolderExpediente))
|
if (!Directory.Exists(Globales.configJson.FolderExpediente))
|
||||||
{
|
{
|
||||||
@@ -48,47 +57,23 @@ namespace EFCDesk
|
|||||||
Properties.Settings.Default.urlEFC = Globales.configJson.DominioExp;
|
Properties.Settings.Default.urlEFC = Globales.configJson.DominioExp;
|
||||||
Properties.Settings.Default.Save();
|
Properties.Settings.Default.Save();
|
||||||
|
|
||||||
|
Globales.ApiClientLarge = new ApiClient(
|
||||||
|
timeout: TimeSpan.FromSeconds(600),
|
||||||
|
maxRetries: 3,
|
||||||
|
retryDelay: TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
Globales.ApiClient = new ApiClient(
|
||||||
|
timeout: TimeSpan.FromSeconds(10),
|
||||||
|
maxRetries: 3,
|
||||||
|
retryDelay: TimeSpan.FromSeconds(2));
|
||||||
|
|
||||||
Globales.gMonitor = new MonitorCarpetas(
|
Globales.gMonitor = new MonitorCarpetas(
|
||||||
carpetaBase: carpetaBase,
|
carpetaBase: carpetaBase,
|
||||||
maxConcurrent: 10,
|
maxConcurrent: 1,
|
||||||
perFileTimeoutSeconds: 30,
|
perFileTimeoutSeconds: 30,
|
||||||
maxReintentos: 10
|
maxReintentos: 10
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
//string? data = SecureDataHandler.ReadDataAsPlainText();
|
|
||||||
//if (string.IsNullOrEmpty(data))
|
|
||||||
//{
|
|
||||||
// Application.Run(new Login());
|
|
||||||
|
|
||||||
//} else if (!SecureDataHandler.IsDataValid())
|
|
||||||
//{
|
|
||||||
// MessageBox.Show("Id Usuario incorrecto. favor de revisar.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
|
||||||
// Application.Run(new Login());
|
|
||||||
|
|
||||||
//} else
|
|
||||||
//{
|
|
||||||
// // Antes de llamar a cualquier m<>todo sobre Globales.gMonitor, verifica que no sea null
|
|
||||||
// if (Globales.gMonitor != null && !Globales.gMonitor.ExisteConfiguracionExpediente())
|
|
||||||
// {
|
|
||||||
// Application.Run(new Login());
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// if (Globales.gMonitor != null)
|
|
||||||
// {
|
|
||||||
// Application.Run(new FormMain(Globales.gMonitor));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("Error interno: el monitor de carpetas no est<73> inicializado.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
// Application.Exit();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Al terminar la aplicaci<63>n, liberar el recurso manualmente
|
|
||||||
// Globales.gMonitor?.Dispose();
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool Esvalido = Utils.Util.StringsValidos(Globales.configJson.UsuarioExp, Globales.configJson.PasswordExp);
|
bool Esvalido = Utils.Util.StringsValidos(Globales.configJson.UsuarioExp, Globales.configJson.PasswordExp);
|
||||||
|
|
||||||
if (!Esvalido)
|
if (!Esvalido)
|
||||||
@@ -127,29 +112,9 @@ namespace EFCDesk
|
|||||||
}
|
}
|
||||||
// Al terminar la aplicaci<63>n, liberar el recurso manualmente
|
// Al terminar la aplicaci<63>n, liberar el recurso manualmente
|
||||||
Globales.gMonitor?.Dispose();
|
Globales.gMonitor?.Dispose();
|
||||||
|
Globales.ApiClientLarge?.Dispose();
|
||||||
|
Globales.ApiClient?.Dispose();
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// // Antes de llamar a cualquier m<>todo sobre Globales.gMonitor, verifica que no sea null
|
|
||||||
// if (Globales.gMonitor != null && !Globales.gMonitor.ExisteConfiguracionExpediente())
|
|
||||||
// {
|
|
||||||
// Application.Run(new Login());
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// if (Globales.gMonitor != null)
|
|
||||||
// {
|
|
||||||
// Application.Run(new FormMain(Globales.gMonitor));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("Error interno: el monitor de carpetas no est<73> inicializado.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
// Application.Exit();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Al terminar la aplicaci<63>n, liberar el recurso manualmente
|
|
||||||
// Globales.gMonitor?.Dispose();
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace EFCDesk.Utils
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var apiClient = new ApiClient(timeout: TimeSpan.FromSeconds(600), maxRetries: 3, retryDelay: TimeSpan.FromSeconds(60));
|
var apiClient = Globales.ApiClientLarge;
|
||||||
|
|
||||||
// Crear diccionario con los datos
|
// Crear diccionario con los datos
|
||||||
var loginData = new Dictionary<string, object>
|
var loginData = new Dictionary<string, object>
|
||||||
@@ -245,6 +245,15 @@ namespace EFCDesk.Utils
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string FolderTemporales()
|
||||||
|
{
|
||||||
|
// Obtiene la ruta raíz de la carpeta temporal del sistema
|
||||||
|
string tempPath = Path.Combine(Path.GetTempPath(), "temp-efc-desk");
|
||||||
|
if (!Directory.Exists(tempPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempPath);
|
||||||
|
}
|
||||||
|
return tempPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user