diff --git a/App_Code/ClsPagoScotia.vb b/App_Code/ClsPagoScotia.vb new file mode 100644 index 000000000..36daff410 --- /dev/null +++ b/App_Code/ClsPagoScotia.vb @@ -0,0 +1,884 @@ +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 + + 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 + + DtPendientesTemp = DtPendientesTemp.FiltraParametros("", "", + {"CLABEDestino", "CLABE", "CveBanco", "CveCuentaDeposito", "EstatusCtaDeposito", "EstatusPagoElectronicoScotia", "BancoNombre", "FechaEliminacion", "ConvenioPagoElectronico"} + ) + + 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 + SBErrores.Append($"Linea {Contador} 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($"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) + + 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 + 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() + + 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/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}

") - 'End If - - If NombreArchivo.Length > 0 Then - - DVDescargaPagos.Visible = True - DVDescargaCuentas1.Visible = False - 'DVDescargaCuentas2.Visible = False - 'DVDescargaCuentas3.Visible = False - DVDescargaReporte.Visible = True - - DT_PagosReporte = DTPendientes.Copy - - LnkDescarga.Text = NombreArchivo - RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") - UpModalDescarga.Update() - - End If - - CargaDatos() - Else - Alert($"Errores detectados
{SBErrores.ToString}", TipoMensaje.MsgAdvertencia) - End If - - End Sub - - '==================================================================== - ' 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 - - - - - - ''==================================================================== - '' 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 Sub GeneraPagoScotiaBank( - ' ByVal DTPendientes As DataTable, - ' ByVal RutaArchivo As String, - ' Optional ByVal NumeroConvenio As String = "12345", _ ' 5 dígitos - ' Optional ByVal CuentaCargo As String = "11987654321", _ ' 11 dígitos - ' Optional ByVal TamanoBloque As Integer = 500 _ ' pagos por bloque - ') - - ' '------------------- 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) - ' End If - - ' '------------------- ConvenioPagoElectronico = "0000000" ' 7 dígitos - ' NumeroConvenio = 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) - ' Exit Sub - ' End If - - ' If NumeroConvenio.Length <> 5 Then - ' Alert("El campo NumeroConvenio debe ser numérico de 5 dígitos.", TipoMensaje.MsgAdvertencia) - ' Exit Sub - ' End If - - - ' If CuentaCargo.Length <> 11 Then - ' Alert("El campo CuentaCargo debe ser numérico de 11 dígitos.", TipoMensaje.MsgAdvertencia) - ' Exit Sub - ' 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 - - ' '------------------- HEADER ARCHIVO (HA) ---------------------------- - ' Dim ha As New StringBuilder(New String(" "c, 370)) - ' ha.Insert(0, "EE") ' 1‑2 Tipo Archivo - ' ha.Insert(2, "HA") ' 3‑4 Tipo Registro - ' ha.Insert(4, NumeroConvenio.PadLeft(5, "0"c)) ' 5‑9 Nº Convenio - ' ha.Insert(9, "01") ' 10‑11 Secuencia fija "01" - ' Dim fechaHoy As String = Date.Now.ToString("yyyyMMdd") - ' ha.Insert(11, fechaHoy) ' 12‑19 Fecha generación - ' ha.Insert(19, "00000000") ' 20‑27 Fecha inicial (opcional) - ' ha.Insert(27, "00000000") ' 28‑35 Fecha final (opcional) - ' ha.Insert(35, "000") ' 36‑38 Código status "000" - ' ' 39‑370 FILLER (espacios) ya está - ' sb.AppendLine(ha.ToString()) - - ' '------------------- RECORRIDO DETALLES ----------------------------- - ' Dim idx As Integer = 0 - ' 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.Insert(0, "EE") ' 1‑2 - ' hb.Insert(2, "HB") ' 3‑4 - ' hb.Insert(4, "00") ' 5‑6 Moneda cuenta cargo (00=MXN) - ' hb.Insert(6, "0000") ' 7‑10 Uso futuro = ceros - ' hb.Insert(10, CuentaCargo) ' 11‑21 Cuenta cargo (11) - ' hb.Insert(21, "0000000001") ' 22‑31 Referencia Empresa (ejemplo) - ' hb.Insert(31, "000") ' 32‑34 Status registro - ' ' 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 _ - ' Throw New ArgumentException($"Importe inválido en fila {idx + 1}") - ' If importe <= 0D Then _ - ' Throw New ArgumentException($"Importe ≤ 0 en fila {idx + 1}") - - ' Dim importeInt As String = CDec(Math.Round(importe * 100)).ToString().PadLeft(15, "0"c) ' 2 dec. - - ' Dim fechaAplicacion As String = Date.Now.ToString("yyyyMMdd") - ' Dim cveBenef As String = LimpiarTextoScotia(Convert.ToString(dr("CveProveedor")), 20).PadRight(20) - ' Dim rfc As String = LimpiarTextoScotia(Convert.ToString(dr("RFC")), 13).PadRight(13) - ' Dim nombreBen As String = LimpiarTextoScotia(Convert.ToString(dr("RazonSocial")), 40).PadRight(40) - ' Dim referenciaPago As String = If(dr.Table.Columns.Contains("Referencia"), - ' LimpiarTextoScotia(Convert.ToString(dr("Referencia")), 16).PadLeft(16, "0"c), - ' New String("0"c, 16)) - ' Dim clabe As String = Convert.ToString(dr("CLABEDestino")) - ' If String.IsNullOrWhiteSpace(clabe) Then clabe = Convert.ToString(dr("CLABE")) - ' clabe = clabe.PadLeft(18, "0"c) - - ' Dim da As New StringBuilder(New String(" "c, 370)) - ' da.Insert(0, "EE") ' 1‑2 - ' da.Insert(2, "DA") ' 3‑4 - ' da.Insert(4, "04") ' 5‑6 Tipo movimiento (04=SPEI) - ' da.Insert(6, "00") ' 7‑8 Moneda pago (00=MXN) - ' da.Insert(8, importeInt) ' 9‑23 Importe (15) - ' da.Insert(23, fechaAplicacion) ' 24‑31 - ' da.Insert(31, "03") ' 32‑33 Servicio‑concepto (03) - ' da.Insert(33, cveBenef) ' 34‑53 - ' da.Insert(53, rfc) ' 54‑66 - ' da.Insert(66, nombreBen) ' 67‑106 - ' da.Insert(106, referenciaPago) ' 107‑122 - ' da.Insert(122, "00000") ' 123‑127 Plaza pago (ceros) - ' da.Insert(127, "00000") ' 128‑132 Sucursal pago (ceros) - ' da.Insert(132, New String("0"c, 34)) ' 133‑166 Uso futuro (ceros) - ' da.Insert(166, New String(" "c, 30)) ' 167‑196 Clave rastreo (espacios) - ' da.Insert(196, New String("0"c, 20)) ' 197‑216 Referencia Banxico (ceros) - ' da.Insert(216, "01") ' 217‑218 Tipo operación (01 default) - ' ' 219‑370 FILLER espacios - ' sb.AppendLine(da.ToString()) - - ' '----------- DETALLE MAIL (DM) 104 bytes ------------------------- - ' Dim correo As String = If(dr.Table.Columns.Contains("Email"), - ' LimpiarTextoScotia(Convert.ToString(dr("Email")), 100), "") - ' Dim dm As New StringBuilder(New String(" "c, 104)) - ' dm.Insert(0, "EE") ' 1‑2 Tipo archivo - ' dm.Insert(2, "DM") ' 3‑4 Tipo registro - ' dm.Insert(4, correo.PadRight(100)) ' 5‑104 Email + 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) - - ' If bloqueCompleto OrElse ultimoRegistro Then - ' Dim tb As New StringBuilder(New String(" "c, 370)) - ' tb.Insert(0, "EE") ' 1‑2 - ' tb.Insert(2, "TB") ' 3‑4 - ' tb.Insert(4, pagosBloque.ToString().PadLeft(7, "0"c)) ' 5‑11 Cnt altas - ' tb.Insert(11, (importeBloque * 100).ToString().PadLeft(17, "0"c)) ' 12‑28 Importe altas - ' ' 29‑370 resto de contadores a cero / espacios - ' tb.Insert(28, New String("0"c, 342)) - ' sb.AppendLine(tb.ToString()) - ' End If - - ' idx += 1 - ' Next - - ' '------------------- TRAILER ARCHIVO (TA) --------------------------- - ' Dim ta As New StringBuilder(New String(" "c, 370)) - ' ta.Insert(0, "EE") ' 1‑2 - ' ta.Insert(2, "TA") ' 3‑4 - ' ta.Insert(4, totalPagos.ToString().PadLeft(7, "0"c)) ' 5‑11 - ' ta.Insert(11, (totalImporte * 100).ToString().PadLeft(17, "0"c)) ' 12‑28 - ' ta.Insert(28, New String("0"c, 342)) ' resto filler - ' sb.AppendLine(ta.ToString()) - - ' '------------------- ESCRIBIR ARCHIVO ------------------------------- - ' File.WriteAllText(RutaArchivo, sb.ToString(), Encoding.ASCII) - 'End Sub - - Protected Sub LnkDescarga_Click(sender As Object, e As EventArgs) Dim FileName As String = NombreArchivo @@ -1364,62 +586,6 @@ Partial Class Bancos_PagoElectronico End Sub - - - Protected Sub LnkDescargaReporte_Click(sender As Object, e As EventArgs) - - 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") - - DT_PagosReporte = DT_PagosReporte.FiltraParametros("EstatusPagoElectronicoGrupos = 'True' AND EstatusCtaDeposito > 0").Copy() - - Dim params As New List(Of ReportParameter) - - If Archivo.Exists Then - ImprimirPDF(String.Format("{0}Formatos\LayoutPagoProveedor.rdlc", UsuarioActual.Empresa.Ruta), DtPago, params, "LayoutPagoProveedor", RDSName:="DSPagoElectronicoV2") - Else - - - 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 - - - - End Sub - 'Protected Sub LnkDescargaCuentas2_Click(sender As Object, e As EventArgs) - ' Dim FileName As String = NombreArchivoInterbancario - ' Dim FilePath As String = $"{UsuarioActual.Empresa.Ruta}Layout\{NombreArchivoInterbancario}" - ' Response.Clear() - ' Response.ContentType = "application/octet-stream" - ' Response.AddHeader("Content-Disposition", "attachment; filename=" & FileName) - ' Response.TransmitFile(FilePath) - ' Response.End() - 'End Sub - - 'Protected Sub LnkDescargaCuentas3_Click(sender As Object, e As EventArgs) - - ' Dim FileName As String = NombreArchivoCIE - ' Dim FilePath As String = $"{UsuarioActual.Empresa.Ruta}Layout\{NombreArchivoCIE}" - ' Response.Clear() - ' Response.ContentType = "application/octet-stream" - ' Response.AddHeader("Content-Disposition", "attachment; filename=" & FileName) - ' Response.TransmitFile(FilePath) - ' Response.End() - 'End Sub - -#End Region - - #Region " TAB PRINCIPAL " Protected Sub GvPendientes_RowDataBound(sender As Object, e As GridViewRowEventArgs) @@ -1505,15 +671,42 @@ Partial Class Bancos_PagoElectronico If DtRegenerar IsNot Nothing Then GeneraPago(DtRegenerar, CveBLE) Else - Alert("Ocurrió un error al obtener los datos para generar el archivo. Por favor vuelva a intentar.", TipoMensaje.MsgError) + Alert("Ocurrió un errorScotia al obtener los datos para generar el archivo. Por favor vuelva a intentar.", TipoMensaje.MsgError) End If End If If OpBancos = 3 Then If DtRegenerar IsNot Nothing Then - GeneraPagoScotiaBank(DtRegenerar, False) + + Dim ErrorScotia As Boolean = False + Using objScotia As New ClsPagoScotia + If objScotia.GeneraPagoScotiaBank(DtRegenerar, False, CveCuenta, UsuarioActual) Then + + If objScotia.ErrorLayout = False And objScotia.TotalPagos > 0 Then + + DVDescargaPagos.Visible = True + DVDescargaCuentas1.Visible = False + DVDescargaReporte.Visible = True + DT_PagosReporte = DTPendientes.Copy + LnkDescarga.Text = objScotia.NombreArchivo + RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") + UpModalDescarga.Update() + Else + Alert($"Errores detectados
{objScotia.LayouErrorStr.ToString}", TipoMensaje.MsgAdvertencia) + ErrorScotia = True + End If + + Else + Alert("Error al generar el pago de ScotiaBank. Por favor vuelva a intentar.", TipoMensaje.MsgError) + ErrorScotia = True + End If + End Using + If Not ErrorScotia Then + CargaDatos() + End If + 'GeneraPagoScotiaBank(DtRegenerar, False) Else - Alert("Ocurrió un error al obtener los datos para generar el archivo. Por favor vuelva a intentar.", TipoMensaje.MsgError) + Alert("Ocurrió un Error al obtener los datos para generar el archivo. Por favor vuelva a intentar.", TipoMensaje.MsgError) End If End If @@ -1552,8 +745,27 @@ Partial Class Bancos_PagoElectronico ElseIf OpBancos = 2 Then 'AltaProveedoresBajio() ElseIf OpBancos = 3 Then + Dim fechaHoy As String = DateTime.Today.ToString("MM/dd/yyyy") - AltaProveedoresScotia(DTPendientes.FiltraParametros($" EstatusPagoElectronicoScotia = False OR FechaEliminacion < #{fechaHoy}#")) + Dim ErrorCuentas As Boolean = False + Using objPagoScotia As New ClsPagoScotia + If objPagoScotia.AltaCuentasScotia(DTPendientes.FiltraParametros($" EstatusPagoElectronicoScotia = False Or FechaEliminacion < #{fechaHoy}#"), UsuarioActual) Then + + DVDescargaPagos.Visible = False + DVDescargaReporte.Visible = False + LblCuentas.Text = "Cuentas Bajio" + DVDescargaCuentas1.Visible = True + LnkDescargaCuentas1.Text = objPagoScotia.NombreArchivo + RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") + UpModalDescarga.Update() + Else + Alert($"Errores detectados
{objPagoScotia.LayouErrorStr.ToString}", TipoMensaje.MsgAdvertencia) + ErrorCuentas = True + End If + End Using + + 'AltaCuentasScotia(DTPendientes.FiltraParametros($" EstatusPagoElectronicoScotia = False Or FechaEliminacion < #{fechaHoy}#")) + End If End Sub @@ -1916,10 +1128,48 @@ Partial Class Bancos_PagoElectronico ElseIf OpBancos = 3 Then If DTPendientes.FiltraParametros("EstatusPagoElectronicoScotia = 'True' AND EstatusCtaDeposito = 'True'") IsNot Nothing AndAlso DTPendientes.FiltraParametros("EstatusPagoElectronicoScotia = 'True' AND EstatusCtaDeposito = 'True'").Rows.Count > 0 Then - GeneraPagoScotiaBank(DTPendientes.FiltraParametros("EstatusPagoElectronicoScotia = 'True' AND EstatusCtaDeposito = 'True'"), True) + + Dim errorScotia As Boolean = False + Using objScotia As New ClsPagoScotia + + If objScotia.GeneraPagoScotiaBank(DTPendientes.FiltraParametros("EstatusPagoElectronicoScotia = 'True' AND EstatusCtaDeposito = 'True'"), True, CveCuenta, UsuarioActual) Then + + If objScotia.ErrorLayout = False And objScotia.TotalPagos > 0 Then + + DVDescargaPagos.Visible = True + DVDescargaCuentas1.Visible = False + DVDescargaReporte.Visible = True + DT_PagosReporte = DTPendientes.Copy + LnkDescarga.Text = objScotia.NombreArchivo + RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") + UpModalDescarga.Update() + + Else + Alert($"Errores detectados
{objScotia.LayouErrorStr.ToString}", TipoMensaje.MsgAdvertencia) + errorScotia = True + End If + + Else + errorScotia = True + Alert("Error al generar el pago de ScotiaBank. Por favor vuelva a intentar.", TipoMensaje.MsgError) + End If + End Using + + If Not errorScotia Then + CargaDatos() + End If + + + 'GeneraPagoScotiaBank(DTPendientes.FiltraParametros("EstatusPagoElectronicoScotia = 'True' AND EstatusCtaDeposito = 'True'"), True) Else Alert("No hay registros para generar pagos en ScotiaBank", TipoMensaje.MsgAdvertencia) End If + + + + + + End If @@ -2160,7 +1410,7 @@ Partial Class Bancos_PagoElectronico If FUTxt.HasFile Then If Not GuardaTXT() Then - Alert("Ocurrio un error al cargar el archivo", TipoMensaje.MsgError) + Alert("Ocurrio un errorScotia al cargar el archivo", TipoMensaje.MsgError) Exit Sub End If Else @@ -2411,7 +1661,7 @@ Partial Class Bancos_PagoElectronico Dim HCodigo As String = H.Substring(40, 3) If HCodigo <> "000" And HCodigo <> " " Then - SBErrores.Append($"EL codigo de la cabecera es incorrecto {HCodigo} - {AltaCuentaScotiaCodigoRespuestaAnexoC(HCodigo)}.
") + SBErrores.Append($"EL codigo de la cabecera es incorrecto {HCodigo} - {ClsPagoScotia.AltaCuentaScotiaCodigoRespuestaAnexoC(HCodigo)}.
") ErrorArchivoScotia = True End If @@ -2451,7 +1701,7 @@ Partial Class Bancos_PagoElectronico ErrorArchivoScotia = True End If Else - SBErrores.Append($"Error Linea {i} cuenta no dada de alta codigo {CodigoRespuesta} - {AltaCuentaScotiaCodigoRespuestaAnexoC(CodigoRespuesta)}.
") + SBErrores.Append($"Error Linea {i} cuenta no dada de alta codigo {CodigoRespuesta} - {ClsPagoScotia.AltaCuentaScotiaCodigoRespuestaAnexoC(CodigoRespuesta)}.
") ErrorArchivoScotia = True End If Else @@ -2486,147 +1736,10 @@ Partial Class Bancos_PagoElectronico End Sub - Public 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 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 + + @@ -2659,7 +1772,7 @@ Partial Class Bancos_PagoElectronico If FUTxt.HasFile Then If Not GuardaTXT() Then - Alert("Ocurrio un error al cargar el archivo", TipoMensaje.MsgError) + Alert("Ocurrio un errorScotia al cargar el archivo", TipoMensaje.MsgError) Exit Sub End If Else @@ -3018,7 +2131,7 @@ Partial Class Bancos_PagoElectronico If CodigoRespuestaDetalle = "000" Then 'ok Else - SBErrores.Append($"Error en la linea {x} Codigo de respuesta {CodigoRespuestaDetalle} - {PagosScotiaCodigoRespuestaAnexoC(CodigoRespuestaDetalle)}.
") + SBErrores.Append($"Error en la linea {x} Codigo de respuesta {CodigoRespuestaDetalle} - {ClsPagoScotia.PagosScotiaCodigoRespuestaAnexoC(CodigoRespuestaDetalle)}.
") ErrorArchivoScotia = True End If @@ -3035,7 +2148,7 @@ Partial Class Bancos_PagoElectronico If PagoScotiaDetalle.OK Then PagoScotiaDetalle.ErrorRechazo = "" Else - PagoScotiaDetalle.ErrorRechazo = PagosScotiaCodigoRespuestaAnexoC(CodigoRespuestaDetalle) + PagoScotiaDetalle.ErrorRechazo = ClsPagoScotia.PagosScotiaCodigoRespuestaAnexoC(CodigoRespuestaDetalle) End If PagoScotiaDetalle.CveIE = CveIE @@ -3062,7 +2175,7 @@ Partial Class Bancos_PagoElectronico Dim objIE As New ClsBancos Dim Respuesta As New StringBuilder - Respuesta.AppendFormat("
Resumen de respuesta: {0}
", PagosScotiaCodigoRespuestaAnexoC(HCodigo)) + Respuesta.AppendFormat("
Resumen de respuesta: {0}
", ClsPagoScotia.PagosScotiaCodigoRespuestaAnexoC(HCodigo)) Respuesta.AppendFormat("Numero de movimientos aceptados: {0}
", TAceptadosCantidad.ToString) Respuesta.AppendFormat("Importe aceptados: {0}
", TImporteAceptados.ToString("C2")) Respuesta.AppendFormat("Numero de movimientos rechazados: {0}
", TRechazadosCantidad.ToString) @@ -3094,7 +2207,7 @@ Partial Class Bancos_PagoElectronico ErrorDB = True End If Else - 'Cancela el IE por error de pago + 'Cancela el IE por errorScotia de pago If objIE.CancelarBancos_IE(UsuarioActual.CveUsuario, PagoScotiaDetalle.CveIE, False, -1, -1) <= 0 Then ErrorDB = True End If @@ -3161,14 +2274,14 @@ Partial Class Bancos_PagoElectronico End If Next Catch ex As Exception - Alert("Ocurrió un error al enviar los correos de notificación.", TipoMensaje.MsgAdvertencia) + Alert("Ocurrió un errorScotia al enviar los correos de notificación.", TipoMensaje.MsgAdvertencia) End Try Alert(Respuesta.ToString, TipoMensaje.MsgInformacion) Else - Alert("Ocurrió un error al procesar el archivo.", TipoMensaje.MsgAdvertencia) + Alert("Ocurrió un errorScotia al procesar el archivo.", TipoMensaje.MsgAdvertencia) objIE.RollBack() End If @@ -3488,7 +2601,27 @@ Partial Class Bancos_PagoElectronico End If If OpBancos = 3 Then - AltaProveedoresScotia(DTProveedores) + 'AltaCuentasScotia(DTProveedores) + + + Dim fechaHoy As String = DateTime.Today.ToString("MM/dd/yyyy") + Dim ErrorCuentas As Boolean = False + Using objPagoScotia As New ClsPagoScotia + If objPagoScotia.AltaCuentasScotia(DTPendientes, UsuarioActual) Then + + DVDescargaPagos.Visible = False + DVDescargaReporte.Visible = False + LblCuentas.Text = "Cuentas Bajio" + DVDescargaCuentas1.Visible = True + LnkDescargaCuentas1.Text = objPagoScotia.NombreArchivo + RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") + UpModalDescarga.Update() + Else + Alert($"Errores detectados
{objPagoScotia.LayouErrorStr.ToString}", TipoMensaje.MsgAdvertencia) + ErrorCuentas = True + End If + End Using + End If @@ -4373,6 +3506,442 @@ Partial Class Bancos_PagoElectronico End Sub + ' Public Class ClsPagoScotia + ' Implements IDisposable + + ' Public Sub New() + ' ' Constructor privado para evitar instanciación directa + ' End Sub + + ' '==================================================================== + ' ' 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 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 + + ' Dim TamanoBloque As Integer = 500 ' 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 = 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 + ' 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) + + + ' NombreArchivo = $"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 = + + ' 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 "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 Friend Class ClsPagoScotiaDetalle diff --git a/Bancos/PagoElectronicoGrupos.aspx.vb b/Bancos/PagoElectronicoGrupos.aspx.vb index 981d83af1..f2a96d9ac 100644 --- a/Bancos/PagoElectronicoGrupos.aspx.vb +++ b/Bancos/PagoElectronicoGrupos.aspx.vb @@ -866,7 +866,7 @@ Partial Class Bancos_PagoElectronicoGrupos ElseIf OpBancos = 2 Then AltaProveedoresBajio() ElseIf OpBancos = 3 Then - 'AltaProveedoresScotia() SE DEJA COMENTADO PORQUE NO SE ESTA USANDO, SE CAMBIO A PAGO ELECTRONICO + 'AltaCuentasScotia() SE DEJA COMENTADO PORQUE NO SE ESTA USANDO, SE CAMBIO A PAGO ELECTRONICO End If @@ -2743,7 +2743,7 @@ Partial Class Bancos_PagoElectronicoGrupos ElseIf OpBancos = 2 Then AltaProveedoresBajio(DTProveedores) ElseIf OpBancos = 3 Then - 'AltaProveedoresScotia(DTProveedores) + 'AltaCuentasScotia(DTProveedores) End If diff --git a/Nomina/Nomina.aspx b/Nomina/Nomina.aspx index 753f2e6f5..b837d749a 100644 --- a/Nomina/Nomina.aspx +++ b/Nomina/Nomina.aspx @@ -4977,20 +4977,53 @@ + + + +
+
+
+ +
+
+ +
+
+
+ + Seleccionar +
+ +
+
+ +
+
+ +
+ + + + +
+ - <%--
- - - - - - - -
--%> + <%-- +
+ + + + + + + + +
+ --%>
@@ -5012,6 +5045,11 @@ + +
+ +
+ diff --git a/Nomina/Nomina.aspx.cs b/Nomina/Nomina.aspx.cs index ac434e9b8..28919681f 100644 --- a/Nomina/Nomina.aspx.cs +++ b/Nomina/Nomina.aspx.cs @@ -1,22 +1,24 @@ -using Extensiones; +using DocumentFormat.OpenXml.Drawing; +using Extensiones; +using Ionic.Zip; using iTextSharp.text.pdf; +using iTextSharp.text.pdf.parser; +using Modelos; +using Profact.TimbraCFDI40; +using StackExchange.Redis; using System; +using System.Activities.Expressions; using System.Collections.Generic; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; +using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using static Extensiones.ModExtensiones; -using Modelos; -using System.Text.RegularExpressions; -using iTextSharp.text.pdf.parser; -using Profact.TimbraCFDI40; -using Ionic.Zip; -using DocumentFormat.OpenXml.Drawing; -using System.Web; public partial class Nomina_Nomina2 : ClsPaginas { @@ -10742,7 +10744,8 @@ public partial class Nomina_Nomina2 : ClsPaginas SinSelccion, Bancomer, Banorte, - Banamex + Banamex, + ScotiaBank } @@ -10786,6 +10789,7 @@ public partial class Nomina_Nomina2 : ClsPaginas CargaCuentas(); DivModalLayoutBancosFecha.Visible = false; + DVCuentasScotia.Visible = false; TxtModalLayoutBancosFecha.Text = ""; RegistraScript("$('#ModalLayoutBancos').modal('show');"); @@ -10798,7 +10802,7 @@ public partial class Nomina_Nomina2 : ClsPaginas DdlCuenta.Items.Clear(); DataTable DTCuentas = get_GlobalDTBancosCuentas(UsuarioActual.CveUsuario, CveEmpresa: UsuarioActual.CveEmpresa).FiltraParametros(" CveTipoCuenta <> 1 AND UsaLayout = 'True' AND LEN(ConvenioPagoElectronico) > 0 "); DTCuentas.CaseSensitive = false; - DdlCuenta.DataSource = DTCuentas.FiltraParametros(" Banco IN('BANCOMER','BANORTE','BBVA Bancomer','BBVA','BANAMEX')"); + DdlCuenta.DataSource = DTCuentas.FiltraParametros(" Banco IN('BANCOMER','BANORTE','BBVA Bancomer','BBVA','BANAMEX') OR Banco LIKE '%SCOTIA%' "); DdlCuenta.DataBind(); DdlCuenta.Items.Insert(0, new ListItem("Seleccione", "-1")); DdlCuenta.SelectedValueExist("-1"); @@ -10808,6 +10812,8 @@ public partial class Nomina_Nomina2 : ClsPaginas { ConvenioPagoElectronico = string.Empty; DivModalLayoutBancosFecha.Visible = false; + DVCuentasScotia.Visible = false; + BtnGenerarAlta.Enabled = false; if (DdlCuenta.SelectedValue.ToEntero() > 0) { @@ -10827,6 +10833,12 @@ public partial class Nomina_Nomina2 : ClsPaginas Banco = Bancos.Banamex; DivModalLayoutBancosFecha.Visible = true; } + else if (DdlCuenta.SelectedItem.Text.ToUpper().Contains("SCOTIA")) + { + DivModalLayoutBancosFecha.Visible = false; + Banco = Bancos.ScotiaBank; + PreparaLayoutBancosScotiaBank(); + } else { ConvenioPagoElectronico = string.Empty; @@ -10838,6 +10850,274 @@ public partial class Nomina_Nomina2 : ClsPaginas } } + #region Layout ScotiaBank + private void PreparaLayoutBancosScotiaBank() + { + BtnGenerarAlta.Enabled = false; + int cuentasPendientes = 0; + using (ClsNominas objnom = new ClsNominas()) + { + if (objnom.GetDispersionNomina(CvePeriodoSeleccionado, UsuarioActual.CveEmpresa, 18)) + { + string fechaHoy = DateTime.Today.ToString("MM/dd/yyyy"); + cuentasPendientes = objnom.DtResultados.FiltraParametros($" EstatusPagoElectronicoScotia = False OR FechaEliminacion < #{fechaHoy}# ").Rows.Count; + } + } + + LblCuentasScotia.Text = string.Format("Pendientes: {0}", cuentasPendientes); + + if (cuentasPendientes > 0) + { + BtnGenerarAlta.Enabled = true; + BtnModalBancosProcesar.Enabled = false; + DVCuentasScotia.Visible = true; + + } + else + { + BtnModalBancosProcesar.Enabled = true; + } + + UpControlesScotia.Update(); + UpModalBancosLayout.Update(); + } + + + protected void BtnGenerarAlta_Click(object sender, EventArgs e) + { + DataTable DTCuentasPendientes = new DataTable(); + using (ClsNominas objnom = new ClsNominas()) + { + if (objnom.GetDispersionNomina(CvePeriodoSeleccionado, UsuarioActual.CveEmpresa, 18)) + { + string fechaHoy = DateTime.Today.ToString("MM/dd/yyyy"); + DTCuentasPendientes = objnom.DtResultados.FiltraParametros($" EstatusPagoElectronicoScotia = False OR FechaEliminacion < #{fechaHoy}# "); + } + } + + string NumeroConvenio = ""; + + using (ClsBancos objBancos = new ClsBancos()) + { + if (objBancos.GetBancosCuentas(DdlCuenta.SelectedValue.ToEntero())) + { + if (objBancos.DtResultados.Rows.Count > 0) + { + NumeroConvenio = objBancos.DtResultados.Rows[0]["ConvenioPagoElectronico"].ToString(); + } + } + } + + if (NumeroConvenio.Length > 0) + { + using (ClsPagoScotia objPagoScotia = new ClsPagoScotia()) + { + if (objPagoScotia.AltaCuentasScotia(DTCuentasPendientes, UsuarioActual, NumeroConvenio)) + { + Response.Clear(); + Response.Buffer = true; + Response.ContentType = "text/plain"; + Response.AddHeader("Content-Disposition", "attachment;filename=" + objPagoScotia.NombreArchivo); + Response.Write(objPagoScotia.LayoutStr); + Response.Flush(); + Response.End(); + } + else{ + Alert(objPagoScotia.LayouErrorStr, TipoMensaje.MsgAdvertencia); + RegistraScript("$('#ModalLayoutBancos').modal('show');"); + UpModalBancosLayout.Update(); + //Response.Clear(); + //Response.Buffer = true; + //Response.ContentType = "text/plain"; + //Response.AddHeader("Content-Disposition", "attachment;filename=" + objPagoScotia.RutaArchivo); + //Response.Write(objPagoScotia.LayoutStr); + //Response.Flush(); + //Response.End(); + } + } + } + else { + Alert("La cuenta seleccionada no tiene un Convenio de Pago Electronico"); + + } + } + + + private string GuardaTXT() + { + string NombreArchivo = ""; + try + { + + string FileName = System.IO.Path.GetFileName(FUTxt.PostedFile.FileName); + NombreArchivo = FileName; + string Extension = System.IO.Path.GetExtension(FUTxt.PostedFile.FileName); + string FolderPath = string.Format("{0}Empresas\\", Request.ApplicationPath); + string FilePath = Server.MapPath(FolderPath + FileName); + FUTxt.SaveAs(FilePath); + NombreArchivo = FilePath; + } + catch (Exception ex) + { + //Retorno = false; + this.GuardaLog( $" Error al guardar el archivo TXT --> {ex.StackTrace}"); + NombreArchivo = ""; + + } + + return NombreArchivo; + } + + protected void BtnCargarAlta_Click(object sender, EventArgs e) + { + bool ErrorArchivo = false; + string RutaArchivo = ""; + + if (FUTxt.HasFile) + { + RutaArchivo = GuardaTXT(); + if (RutaArchivo.Length == 0) + { + Alert("Ocurrió un error Scotia al cargar el archivo", TipoMensaje.MsgError); + return; + } + } + else + { + Alert("No tiene ningún archivo", TipoMensaje.MsgAdvertencia); + return; + } + + // LEE TXT + string Texto; + Texto = System.IO.File.ReadAllText(RutaArchivo); + string[] TextoArreglo = Texto.Split(new[] { "\r\n" }, StringSplitOptions.None); + + //if (OpBancos == 3) + //{ + TextoArreglo = System.IO.File.ReadAllLines(RutaArchivo); + + StringBuilder SBCuentasAltas = new StringBuilder(); + StringBuilder SBErrores = new StringBuilder(); + bool ErrorArchivoScotia = false; + + string H = TextoArreglo[0]; + + if (!(TextoArreglo.Length >= 3)) + { + Alert("El archivo no tiene el formato correcto, debe tener al menos 3 líneas (Header, Detalle y Trailer)", TipoMensaje.MsgAdvertencia); + return; + } + + if (H.Length != 140) + { + Alert("La longitud de la cabecera es incorrecta", TipoMensaje.MsgAdvertencia); + return; + } + + string TipoArchivo = H.Substring(0, 2).ToUpper(); + + if (TipoArchivo != "SP") + { + Alert($"El archivo no es un archivo de respuesta, inicia con código {TipoArchivo}", TipoMensaje.MsgAdvertencia); + } + + string HCodigo = H.Substring(40, 3); + if (HCodigo != "000" && HCodigo != " ") + { + SBErrores.Append($"El código de la cabecera es incorrecto {HCodigo} - {ClsPagoScotia.AltaCuentaScotiaCodigoRespuestaAnexoC(HCodigo)}.
"); + ErrorArchivoScotia = true; + } + + ClsBancos ObjBancos = new ClsBancos(); + ObjBancos.IniciaTransacSQL(); + + for (int i = 1; i <= TextoArreglo.Length - 2; i++) + { + string Linea = TextoArreglo[i]; + + if (Linea.Length == 140) + { + string CodigoRespuesta = Linea.Substring(109, 3); + string DTipoArchivo = Linea.Substring(0, 2); + string Cuenta = Linea.Substring(12, 20); + + DateTime FechaEliminacion = DateTime.ParseExact(Linea.Substring(32, 8), "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture); + + if (DTipoArchivo != "SP") + { + SBErrores.Append($"Error Línea {i} el tipo de archivo no es un archivo de respuesta (SP), inicia con código {DTipoArchivo}.
"); + ErrorArchivoScotia = true; + } + + if (CodigoRespuesta == "000" || CodigoRespuesta == " ") + { + int CveCuentaDeposito = Linea.Substring(40, 50).Trim().ToEntero(); + + if (CveCuentaDeposito > 0) + { + if (ObjBancos.UpdateCuentaDepositoPagoElectronico(CveCuentaDeposito, Opcion: 3, FechaEliminacion: FechaEliminacion)) + { + SBCuentasAltas.Append($"Cuenta: {Cuenta} registrada correctamente.
"); + } + else + { + ErrorArchivoScotia = true; + } + } + else + { + SBErrores.Append($"Error Línea {i} Cve: {CveCuentaDeposito} cuenta: {Cuenta} no encontrada.
"); + ErrorArchivoScotia = true; + } + } + else + { + SBErrores.Append($"Error Línea {i} cuenta no dada de alta código {CodigoRespuesta} - {ClsPagoScotia.AltaCuentaScotiaCodigoRespuestaAnexoC(CodigoRespuesta)}.
"); + ErrorArchivoScotia = true; + } + } + else + { + SBErrores.Append($"Error en longitud de la línea {i} es incorrecta.
"); + ErrorArchivoScotia = true; + } + } + + if (ErrorArchivoScotia) + { + ObjBancos.RollBack(); + Alert($"El archivo presentó errores en su procesamiento ({SBErrores.Length}). Correctos {SBCuentasAltas.Length} cuentas.
Altas:
{SBCuentasAltas.ToString()}

Errores:
{SBErrores.ToString()}", TipoMensaje.MsgAdvertencia); + } + else + { + ObjBancos.Commit(); + Alert($"El archivo se analizó correctamente y se efectuaron todos los cambios en el sistema. Cuentas procesadas:
{SBCuentasAltas.ToString()}", TipoMensaje.MsgInformacion); + } + + ObjBancos.Dispose(); + + + if (ErrorArchivo) + { + Alert("Ocurrió un error al cargar el archivo", TipoMensaje.MsgError); + return; + } + else { + Alert("El archivo se cargó correctamente", TipoMensaje.MsgInformacion); + System.IO.File.Delete(RutaArchivo); + PreparaLayoutBancosScotiaBank(); + RegistraScript("$('#ModalLayoutBancos').modal('show');"); + } + + + } + + + + #endregion + + protected void BtnLayoutXLS_Click(object sender, EventArgs e) { @@ -10970,6 +11250,7 @@ public partial class Nomina_Nomina2 : ClsPaginas } protected void BtnModalBancosProcesar_Click(object sender, EventArgs e) { + BtnModalBancosProcesar.Enabled = true; if (Banco == Bancos.Bancomer) { @@ -11001,6 +11282,104 @@ public partial class Nomina_Nomina2 : ClsPaginas } } } + else if (Banco == Bancos.ScotiaBank) + { + + DataTable DTResultados = new DataTable(); + using (ClsNominas objnom = new ClsNominas()) + { + if (objnom.GetDispersionNomina(CvePeriodoSeleccionado, UsuarioActual.CveEmpresa, 18)) + { + DTResultados = objnom.DtResultados; + } + } + + if (DTResultados.Rows.Count > 0) + { + using (ClsPagoScotia objPagoScotia = new ClsPagoScotia()) + { + + string ConvenioPagoElectronicoScotia = get_GlobalDTBancosCuentas(UsuarioActual.CveUsuario, CveEmpresa: UsuarioActual.CveEmpresa).FiltroPrimeroValor("ConvenioPagoElectronico", $" CveCuenta = {DdlCuenta.SelectedValue}").ToString(); + string NumCuentaOrigen = get_GlobalDTBancosCuentas(UsuarioActual.CveUsuario, CveEmpresa: UsuarioActual.CveEmpresa).FiltroPrimeroValor("NumCuenta", $" CveCuenta = {DdlCuenta.SelectedValue}").ToString(); + string CLABEOrigen = get_GlobalDTBancosCuentas(UsuarioActual.CveUsuario, CveEmpresa: UsuarioActual.CveEmpresa).FiltroPrimeroValor("CLABE", $" CveCuenta = {DdlCuenta.SelectedValue}").ToString(); + //CASE WHEN LEN(BC.NumCuenta) > 0 THEN BC.NumCuenta ELSE BC.CLABE END AS CLABEOrigen, + + if (!DTResultados.Columns.Contains("ConvenioPagoElectronico")) + { + DTResultados.Columns.Add("ConvenioPagoElectronico", typeof(string)); + } + + if (!DTResultados.Columns.Contains("CLABEOrigen")) + { + DTResultados.Columns.Add("CLABEOrigen", typeof(string)); + } + if (!DTResultados.Columns.Contains("Observaciones")) + { + DTResultados.Columns.Add("Observaciones", typeof(string)); + } + + + foreach (DataRow dRow in DTResultados.Rows) + { + dRow["ConvenioPagoElectronico"] = ConvenioPagoElectronicoScotia; + dRow["CLABEOrigen"] = NumCuentaOrigen.Length > 0 ? NumCuentaOrigen : CLABEOrigen; // Si no tiene numero de cuenta, se usa la CLABE + dRow["Observaciones"] = dRow["CveNominaDetalle"].ToString(); + } + + + //DTResultados.Columns["CLABEOrigen"].ColumnName = "CLABEOrigen"; // CLABE Origen + //DTResultados.Columns["ConvenioPagoElectronico"].ColumnName = "ConvenioPagoElectronico"; // Convenio Pago Electronico + //DTResultados.Columns["Importe"].ColumnName = "Importe"; // Importe + DTResultados.Columns["CvePersonal"].ColumnName = "CveProveedor"; // Cve Proveedor + //DTResultados.Columns["RFC"].ColumnName = "RFC"; // RFC + DTResultados.Columns["Nombre"].ColumnName = "RazonSocial"; // Razon Social + DTResultados.Columns["CveNominaDetalle"].ColumnName = "CveIE"; // Cve IE + //DTResultados.Columns["CLABEDestino"].ColumnName = "CLABEDestino"; // CLABE Destino + //DTResultados.Columns["CLABE"].ColumnName = "CLABE"; // CLABE + //DTResultados.Columns["CveBanco"].ColumnName = "CveBanco"; // Cve Banco + DTResultados.Columns["Observaciones"].ColumnName = "Observaciones"; // Observaciones + DTResultados.Columns["Correo"].ColumnName = "Correo"; // Correo + //DTResultados.Columns["CvePersonal"].ColumnName = "CvePersonal"; // Cve Personal + + + /* + CLABEOrigen + ConvenioPagoElectronico + Importe + CveProveedor + RFC + RazonSocial + CveIE + CLABEDestino + CLABE + CveBanco + Observaciones + Correo + CvePersonal + */ + + + if (objPagoScotia.GeneraPagoScotiaBank(DTResultados, false, DdlCuenta.SelectedValue.ToEntero(), UsuarioActual)) + { + Response.Clear(); + Response.Buffer = true; + Response.ContentType = "text/plain"; + Response.AddHeader("Content-Disposition", "attachment;filename=" + objPagoScotia.NombreArchivo); + Response.Write(objPagoScotia.LayoutStr); + Response.Flush(); + Response.End(); + } + else + { + Alert(objPagoScotia.LayouErrorStr, TipoMensaje.MsgAdvertencia); + RegistraScript("$('#ModalLayoutBancos').modal('show');"); + } + } + } + else{ + Alert("No se encontraron registros para generar el layout de ScotiaBank", TipoMensaje.MsgAdvertencia); + } + } } private void CrearLayoutNominaBancomer(DataTable DTNomina) { @@ -12489,4 +12868,5 @@ public partial class Nomina_Nomina2 : ClsPaginas { CargaMovtoPermanente(); } + } \ No newline at end of file diff --git a/OC/OC.aspx.vb b/OC/OC.aspx.vb index 728d18b1c..f881cb54c 100644 --- a/OC/OC.aspx.vb +++ b/OC/OC.aspx.vb @@ -3976,6 +3976,8 @@ Partial Class OC_OC Protected Sub BtnCancelar_Click(sender As Object, e As EventArgs) Handles BtnCancelar.Click Dim ObjEventos As New ClsOIEventos + + If CveEstatusFinalError > 0 Then Dim objOrdenCompra As New ClsOC objOrdenCompra.IniciaTransacSQL() @@ -9499,6 +9501,10 @@ Partial Class OC_OC Dim Respuesta As Boolean = True + If TipoOC <> "OC" Then + Return True 'solo genera poliza de presupuesto si es OC + End If + If UsuarioActual.Empresa.Funcionalidad(532).Contiene("2") Then Dim CveMonedaPresupuesto As Integer = DdlMoneda.SelectedValue.ToEntero