diff --git a/App_Code/ClsGenerales.vb b/App_Code/ClsGenerales.vb
index 9df264da9..ba614ae20 100644
--- a/App_Code/ClsGenerales.vb
+++ b/App_Code/ClsGenerales.vb
@@ -4018,7 +4018,7 @@ Public Class ClsGenerales
End Try
Return Retorno
End Function
- Public Function CancelarTimbreTimbrado(CveTimbre As Integer, FechaCancelacion As DateTime, CvePACCancelacion As Integer, SelloCancelacion As String, CveUsuario As Integer, CveEmpresa As Integer) As Boolean
+ Public Function CancelarTimbreTimbrado(CveTimbre As Integer, FechaCancelacion As DateTime, CvePACCancelacion As Integer, SelloCancelacion As String, CveUsuario As Integer, CveEmpresa As Integer, Optional RegenerarTimbre As Boolean = False) As Boolean
Dim Retorno As Boolean = False
DataAdapter("PA_Gral_TimbreTimbradoCancelar")
@@ -4030,6 +4030,27 @@ Public Class ClsGenerales
.Add("@SelloCancelacion", SqlDbType.VarChar).Value = SelloCancelacion
.Add("@CveUsuario", SqlDbType.Int).Value = CveUsuario
.Add("@CveEmpresa", SqlDbType.Int).Value = CveEmpresa
+ .Add("@RegenerarTimbre", SqlDbType.Bit).Value = RegenerarTimbre
+ End With
+
+ Try
+ SqlAdapter.Fill(Data)
+ Retorno = True
+ Catch ex As Exception
+ OnError("Ocurrió un error al actualizar el timbrado", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo)
+ End Try
+ Return Retorno
+ End Function
+
+ Public Function ReactivarTimbreEntregaAlmacen(CveTimbre As Integer, CveEntregaAlmacen As Integer, CveUsuario As Integer, CveEmpresa As Integer) As Boolean
+ Dim Retorno As Boolean = False
+ DataAdapter("PA_Gral_TimbreReactivarUpdate")
+
+ With SqlAdapter.SelectCommand.Parameters
+ .Add("@CveTimbre", SqlDbType.Int).Value = CveTimbre
+ .Add("@CveEntregaAlmacen", SqlDbType.Int).Value = CveEntregaAlmacen
+ .Add("@CveUsuario", SqlDbType.Int).Value = CveUsuario
+ .Add("@CveEmpresa", SqlDbType.Int).Value = CveEmpresa
End With
Try
@@ -4040,6 +4061,7 @@ Public Class ClsGenerales
End Try
Return Retorno
End Function
+
Public Function RemoveGralTimbre(CveTimbre As Integer, CveEmpresa As Integer) As Boolean
Dim Retorno As Boolean = False
DataAdapter("PA_Gral_TimbreRemove")
diff --git a/App_Code/ClsPagoScotia.vb b/App_Code/ClsPagoScotia.vb
new file mode 100644
index 000000000..377f7f3b4
--- /dev/null
+++ b/App_Code/ClsPagoScotia.vb
@@ -0,0 +1,910 @@
+Option Explicit On
+Option Strict On
+
+Imports System.Data
+Imports System.Data.SqlClient
+Imports System.IO
+Imports DocumentFormat.OpenXml.Math
+Imports Extensiones
+
+
+Public Class ClsPagoScotia
+ Implements IDisposable
+
+ Public Sub New()
+ ' Constructor privado para evitar instanciación directa
+ End Sub
+
+ '====================================================================
+ ' GeneraPagoScotiaBank – Layout Pagos Scotiabank
+ '====================================================================
+ ' ▸ Genera un archivo de pagos masivos para Scotiabank (Archivo de intercambio EE).
+ ' ▸ Registros y longitudes exactas:
+ ' • HA, HB, DA, TB, TA → 370 caracteres
+ ' • DM (correo) → 104 caracteres
+ ' ▸ Se permite partición por bloques (TamanoBloque), pero todo dentro de un
+ ' mismo método para claridad. Sólo se complementa con LimpiarTextoScotia().
+ '====================================================================
+
+ Public Property ErrorLayout As Boolean = False
+ Public Property LayoutStr As String = String.Empty
+ Public Property LayouErrorStr As String = String.Empty
+ Public Property TotalPagos As Integer = 0
+ Public Property NombreArchivo As String = ""
+
+ Public Function GeneraPagoScotiaBank(ByVal DTPendientes As DataTable, InsertaEnDB As Boolean, CveCuenta As Integer, UsuarioActual As Usuario) As Boolean
+ 'ConvenioPagoElectronico = get_GlobalDTBancosCuentas(UsuarioActual.CveUsuario, CveEmpresa: UsuarioActual.CveEmpresa).FiltroPrimeroValor("ConvenioPagoElectronico", $" CveCuenta = {DdlCuenta.SelectedValue}").ToString();
+ Dim TamanoBloque As Integer = 5000 ' pagos por bloque
+
+ ErrorLayout = False
+ LayoutStr = ""
+ LayouErrorStr = ""
+ TotalPagos = 0
+ NombreArchivo = ""
+ 'Dim ErrorLayout As Boolean = False
+
+ '------------------- VALIDACIONES BÁSICAS ---------------------------
+ If DTPendientes Is Nothing OrElse DTPendientes.Rows.Count = 0 Then
+ LayouErrorStr = "No hay datos pendientes para generar el Layout de ScotiaBank."
+ ErrorLayout = True
+ End If
+
+ Dim CuentaCargo As String = DTPendientes.Rows(0)("CLABEOrigen").ToString
+ If CuentaCargo.Length <> 11 Then
+ LayouErrorStr = "El campo CuentaCargo debe ser numérico de 11 dígitos."
+ ErrorLayout = True
+
+ End If
+
+ Dim NumeroConvenio As String = DTPendientes.Rows(0)("ConvenioPagoElectronico").ToString
+ If NumeroConvenio.Trim.Length = 0 Then
+ LayouErrorStr = "El campo NumeroConvenio (ConvenioPagoElectronico) no está definido en los datos de la cuenta."
+ ErrorLayout = True
+
+ End If
+
+ If NumeroConvenio.Length <> 5 Then
+ LayouErrorStr = "El campo NumeroConvenio debe ser numérico de 5 dígitos."
+ ErrorLayout = True
+
+ End If
+
+
+ '------------------- ACUMULADORES -----------------------------------
+ Dim sb As New StringBuilder()
+ 'Dim totalPagos As Integer = 0
+ Dim totalImporte As Decimal = 0D
+ Dim pagosBloque As Integer = 0
+ Dim importeBloque As Decimal = 0D
+ Dim numBloque As Integer = 0
+
+ Dim SPACE As Char = " "c
+ Dim CERO As Char = "0"c
+
+ '------------------- HEADER ARCHIVO (HA) ----------------------------
+ Dim ha As New StringBuilder()
+ ha.Append("EE") ' 1‑2 Tipo Archivo
+ ha.Append("HA") ' 3‑4 Tipo Registro
+ ha.Append(NumeroConvenio.PadLeft(5, "0"c)) ' 5‑9 Nº Convenio
+ ha.Append("01") ' 10‑11 Secuencia fija "01"
+ ha.Append("00000000") ' 12‑19 Fecha generación
+ ha.Append("00000000") ' 20‑27 Fecha inicial (opcional)
+ ha.Append("00000000") ' 28‑35 Fecha final (opcional)
+ ha.Append("000") ' 36‑38 Código status "000"
+ ha.Append(" ".PadLeft(332, SPACE)) ' 39‑370 FILLER (espacios)
+
+ sb.AppendLine(ha.ToString())
+
+ '------------------- RECORRIDO DETALLES -----------------------------
+ Dim SBErrores As StringBuilder = New StringBuilder()
+ 'Dim esError As Boolean = False
+ Dim idx As Integer = 0
+
+ Dim hb As New StringBuilder()
+ hb.Append("EE") ' 1‑2
+ hb.Append("HB") ' 3‑4
+ hb.Append("00") ' 5‑6 Moneda cuenta cargo (00=MXN)
+ hb.Append("0000") ' 7‑10 Uso futuro = ceros
+ hb.Append(CuentaCargo) ' 11‑21 Cuenta cargo (11)
+ hb.Append("0000000001") ' 22‑31 Referencia de cargo? (ejemplo)
+ hb.Append("000") ' 32‑34 Codigo del registro
+ hb.Append(" ".PadLeft(336, SPACE)) ' 35‑370 FILLER espacios
+
+ sb.AppendLine(hb.ToString())
+
+ For Each dr As DataRow In DTPendientes.Rows
+
+ ''--- ¿Inicia BLOQUE? (HB) ---------------------------------------
+ 'If idx Mod TamanoBloque = 0 Then
+ ' numBloque += 1
+ ' pagosBloque = 0
+ ' importeBloque = 0D
+
+ ' Dim hb As New StringBuilder(New String(" "c, 370))
+ ' hb.Append("EE") ' 1‑2
+ ' hb.Append("HB") ' 3‑4
+ ' hb.Append("00") ' 5‑6 Moneda cuenta cargo (00=MXN)
+ ' hb.Append("0000") ' 7‑10 Uso futuro = ceros
+ ' hb.Append(CuentaCargo) ' 11‑21 Cuenta cargo (11)
+ ' hb.Append("0000000001") ' 22‑31 Referencia de cargo? (ejemplo)
+ ' hb.Append("000") ' 32‑34 Codigo del registro
+ ' hb.Append(" ".PadLeft(336, SPACE)) ' 35‑370 FILLER espacios
+
+ ' sb.AppendLine(hb.ToString())
+ 'End If
+
+ '----------- DETALLE ALTA (DA) ----------------------------------
+ Dim importe As Decimal = 0D
+ If Not Decimal.TryParse(Convert.ToString(dr("Importe")), importe) Then
+ 'Alert($"Importe inválido en fila {idx + 1}", TipoMensaje.MsgAdvertencia)
+ SBErrores.Append($"Importe inválido en fila {idx + 1}")
+ ErrorLayout = True
+ End If
+
+ If importe <= 0D Then
+ Alert($"Importe debe ser mayor a 0 en fila {idx + 1}", TipoMensaje.MsgAdvertencia)
+ ErrorLayout = True
+ End If
+
+ Dim importeInt As String = CDec(Math.Round(importe * 100).ToEntero).ToString().PadLeft(15, CERO) ' 2 dec.
+
+ Dim fechaAplicacion As String = ClsPaginas.NowADS.ToString("yyyyMMdd")
+ Dim cveBenef As String = LimpiarTextoScotia(Convert.ToString(dr("CveProveedor"))).PadRight(20)
+ Dim rfc As String = LimpiarTextoScotia(Convert.ToString(dr("RFC"))).PadRight(13)
+ Dim nombreBen As String = LimpiarTextoScotia(Convert.ToString(dr("RazonSocial"))).PadRight(40)
+ Dim CveIE As Integer = dr("CveIE").ToString.ToEntero
+ Dim referenciaPago As String = CveIE.ToString.PadLeft(16, CERO) 'If(dr.Table.Columns.Contains("Referencia"), LimpiarTextoScotia(Convert.ToString(dr("Referencia"))).PadLeft(16, "0"c), New String("0"c, 16))
+
+ Dim CuentaDestino As String = ""
+ Dim cuentaDigitos As String = Convert.ToString(dr("CLABEDestino"))
+ Dim clabe As String = Convert.ToString(dr("CLABE"))
+ Dim CveBanco As String = dr("CveBanco").ToString.PadLeft(3, CERO)
+
+
+ If cuentaDigitos.Length = 11 AndAlso CveBanco = "044" Then
+ CuentaDestino = cuentaDigitos
+ ElseIf clabe.Length = 18 Then
+ CuentaDestino = clabe
+ Else
+ CuentaDestino = clabe
+ SBErrores.Append($"Cuenta {CuentaDestino} debe tener 11 o 18 dígitos. ")
+ ErrorLayout = True
+ End If
+
+
+ Dim TipoCuenta As String = If(CuentaDestino.Length = 18, "9", "1") ' 09=18 dígitos, 01=11 dígitos
+
+ CuentaDestino = CuentaDestino.PadLeft(20, CERO)
+
+
+
+ If CveBanco = "000" Then
+ SBErrores.Append($"CveBanco inválida en fila {idx + 1}. Debe ser numérico de 3 dígitos.")
+ ErrorLayout = True
+ End If
+
+ Dim ConceptoPago As String = dr("Observaciones").ToString.Trim
+
+ If ConceptoPago.Length > 50 Then
+ ConceptoPago = ConceptoPago.Substring(0, 50) ' Limitar a 50 caracteres
+ End If
+ ConceptoPago = ConceptoPago.PadRight(50, SPACE)
+
+ Dim da As New StringBuilder()
+ da.Append("EE") ' 1‑2
+ da.Append("DA") ' 3‑4
+ da.Append("04") ' 5‑6 Tipo movimiento (04=SPEI)
+ da.Append("00") ' 7‑8 Moneda pago (00=MXN)
+ da.Append(importeInt) ' 9‑23 Importe (15)
+ da.Append(fechaAplicacion) ' 24‑31
+ da.Append("03") ' 32‑33 Servicio‑concepto (03)
+ da.Append(cveBenef) ' 34‑53
+ da.Append(rfc) ' 54‑66
+ da.Append(nombreBen) ' 67‑106
+ da.Append(referenciaPago) ' 107‑122
+ da.Append("00000") ' 123‑127 Plaza pago (ceros)
+ da.Append("00000") ' 128‑132 Sucursal pago (ceros)
+
+ da.Append(CuentaDestino) ' 133‑152 clabe destino (ceros)
+ da.Append("00000") ' 153‑157 PAIS (ceros)
+ da.Append("".PadLeft(40, SPACE)) ' 158‑197 Ciudad espacio (espacios en blanco)
+ da.Append(TipoCuenta) ' 198-198 Tipo cuenta
+ da.Append(SPACE) ' 199-199 digito intercambio
+ da.Append("00000") ' 200-204 plaza cuenta banco
+ da.Append("044") ' 205-207 num banco emisor (044=ScotiaBank)
+ da.Append(CveBanco) ' 208-210 num banco receptor (044=ScotiaBank)
+
+ da.Append("001") ' 211-213 dias vigencia
+ da.Append(ConceptoPago) ' 214-263 Concepto pago
+ da.Append("".PadLeft(60, SPACE)) '264-283 CAMPO-USO-EMPRESA-1
+ ' 284-303 CAMPO-USO - Empresa - 2
+ ' 304-323 CAMPO-USO - Empresa - 3
+ da.Append("".PadLeft(41, CERO)) ' 324-326 CODIGO-STATUS - REGISTRO NUM 3
+ ' 327-327 CVE-CAMBIO - INST NUM 1
+ ' 328-330 CODIGO-STATUS - CAMBIO - INST NUM 3
+ ' 331-338 FECHA DE PAGO (Pago en ventanilla) NUM 8
+ ' 339-343 PLAZA DE PAGO (Pago en ventanilla) NUM 5
+ ' 344-348 SUCURSAL DE PAGO (Pago en ventanilla) NUM 5
+ ' 349-364 FOLIO-UNICO NUM 16
+ da.Append("".PadLeft(6, SPACE))
+ sb.AppendLine(da.ToString()) '345-370 FILLER ALF 6
+
+ '----------- DETALLE MAIL (DM) 104 -------------------------
+
+ Dim correo As String = dr("Correo").ToString.Trim
+ If correo.Trim.Length = 0 Then
+ SBErrores.Append($" {nombreBen} Email no definido en fila {idx + 1}. Debe ser un correo electrónico válido. ")
+ ErrorLayout = True
+ End If
+
+ Dim dm As New StringBuilder()
+ dm.Append("EE") ' 1‑2 Tipo archivoz
+ dm.Append("DM") ' 3‑4 Tipo registro
+ dm.Append(correo.PadRight(100)) ' 5‑104 Email + filler
+ da.Append("".PadLeft(34, CERO)) ' 105-138 Uso Futuro
+ da.Append("".PadLeft(30, SPACE)) ' 139-168 Clave de Rastreo llenar con espacios en blanco
+ da.Append("".PadLeft(20, SPACE)) ' 169-188 Referencia de Abono Banxico
+ dm.Append(" ") ' 189-190 Tipo de Operación anexo G
+ da.Append("".PadLeft(232, SPACE)) ' 191-370 FILLER
+
+
+ sb.AppendLine(dm.ToString())
+
+ '----------- ACUMULADORES ---------------------------------------
+ TotalPagos += 1
+ totalImporte += importe
+ pagosBloque += 1
+ importeBloque += importe
+
+ '----------- ¿CIERRA BLOQUE? (TB) -------------------------------
+ Dim bloqueCompleto As Boolean = (pagosBloque = TamanoBloque)
+ Dim ultimoRegistro As Boolean = (idx = DTPendientes.Rows.Count - 1)
+ idx += 1
+ Next
+
+ 'If bloqueCompleto OrElse ultimoRegistro Then
+ Dim tb As New StringBuilder()
+ tb.Append("EE") ' 1‑2
+ tb.Append("TB") ' 3‑4
+ tb.Append(pagosBloque.ToString().PadLeft(7, CERO)) ' 5‑11 Cnt altas
+ tb.Append((importeBloque * 100).ToEntero.ToString().PadLeft(17, CERO)) ' 12‑28 Importe altas
+ tb.Append("".PadLeft(7, CERO)) ' 29‑35 Cnt bajas
+ tb.Append("".PadLeft(17, CERO)) ' 36‑52 Importe bajas
+ tb.Append("".PadLeft(195, CERO))
+ ' 53-59 CANTIDAD DE MOVIMIENTOS ALTAS
+ ' 60-76 IMPORTE DE MOVIMIENTOS ALTAS
+ ' 77-83 CANTIDAD DE MOVIMIENTOS BAJAS
+ ' 84-100 IMPORTE DE MOVIMIENTOS BAJAS
+ ' 101-107 CANTIDAD DE MOVIMIENTOS ALTAS
+ ' 108-124 IMPORTE DE MOVIMIENTOS ALTAS
+ ' 125-131 CANTIDAD DE MOVIMIENTOS BAJAS
+ ' 132-148 IMPORTE DE MOVIMIENTOS BAJAS
+ ' 149-155 CANTIDAD DE MOVIMIENTOS PAGADOS
+ ' 156-172 IMPORTE DE MOVIMIENTOS PAGADOS
+ ' 173-179 CANTIDAD DE MOVIMIENTOS DEVUELTOS
+ ' 180-196 IMPORTE DE MOVIMIENTOS DEVUELTOS
+ ' 197-203 CANTIDAD DE MOVIMIENTOS RECH
+ ' 204-220 IMPORTE DE MOVIMIENTOS RECH
+ ' 221-227 CANTIDAD DE MOVIMIENTOS BAJA
+ ' 228-244 IMPORTE DE MOVIMIENTOS BAJA
+ ' 245-247 CODIGO-STATUS-REGISTRO
+ tb.Append("".PadLeft(123, SPACE)) ' 248-370 FILLER (espacios)
+ sb.AppendLine(tb.ToString())
+ 'End If
+
+ '------------------- TRAILER ARCHIVO (TA) ---------------------------
+ Dim ta As New StringBuilder()
+ ta.Append("EE") ' 1‑2
+ ta.Append("TA") ' 3‑4
+ ta.Append(TotalPagos.ToString().PadLeft(7, CERO)) ' 5‑11
+ ta.Append((totalImporte * 100).ToEntero.ToString().PadLeft(17, CERO)) ' 12‑28
+ ta.Append("".PadLeft(7, CERO)) ' 29‑35 Cnt bajas
+ ta.Append("".PadLeft(17, CERO)) ' 36‑52 Importe bajas
+ ta.Append("".PadLeft(198, CERO))
+ ' 53-59 CANTIDAD DE MOVIMIENTOS ALTAS
+ ' 60-76 IMPORTE DE MOVIMIENTOS ALTAS
+ ' 77-83 CANTIDAD DE MOVIMIENTOS BAJAS
+ ' 84-100 IMPORTE DE MOVIMIENTOS BAJAS
+ ' 101-107 CANTIDAD DE MOVIMIENTOS ALTAS
+ ' 108-124 IMPORTE DE MOVIMIENTOS ALTAS
+ ' 125-131 IMPORTE DE MOVIMIENTOS BAJAS
+ ' 132-148 MOVIMIENTOS PAGADOS
+ ' 149-155 IMPORTE DE MOVIMIENTOS PAGADOS
+ ' 156-172 MOVIMIENTOS DEVUELTOS
+ ' 173-179 IMPORTE DE MOVIMIENTOS DEVUELTOS
+ ' 180-196 MOVIMIENTOS RECHAZADOS
+ ' 197-203 CANTIDAD DE MOVIMIENTOS RECH
+ ' 204-220 IMPORTE DE MOVIMIENTOS RECH
+ ' 221-227 CANTIDAD DE MOVIMIENTOS BAJA
+ ' 228-244 IMPORTE DE MOVIMIENTOS BAJA
+ ' 245-247 CODIGO-STATUS-REGISTRO
+ ' 248-250 CODIGO-STATUS-ARCHIVO
+
+ ta.Append("".PadLeft(120, SPACE))
+
+ sb.Append(ta.ToString())
+
+ '------------------- ESCRIBIR ARCHIVO -------------------------------
+ 'File.WriteAllText(RutaArchivo, sb.ToString(), Encoding.ASCII)
+
+
+ NombreArchivo = $"pagos_{ClsPaginas.NowADS.ToString("ddMMyyyy")}_001.txt"
+ '"pagos_03062025_001.txt"
+
+ If InsertaEnDB Then
+
+ Dim ObjBancos As New ClsBancos
+ ObjBancos.IniciaTransacSQL()
+
+ Dim CveLayoutEnvio As Integer = ObjBancos.AddLayoutEnvios(NombreArchivo, ClsPaginas.NowADS(), CveCuenta, PorGrupos:=True)
+
+ If CveLayoutEnvio > 0 Then
+ For Each dr As DataRow In DTPendientes.Rows
+ If dr("CveProveedor").ToString <> "" Or dr("CvePersonal").ToString <> "" Then
+ If Not ObjBancos.AddLayoutEnviosDetalle(CveLayoutEnvio, dr("CveIE").ToString.ToEntero, dr("CveProveedor").ToString.ToEntero, dr("CvePersonal").ToString.ToEntero, 1, "Observaciones") Then
+ ErrorLayout = True
+ Exit For
+ End If
+ End If
+ Next
+ Else
+ ErrorLayout = True
+ End If
+
+ If ErrorLayout Then
+ ObjBancos.RollBack()
+ ObjBancos.Dispose()
+ Else
+ ObjBancos.Commit()
+ ObjBancos.Dispose()
+ End If
+
+ End If
+
+ Dim path As String = String.Format("{0}Layout\{1}", UsuarioActual.Empresa.Ruta, NombreArchivo)
+ Dim pathDirectorio As String = String.Format("{0}Layout\", UsuarioActual.Empresa.Ruta)
+
+ If File.Exists(path) Then
+ File.Delete(path)
+ End If
+
+ If Not Directory.Exists(pathDirectorio) Then
+ Directory.CreateDirectory(pathDirectorio)
+ End If
+
+ 'Dim Texto As String =
+
+ Dim fs As FileStream = File.Create(path)
+ Dim info As Byte() = New UTF8Encoding(True).GetBytes(sb.ToString)
+ fs.Write(info, 0, info.Length)
+ fs.Close()
+
+ If ErrorLayout Then
+ LayouErrorStr = LayouErrorStr & $"{SBErrores.ToString}"
+ Return False
+ Else
+ LayoutStr = sb.ToString()
+ Return True
+ End If
+
+
+
+ End Function
+
+ '====================================================================
+ ' Limpia texto: A‑Z, 0‑9, «@» y «.» (UpperCase) – el resto se descarta
+ '====================================================================
+ Private Function LimpiarTextoScotia(ByVal valor As String) As String
+ Dim sb As New StringBuilder()
+ For Each ch As Char In If(valor, String.Empty).ToUpperInvariant()
+ If Char.IsLetterOrDigit(ch) OrElse ch = "@"c OrElse ch = "."c Then sb.Append(ch)
+ Next
+ Return sb.ToString()
+ End Function
+
+
+#Region "LAYOUT SCOTIABANK"
+
+ '====================================================================
+ ' GenerarLayoutPagosScotia
+ '====================================================================
+ Public Function AltaCuentasScotia(
+ DtPendientesTemp As DataTable,
+ UsuarioActual As Usuario,
+ Optional NumeroConvenio As String = "", ' 5 dígitos
+ Optional SistemaCentral As String = "001", ' 3 dígitos
+ Optional TipoArchivo As String = "EE", ' 2 digitos (define tu propio código)
+ Optional Secuencia As Integer = 1, ' 3 dígitos, consecutivo del día
+ Optional MovimientoDefault As Char = "P"c ' P =pago, cambia si usas A/C/B
+ ) As Boolean
+
+ Dim objBanco As New ClsBancos
+ objBanco.IniciaTransacSQL()
+
+ ErrorLayout = False
+ LayoutStr = ""
+ LayouErrorStr = ""
+ TotalPagos = 0
+ NombreArchivo = ""
+
+ '------------------- Constantes de layout -------------------
+ Dim LARGO_REGISTRO As Integer = 140
+ Dim Cero As Char = "0"c
+ Dim Space As Char = " "c
+
+ Dim NumeroArchivo As Integer = 1 ' ajústalo si manejas consecutivo diario
+ Dim FechaArchivo As Date = ClsPaginas.NowADS().Date
+
+ 'If DtPendientesTemp Is Nothing Then DtPendientesTemp = DTPendientes.Copy
+ DtPendientesTemp.CaseSensitive = False
+
+ If DtPendientesTemp.Columns.Contains("Nombre") Then
+
+ DtPendientesTemp = DtPendientesTemp.FiltraParametros("", "",
+ {"CLABEDestino", "CLABE", "CveBanco", "CveCuentaDeposito", "EstatusCtaDeposito", "EstatusPagoElectronicoScotia", "BancoNombre", "FechaEliminacion", "ConvenioPagoElectronico", "Nombre"}
+ )
+ Else
+
+ DtPendientesTemp = DtPendientesTemp.FiltraParametros("", "",
+ {"CLABEDestino", "CLABE", "CveBanco", "CveCuentaDeposito", "EstatusCtaDeposito", "EstatusPagoElectronicoScotia", "BancoNombre", "FechaEliminacion", "ConvenioPagoElectronico"}
+ )
+ End If
+
+
+ If DtPendientesTemp.Rows.Count = 0 Then
+ LayouErrorStr = "No hay datos pendientes para generar el Layout de ScotiaBank."
+ ErrorLayout = True
+ End If
+
+ '------------------- Acumulados para el trailer -------------
+ Dim Altas As Integer = 0, Cambios As Integer = 0
+ Dim Bajas As Integer = 0, Consultas As Integer = 0
+ '------------------- Acumulados para el trailer -------------
+
+ '------------------- ConvenioPagoElectronico = "0000000" ' 5 dígitos
+ If Not NumeroConvenio.Trim.Length > 0 Then
+ NumeroConvenio = DtPendientesTemp.Rows(0)("ConvenioPagoElectronico").ToString
+ End If
+
+
+
+ If NumeroConvenio.Trim.Length = 0 Then
+ LayouErrorStr = "El campo NumeroConvenio (ConvenioPagoElectronico) no está definido en los datos de la cuenta."
+ ErrorLayout = True
+ End If
+
+ Dim sb As New StringBuilder
+
+ '=============================================================
+ ' 1) HEADER (140 )
+ '=============================================================
+ 'Dim hoy As Date = Now.Date
+ 'Dim hora As String = Now.ToString("HHmmss")
+
+ Dim Header As New StringBuilder()
+ Header.Append(TipoArchivo.PadRight(2, Space)) 'TIPO ARCHIVO (2)
+ Header.Append("HA") 'TIPO REGISTRO (2)
+ Header.Append("JDF") 'SISTEMA-CENTRAL (3)
+ Header.Append(NumeroConvenio.PadLeft(7, Cero)) 'NUMERO DE CONTRATO (7) ' ocupa 5 dígitos pero en el layout se usa 7
+ Header.Append(ClsPaginas.NowADS.ToString("yyyyMMdd")) 'FECHA-SOLICITUD (8)
+ Header.Append("001") 'SECUENCIA (3)
+ Header.Append("M") 'MANTENIMIENTO-O-CONSULTA (1)
+ Header.Append(" ".PadLeft(8, Space)) 'FECHA GENERACIÓN ARCHIVO (8) *** Respusta de ScotiaBank ***
+ Header.Append(" ".PadLeft(6, Space)) 'Hora GENERACIÓN ARCHIVO (6) *** Respusta de ScotiaBank ***
+ Header.Append(" ".PadLeft(3, Space)) 'CÓDIGO-RESPUESTA (3) *** Respusta de ScotiaBank ***
+ Header.Append(" ".PadLeft(97, Space)) 'FILLER (97)
+
+ sb.AppendLine(Header.ToString)
+
+ '=============================================================
+ ' 2) DETALLES (140 )
+ '=============================================================
+ Dim Contador As Integer = 2
+ Dim SBErrores As New StringBuilder
+ For Each dr As DataRow In DtPendientesTemp.Rows
+
+ Dim registro As New StringBuilder()
+ Dim esError As Boolean = False
+
+ '---- Datos base tomados de DTPendientes ------------------
+
+ Dim CuentaDestino As String = ""
+ Dim cuentaDigitos As String = dr("CLABEDestino").ToString.Trim
+ Dim Clabe As String = dr("CLABE").ToString.Trim
+ Dim limite As String = (9000000000 * 100D).ToString("F0")
+ Dim banco As String = dr("CveBanco").ToString.PadLeft(3, Cero)
+
+ If cuentaDigitos.Length = 11 AndAlso banco = "044" Then
+ CuentaDestino = cuentaDigitos
+ ElseIf Clabe.Length = 18 Then
+ CuentaDestino = Clabe
+ Else
+ CuentaDestino = Clabe
+
+ If DtPendientesTemp.Columns.Contains("Nombre") Then
+ SBErrores.Append($"Empleado {dr("Nombre").ToString} Cuenta *{CuentaDestino}* debe tener 11 o 18 dígitos. ")
+ Else
+ SBErrores.Append($"Linea {Contador} Cuenta *{CuentaDestino}* debe tener 11 o 18 dígitos. ")
+ End If
+
+ esError = True
+ End If
+
+ If banco.Length <> 3 OrElse Not IsNumeric(banco) OrElse banco = "000" Then
+ SBErrores.Append($"Linea {Contador} Cuenta *{CuentaDestino}* código {banco} no es un banco válido. Debe ser numérico de 3 dígitos. ")
+ esError = True
+ End If
+
+ Dim CveCuentaDeposito As String = dr("CveCuentaDeposito").ToString
+
+ 'Dim movimiento As Char = If(dr.Table.Columns.Contains("Movimiento"),
+ ' dr("Movimiento").ToString.FirstOrDefault(), MovimientoDefault)
+
+ Dim CVETIPOCUENTA As String = If(CuentaDestino.Length = 18, "09", "01")
+
+
+ '---- TIPO DE REGISTRO ------------------
+
+ 'ANEXO E de ScotiaBank
+ 'DA = DETALLE ALTA DE DATOS DE CUENTA Y LIMITE RELACIONADO
+ 'DC = DETALLE CAMBIOS DE DATOS DE CUENTA Y LIMITE RELACIONADO
+ 'DB = DETALLE BAJA DE DATOS DE CUENTA Y LIMITE RELACIONADO
+ 'DQ = DETALLE CONSULTA DE DATOS DE CUENTA Y LIMITE RELACIONADO
+ 'DR = DETALLE RESPUESTA *** Respusta de ScotiaBank ***
+
+ Dim TipoRegistro As String = "DA" ' Por default es D (Alta), cambia a C si es cambio o baja
+ '---- TIPO DE REGISTRO ------------------
+
+ '---- Construcción del registro ---------------------------
+ registro.Append(TipoArchivo.PadRight(2, Space)) 'TIPO ARCHIVO (2)
+ registro.Append(TipoRegistro) 'TIPO REGISTRO (2)
+ registro.Append("A") 'CVE-MOVIMIENTO-CUENTA (1)
+ registro.Append(CVETIPOCUENTA) 'CVE-TIPO - CUENTA (2)
+ registro.Append("00") 'CVE-MONEDA - CUENTA (2) 00 Pesps 01 Dollares
+ registro.Append(banco) 'NUM-banco - CUENTA (3)
+ registro.Append(CuentaDestino.PadLeft(20, Cero)) 'NUM-CUENTA (20)
+ registro.Append(ClsPaginas.NowADS.AddDays(364).ToString("yyyyMMdd")) 'FECHA DE ELIMINACIÓN (8)
+ registro.Append(CveCuentaDeposito.PadRight(50, Space)) 'DESCRIPCIÓN (50)
+ registro.Append(limite.PadLeft(17, Cero)) 'LIMITE-POR-TRANSACCIÓN (17)
+ registro.Append("04") 'TIPO DE PAGO (2)
+ registro.Append(" ") 'CÓDIGO-RESPUESTA (3) CÓDIGO DE RESPUESTA DE REG. "D*", ANEXO 'C' *** Respusta de ScotiaBank ***
+ registro.Append(" ".PadLeft(28, Space)) 'FILLER (28)
+
+
+ sb.AppendLine(registro.ToString)
+ If registro.Length = LARGO_REGISTRO AndAlso Not esError Then
+ Select Case TipoRegistro
+ Case "DA"
+ Altas = Altas + 1
+ Case "DC"
+ Cambios = Cambios + 1
+ Case "DB"
+ Bajas = Bajas + 1
+ Case "DQ"
+ Consultas = Consultas + 1
+ Case Else
+ esError = True
+ ErrorLayout = True
+ End Select
+ Else
+
+ If registro.Length <> LARGO_REGISTRO Then
+ SBErrores.Append($"Error linea {Contador} tamaño esperado: {LARGO_REGISTRO} tamaño: {registro.Length}, ")
+ End If
+
+ ErrorLayout = True
+
+ End If
+ Contador += 1
+ Next
+
+ '=============================================================
+ ' 3) TRAILER (PIE) (140)
+ '=============================================================
+ Dim trailer As New StringBuilder()
+
+
+ trailer.Append(TipoArchivo.PadRight(2, Space)) 'TIPO DE ARCHIVO (2)
+ trailer.Append("TA") 'TIPO DE REGISTRO (2)
+ trailer.Append(Altas.ToString.PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS ALTAS (8)
+ trailer.Append(Cambios.ToString.PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS CAMBIOS (8)
+ trailer.Append(Bajas.ToString.PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS BAJAS (8)
+ trailer.Append(Consultas.ToString.PadLeft(8, Cero)) 'CANTIDAD DE CONSULTAS (8)
+ 'MOVIMIENTOS ACEPTADOS
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS ALTAS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS CAMBIOS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS BAJAS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE CONSULTAS (8) *** Respusta de ScotiaBank ***
+ 'MOVIMIENTOS RECHAZADOS
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS ALTAS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS CAMBIOS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS BAJAS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE CONSULTAS (8) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(3, Cero)) 'CÓDIGO-RESPUESTA (3) *** Respusta de ScotiaBank ***
+ trailer.Append("0".PadLeft(3, Cero)) 'CÓDIGO-RESPUESTA - Archivo (3) *** Respusta de ScotiaBank ***
+ trailer.Append(" ".PadLeft(34, Space)) 'FILLER (34)
+
+ sb.Append(trailer.ToString)
+
+ '------------------- Crear archivo y mostrar descargas ------------------
+
+ If sb.Length = 0 Then
+ SBErrores.Append("No se generó ningún registro válido para Bajío. ")
+ ErrorLayout = True
+ End If
+
+ NombreArchivo = $"altacuentasScotia_{FechaArchivo:ddMMyyyy}_{NumeroArchivo:D3}.txt"
+
+ If SBErrores.Length > 0 Then
+ LayouErrorStr = "Errores encontrados al generar el layout de ScotiaBank: " & SBErrores.ToString
+ ErrorLayout = True
+ Else
+ If Not CreaArchivo(sb.ToString, NombreArchivo, UsuarioActual:=UsuarioActual) Then
+ ErrorLayout = True
+ End If
+ End If
+
+ LayoutStr = sb.ToString()
+
+
+ If Not ErrorLayout Then
+ objBanco.Commit()
+ Else
+ objBanco.RollBack()
+ End If
+
+ Return If(ErrorLayout, False, True)
+
+
+ 'If SBErrores.Length > 0 Then
+ ' LayouErrorStr = "Errores encontrados al generar el layout de ScotiaBank: " & SBErrores.ToString
+ ' ErrorLayout = True
+ 'Else
+ ' If CreaArchivo(sb.ToString, NombreArchivo, UsuarioActual:=UsuarioActual) Then
+ ' DVDescargaPagos.Visible = False
+ ' DVDescargaReporte.Visible = False
+ ' LblCuentas.Text = "Cuentas Bajio"
+ ' 'NombreArchivoBancomer = "" 'No usamos estos para scotia
+ ' 'NombreArchivoInterbancario = ""
+ ' 'NombreArchivoCIE = ""
+ ' 'NombreArchivo = NombreArchivoEnviado
+ ' DVDescargaCuentas1.Visible = True
+ ' LnkDescargaCuentas1.Text = NombreArchivo
+ ' RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});")
+ ' UpModalDescarga.Update()
+ ' End If
+ 'End If
+
+
+
+ 'CargaDatos()
+
+ End Function
+
+
+ Private Function CreaArchivo(TextoCompleto As String, NombreArchivoEnviado As String, UsuarioActual As Usuario) As Boolean
+
+
+ DirectoryExistsCreate(String.Format("{0}Layout", UsuarioActual.Empresa.Ruta))
+ Dim path As String = String.Format("{0}Layout\{1}", UsuarioActual.Empresa.Ruta, NombreArchivo)
+
+ Try
+ If File.Exists(path) Then
+ File.Delete(path)
+ End If
+
+ Dim fs As FileStream = File.Create(path)
+
+ Dim info As Byte() = New UTF8Encoding(True).GetBytes(TextoCompleto)
+ fs.Write(info, 0, info.Length)
+ fs.Close()
+ Catch ex As Exception
+ ErrorLayout = True
+
+ End Try
+
+
+
+ Return True
+
+ End Function
+
+ '---------------------------------------------------------------
+ ' Limpia y normaliza texto para Scotia (solo A-Z,0-9,espacio)
+ '---------------------------------------------------------------
+ Private Function LimpiarTextoScotia(txt As String, largo As Integer) As String
+ Dim clean = New String(txt _
+ .Normalize(System.Text.NormalizationForm.FormD) _
+ .Where(Function(ch) Char.IsLetterOrDigit(ch) OrElse ch = " "c) _
+ .ToArray()) _
+ .ToUpperInvariant()
+ Return clean.PadRight(largo).Substring(0, largo)
+ End Function
+
+
+ Public Shared Function AltaCuentaScotiaCodigoRespuestaAnexoC(ByVal codigo As String) As String
+ Select Case codigo
+ Case "002" : Return "NO EXISTE NOMBRE DE APLICACION EN EL NOMBRE DE ARCHIVO"
+ Case "003" : Return "EL NUM DE CONTRATO EN EL NOMBRE DE ARCHIVO NO ES NUMERICO"
+ Case "004" : Return "EL NUMERO DE CONTRATO EN EL NOMBRE DE ARCHIVO ES CERO"
+ Case "005" : Return "EL NUM DE SECUENCIA EN NOMBRE DE ARCHIVO NO ES NUMERICO"
+ Case "006" : Return "EL NUMERO DE SECUENCIA EN EL NOMBRE DE ARCHIVO ES CERO"
+ Case "007" : Return "LA CLAVE DE ARCHIVO ES INVALIDA"
+ Case "008" : Return "LA CLAVE DE REGISTRO ES INVALIDA"
+ Case "009" : Return "NO EXISTE NOMBRE DE APLICACION EN EL REGISTRO HA"
+ Case "010" : Return "EL NOMBRE DE APLICACION NO CORRESPONDE AL ARCHIVO"
+ Case "011" : Return "EL NUMERO DE CONTRATO EN EL REGISTRO HA NO ES NUMERICO"
+ Case "012" : Return "EL NUMERO DE CONTRATO EN EL REGISTRO HA ES CERO"
+ Case "013" : Return "EL NUMERO DE CONTRATO NO CORRESPONDE AL ARCHIVO"
+ Case "014" : Return "EL CONTRATO NO EXISTE"
+ Case "015" : Return "EL NUMERO DE SECUENCIA EN EL REGISTRO HA NO ES NUMERICO"
+ Case "016" : Return "EL NUMERO DE SECUENCIA EN EL REGISTRO HA ES CERO"
+ Case "017" : Return "EL NUMERO DE SECUENCIA NO CORRESPONDE AL ARCHIVO"
+ Case "018" : Return "EL MOVIMIENTO CUENTA ES UN DATO OBLIGATORIO"
+ Case "019" : Return "EL MOVIMIENTO CUENTA DEBE SER A"
+ Case "020" : Return "EL NUMERO DE BANCO NO ES NUMERICO"
+ Case "021" : Return "EL NUMERO DE BANCO NO EXISTE EN EL CATALOGO"
+ Case "022" : Return "EL TIPO DE CUENTA ES INVALIDO PARA ESE BANCO"
+ Case "023" : Return "EL TIPO DE CUENTA NO ES NUMERICO"
+ Case "024" : Return "LA MONEDA DE LA CUENTA NO ES NUMERICO"
+ Case "025" : Return "LA MONEDA DE LA CUENTA NO TIENE UN VALOR PERMITIDO"
+ Case "026" : Return "LA FECHA DE DE VIGENCIA NO ES NUMERICA"
+ Case "027" : Return "LA FECHA DE VIGENCIA ESTA FUERA DE RANGO"
+ Case "028" : Return "EL IMPORTE LIMITE ES NO NUMERICO"
+ Case "029" : Return "EL NUMERO DE ALTAS SOLICITADAS NO ES NUMERICO"
+ Case "030" : Return "EL NUMERO DE CAMBIOS SOLICITADOS NO ES NUMERICO"
+ Case "031" : Return "EL NUMERO DE BAJAS SOLICITADAS NO ES NUMERICO"
+ Case "032" : Return "EL NUMERO DE CONSULTAS SOLICITADAS NO ES NUMERICO"
+ Case "033" : Return "EL NUMERO DE ALTAS SOLICITADAS NO COINCIDE"
+ Case "034" : Return "EL NUMERO DE CAMBIOS SOLICITADOS NO COINCIDE"
+ Case "035" : Return "EL NUMERO DE BAJAS SOLICITADAS NO COINCIDE"
+ Case "036" : Return "EL NUMERO DE CONSULTAS SOLICITADAS NO COINCIDE"
+ Case "037" : Return "ARCHIVO RECHAZADO POR MOVIMIENTOS RECHAZADOS"
+ Case "038" : Return "ARCHIVO RECHAZADO POR NO EXISTIR MOVIMIENTOS CORRECTOS"
+ Case "039" : Return "EL NUMERO DE CUENTA NO ES NUMERICO"
+ Case "040" : Return "EL NUMERO DE CUENTA NO CERO"
+ Case "041" : Return "EL NUMERO DE CUENTA NO EXISTE"
+ Case "042" : Return "EL NUMERO DE CUENTA NO PERTENECE A ESE BANCO"
+ Case "043" : Return "LA PLAZA ABM NO EXISTE"
+ Case "044" : Return "EL DIGITO VERIFICADOR DE LA CLABE NO CORRESPONDE"
+ Case "045" : Return "LA CUENTA NO ESTA ACTIVA"
+ Case "046" : Return "LA CUENTA YA EXISTE"
+ Case "047" : Return "LA CUENTA NO EXISTE"
+ Case "048" : Return "EL TIPO DE CUENTA NO ES NUMERICO"
+ Case "049" : Return "EL TIPO DE CUENTA NO TIENE UN VALOR PERMITIDO"
+ Case "050" : Return "EL IMPORTE LIMITE ES CERO"
+ Case "051" : Return "NO EXISTE LA CLAVE DE MANTEMIMIENTO/CONSULTA"
+ Case "052" : Return "LA CLAVE DE MANT/CONS NO TIENE UN VALOR PERMITIDO"
+ Case "053" : Return "TIPO DE REGISTRO NO VALIDO PARA ARCHIVO DE CONSULTA"
+ Case Else : Return "CÓDIGO DESCONOCIDO"
+ End Select
+ End Function
+
+ Public Shared Function PagosScotiaCodigoRespuestaAnexoC(ByVal codigo As String) As String
+ codigo = codigo.PadLeft(3, "0"c)
+ Select Case codigo
+ Case "000" : Return "NO ERROR (OK)"
+ Case "001" : Return "FIN DE ARCHIVO"
+ Case "002" : Return "ARCHIVO NO ENCONTRADO"
+ Case "003" : Return "LECTURA: REGISTRO NO UNICO"
+ Case "006" : Return "ERROR FUERA DE CATEGORIAS DE CICS"
+ Case "007" : Return "COMANDOS EN ORDEN ILOGICO"
+ Case "008" : Return "NO SE TIENE AUTORIZACION"
+ Case "009" : Return "MISMO BANCO PROGRAMADO - VALIDACION DE ESTRUCTURA Y ESTATUS (INACTIVO, CANCELADO)"
+ Case "010" : Return "ARCHIVO NO ABIERTO"
+ Case "011" : Return "TEF - VALIDACION DE ESTRUCTURA (ERRONEA)"
+ Case "012" : Return "SPEI - VALIDACION DE ESTRUCTURA (ERRONEA)"
+ Case "013" : Return "ERROR DE I/O NO CUBIERTO POR CICS"
+ Case "014" : Return "LONGITUD DE REGISTRO ERRONEA"
+ Case "015" : Return "ARCHIVO NO DISPONIBLE"
+ Case "016" : Return "ESCRITURA: REGISTRO DUPLICADO"
+ Case "017" : Return "NO HAY ESPACIO EN EL DISPOSITIVO PARA ADICIONAR REGISTRO"
+ Case "019" : Return "OTRO ERROR DE I/O"
+ Case "020" : Return "DATO NO NUMERICO"
+ Case "021" : Return "DATO REQUERIDO (SI LA OPERACIÓN ES SPID CONTACTE A SU EJECUTIVO DE RELACIÓN PARA REVISAR LA DIRECCION REGISTRADA)"
+ Case "022" : Return "VALOR FUERA DE RANGO"
+ Case "023" : Return "DATO NO COINCIDE CON NOMBRE DE ARCHIVO"
+ Case "024" : Return "ERROR EN SECUENCIA DE REGISTROS"
+ Case "025" : Return "NO EXISTE CONTRATO"
+ Case "026" : Return "NO EXISTE PLAZA"
+ Case "027" : Return "NO EXISTE SUCURSAL"
+ Case "028" : Return "NO EXISTE CUENTA"
+ Case "029" : Return "CUENTA NO ACTIVA"
+ Case "030" : Return "CUENTA NO RELACIONADA AL CONTRATO"
+ Case "031" : Return "NO EXISTE BANCO"
+ Case "032" : Return "MONEDA INVALIDA PARA ESE PRODUCTO"
+ Case "033" : Return "ERROR EN CIFRA DE CONTROL"
+ Case "034" : Return "ARCHIVO RECHAZADO POR REGISTROS RECHAZADOS"
+ Case "035" : Return "PAGO DUPLICADO"
+ Case "036" : Return "NO EXISTE PAGO"
+ Case "037" : Return "ARCHIVO NO PENDIENTE DE VALIDACION"
+ Case "038" : Return "CONTRATO NO ACTIVO"
+ Case "039" : Return "ARCHIVO RECHAZADO POR QUE NO TIENE REGISTROS CORRECTOS"
+ Case "040" : Return "MONEDA DE REGISTRO DETALLE DIFERENTE A MONEDA DE CUENTA DE CARGO"
+ Case "041" : Return "FECHA INHABIL"
+ Case "042" : Return "FECHA DE APLICACION INVALIDA PARA ESE TIPO DE PAGO"
+ Case "043" : Return "NUMERO DE BANCO INVALIDO PARA ESE TIPO DE PAGO"
+ Case "044" : Return "HORARIO SUCURSAL NO DISPONIBLE"
+ Case "045" : Return "IMPORTE SUPERIOR AL PERMITIDO SPEI"
+ Case "046" : Return "LA CUENTA DE ABONO NO ESTA REGISTRADA EN LA BASE DE DATOS DEL BANCO PARA ESE CONTRATO"
+ Case "047" : Return "IMPORTE SUPERIOR AL AUTORIZADO POR EL CLIENTE PARA ESA CUENTA DE ABONO"
+ Case "048" : Return "FECHA DE CONSTITUCION ERRONEA"
+ Case "049" : Return "TIPO DE CUENTA INVALIDA SPID"
+ Case "050" : Return "SPID ES SOLO PARA PERSONAS MORALES"
+ Case "051" : Return "ERROR AL HACER REGISTRO EN TOTALES"
+ Case "052" : Return "ERROR AL HACER CARGO A CHEQUES"
+ Case "053" : Return "EL MOVIMIENTO NO ESTA PENDIENTE DE PAGO"
+ Case "054" : Return "ERROR AL REVERSAR CARGO A CHEQUES"
+ Case "055" : Return "SU TRANSACCIÓN NO PUEDE SER PROCESADA EN ESTE MOMENTO CONTACTE A SU EJECUTIVO DE RELACIÓN (CLAVE 99)."
+ Case "056" : Return "EL CERTIFICADO DE SU FIEL NO ES VIGENTE. FAVOR DE SOLICITAR A SU EJECUTIVO LA ACTUALIZACIÓN PARA PODER OPERAR SPID."
+ Case "057" : Return "SU TRANSACCIÓN NO PUEDE SER PROCESADA EN ESTE MOMENTO CONTACTE A SU EJECUTIVO DE RELACIÓN (CLAVE 88)."
+ Case "058" : Return "EL MONTO DE LA OPERACIÓN SOBREPASA EL DISPONIBLE PARA ESTE BENEFICIARIO."
+ Case "059" : Return "TRANSACCION SPID DEVUELTA"
+ Case "060" : Return "PAGO NO DISPONIBLE EN HORARIO EXTENDIDO"
+ Case "061" : Return "INSUFICIENCIA DE FONDOS"
+ Case "062" : Return "CAMBIO A ABONO EN CUENTA DE DEVOLUCIONES"
+ Case "063" : Return "CAMBIO A PAGO EN VENTANILLA EFECTIVO"
+ Case "064" : Return "CAMBIO A CHEQUE DE CAJA AL BENEFICIARIO EN VENTANILLA"
+ Case "065" : Return "CAMBIO A CHEQUE DE CAJA CENTRAL AL BENEFICIARIO"
+ Case "066" : Return "CAMBIO A CHEQUE DE CAJA CENTRAL A LA EMPRESA POR TOTAL"
+ Case "067" : Return "CAMBIO A CHEQUE DE CAJA CENTRAL A LA EMPRESA POR DETALLE"
+ Case "068" : Return "CAMBIO ORIGINADO POR UN PAGO EN VENTANILLA"
+ Case "069" : Return "CAMBIO ORIGINADO POR UN ABONO A CHEQUES"
+ Case "070" : Return "CAMBIO ORIGINADO POR UN ABONO A AHORROS"
+ Case "071" : Return "CAMBIO ORIGINADO POR UN DEPOSITO INTERBANCARIO"
+ Case "072" : Return "CAMBIO ORIGINADO POR UN MOVIMIENTO DE TRANSFERENCIA DE FONDOS"
+ Case "073" : Return "BAJA RECHAZADA POR PAGO EN LINEA"
+ Case "074" : Return "DEVOLUCION GLOBAL POR RECHAZOS"
+ Case "075" : Return "DEVOLUCION GLOBAL POR VENCIMIENTO DE VIGENCIAS"
+ Case "076" : Return "DEVOLUCION GLOBAL POR BAJAS SOLICITADAS"
+ Case "077" : Return "HORARIO DE OPERACIÓN NO DISPONIBLE SPID"
+ Case "078" : Return "EL ABONO EXCEDE EL MÁXIMO PERMITIDO A LA CUENTA"
+ Case Else : Return "CÓDIGO DESCONOCIDO"
+ End Select
+ End Function
+
+#End Region
+
+
+#Region "IDisposable Support"
+
+
+ Private disposedValue As Boolean = False
+ ' IDisposable
+ Protected Overridable Sub Dispose(disposing As Boolean)
+ If Not Me.disposedValue Then
+ If disposing Then
+ ' TODO: dispose managed state (managed objects).
+
+ 'If Not Data Is Nothing Then Data.Dispose() : Data = Nothing
+ 'If Not SqlAdapter Is Nothing Then SqlAdapter.Dispose() : SqlAdapter = Nothing
+ 'If Not SqlCommand Is Nothing Then SqlCommand.Dispose() : SqlCommand = Nothing
+ 'If Not SqlTransacc Is Nothing Then SqlTransacc.Dispose() : SqlTransacc = Nothing
+ 'If SqlConexion.State <> ConnectionState.Closed Then SqlConexion.Close()
+ 'If Not SqlConexion Is Nothing Then SqlConexion.Dispose() : SqlConexion = Nothing
+
+ End If
+
+ ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
+ ' TODO: set large fields to null.
+ End If
+ Me.disposedValue = True
+ End Sub
+
+ ' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources.
+ 'Protected Overrides Sub Finalize()
+ ' ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
+ ' Dispose(False)
+ ' MyBase.Finalize()
+ 'End Sub
+
+ ' This code added by Visual Basic to correctly implement the disposable pattern.
+ Public Sub Dispose() Implements IDisposable.Dispose
+ ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
+ 'ConexionClose()
+ Dispose(True)
+ GC.SuppressFinalize(Me)
+ End Sub
+#End Region
+
+End Class
diff --git a/Bancos/ConciliacionesBancarias.aspx.vb b/Bancos/ConciliacionesBancarias.aspx.vb
index eac3b39ba..184740034 100644
--- a/Bancos/ConciliacionesBancarias.aspx.vb
+++ b/Bancos/ConciliacionesBancarias.aspx.vb
@@ -6,6 +6,7 @@ Imports Extensiones
Imports System.Xml
Imports Microsoft.Reporting.WebForms
Imports System.Globalization
+Imports Telerik.Web.UI
Partial Class Bancos_ConciliacionesBancariasaspx
Inherits ClsPaginas
@@ -231,15 +232,20 @@ Partial Class Bancos_ConciliacionesBancariasaspx
RegistraScript("$('#DModalCriterio').modal()")
End Sub
Private Sub ConciliacionManual()
+
+ If GvDatos.Rows.Cast(Of GridViewRow).Where(Function(gvr) gvr.FCCheckBox("ChkConciliado").Checked).Count = 0 OrElse GvEdoConciliacion.Rows.Cast(Of GridViewRow).Where(Function(gvr) gvr.FCCheckBox("ChkConciliado").Checked).Count = 0 Then
+ Alert("Debe seleccionar un folio", TipoMensaje.MsgAdvertencia)
+ Exit Sub
+ End If
+
Dim SumaSIGAbono As Double = 0
Dim SumaSIGCargo As Double = 0
Dim SumaExcelAbono As Double = 0
Dim SumaExcelCargo As Double = 0
- Dim Seleccionados As Integer = 0
Dim Fecha As Date
+
For Each Gvr As GridViewRow In GvDatos.Rows
If Gvr.FCCheckBox("ChkConciliado").Checked And Gvr.FCCheckBox("ChkConciliado").Enabled Then
- Seleccionados += 1
Fecha = Gvr.DataKey("FechaDocumento").ToDate
If Gvr.DataKey("Tipo") = "Cargo" Then
If Gvr.DataKey("Importe").ToDouble < 0 Then ' cuando es negativo suma para el abono
@@ -258,13 +264,7 @@ Partial Class Bancos_ConciliacionesBancariasaspx
End If
End If
Next
- If Seleccionados > 1 Then
- Alert("Tiene que tener seleccionado solamente un movimiento.", TipoMensaje.MsgAdvertencia)
- Exit Sub
- ElseIf Not Seleccionados > 0 Then
- Alert("Tiene que tener seleccionado .", TipoMensaje.MsgAdvertencia)
- Exit Sub
- End If
+
For Each Gvr As GridViewRow In GvEdoConciliacion.Rows
If Gvr.FCCheckBox("ChkConciliado").Checked And Gvr.FCCheckBox("ChkConciliado").Enabled Then
If (Gvr.DataKey("FechaDocumento").ToDate = Fecha And DdlCriterio.SelectedValue.ToEntero = 1) Or DdlCriterio.SelectedValue.ToEntero = 2 Then
@@ -279,10 +279,20 @@ Partial Class Bancos_ConciliacionesBancariasaspx
End If
End If
Next
+
If SumaSIGCargo <> SumaExcelCargo OrElse SumaSIGAbono <> SumaExcelAbono Then
Alert($"La suma de los importes no cuadran ({SumaSIGCargo}-{SumaExcelCargo}**{SumaSIGAbono}-{SumaExcelAbono})", TipoMensaje.MsgAdvertencia)
Exit Sub
End If
+
+ Dim CumpleCriterioContable = GvDatos.Rows.Cast(Of GridViewRow).Where(Function(gvr) gvr.FCCheckBox("ChkConciliado").Checked).Count = 1 AndAlso GvEdoConciliacion.Rows.Cast(Of GridViewRow).Where(Function(gvr) gvr.FCCheckBox("ChkConciliado").Checked).Count >= 1
+ Dim CumpleCriterioBancario = GvEdoConciliacion.Rows.Cast(Of GridViewRow).Where(Function(gvr) gvr.FCCheckBox("ChkConciliado").Checked).Count = 1 AndAlso GvDatos.Rows.Cast(Of GridViewRow).Where(Function(gvr) gvr.FCCheckBox("ChkConciliado").Checked).Count >= 1
+
+ If Not (CumpleCriterioContable OrElse CumpleCriterioBancario) Then
+ Alert("Debe seleccionar solo 1 folio del lado contable o bancario", TipoMensaje.MsgAdvertencia)
+ Exit Sub
+ End If
+
Dim ObjBancos As New ClsBancos
Dim ObjOI As New ClsOIEventos(ObjBancos.IniciaTransacSQL())
Dim ErrorTrans As Boolean = False
diff --git a/Bancos/PagoElectronico.aspx.vb b/Bancos/PagoElectronico.aspx.vb
index b058e60bb..20b6d6744 100644
--- a/Bancos/PagoElectronico.aspx.vb
+++ b/Bancos/PagoElectronico.aspx.vb
@@ -5,6 +5,8 @@ Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Data
+Imports System.Data.Entity
+Imports System.Data.SqlClient
Imports System.IO
Imports System.Runtime.Remoting
Imports AjaxControlToolkit.AsyncFileUpload.Constants
@@ -513,818 +515,38 @@ Partial Class Bancos_PagoElectronico
End Function
#End Region
-#Region "LAYOUT SCOTIABANK"
-
- '====================================================================
- ' GenerarLayoutPagosScotia
- '====================================================================
- Private Sub AltaProveedoresScotia(
- Optional ByVal DtPendientesTemp As DataTable = Nothing,
- Optional ByVal NumeroConvenio As String = "00000", ' 5 dígitos
- Optional ByVal SistemaCentral As String = "001", ' 3 dígitos
- Optional ByVal TipoArchivo As String = "EE", ' 2 digitos (define tu propio código)
- Optional ByVal Secuencia As Integer = 1, ' 3 dígitos, consecutivo del día
- Optional ByVal MovimientoDefault As Char = "P"c ' P =pago, cambia si usas A/C/B
- )
-
- '------------------- Constantes de layout -------------------
- Dim LARGO_REGISTRO As Integer = 140
- Dim Cero As Char = "0"c
- Dim Space As Char = " "c
-
- Dim NumeroArchivo As Integer = 1 ' ajústalo si manejas consecutivo diario
- Dim FechaArchivo As Date = NowADS().Date
-
- If DtPendientesTemp Is Nothing Then DtPendientesTemp = DTPendientes.Copy
- DtPendientesTemp.CaseSensitive = False
-
- DtPendientesTemp = DtPendientesTemp.FiltraParametros("", "",
- {"CLABEDestino", "CLABE", "CveBanco", "CveCuentaDeposito", "EstatusCtaDeposito", "EstatusPagoElectronico", "EstatusPagoElectronicoScotia", "AltaCuenta", "BancoNombre", "FechaEliminacion", "ConvenioPagoElectronico"}
- )
-
- If DtPendientesTemp.Rows.Count = 0 Then
- Alert("No hay datos pendientes para generar el Layout de ScotiaBank.", TipoMensaje.MsgAdvertencia)
- Exit Sub
- End If
-
- '------------------- Acumulados para el trailer -------------
- Dim Altas As Integer = 0, Cambios As Integer = 0
- Dim Bajas As Integer = 0, Consultas As Integer = 0
- '------------------- Acumulados para el trailer -------------
-
- '------------------- ConvenioPagoElectronico = "0000000" ' 5 dígitos
- NumeroConvenio = DtPendientesTemp.Rows(0)("ConvenioPagoElectronico").ToString
-
- If NumeroConvenio.Trim.Length = 0 Then
- Alert("El campo NumeroConvenio (ConvenioPagoElectronico) no está definido en los datos de la cuenta.", TipoMensaje.MsgAdvertencia)
- End If
-
- Dim sb As New StringBuilder
-
- '=============================================================
- ' 1) HEADER (140 )
- '=============================================================
- 'Dim hoy As Date = Now.Date
- 'Dim hora As String = Now.ToString("HHmmss")
-
- Dim Header As New StringBuilder()
- Header.Append(TipoArchivo.PadRight(2, Space)) 'TIPO ARCHIVO (2)
- Header.Append("HA") 'TIPO REGISTRO (2)
- Header.Append("JDF") 'SISTEMA-CENTRAL (3)
- Header.Append(NumeroConvenio.PadLeft(7, Cero)) 'NUMERO DE CONTRATO (7) ' ocupa 5 dígitos pero en el layout se usa 7
- Header.Append(NowADS.ToString("yyyyMMdd")) 'FECHA-SOLICITUD (8)
- Header.Append("001") 'SECUENCIA (3)
- Header.Append("M") 'MANTENIMIENTO-O-CONSULTA (1)
- Header.Append(" ".PadLeft(8, Space)) 'FECHA GENERACIÓN ARCHIVO (8) *** Respusta de ScotiaBank ***
- Header.Append(" ".PadLeft(6, Space)) 'Hora GENERACIÓN ARCHIVO (6) *** Respusta de ScotiaBank ***
- Header.Append(" ".PadLeft(3, Space)) 'CÓDIGO-RESPUESTA (3) *** Respusta de ScotiaBank ***
- Header.Append(" ".PadLeft(97, Space)) 'FILLER (97)
-
- sb.AppendLine(Header.ToString)
-
- '=============================================================
- ' 2) DETALLES (140 )
- '=============================================================
- Dim SBErrores As New StringBuilder
- For Each dr As DataRow In DtPendientesTemp.Rows
-
- Dim registro As New StringBuilder()
- Dim esError As Boolean = False
-
- '---- Datos base tomados de DTPendientes ------------------
-
- Dim CuentaDestino As String = ""
- Dim cuentaDigitos As String = dr("CLABEDestino").ToString.Trim
- Dim Clabe As String = dr("CLABE").ToString.Trim
- Dim limite As String = (9000000000 * 100D).ToString("F0")
- Dim banco As String = dr("CveBanco").ToString.PadLeft(3, Cero)
-
- If cuentaDigitos.Length = 11 AndAlso banco = "044" Then
- CuentaDestino = cuentaDigitos
- ElseIf Clabe.Length = 18 Then
- CuentaDestino = Clabe
- Else
- CuentaDestino = Clabe
- SBErrores.Append($"Cuenta {CuentaDestino} debe tener 11 o 18 dígitos. ")
- esError = True
- End If
-
- If banco.Length <> 3 OrElse Not IsNumeric(banco) OrElse banco = "000" Then
- SBErrores.Append($"Cuenta {CuentaDestino} código {banco} no es un banco válido. Debe ser numérico de 3 dígitos. ")
- esError = True
- End If
-
- Dim CveCuentaDeposito As String = dr("CveCuentaDeposito").ToString
-
- 'Dim movimiento As Char = If(dr.Table.Columns.Contains("Movimiento"),
- ' dr("Movimiento").ToString.FirstOrDefault(), MovimientoDefault)
-
- Dim CVETIPOCUENTA As String = If(CuentaDestino.Length = 18, "09", "01")
- '---- TIPO DE REGISTRO ------------------
+ Protected Sub LnkDescargaReporte_Click(sender As Object, e As EventArgs)
- 'ANEXO E de ScotiaBank
- 'DA = DETALLE ALTA DE DATOS DE CUENTA Y LIMITE RELACIONADO
- 'DC = DETALLE CAMBIOS DE DATOS DE CUENTA Y LIMITE RELACIONADO
- 'DB = DETALLE BAJA DE DATOS DE CUENTA Y LIMITE RELACIONADO
- 'DQ = DETALLE CONSULTA DE DATOS DE CUENTA Y LIMITE RELACIONADO
- 'DR = DETALLE RESPUESTA *** Respusta de ScotiaBank ***
+ Dim Archivo As New System.IO.FileInfo(String.Format("{0}Formatos/LayoutAltaProveedor.rdlc", UsuarioActual.Empresa.Ruta))
+ Dim Imagen As New System.IO.FileInfo($"{UsuarioActual.Empresa.Ruta}/Logo.png")
- Dim TipoRegistro As String = "DA" ' Por default es D (Alta), cambia a C si es cambio o baja
- '---- TIPO DE REGISTRO ------------------
+ DT_PagosReporte = DT_PagosReporte.FiltraParametros("EstatusPagoElectronicoGrupos = 'True' AND EstatusCtaDeposito > 0").Copy()
- '---- Construcción del registro ---------------------------
- registro.Append(TipoArchivo.PadRight(2, Space)) 'TIPO ARCHIVO (2)
- registro.Append(TipoRegistro) 'TIPO REGISTRO (2)
- registro.Append("A") 'CVE-MOVIMIENTO-CUENTA (1)
- registro.Append(CVETIPOCUENTA) 'CVE-TIPO - CUENTA (2)
- registro.Append("00") 'CVE-MONEDA - CUENTA (2) 00 Pesps 01 Dollares
- registro.Append(banco) 'NUM-banco - CUENTA (3)
- registro.Append(CuentaDestino.PadLeft(20, Cero)) 'NUM-CUENTA (20)
- registro.Append(NowADS.AddDays(364).ToString("yyyyMMdd")) 'FECHA DE ELIMINACIÓN (8)
- registro.Append(CveCuentaDeposito.PadRight(50, Space)) 'DESCRIPCIÓN (50)
- registro.Append(limite.PadLeft(17, Cero)) 'LIMITE-POR-TRANSACCIÓN (17)
- registro.Append("04") 'TIPO DE PAGO (2)
- registro.Append(" ") 'CÓDIGO-RESPUESTA (3) CÓDIGO DE RESPUESTA DE REG. "D*", ANEXO 'C' *** Respusta de ScotiaBank ***
- registro.Append(" ".PadLeft(28, Space)) 'FILLER (28)
+ Dim params As New List(Of ReportParameter)
- If registro.Length = LARGO_REGISTRO AndAlso Not esError Then
- sb.AppendLine(registro.ToString)
- Select Case TipoRegistro
- Case "DA"
- Altas = Altas + 1
- Case "DC"
- Cambios = Cambios + 1
- Case "DB"
- Bajas = Bajas + 1
- Case "DQ"
- Consultas = Consultas + 1
- Case Else
- esError = True
- End Select
- End If
- Next
-
- '=============================================================
- ' 3) TRAILER (PIE) (140)
- '=============================================================
- Dim trailer As New StringBuilder()
-
-
- trailer.Append(TipoArchivo.PadRight(2, Space)) 'TIPO DE ARCHIVO (2)
- trailer.Append("TA") 'TIPO DE REGISTRO (2)
- trailer.Append(Altas.ToString.PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS ALTAS (8)
- trailer.Append(Cambios.ToString.PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS CAMBIOS (8)
- trailer.Append(Bajas.ToString.PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS BAJAS (8)
- trailer.Append(Consultas.ToString.PadLeft(8, Cero)) 'CANTIDAD DE CONSULTAS (8)
- 'MOVIMIENTOS ACEPTADOS
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS ALTAS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS CAMBIOS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS BAJAS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE CONSULTAS (8) *** Respusta de ScotiaBank ***
- 'MOVIMIENTOS RECHAZADOS
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS ALTAS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS CAMBIOS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE MOVIMIENTOS BAJAS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(8, Cero)) 'CANTIDAD DE CONSULTAS (8) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(3, Cero)) 'CÓDIGO-RESPUESTA (3) *** Respusta de ScotiaBank ***
- trailer.Append("0".PadLeft(3, Cero)) 'CÓDIGO-RESPUESTA - Archivo (3) *** Respusta de ScotiaBank ***
- trailer.Append(" ".PadLeft(34, Space)) 'FILLER (34)
-
- sb.Append(trailer.ToString)
-
- '------------------- Crear archivo y mostrar descargas ------------------
- TextoCompleto = sb.ToString
- If sb.Length = 0 Then
- Alert("No se generó ningún registro válido para Bajío.", TipoMensaje.MsgAdvertencia)
- Exit Sub
- End If
-
-
-
- If SBErrores.Length > 0 Then
- Alert("Errores encontrados al generar el layout de ScotiaBank: " & SBErrores.ToString, TipoMensaje.MsgAdvertencia)
+ If Archivo.Exists Then
+ ImprimirPDF(String.Format("{0}Formatos\LayoutPagoProveedor.rdlc", UsuarioActual.Empresa.Ruta), DtPago, params, "LayoutPagoProveedor", RDSName:="DSPagoElectronicoV2")
Else
- Dim NombreArchivoEnviado As String = $"altacuentasScotia_{FechaArchivo:ddMMyyyy}_{NumeroArchivo:D3}.txt"
- If CreaArchivo(2, True, NombreArchivoEnviado) Then
- DVDescargaPagos.Visible = False
- DVDescargaReporte.Visible = False
- LblCuentas.Text = "Cuentas Bajio"
- 'NombreArchivoBancomer = "" 'No usamos estos para scotia
- 'NombreArchivoInterbancario = ""
- 'NombreArchivoCIE = ""
- NombreArchivo = NombreArchivoEnviado
- DVDescargaCuentas1.Visible = True
- LnkDescargaCuentas1.Text = NombreArchivo
- RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});")
- UpModalDescarga.Update()
- End If
+
+ params.Add(New ReportParameter("LogoPath", If(Imagen.Exists, $"file://{Imagen.FullName}", "")))
+
+ params.Add(New ReportParameter("NombreEmpresa", UsuarioActual.Empresa.Empresa))
+ params.Add(New ReportParameter("Direccion", UsuarioActual.Empresa.Direccion))
+ params.Add(New ReportParameter("RFC", UsuarioActual.Empresa.RFC))
+ params.Add(New ReportParameter("FechaImpresion", NowADS().ToString("dd/MM/yyyy")))
+
+ params.Add(New ReportParameter("UsuarioImprimio", UsuarioActual.Nombre))
+ params.Add(New ReportParameter("Titulo", "Reporte Pago Proveedor Layout"))
+
+ ImprimirPDF("Empresas/Grales/Formatos/LayoutPagoProveedor.rdlc", DT_PagosReporte, params, "LayoutPagoProveedor", RDSName:="DSPagoElectronicoV2")
End If
- CargaDatos()
-
- End Sub
-
- '---------------------------------------------------------------
- ' Limpia y normaliza texto para Scotia (solo A-Z,0-9,espacio)
- '---------------------------------------------------------------
- Private Function LimpiarTextoScotia(txt As String, largo As Integer) As String
- Dim clean = New String(txt _
- .Normalize(System.Text.NormalizationForm.FormD) _
- .Where(Function(ch) Char.IsLetterOrDigit(ch) OrElse ch = " "c) _
- .ToArray()) _
- .ToUpperInvariant()
- Return clean.PadRight(largo).Substring(0, largo)
- End Function
-
-
- '====================================================================
- ' GeneraPagoScotiaBank – Layout Pagos Scotiabank (For Each, método único)
- '====================================================================
- ' ▸ Genera un archivo de pagos masivos para Scotiabank (Archivo de intercambio EE).
- ' ▸ Registros y longitudes exactas:
- ' • HA, HB, DA, TB, TA → 370 caracteres
- ' • DM (correo) → 104 caracteres
- ' ▸ Se permite partición por bloques (TamanoBloque), pero todo dentro de un
- ' mismo método para claridad. Sólo se complementa con LimpiarTextoScotia().
- '====================================================================
-
- Public Sub GeneraPagoScotiaBank(ByVal DTPendientes As DataTable, InsertaEnDB As Boolean)
-
- Dim TamanoBloque As Integer = 500 ' pagos por bloque
-
- Dim ErrorLayout As Boolean = False
-
- '------------------- VALIDACIONES BÁSICAS ---------------------------
- If DTPendientes Is Nothing OrElse DTPendientes.Rows.Count = 0 Then
- Alert("No hay datos pendientes para generar el Layout de ScotiaBank.", TipoMensaje.MsgAdvertencia)
- ErrorLayout = True
- End If
-
- Dim CuentaCargo As String = DTPendientes.Rows(0)("CLABEOrigen").ToString
- If CuentaCargo.Length <> 11 Then
- Alert("El campo CuentaCargo debe ser numérico de 11 dígitos.", TipoMensaje.MsgAdvertencia)
- ErrorLayout = True
-
- End If
-
- Dim NumeroConvenio As String = DTPendientes.Rows(0)("ConvenioPagoElectronico").ToString
- If NumeroConvenio.Trim.Length = 0 Then
- Alert("El campo NumeroConvenio (ConvenioPagoElectronico) no está definido en los datos de la cuenta.", TipoMensaje.MsgAdvertencia)
- ErrorLayout = True
-
- End If
-
- If NumeroConvenio.Length <> 5 Then
- Alert("El campo NumeroConvenio debe ser numérico de 5 dígitos.", TipoMensaje.MsgAdvertencia)
- ErrorLayout = True
-
- End If
-
-
- '------------------- ACUMULADORES -----------------------------------
- Dim sb As New StringBuilder()
- Dim totalPagos As Integer = 0
- Dim totalImporte As Decimal = 0D
- Dim pagosBloque As Integer = 0
- Dim importeBloque As Decimal = 0D
- Dim numBloque As Integer = 0
-
- Dim SPACE As Char = " "c
- Dim CERO As Char = "0"c
-
- '------------------- HEADER ARCHIVO (HA) ----------------------------
- Dim ha As New StringBuilder()
- ha.Append("EE") ' 1‑2 Tipo Archivo
- ha.Append("HA") ' 3‑4 Tipo Registro
- ha.Append(NumeroConvenio.PadLeft(5, "0"c)) ' 5‑9 Nº Convenio
- ha.Append("01") ' 10‑11 Secuencia fija "01"
- ha.Append("00000000") ' 12‑19 Fecha generación
- ha.Append("00000000") ' 20‑27 Fecha inicial (opcional)
- ha.Append("00000000") ' 28‑35 Fecha final (opcional)
- ha.Append("000") ' 36‑38 Código status "000"
- ha.Append(" ".PadLeft(332, SPACE)) ' 39‑370 FILLER (espacios)
-
- sb.AppendLine(ha.ToString())
-
- '------------------- RECORRIDO DETALLES -----------------------------
- Dim SBErrores As StringBuilder = New StringBuilder()
- 'Dim esError As Boolean = False
- Dim idx As Integer = 0
-
- Dim hb As New StringBuilder()
- hb.Append("EE") ' 1‑2
- hb.Append("HB") ' 3‑4
- hb.Append("00") ' 5‑6 Moneda cuenta cargo (00=MXN)
- hb.Append("0000") ' 7‑10 Uso futuro = ceros
- hb.Append(CuentaCargo) ' 11‑21 Cuenta cargo (11)
- hb.Append("0000000001") ' 22‑31 Referencia de cargo? (ejemplo)
- hb.Append("000") ' 32‑34 Codigo del registro
- hb.Append(" ".PadLeft(336, SPACE)) ' 35‑370 FILLER espacios
-
- sb.AppendLine(hb.ToString())
-
- For Each dr As DataRow In DTPendientes.Rows
-
- ''--- ¿Inicia BLOQUE? (HB) ---------------------------------------
- 'If idx Mod TamanoBloque = 0 Then
- ' numBloque += 1
- ' pagosBloque = 0
- ' importeBloque = 0D
-
- ' Dim hb As New StringBuilder(New String(" "c, 370))
- ' hb.Append("EE") ' 1‑2
- ' hb.Append("HB") ' 3‑4
- ' hb.Append("00") ' 5‑6 Moneda cuenta cargo (00=MXN)
- ' hb.Append("0000") ' 7‑10 Uso futuro = ceros
- ' hb.Append(CuentaCargo) ' 11‑21 Cuenta cargo (11)
- ' hb.Append("0000000001") ' 22‑31 Referencia de cargo? (ejemplo)
- ' hb.Append("000") ' 32‑34 Codigo del registro
- ' hb.Append(" ".PadLeft(336, SPACE)) ' 35‑370 FILLER espacios
-
- ' sb.AppendLine(hb.ToString())
- 'End If
-
- '----------- DETALLE ALTA (DA) ----------------------------------
- Dim importe As Decimal = 0D
- If Not Decimal.TryParse(Convert.ToString(dr("Importe")), importe) Then
- 'Alert($"Importe inválido en fila {idx + 1}", TipoMensaje.MsgAdvertencia)
- SBErrores.Append($"Importe inválido en fila {idx + 1}")
- ErrorLayout = True
- End If
-
- If importe <= 0D Then
- Alert($"Importe debe ser mayor a 0 en fila {idx + 1}", TipoMensaje.MsgAdvertencia)
- ErrorLayout = True
- End If
-
- Dim importeInt As String = CDec(Math.Round(importe * 100).ToEntero).ToString().PadLeft(15, CERO) ' 2 dec.
-
- Dim fechaAplicacion As String = NowADS.ToString("yyyyMMdd")
- Dim cveBenef As String = LimpiarTextoScotia(Convert.ToString(dr("CveProveedor"))).PadRight(20)
- Dim rfc As String = LimpiarTextoScotia(Convert.ToString(dr("RFC"))).PadRight(13)
- Dim nombreBen As String = LimpiarTextoScotia(Convert.ToString(dr("RazonSocial"))).PadRight(40)
- Dim CveIE As Integer = dr("CveIE").ToString.ToEntero
- Dim referenciaPago As String = CveIE.ToString.PadLeft(16, CERO) 'If(dr.Table.Columns.Contains("Referencia"), LimpiarTextoScotia(Convert.ToString(dr("Referencia"))).PadLeft(16, "0"c), New String("0"c, 16))
-
- Dim CuentaDestino As String = ""
- Dim cuentaDigitos As String = Convert.ToString(dr("CLABEDestino"))
- Dim clabe As String = Convert.ToString(dr("CLABE"))
- Dim CveBanco As String = dr("CveBanco").ToString.PadLeft(3, CERO)
-
-
- If cuentaDigitos.Length = 11 AndAlso CveBanco = "044" Then
- CuentaDestino = cuentaDigitos
- ElseIf clabe.Length = 18 Then
- CuentaDestino = clabe
- Else
- CuentaDestino = clabe
- SBErrores.Append($"Cuenta {CuentaDestino} debe tener 11 o 18 dígitos. ")
- ErrorLayout = True
- End If
-
-
- Dim TipoCuenta As String = If(CuentaDestino.Length = 18, "9", "1") ' 09=18 dígitos, 01=11 dígitos
-
- CuentaDestino = CuentaDestino.PadLeft(20, CERO)
-
-
-
- If CveBanco = "000" Then
- Alert($"CveBanco inválida en fila {idx + 1}. Debe ser numérico de 3 dígitos.", TipoMensaje.MsgAdvertencia)
- ErrorLayout = True
- End If
-
- Dim ConceptoPago As String = dr("Observaciones").ToString.Trim
-
- If ConceptoPago.Length > 50 Then
- ConceptoPago = ConceptoPago.Substring(0, 50) ' Limitar a 50 caracteres
- End If
- ConceptoPago = ConceptoPago.PadRight(50, SPACE)
-
- Dim da As New StringBuilder()
- da.Append("EE") ' 1‑2
- da.Append("DA") ' 3‑4
- da.Append("04") ' 5‑6 Tipo movimiento (04=SPEI)
- da.Append("00") ' 7‑8 Moneda pago (00=MXN)
- da.Append(importeInt) ' 9‑23 Importe (15)
- da.Append(fechaAplicacion) ' 24‑31
- da.Append("03") ' 32‑33 Servicio‑concepto (03)
- da.Append(cveBenef) ' 34‑53
- da.Append(rfc) ' 54‑66
- da.Append(nombreBen) ' 67‑106
- da.Append(referenciaPago) ' 107‑122
- da.Append("00000") ' 123‑127 Plaza pago (ceros)
- da.Append("00000") ' 128‑132 Sucursal pago (ceros)
-
- da.Append(CuentaDestino) ' 133‑152 clabe destino (ceros)
- da.Append("00000") ' 153‑157 PAIS (ceros)
- da.Append("".PadLeft(40, SPACE)) ' 158‑197 Ciudad espacio (espacios en blanco)
- da.Append(TipoCuenta) ' 198-198 Tipo cuenta
- da.Append(SPACE) ' 199-199 digito intercambio
- da.Append("00000") ' 200-204 plaza cuenta banco
- da.Append("044") ' 205-207 num banco emisor (044=ScotiaBank)
- da.Append(CveBanco) ' 208-210 num banco receptor (044=ScotiaBank)
-
- da.Append("001") ' 211-213 dias vigencia
- da.Append(ConceptoPago) ' 214-263 Concepto pago
- da.Append("".PadLeft(60, SPACE)) '264-283 CAMPO-USO-EMPRESA-1
- ' 284-303 CAMPO-USO - Empresa - 2
- ' 304-323 CAMPO-USO - Empresa - 3
- da.Append("".PadLeft(41, CERO)) ' 324-326 CODIGO-STATUS - REGISTRO NUM 3
- ' 327-327 CVE-CAMBIO - INST NUM 1
- ' 328-330 CODIGO-STATUS - CAMBIO - INST NUM 3
- ' 331-338 FECHA DE PAGO (Pago en ventanilla) NUM 8
- ' 339-343 PLAZA DE PAGO (Pago en ventanilla) NUM 5
- ' 344-348 SUCURSAL DE PAGO (Pago en ventanilla) NUM 5
- ' 349-364 FOLIO-UNICO NUM 16
- sb.AppendLine(da.ToString())
-
- '----------- DETALLE MAIL (DM) 104 -------------------------
-
- Dim correo As String = dr("Correo").ToString.Trim
- If correo.Trim.Length = 0 Then
- SBErrores.Append($" {nombreBen} Email no definido en fila {idx + 1}. Debe ser un correo electrónico válido. ")
- ErrorLayout = True
- End If
-
- Dim dm As New StringBuilder()
- dm.Append("EE") ' 1‑2 Tipo archivoz
- dm.Append("DM") ' 3‑4 Tipo registro
- dm.Append(correo.PadRight(100)) ' 5‑104 Email + filler
- da.Append("".PadLeft(34, CERO)) ' 105-138 Uso Futuro
- da.Append("".PadLeft(30, SPACE)) ' 139-168 Clave de Rastreo llenar con espacios en blanco
- da.Append("".PadLeft(20, SPACE)) ' 169-188 Referencia de Abono Banxico
- dm.Append(" ") ' 189-190 Tipo de Operación anexo G
- da.Append("".PadLeft(232, SPACE)) ' 191-370 FILLER
-
-
- sb.AppendLine(dm.ToString())
-
- '----------- ACUMULADORES ---------------------------------------
- totalPagos += 1
- totalImporte += importe
- pagosBloque += 1
- importeBloque += importe
-
- '----------- ¿CIERRA BLOQUE? (TB) -------------------------------
- Dim bloqueCompleto As Boolean = (pagosBloque = TamanoBloque)
- Dim ultimoRegistro As Boolean = (idx = DTPendientes.Rows.Count - 1)
- idx += 1
- Next
-
- 'If bloqueCompleto OrElse ultimoRegistro Then
- Dim tb As New StringBuilder()
- tb.Append("EE") ' 1‑2
- tb.Append("TB") ' 3‑4
- tb.Append(pagosBloque.ToString().PadLeft(7, CERO)) ' 5‑11 Cnt altas
- tb.Append((importeBloque * 100).ToEntero.ToString().PadLeft(17, CERO)) ' 12‑28 Importe altas
- tb.Append("".PadLeft(7, CERO)) ' 29‑35 Cnt bajas
- tb.Append("".PadLeft(17, CERO)) ' 36‑52 Importe bajas
- tb.Append("".PadLeft(195, CERO))
- ' 53-59 CANTIDAD DE MOVIMIENTOS ALTAS
- ' 60-76 IMPORTE DE MOVIMIENTOS ALTAS
- ' 77-83 CANTIDAD DE MOVIMIENTOS BAJAS
- ' 84-100 IMPORTE DE MOVIMIENTOS BAJAS
- ' 101-107 CANTIDAD DE MOVIMIENTOS ALTAS
- ' 108-124 IMPORTE DE MOVIMIENTOS ALTAS
- ' 125-131 CANTIDAD DE MOVIMIENTOS BAJAS
- ' 132-148 IMPORTE DE MOVIMIENTOS BAJAS
- ' 149-155 CANTIDAD DE MOVIMIENTOS PAGADOS
- ' 156-172 IMPORTE DE MOVIMIENTOS PAGADOS
- ' 173-179 CANTIDAD DE MOVIMIENTOS DEVUELTOS
- ' 180-196 IMPORTE DE MOVIMIENTOS DEVUELTOS
- ' 197-203 CANTIDAD DE MOVIMIENTOS RECH
- ' 204-220 IMPORTE DE MOVIMIENTOS RECH
- ' 221-227 CANTIDAD DE MOVIMIENTOS BAJA
- ' 228-244 IMPORTE DE MOVIMIENTOS BAJA
- ' 245-247 CODIGO-STATUS-REGISTRO
- tb.Append("".PadLeft(123, SPACE)) ' 248-370 FILLER (espacios)
- sb.AppendLine(tb.ToString())
- 'End If
-
- '------------------- TRAILER ARCHIVO (TA) ---------------------------
- Dim ta As New StringBuilder()
- ta.Append("EE") ' 1‑2
- ta.Append("TA") ' 3‑4
- ta.Append(totalPagos.ToString().PadLeft(7, CERO)) ' 5‑11
- ta.Append((totalImporte * 100).ToEntero.ToString().PadLeft(17, CERO)) ' 12‑28
- ta.Append("".PadLeft(7, CERO)) ' 29‑35 Cnt bajas
- ta.Append("".PadLeft(17, CERO)) ' 36‑52 Importe bajas
- ta.Append("".PadLeft(198, CERO))
- ' 53-59 CANTIDAD DE MOVIMIENTOS ALTAS
- ' 60-76 IMPORTE DE MOVIMIENTOS ALTAS
- ' 77-83 CANTIDAD DE MOVIMIENTOS BAJAS
- ' 84-100 IMPORTE DE MOVIMIENTOS BAJAS
- ' 101-107 CANTIDAD DE MOVIMIENTOS ALTAS
- ' 108-124 IMPORTE DE MOVIMIENTOS ALTAS
- ' 125-131 IMPORTE DE MOVIMIENTOS BAJAS
- ' 132-148 MOVIMIENTOS PAGADOS
- ' 149-155 IMPORTE DE MOVIMIENTOS PAGADOS
- ' 156-172 MOVIMIENTOS DEVUELTOS
- ' 173-179 IMPORTE DE MOVIMIENTOS DEVUELTOS
- ' 180-196 MOVIMIENTOS RECHAZADOS
- ' 197-203 CANTIDAD DE MOVIMIENTOS RECH
- ' 204-220 IMPORTE DE MOVIMIENTOS RECH
- ' 221-227 CANTIDAD DE MOVIMIENTOS BAJA
- ' 228-244 IMPORTE DE MOVIMIENTOS BAJA
- ' 245-247 CODIGO-STATUS-REGISTRO
- ' 248-250 CODIGO-STATUS-ARCHIVO
-
- ta.Append("".PadLeft(120, SPACE))
-
- sb.Append(ta.ToString())
-
- '------------------- ESCRIBIR ARCHIVO -------------------------------
- 'File.WriteAllText(RutaArchivo, sb.ToString(), Encoding.ASCII)
-
-
- Dim NombreArchivo As String = $"pagos_{NowADS.ToString("ddMMyyyy")}_001.txt"
- '"pagos_03062025_001.txt"
-
- If InsertaEnDB Then
-
- Dim ObjBancos As New ClsBancos
- ObjBancos.IniciaTransacSQL()
-
- Dim CveLayoutEnvio As Integer = ObjBancos.AddLayoutEnvios(NombreArchivo, NowADS(), CveCuenta, PorGrupos:=True)
-
- If CveLayoutEnvio > 0 Then
- For Each dr As DataRow In DTPendientes.Rows
- If dr("CveProveedor").ToString <> "" Or dr("CvePersonal").ToString <> "" Then
- If Not ObjBancos.AddLayoutEnviosDetalle(CveLayoutEnvio, dr("CveIE").ToString.ToEntero, dr("CveProveedor").ToString.ToEntero, dr("CvePersonal").ToString.ToEntero, 1, "Observaciones") Then
- ErrorLayout = True
- Exit For
- End If
- End If
- Next
- Else
- ErrorLayout = True
- End If
-
- If ErrorLayout Then
- ObjBancos.RollBack()
- ObjBancos.Dispose()
- Else
- ObjBancos.Commit()
- ObjBancos.Dispose()
- End If
-
- End If
-
- Dim path As String = String.Format("{0}Layout\{1}", UsuarioActual.Empresa.Ruta, NombreArchivo)
- Dim pathDirectorio As String = String.Format("{0}Layout\", UsuarioActual.Empresa.Ruta)
-
- If File.Exists(path) Then
- File.Delete(path)
- End If
-
- If Not Directory.Exists(pathDirectorio) Then
- Directory.CreateDirectory(pathDirectorio)
- End If
-
- Dim Texto As String = sb.ToString
-
- Dim fs As FileStream = File.Create(path)
- Dim info As Byte() = New UTF8Encoding(True).GetBytes(Texto)
- fs.Write(info, 0, info.Length)
- fs.Close()
-
-
- If ErrorLayout = False And totalPagos > 0 Then
-
- Dim Mensaje As New StringBuilder
-
- Mensaje.Append("Descarga Layout ")
-
- 'If NombreArchivo.Length > 0 Then
- ' NombreArchivoPago = NombreArchivoEnviado
- 'End If
-
- 'If NombreArchivoPago.Trim.Length > 0 Then
- ' Mensaje.Append($"Pagos Descarga {NombreArchivoPago}