diff --git a/App_Code/ClsBancos.vb b/App_Code/ClsBancos.vb index 6723cdd82..0be6651c1 100644 --- a/App_Code/ClsBancos.vb +++ b/App_Code/ClsBancos.vb @@ -3,6 +3,7 @@ Option Strict On Imports System.Data Imports System.Data.SqlClient +Imports DocumentFormat.OpenXml.Math Imports Extensiones Public Class ClsBancos @@ -1284,7 +1285,7 @@ Public Class ClsBancos End With Try SqlAdapter.Fill(Data) - Retorno = True + retorno = True Catch ex As Exception retorno = False OnError("Ocurrió un error al cancelar estatus complemento de pago", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo) @@ -1301,7 +1302,7 @@ Public Class ClsBancos End With Try SqlAdapter.Fill(Data) - Retorno = True + retorno = True Catch ex As Exception retorno = False OnError("Ocurrió un error al cancelar estatus complemento de pago", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo) @@ -3344,7 +3345,10 @@ Public Class ClsBancos Return Retorno End Function - Public Function GetLayoutProveedores(CveCuenta As Integer, CveEmpresa As Integer, Optional PorGrupos As Boolean = False) As Boolean + Public Function GetLayoutProveedores(CveCuenta As Integer, CveEmpresa As Integer, Optional PorGrupos As Boolean = False, Optional OpBanco As Integer = 1) As Boolean + + 'OpBanco 1 Bancomer, 2 Bajio, 3 Scotia + Dim Retorno As Boolean = False DataAdapter("PA_Banc_LayoutProveedores") @@ -3353,6 +3357,7 @@ Public Class ClsBancos .Add("@CveCuenta", SqlDbType.Int).Value = CveCuenta .Add("@CveEmpresa", SqlDbType.Int).Value = CveEmpresa .Add("@PorGrupos", SqlDbType.Bit).Value = PorGrupos + .Add("@OpBanco", SqlDbType.Int).Value = OpBanco End With Try diff --git a/App_Code/ClsGenerales.vb b/App_Code/ClsGenerales.vb index 1e444e23b..37a62c152 100644 --- a/App_Code/ClsGenerales.vb +++ b/App_Code/ClsGenerales.vb @@ -748,55 +748,55 @@ Public Class ClsGenerales End Try Return Retorno - End Function - + End Function + #End Region - - '#Region " E S T A D O S" - ' Public Function GetGralEstados() As Boolean - ' Dim Retorno As Boolean = False - ' DataAdapter("PA_Gral_EstadoGet") - ' Try - ' SqlAdapter.Fill(Data) - ' Retorno = True - ' Catch ex As Exception - ' OnError("Ocurrió un error al obtener el Catálogo de Estados.", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo()) - ' End Try - - ' Return Retorno - ' End Function - '#End Region - - '#Region " M U N I C I P I O S" - ' Public Function GetGralMunicipios() As Boolean - ' Dim Retorno As Boolean = False - ' DataAdapter("PA_Gral_MunicipioGet") - ' Try - ' SqlAdapter.Fill(Data) - ' Retorno = True - ' Catch ex As Exception - ' OnError("Ocurrió un error al obtener el Catálogo de Municipios.", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo()) - ' End Try - - ' Return Retorno - ' End Function - '#End Region - - '#Region " P A I S E S" - ' Public Function GetGralPaises() As Boolean - ' Dim Retorno As Boolean = False - ' DataAdapter("PA_Gral_PaisGet") - ' Try - ' SqlAdapter.Fill(Data) - ' Retorno = True - ' Catch ex As Exception - ' OnError("Ocurrió un error al obtener el Catálogo de Paises.", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo()) - ' End Try - - ' Return Retorno - ' End Function - '#End Region - + + '#Region " E S T A D O S" + ' Public Function GetGralEstados() As Boolean + ' Dim Retorno As Boolean = False + ' DataAdapter("PA_Gral_EstadoGet") + ' Try + ' SqlAdapter.Fill(Data) + ' Retorno = True + ' Catch ex As Exception + ' OnError("Ocurrió un error al obtener el Catálogo de Estados.", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo()) + ' End Try + + ' Return Retorno + ' End Function + '#End Region + + '#Region " M U N I C I P I O S" + ' Public Function GetGralMunicipios() As Boolean + ' Dim Retorno As Boolean = False + ' DataAdapter("PA_Gral_MunicipioGet") + ' Try + ' SqlAdapter.Fill(Data) + ' Retorno = True + ' Catch ex As Exception + ' OnError("Ocurrió un error al obtener el Catálogo de Municipios.", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo()) + ' End Try + + ' Return Retorno + ' End Function + '#End Region + + '#Region " P A I S E S" + ' Public Function GetGralPaises() As Boolean + ' Dim Retorno As Boolean = False + ' DataAdapter("PA_Gral_PaisGet") + ' Try + ' SqlAdapter.Fill(Data) + ' Retorno = True + ' Catch ex As Exception + ' OnError("Ocurrió un error al obtener el Catálogo de Paises.", ex, SqlAdapter.SelectCommand.Parameters.ParametrosInfo()) + ' End Try + + ' Return Retorno + ' End Function + '#End Region + #Region " P O B L A C I O N E S" Public Function GetGralPoblaciones() As Boolean Dim Retorno As Boolean = False diff --git a/Bancos/Devoluciones.aspx.cs b/Bancos/Devoluciones.aspx.cs index 4ab715711..a1e7410da 100644 --- a/Bancos/Devoluciones.aspx.cs +++ b/Bancos/Devoluciones.aspx.cs @@ -471,7 +471,7 @@ public partial class Bancos_Devoluciones : ClsPaginas if (gvr.FCTextBox("TxtIVA").Text.ToDecimal() > 0) { //INGxC - if (!ObjMov.AddPrePolizasDetalle(CvePrePoliza, true, gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), CveConceptoContableDevolucion, Ref, Conc, CveIE: gvr.DataKey("CveIE").ToEntero(), CveSubProyecto: DdlSubProyecto.SelectedValue.ToEntero(), CveCliente: DdlCliente.SelectedValue.ToEntero(), CveIEDevolucion: CveIE)) + if (!ObjMov.AddPrePolizasDetalle(CvePrePoliza, true, gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), CveConceptoContableDevolucion, Ref, Conc, CveIE: gvr.DataKey("CveIE").ToEntero(), CveSubProyecto: DdlSubProyecto.SelectedValue.ToEntero(), CveCliente: DdlCliente.SelectedValue.ToEntero())) { MsgError = "No se pudo insertar concepto de devolución"; } @@ -488,7 +488,7 @@ public partial class Bancos_Devoluciones : ClsPaginas else { //INGxC - if (!ObjMov.AddPrePolizasDetalle(CvePrePoliza, TipoMovtoDevolucion, gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), CveConceptoContableDevolucion, Ref, Conc, CveIE: CveIE, CveSubProyecto: DdlSubProyecto.SelectedValue.ToEntero(), CveCliente: DdlCliente.SelectedValue.ToEntero(), CveIEDevolucion: gvr.DataKey("CveIE").ToEntero())) + if (!ObjMov.AddPrePolizasDetalle(CvePrePoliza, TipoMovtoDevolucion, gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), gvr.FCTextBox("TxtAbonar").Text.ToDecimal(), CveConceptoContableDevolucion, Ref, Conc, CveIE: gvr.DataKey("CveIE").ToEntero(), CveSubProyecto: DdlSubProyecto.SelectedValue.ToEntero(), CveCliente: DdlCliente.SelectedValue.ToEntero() )) { MsgError = "No se pudo insertar concepto de bancos"; } diff --git a/Bancos/PagoElectronicoGrupos.aspx b/Bancos/PagoElectronicoGrupos.aspx index c684b31da..765b77523 100644 --- a/Bancos/PagoElectronicoGrupos.aspx +++ b/Bancos/PagoElectronicoGrupos.aspx @@ -33,7 +33,10 @@
-

Cuentas Bancomer

+

diff --git a/Bancos/PagoElectronicoGrupos.aspx.vb b/Bancos/PagoElectronicoGrupos.aspx.vb index 3d7cbcf63..d6981455e 100644 --- a/Bancos/PagoElectronicoGrupos.aspx.vb +++ b/Bancos/PagoElectronicoGrupos.aspx.vb @@ -4,8 +4,10 @@ Option Strict On Imports System.Data Imports System.Globalization Imports System.IO +Imports CFDI_GenCodigo Imports Extensiones Imports Ionic.Zip +Imports iText.Barcodes.Dmcode Imports Microsoft.Reporting.WebForms Partial Class Bancos_PagoElectronicoGrupos @@ -283,6 +285,28 @@ Partial Class Bancos_PagoElectronicoGrupos End Property + ReadOnly Property OpBancos As Integer + Get + Dim OpBanco As Integer = -1 + If (DdlCuenta.SelectedItem.Text.ToUpper.Contains("BANCOMER") OrElse DdlCuenta.SelectedItem.Text.ToUpper.Contains("BBVA")) Then + OpBanco = 1 + End If + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BAJIO") Then + OpBanco = 2 + End If + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("SCOTIA") Then + OpBanco = 3 + End If + + Return OpBanco + + End Get + + End Property + + #End Region Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load @@ -302,7 +326,7 @@ Partial Class Bancos_PagoElectronicoGrupos txtFechaF.Text = NowADS().ToShortDateString CargaCuentas() - CargaProveedores() + 'CargaProveedores() InicializaDatosGenerales() End If @@ -385,38 +409,146 @@ Partial Class Bancos_PagoElectronicoGrupos Dim Altas As Integer = 0 Dim Interbancarias As Integer = 0 Dim Bancomer As Integer = 0 + Dim Bajio As Integer = 0 + Dim Scotia As Integer = 0 Dim Movimientos As Integer = 0 Dim Importe As Decimal = 0 - For Each dr As DataRow In DTPendientes.Rows + TrNumeroBancomer.Visible = False + TrNumeroBajio.Visible = False + TrNumeroScotia.Visible = False + + '--- Asume que existen contadores: Altas, Movimientos, Importe, Bancomer, + ' Bajio, Scotia, Interbancarias declarados y con valor inicial 0. + + For Each dr As DataRow In DTPendientes.Rows + + ' 1. Filtrar filas cuya cuenta‑depósito no está activa + If dr("EstatusCtaDeposito").ToString <> "True" Then Continue For + + Dim tieneCuenta As Boolean = dr("CveCuentaDeposito").ToString <> "" + Dim altaCuenta As Boolean = dr("AltaCuenta").ToString = "1" + + ' 2. ALTA de cuentas NO habilitadas todavía + If tieneCuenta AndAlso altaCuenta Then + + '–– Determina si la cuenta ya está **habilitada** para el banco elegido en la pantalla ––' + Dim habilitada As Boolean + Select Case True + Case DdlCuenta.SelectedItem.Text.ToUpper.Contains("BANCOMER") _ + OrElse DdlCuenta.SelectedItem.Text.ToUpper.Contains("BBVA") + habilitada = (dr("EstatusPagoElectronicoGrupos").ToString = "True") + + Case DdlCuenta.SelectedItem.Text.ToUpper.Contains("BAJIO") + habilitada = (dr("EstatusPagoElectronicoGruposBajio").ToString = "True") + + Case DdlCuenta.SelectedItem.Text.ToUpper.Contains("SCOTIA") + habilitada = (dr("EstatusPagoElectronicoGruposScotia").ToString = "True") + + Case Else + habilitada = False 'Otros bancos → sin bandera propia + End Select + + If Not habilitada Then + Altas += 1 '‑‑‑ cuenta el alta sólo una vez + + '‑‑‑ Clasificación por banco real del beneficiario –‑‑' + Select Case True + Case dr("BancoNombre").ToString.ToUpper.Contains("BANCOMER") _ + OrElse dr("BancoNombre").ToString.ToUpper.Contains("BBVA") + Bancomer += 1 + + Case dr("BancoNombre").ToString.ToUpper.Contains("BAJIO") + Bajio += 1 + + Case dr("BancoNombre").ToString.ToUpper.Contains("SCOTIA") + Scotia += 1 + + Case Else + Interbancarias += 1 + End Select + End If + + ' 3. MOVIMIENTOS de cuentas ya existentes + ElseIf dr("CveCuentaDeposito").ToString.ToEntero > 0 Then + Movimientos += 1 + Importe += dr("Abonado").ToString.ToDecimal + End If + Next + + + 'For Each dr As DataRow In DTPendientes.Rows - If dr("EstatusCtaDeposito").ToString <> "True" Then - Continue For - End If + ' If dr("EstatusCtaDeposito").ToString <> "True" Then + ' Continue For + ' End If - If dr("CveCuentaDeposito").ToString <> "" And dr("EstatusPagoElectronicoGrupos").ToString <> "True" And dr("AltaCuenta").ToString = "1" Then - Altas += 1 - If dr("BancoNombre").ToString.ToUpper.Contains("BANCOMER") OrElse dr("BancoNombre").ToString.ToUpper.Contains("BBVA") Then - Bancomer += 1 - Else - Interbancarias += 1 - End If + ' If dr("CveCuentaDeposito").ToString <> "" And dr("AltaCuenta").ToString = "1" Then - ElseIf dr("CveCuentaDeposito").ToString.ToEntero > 0 Then - Movimientos += 1 - Importe += dr("Abonado").ToString.ToDecimal - End If - Next + ' If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BANCOMER") OrElse DdlCuenta.SelectedItem.Text.ToUpper.Contains("BBVA") Then + ' If dr("EstatusPagoElectronicoGrupos").ToString <> "True" Then + ' If dr("BancoNombre").ToString.ToUpper.Contains("BANCOMER") OrElse dr("BancoNombre").ToString.ToUpper.Contains("BBVA") Then + ' Bancomer += 1 + ' Else + ' Interbancarias += 1 + ' End If + ' Altas += 1 + ' End If + ' End If + + ' If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BAJIO") Then + ' If dr("EstatusPagoElectronicoGruposBajio").ToString <> "True" Then + ' If dr("BancoNombre").ToString.ToUpper.Contains("BAJIO") Then + ' Bajio += 1 + ' Else + ' Interbancarias += 1 + ' End If + ' Altas += 1 + ' End If + ' End If + + ' If DdlCuenta.SelectedItem.Text.ToUpper.Contains("SCOTIA") Then + ' If dr("EstatusPagoElectronicoGruposScotia").ToString <> "True" Then + ' If dr("BancoNombre").ToString.ToUpper.Contains("SCOTIA") Then + ' Scotia += 1 + ' Else + ' Interbancarias += 1 + ' End If + ' Altas += 1 + ' End If + ' End If + + ' ElseIf dr("CveCuentaDeposito").ToString.ToEntero > 0 Then + ' Movimientos += 1 + ' Importe += dr("Abonado").ToString.ToDecimal + ' End If + 'Next LnkNumeroAltas.Text = Altas.ToString LbNumeroInterbancarias.Text = Interbancarias.ToString LbNumeroBancomer.Text = Bancomer.ToString + LbNumeroBajio.Text = Bajio.ToString + LbNumeroScotia.Text = Scotia.ToString LbNumeroMovimientos.Text = Movimientos.ToString LbImporteMovimientos.Text = Importe.ToString.FormatoNumero - UpComandosGeneracion.Update() + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BANCOMER") OrElse DdlCuenta.SelectedItem.Text.ToUpper.Contains("BBVA") Then + TrNumeroBancomer.Visible = True + End If + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BAJIO") Then + TrNumeroBajio.Visible = True + End If + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("SCOTIA") Then + TrNumeroScotia.Visible = True + End If + + UpComandosGeneracion.Update() + End Sub #End Region @@ -544,15 +676,29 @@ Partial Class Bancos_PagoElectronicoGrupos 'Colorea GV If e.Row.DBCampo("RazonSocial").ToString = "" Then e.Row.BackColor = Drawing.Color.WhiteSmoke - Else - If e.Row.DBCampo("EstatusPagoElectronicoGrupos").ToString <> "True" Then + Else + Dim CuentaDepositoSinAlta As Boolean = False + + If (DdlCuenta.SelectedItem.Text.ToUpper.Contains("BANCOMER") OrElse DdlCuenta.SelectedItem.Text.ToUpper.Contains("BBVA")) AndAlso e.Row.DBCampo("EstatusPagoElectronicoGrupos").ToString <> "True" Then + CuentaDepositoSinAlta = True + End If + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BAJIO") AndAlso e.Row.DBCampo("EstatusPagoElectronicoGruposBajio").ToString <> "True" Then + CuentaDepositoSinAlta = True + End If + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("SCOTIA") AndAlso e.Row.DBCampo("EstatusPagoElectronicoGruposScotia").ToString <> "True" Then + CuentaDepositoSinAlta = True + End If + + + If CuentaDepositoSinAlta Then 'e.Row.BackColor = Drawing.Color.LightSalmon e.Row.ToolTip = "Cuenta Deposito aun sin dar de Alta." LnkAyuda.Attributes.Add("data-content", "Cuenta Deposito aún sin dar de Alta.") LnkAyuda.Visible = True - End If If e.Row.DBCampo("CveProveedor").ToString.ToEntero > 0 Then @@ -688,10 +834,15 @@ Partial Class Bancos_PagoElectronicoGrupos Private Sub RecargaDatos() CargaDatos() TipoMasiva = 1 - DdlTipoCargaMasiva.SelectedValueExist("1") - CargaProveedores() + DdlTipoCargaMasiva.SelectedValueExist("1") + + + CargaProveedores(OpBancos) + End Sub + + #End Region @@ -707,9 +858,17 @@ Partial Class Bancos_PagoElectronicoGrupos If Not DdlCuenta.SelectedValue.ToEntero > 0 Then Alert("Primero debe seleccionar una Cuenta", TipoMensaje.MsgAdvertencia) Exit Sub - End If - - AltaProveedores() + End If + + If OpBancos = 1 Then + AltaProveedores() + ElseIf OpBancos = 2 Then + AltaProveedoresBajio() + ElseIf OpBancos = 3 Then + 'AltaProveedoresScotia() + End If + + End Sub Private Sub AltaProveedores(Optional DtCuentasPendientesTemp As DataTable = Nothing) @@ -960,6 +1119,7 @@ Partial Class Bancos_PagoElectronicoGrupos If NombreArchivoBancomer.Length > 0 Or NombreArchivoInterbancario.Length > 0 Or NombreArchivoCIE.Length > 0 Then + LblCuentas.Text = "Cuentas Bancomer" LnkDescargaCuentas1.Text = NombreArchivoBancomer LnkDescargaCuentas2.Text = NombreArchivoInterbancario LnkDescargaCuentas3.Text = NombreArchivoCIE @@ -974,6 +1134,217 @@ Partial Class Bancos_PagoElectronicoGrupos End Sub + '--------------------------------------------------------------------------------- + ' Banco: BAJÍO – Alta de Proveedores y Cuentas (layout 541 espacios) + ' Notas: + ' • Header: 01 + Nº archivo(7) + fecha(yyyyMMdd) + divisa("001") = 20 bytes + ' • Detalle: 02 + consecutivo(7) + "0140" + [banco(3)+tipo(2)+cta(20)] + alias(15) + + ' nombre(40) + RFC(13) + correo(55) + importeMax(15) + tiempoUso(20) + + ' periodoImp(40) + usuarios(100) + moneda(3) + tipoRel(2) + otroRel(60) + + ' filler(140) = 541 bytes + ' • Pie: 09 + totalLíneas(7) + totalReg(7) + "00000000" + "0000000000" = 34 bytes + '--------------------------------------------------------------------------------- + Private Sub AltaProveedoresBajio(Optional ByVal DtCuentasPendientesTemp As DataTable = Nothing) + + '------------------- Inicialización de variables y filtros ---------------- + NombreArchivo = "" + DVDescargaCuentas1.Visible = False 're uso los mismos controles que Bancomer + DVDescargaCuentas2.Visible = False + DVDescargaCuentas3.Visible = False + + Dim RegistrosAltaBajio As New StringBuilder + Dim SBErrores As New StringBuilder + Dim CeroRelleno As Char = "0"c + Dim EspacioRelleno As Char = ChrW(32) + + If DtCuentasPendientesTemp Is Nothing Then DtCuentasPendientesTemp = DTPendientes.Copy + DtCuentasPendientesTemp.CaseSensitive = False + + 'Sólo tomamos cuentas cuyo estatus aún no está confirmado + Dim DtCuentasPendientes As DataTable = + DtCuentasPendientesTemp.FiltraParametros( + "(EstatusPagoElectronicoGruposBajio IS NULL OR EstatusPagoElectronicoGruposBajio = 0)", + "", + {"BancoNombre", "CveBanco", "CLABEDestino", "Cuenta", "Abreviatura", + "RazonSocial", "RFC", "BBVAAlias"}) + + If DtCuentasPendientes.Rows.Count = 0 Then + Alert("No hay cuentas pendientes de alta para Bajío.", TipoMensaje.MsgAdvertencia) + Exit Sub + End If + + '------------------- Constantes de layout ---------------- + Const CABECERA_LEN As Integer = 20 + Const DETALLE_LEN As Integer = 541 + Const PIE_LEN As Integer = 16 + Const DIVISA_MXN As String = "001" + 'Const FILLER_8CEROS As String = "00000000" + Const FILLER_140ESP As String = " " '140 espacios + Const CONST_0140 As String = "0140" + + Dim NumeroArchivo As Integer = 1 '→ ajústalo si manejas consecutivo diario + Dim FechaArchivo As Date = NowADS().Date + + '------------------- CABECERA (20 espacios) ---------------- + Dim Header As String = $"01{NumeroArchivo:D7}{FechaArchivo:yyyyMMdd}{DIVISA_MXN}" + If Header.Length <> CABECERA_LEN Then + Alert($"Header inválido. Esperado: {CABECERA_LEN} bytes, real: {Header.Length}.", TipoMensaje.MsgAdvertencia) + Exit Sub + End If + RegistrosAltaBajio.Append(Header & vbCrLf) + + '------------------- DETALLES (541 espacios) ---------------- + Dim ConsecArchivo As Integer = 2 'Ya contamos el header + For Each dRow As DataRow In DtCuentasPendientes.Rows + + Dim SBTmp As New StringBuilder + Dim SBErrLinea As New StringBuilder + Dim ErrorLinea As Boolean = False + + SBErrLinea.Append($"[{dRow("RazonSocial")}] ") + + '---- Banco (3) + TipoCuenta (2) + Cuenta/CLABE (≤20) --------------- + Dim CveBanco As String = dRow("CveBanco").ToString.Trim.PadLeft(3, CeroRelleno) + If CveBanco.Length <> 3 OrElse Not IsNumeric(CveBanco) Then + SBErrLinea.Append("Banco inválido. ") + ErrorLinea = True + End If + + Dim Cuenta As String = New String( + dRow("CLABEDestino").ToString _ + .Where(AddressOf Char.IsDigit).ToArray()) 'sólo dígitos + + If Cuenta.Length = 18 Then + Cuenta = Cuenta.PadLeft(20, CeroRelleno) + SBTmp.Append("40") 'tipo cuenta + ElseIf Cuenta.Length = 11 Or Cuenta.Length = 12 Then + Cuenta = Cuenta.PadLeft(20, CeroRelleno) + SBTmp.Append("01") 'tipo cuenta + Else + SBErrLinea.Append("Cuenta/CLABE debe tener 11-12-18 dígitos. ") + ErrorLinea = True + Cuenta = Cuenta.PadLeft(20, CeroRelleno) + SBTmp.Append("00") + End If + + '---- AliasProveedor (15) + Nombre (40) -------------------------------------- + Dim AliasProveedor As String = LimpiarBajio(If(dRow("BBVAAlias").ToString.Trim.Length > 0, dRow("BBVAAlias").ToString, dRow("RazonSocial").ToString).ToString, 15) + Dim Nombre As String = LimpiarBajio(dRow("RazonSocial").ToString, 40) + + '---- RFC (13) + Correo (55) ---------------------------------------- + Dim Rfc As String = LimpiarBajio(dRow("RFC").ToString, 13, True) + 'Dim Correo As String = LimpiarBajio(dRow("CorreoElectronico").ToString, 55, True) + Dim Correo As String = LimpiarBajio("", 55, True) + + '---- Campos opcionales en blanco / ceros --------------------------- + Const IMPORTE_MAX As String = "000000000000000" + Const TIEMPO_USO As String = " " '20 esp + Const PERIODO_IMP As String = " " '40 esp + Const USUARIOS As String = " " '94 esp + Const MONEDA As String = " " + Const TIPO_REL As String = " " + Const OTRO_REL As String = " " + + '---- Armar línea detalle ------------------------------------------- + If Not ErrorLinea Then + With SBTmp + .Insert(0, "02") 'tipo registro + .Insert(2, ConsecArchivo.ToString("D7")) 'consecutivo archivo + .Insert(9, CONST_0140) 'constante 0140 + .Insert(13, CveBanco) 'banco (3) + 'En 16 ya está tipo (2) y cuenta (20) que añadimos antes + .Append(Cuenta) '20 + .Append(AliasProveedor.PadRight(15, EspacioRelleno)) + .Append(Nombre.PadRight(40, EspacioRelleno)) + .Append(Rfc.PadRight(13, EspacioRelleno)) + .Append(Correo.PadRight(55, EspacioRelleno)) + .Append(IMPORTE_MAX) + .Append(TIEMPO_USO) + .Append(PERIODO_IMP) + .Append(USUARIOS) + .Append(MONEDA) + .Append(TIPO_REL) + .Append(OTRO_REL) + .Append(FILLER_140ESP) + End With + + If SBTmp.Length <> DETALLE_LEN Then + SBErrLinea.Append($"Longitud {SBTmp.Length}/541 incorrecta. ") + ErrorLinea = True + End If + End If + + '---- Añadir al archivo o a la lista de errores ---------------------- + If ErrorLinea Then + RegistrosAltaBajio.Append(SBTmp.ToString & vbCrLf) + SBErrLinea.Append("
") + SBErrores.AppendLine(SBErrLinea.ToString) + Else + RegistrosAltaBajio.Append(SBTmp.ToString & vbCrLf) + 'Aquí puedes marcar la cuenta como “AltaGenerada” en BD si lo deseas + ConsecArchivo += 1 + End If + Next + + '------------------- PIE (16 ) ---------------- + Dim TotalLineas As Integer = ConsecArchivo 'header + detalles + pie aún no añadido + Dim TotalRegistros As Integer = TotalLineas - 2 + Dim Pie As String = $"09{TotalLineas:D7}{TotalRegistros:D7}" + If Pie.Length <> PIE_LEN Then + Alert($"Pie inválido ({Pie.Length} bytes).", TipoMensaje.MsgAdvertencia) + Exit Sub + End If + RegistrosAltaBajio.Append(Pie) + + '------------------- Crear archivo y mostrar descargas ------------------ + TextoCompleto = RegistrosAltaBajio.ToString + If RegistrosAltaBajio.Length = 0 Then + Alert("No se generó ningún registro válido para Bajío.", TipoMensaje.MsgAdvertencia) + Exit Sub + End If + + Dim NombreArchivoEnviado As String = $"altacuentasbajio_{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 Bajío + NombreArchivoInterbancario = "" + NombreArchivoCIE = "" + NombreArchivo = NombreArchivoEnviado + DVDescargaCuentas1.Visible = True + LnkDescargaCuentas1.Text = NombreArchivo + RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") + UpModalDescarga.Update() + End If + + If SBErrores.Length > 0 Then + Alert(SBErrores.ToString, TipoMensaje.MsgAdvertencia) + End If + + CargaDatos() + + End Sub + + Private Function LimpiarBajio(ByVal texto As String, + ByVal maxLen As Integer, + Optional ByVal permitirVacio As Boolean = False) As String + + Dim _rxProhibidos As New Regex("[\$\,\./\-ñÑÁÉÍÓÚÜáéíóúü]", RegexOptions.Compiled) + + texto = If(texto, "").Trim() + If Not permitirVacio AndAlso texto.Length = 0 Then Return "" + + texto = New String(texto.Normalize(NormalizationForm.FormD) _ + .Where(Function(ch) CharUnicodeInfo.GetUnicodeCategory(ch) <> UnicodeCategory.NonSpacingMark) _ + .ToArray()) _ + .Normalize(NormalizationForm.FormC) + + texto = _rxProhibidos.Replace(texto, "") + If texto.Length > maxLen Then texto = texto.Substring(0, maxLen) + Return texto + End Function @@ -1177,7 +1548,7 @@ Partial Class Bancos_PagoElectronicoGrupos If DTPendientes.FiltraParametros("EstatusPagoElectronicoGrupos = 'True' AND EstatusCtaDeposito = 'True'") IsNot Nothing Then - Dim CuentaCargo As String = "0382755740201" + Dim CuentaCargo As String = "382755740201" If DdlCuenta.SelectedItem.Text.Contains("BAJIO") Then @@ -1185,7 +1556,9 @@ Partial Class Bancos_PagoElectronicoGrupos numeroArchivo:=1, fechaCargo:=NowADS, cuentaCargo:=CuentaCargo, - DTPendientes.FiltraParametros("EstatusPagoElectronicoGrupos = 'True' AND EstatusCtaDeposito > 0")) + DTDatos:=DTPendientes.FiltraParametros("EstatusPagoElectronicoGrupos = 'True' AND EstatusCtaDeposito > 0"), + InsertaEnDB:=False + ) ElseIf DdlCuenta.SelectedItem.Text.Contains("Scotiabank") Then @@ -1210,30 +1583,35 @@ Partial Class Bancos_PagoElectronicoGrupos Public Sub GeneraPagoBajio(numeroArchivo As Integer, fechaCargo As Date, cuentaCargo As String, - DTDatos As DataTable) + DTDatos As DataTable, + InsertaEnDB As Boolean) + + Dim ErrorLayout As Boolean = False - Dim HEADER_LEN As Integer = 20 + Dim CABECERA_LEN As Integer = 20 Dim DETALLE_LEN As Integer = 384 - Dim TRAILER_LEN As Integer = 34 + Dim PIE_LEN As Integer = 34 - ' --- columnas fijas del header / trailer --- + ' --- columnas fijas del header / Pie --- Dim DIVISA_MXN As String = "001" + 'Dim FILLER_7CEROS As String = "0000000" Dim FILLER_8CEROS As String = "00000000" - Dim FILLER_4CEROS As String = "0000" + Dim FILLER_9CEROS As String = "000000000" + 'Dim FILLER_4CEROS As String = "0000" Dim CONST_0140 As String = "0140" '/** Pregunta */: tu banco usa siempre 0140? Dim _mediosValidos As HashSet(Of String) = New HashSet(Of String)({"BCO", "TEF", "SPE", "SPD"}) Dim _tiposCuentaValidos As HashSet(Of String) = New HashSet(Of String)({"40", "1", "3"}) - ' --------------------------- Header (20 bytes) --------------------------- + Dim header As String = $"01{numeroArchivo:D7}{fechaCargo:yyyyMMdd}{DIVISA_MXN}" - If header.Length <> HEADER_LEN Then - Alert($"Header debe medir {HEADER_LEN} bytes, mide {header.Length}.", TipoMensaje.MsgAdvertencia) + If header.Length <> CABECERA_LEN Then + Alert($"Header debe medir {CABECERA_LEN} bytes, mide {header.Length}.", TipoMensaje.MsgAdvertencia) Exit Sub End If - ' --------------------------- Detalles (384 bytes) ------------------------ + Dim detalles As New List(Of String)(DTDatos.Rows.Count) Dim consecArchivo As Integer = 2 'el #1 lo ocupa el header Dim consecPago As Integer = 1 @@ -1250,6 +1628,7 @@ Partial Class Bancos_PagoElectronicoGrupos Dim TipoCuentaDestino As String = "" Dim Importe As Decimal = DRow("Importe").ToString.ToDecimal Dim IVA As Decimal = 0D + Dim CveBanco As String = DRow("CveBanco").ToString.Trim 'CveBanco es el código SAT del banco tres dígitos If nCaracteresClabeCuenta <> 18 Then If nCaracteresClabeCuenta <> 12 Then @@ -1265,9 +1644,9 @@ Partial Class Bancos_PagoElectronicoGrupos End If - ' ----------- Validaciones de negocio -------------------------------- - DRow("RazonSocial") = LimpiarDatosBajio(DRow("RazonSocial").ToString, 15, "Alias") - DRow("RazonSocial") = LimpiarDatosBajio(DRow("RazonSocial").ToString, 250, "Descripción") + ' ----------- Validaciones -------------------------------- + DRow("RazonSocial") = LimpiarDatosBajio(DRow("RazonSocial").ToString, 15, "AliasProveedor") + DRow("Observaciones") = LimpiarDatosBajio(DRow("Observaciones").ToString, 250, "Descripción") If Not _tiposCuentaValidos.Contains(TipoCuentaDestino) Then Alert($"TipoCuentaDestino inválido: {TipoCuentaDestino}", TipoMensaje.MsgAdvertencia) @@ -1294,6 +1673,16 @@ Partial Class Bancos_PagoElectronicoGrupos Exit Sub End If + If cuentaCargo.Length <> 12 Then + Alert($"Cuenta de cargo debe tener 12 caracteres, tiene {cuentaCargo.Length}.", TipoMensaje.MsgAdvertencia) + Exit Sub + End If + + If CveBanco.Length <> 3 Then + Alert($"Clabe SAT de cuenta deposito no valida, cuenta: {ClabeOCuenta}, valor SAT:{CveBanco}.", TipoMensaje.MsgAdvertencia) + Exit Sub + End If + 'If DRow.IVA < 0D Then ' Alert("IVA no puede ser negativo.", TipoMensaje.MsgAdvertencia) ' Exit Sub @@ -1302,47 +1691,138 @@ Partial Class Bancos_PagoElectronicoGrupos ' ----------- Construcción de la línea -------------------------------- Dim sb As New StringBuilder(DETALLE_LEN) - sb.Append("02") 'tipo registro - sb.Append(consecArchivo.ToString("D7")) 'consec archivo - sb.Append("01") 'tipo cta origen fijo - sb.Append(FILLER_8CEROS) 'filler - sb.Append(cuentaCargo.PadLeft(12, "0"c)) 'cta cargo - sb.Append(CONST_0140) 'constante 0140 - sb.Append(ClabeOCuenta.PadLeft(3, "0"c)) - sb.Append("00") '5 dígitos banco destino - sb.Append(consecPago.ToString("D10")) 'consec pago - sb.Append("000" & fechaCargo.ToString("yyyyMMdd")) 'prefijo 000 + fecha + sb.Append("02") 'tipo registro + sb.Append(consecArchivo.ToString("D7")) 'consec archivo + sb.Append("01") 'tipo cta origen fijo + sb.Append(FILLER_8CEROS) 'filler + sb.Append(cuentaCargo.PadLeft(12, "0"c)) 'cta cargo + sb.Append(CONST_0140) 'constante 0140? + sb.Append(CveBanco.Substring(0, 3).PadLeft(3, "0"c)) 'codigo de banco SAT + sb.Append(consecPago.ToString.PadLeft(10, "0"c)) 'consec pago + sb.Append("00000" & fechaCargo.ToString("yyyyMMdd")) 'prefijo 000 + fecha sb.Append(MedioPago) 'BCO/TEF/SPE/SPD sb.Append(TipoCuentaDestino.PadLeft(2, "0"c)) 'tipo cta destino - sb.Append(FILLER_4CEROS) 'filler - sb.Append(DRow("RazonSocial").ToString.PadRight(15)) 'alias (15) + 'sb.Append(FILLER_4CEROS) 'filler + sb.Append(ClabeOCuenta.PadLeft(20, "0"c)) + sb.Append(FILLER_9CEROS) + 'sb.Append(DRow("RazonSocial").ToString.PadRight(15)) + sb.Append(LimpiarBajio(If(DRow("BBVAAlias").ToString.Trim.Length > 0, DRow("BBVAAlias").ToString, DRow("RazonSocial").ToString).ToString, 15)) 'alias (15) sb.Append(CLng(IVA).ToString("D15")) 'IVA ×100 - sb.Append(DRow("RazonSocial").ToString.PadRight(250)) 'descripción (250) + sb.Append(DRow("Observaciones").ToString.PadRight(250)) 'descripción (250) sb.Append(If(String.IsNullOrEmpty(ReferenciaSPEI), New String("0"c, 7), - ReferenciaSPEI)) 'referencia SPEI + ReferenciaSPEI)) 'referencia SPEI sb.Append(If(String.IsNullOrEmpty(ClasificacionSPID), "00", - ClasificacionSPID.PadLeft(2, "0"c))) 'clasif SPID - sb.Append(New String(" "c, 25)) 'filler final + ClasificacionSPID.PadLeft(2, "0"c))) 'clasif SPID + sb.Append(New String(" "c, 25)) 'filler final - If sb.Length <> DETALLE_LEN Then - Throw New InvalidOperationException($"Detalle #{consecPago} mide {sb.Length} bytes, debería {DETALLE_LEN}.") - End If - detalles.Add(sb.ToString()) + + detalles.Add($"{sb.ToString()}{vbCrLf}") consecArchivo += 1 consecPago += 1 totalCentavos += CLng(Importe * 100) Next - ' --------------------------- Trailer (34 bytes) ------------------------- - Dim totalLineas As Integer = 1 + DTDatos.Rows.Count + 1 'header + detalles + trailer - Dim trailer As String = $"09{totalLineas:D7}{DTDatos.Rows.Count:D7}{FILLER_8CEROS}{totalCentavos:D10}" - If trailer.Length <> TRAILER_LEN Then Throw New InvalidOperationException($"Trailer debe medir {TRAILER_LEN} bytes, mide {trailer.Length}.") - ' --------------------------- Resultado ---------------------------------- - 'Return {header}.Concat(detalles).Concat({trailer}) + Dim totalLineas As Integer = 1 + DTDatos.Rows.Count + 1 'header + detalles + Pie + Dim Pie As String = $"09{totalLineas:D7}{DTDatos.Rows.Count:D7}{FILLER_8CEROS}{totalCentavos:D10}" + + If Pie.Length <> PIE_LEN Then + Alert($"Pie debe medir {PIE_LEN} bytes, mide {Pie.Length}.", TipoMensaje.MsgAdvertencia) + ErrorLayout = True + End If + + + + + 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 DTDatos.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 = $"{header}{vbCrLf}{String.Join(vbCrLf, detalles)}{Pie}" + + 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 consecPago > 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 = DTDatos.Copy + + LnkDescarga.Text = NombreArchivo + RegistraScript("$('#ModalDescarga').modal({ backdrop: 'static', keyboard: false});") + UpModalDescarga.Update() + + End If + + CargaDatos() + + End If + End Sub Private Function LimpiarDatosBajio(texto As String, maxLen As Integer, campo As String) As String @@ -1350,7 +1830,7 @@ Partial Class Bancos_PagoElectronicoGrupos Dim _rxProhibidos As Regex = New Regex("[\$\,\./\-ñÑÁÉÍÓÚÜáéíóúü]", RegexOptions.Compiled) If String.IsNullOrWhiteSpace(texto) Then - Throw New ArgumentException($"{campo} es obligatorio.") + Alert($"{campo} es obligatorio.", TipoMensaje.MsgAdvertencia) End If ' Normalizar y quitar diacríticos @@ -1363,9 +1843,16 @@ Partial Class Bancos_PagoElectronicoGrupos s = _rxProhibidos.Replace(s, "") If s.Length > maxLen Then - Throw New ArgumentException($"{campo} ({s}) excede {maxLen} caracteres.") + + If campo = "AliasProveedor" Or campo = "Descripción" Then + s = s.Substring(0, maxLen) + Else + Alert($"{campo} ({s}) excede {maxLen} caracteres.", TipoMensaje.MsgAdvertencia) + End If End If + Return s + End Function Private Sub GeneraPagoScotiabank(dataTable As DataTable) @@ -1621,31 +2108,22 @@ Partial Class Bancos_PagoElectronicoGrupos End If - - - - If ErrorLayout = False And RegistrosPago.Length > 0 Then Dim Mensaje As New StringBuilder Mensaje.Append("Descarga Layout
") - If NombreArchivoEnviado.Length > 0 Then NombreArchivoPago = NombreArchivoEnviado End If 'If NombreArchivoPago.Trim.Length > 0 Then - ' Mensaje.Append($"Pagos Descarga
{NombreArchivoPago}

") - 'End If - If NombreArchivoPago.Length > 0 Then - DVDescargaPagos.Visible = True DVDescargaCuentas1.Visible = False DVDescargaCuentas2.Visible = False @@ -2239,7 +2717,7 @@ Partial Class Bancos_PagoElectronicoGrupos If DdlTipoCargaMasiva.SelectedValue.ToEntero = 1 Then TipoMasiva = 1 GvProveedores.Columns(0).HeaderText = "Proveedor" - CargaProveedores() + CargaProveedores(OpBancos) BtnGenerarProveedores.Text = "Generar Layout Alta Proveedores" Else TipoMasiva = 2 @@ -2255,17 +2733,28 @@ Partial Class Bancos_PagoElectronicoGrupos Exit Sub End If - If TipoMasiva = 1 Then - AltaProveedores(DTProveedores) + If TipoMasiva = 1 Then + + If OpBancos = 1 Then + AltaProveedores(DTProveedores) + ElseIf OpBancos = 2 Then + AltaProveedoresBajio(DTProveedores) + ElseIf OpBancos = 3 Then + 'AltaProveedoresScotia(DTProveedores) + End If + + + + Else AltaFyE() End If End Sub - Private Sub CargaProveedores() + Private Sub CargaProveedores(OpBanco As Integer) Dim ObjBancos As New ClsBancos - If ObjBancos.GetLayoutProveedores(DdlCuenta.SelectedValue.ToEntero, UsuarioActual.CveEmpresa, PorGrupos:=True) Then + If ObjBancos.GetLayoutProveedores(DdlCuenta.SelectedValue.ToEntero, UsuarioActual.CveEmpresa, PorGrupos:=True, OpBanco:=OpBanco) Then DTProveedores = ObjBancos.DtResultados.FiltraParametros("LEN(RFC) IN (12,13)") Else DTProveedores = New DataTable @@ -2925,13 +3414,21 @@ Partial Class Bancos_PagoElectronicoGrupos Protected Sub LnkDescargaCuentas1_Click(sender As Object, e As EventArgs) + Dim FileName As String = NombreArchivoBancomer Dim FilePath As String = $"{UsuarioActual.Empresa.Ruta}Layout\{NombreArchivoBancomer}" + + If DdlCuenta.SelectedItem.Text.ToUpper.Contains("BAJIO") Or DdlCuenta.SelectedItem.Text.ToUpper.Contains("SCOTIA") Then + FileName = LnkDescargaCuentas1.Text + FilePath = $"{UsuarioActual.Empresa.Ruta}Layout\{LnkDescargaCuentas1.Text}" + End If + Response.Clear() Response.ContentType = "application/octet-stream" Response.AddHeader("Content-Disposition", "attachment; filename=" & FileName) Response.TransmitFile(FilePath) Response.End() + End Sub Protected Sub LnkDescargaCuentas2_Click(sender As Object, e As EventArgs) Dim FileName As String = NombreArchivoInterbancario @@ -3057,4 +3554,28 @@ Partial Class Bancos_PagoElectronicoGrupos Alert("Correos ya enviados.") End Sub + + Protected Sub DdlCuenta_SelectedIndexChanged(sender As Object, e As EventArgs) + + DdlTipoCargaMasiva.Items(1).Enabled = False + DdlTipoCargaMasiva.SelectedValueExist(-1) + + DdlTipoGeneracion.Items(2).Enabled = False + DdlTipoGeneracion.Items(3).Enabled = False + DdlTipoGeneracion.SelectedValueExist(-1) + + If OpBancos = 1 Then + DdlTipoGeneracion.Items(2).Enabled = True + DdlTipoGeneracion.Items(3).Enabled = True + DdlTipoCargaMasiva.Items(1).Enabled = True + ElseIf OpBancos = 2 Then + ' + ElseIf OpBancos = 3 Then + ' + End If + + UpFiltroCargaMasiva.Update() + UpFiltros.Update() + End Sub + End Class diff --git a/Bancos/RepComplementoPago.aspx.vb b/Bancos/RepComplementoPago.aspx.vb index e7360a3c1..70afb4986 100644 --- a/Bancos/RepComplementoPago.aspx.vb +++ b/Bancos/RepComplementoPago.aspx.vb @@ -238,6 +238,10 @@ Partial Class Bancos_RepComplementoPago e.Row.FCLabel("LblImp").Text = e.Row.DBCampo("VentasTotalPagado").FormatoNumero e.Row.FCLabel("LblImp").ToolTip = String.Format("Importe Pagado:{0} ", e.Row.DBCampo("Importe").FormatoNumero) ' VentasTotalPagado + + Dim importe As Decimal = e.Row.DBCampo("Importe").ToDecimal.RoundAD + Dim ventasTotalPagado As Decimal = e.Row.DBCampo("VentasTotalPagado").ToDecimal.RoundAD + If e.Row.DBCampo("Importe").ToDecimal.RoundAD <> e.Row.DBCampo("VentasTotalPagado").ToDecimal.RoundAD Then e.Row.FCLabel("LblImp").ForeColor = Drawing.Color.Red e.Row.FCLabel("LblImp").ToolTip = String.Format("Importe Pagado:{0} Importe Pagado PUE: {1}, Ot. Ingresos {2}", e.Row.DBCampo("Importe").FormatoNumero, e.Row.DBCampo("PagadoPUE").FormatoNumero, e.Row.DBCampo("PagadoOtIngresos").FormatoNumero) ' VentasTotalPagado diff --git a/Contabilidad/DiarioPagos.aspx b/Contabilidad/DiarioPagos.aspx index f5c6ef30a..6c193ac59 100644 --- a/Contabilidad/DiarioPagos.aspx +++ b/Contabilidad/DiarioPagos.aspx @@ -251,6 +251,8 @@ + + @@ -432,6 +434,7 @@ +
que tengan
diff --git a/Contabilidad/DiarioPagos.aspx.vb b/Contabilidad/DiarioPagos.aspx.vb index 2996b6b4a..ed239eb38 100644 --- a/Contabilidad/DiarioPagos.aspx.vb +++ b/Contabilidad/DiarioPagos.aspx.vb @@ -649,13 +649,27 @@ Partial Class Contabilidad_DiarioPagos 'recorro el grid de compras Dim GvCompras As GridView = gvr.FCGridView("GvPC") + + Dim MonExtOriginal As Boolean = MonExt For Each gvrc As GridViewRow In GvCompras.Rows + + MonExt = MonExtOriginal + + Dim CveMonedaCompra As Integer = gvrc.FCHiddenField("HdnCveMonedaCompra").Value.ToEntero() + + If CveMoneda = 1 AndAlso CveMonedaCompra = 2 Then + MonExt = True + End If + Dim PorcentajeIVA As Decimal = (gvrc.FCHiddenField("HdnPorcentajeIVA").Value.ToDecimal() * 100).ToEntero Cargos = 0 AbonoProveedor = 0 : CargoProveedor = 0 : CargoAnticipo = 0 : AbonoAnticipo = 0 'ya viene el tipo de cambio entre la fecha de compra y la ultima fluctuacion - If CveMoneda = 2 Then TipoCambioCompra = gvrc.FCHiddenField("HdnTC").Value.ToDecimal Else TipoCambioCompra = 1 + If CveMoneda = 2 Or MonExt Then TipoCambioCompra = gvrc.FCHiddenField("HdnTC").Value.ToDecimal Else TipoCambioCompra = 1 + + + ConceptoDetalle = gvrc.FCHiddenField("HdnRazonSocial").Value CargoProveedor = 0 : CargoAnticipo = 0 @@ -1016,7 +1030,7 @@ Partial Class Contabilidad_DiarioPagos If CargoProveedor > 0 Then ' cuando el pago no cubre el 100% Dim TmpTotal As Decimal Dim TmpTotalME As Decimal = CargoProveedor - If CveMoneda = 2 Then + If CveMoneda = 2 Or (CveMoneda = 1 And CveMonedaCompra = 2) Then 'registro a la cuenta complementaria del proveedor If gvr.DataKey("IdCtaContComplementaria").ToEntero > 0 Then diff --git a/Contabilidad/RepAnexoCatalogoCC.aspx b/Contabilidad/RepAnexoCatalogoCC.aspx index 0e105651a..d05a8aad4 100644 --- a/Contabilidad/RepAnexoCatalogoCC.aspx +++ b/Contabilidad/RepAnexoCatalogoCC.aspx @@ -574,7 +574,7 @@ @@ -1049,6 +1866,166 @@ } + function generarGraficaSucursales() { + // 1) Obtener la tabla completa + var $grid = $('table[id$="gvResumenSucursales"]'); + + // 2) Buscar TODOS los checkbox marcados + var $checks = $grid.find('input.header-checkbox:checked'); + if ($checks.length === 0) { + alert('Por favor, seleccione al menos una columna para graficar.'); + return false; + } + + // 3) Filas de datos: todas las
+ var $dataRows = $grid.find('tr').has('td'); + + // 4) Categorías = texto de la primera celda (Sucursal) + var categorias = $dataRows.map(function () { + return $(this).find('td').eq(0).text().trim(); + }).get(); + + // 5) Localizar tus subheaders (segunda fila de encabezado) + var $headerRows = $grid.find('tr').filter(function () { + return $(this).find('th').length > 1; + }); + var $subThs = $headerRows.eq(1).find('th'); // esos 4 + + // 6) Construir las series + var series = $checks.map(function () { + var $chk = $(this); + var $th = $chk.closest('th'); + // idxSub = posición dentro de los 4 subheaders (0..3) + var idxSub = $subThs.index($th); + // +1 porque la columna 0 es "Sucursal" + var colIndex = idxSub + 1; + // Leer data-field (VentaAnual, UtilidadAnual, etc.) y formatear nombre + var field = $chk.data('field'); + var name = field.replace(/([a-z])([A-Z])/g, '$1 $2'); + // Mapear los valores de cada fila para esta columna + var data = $dataRows.map(function () { + var txt = $(this).find('td').eq(colIndex).text().replace(/,/g, ''); + return parseFloat(txt) || 0; + }).get(); + return { name: name, data: data }; + }).get(); + + // 7) Dibujar Highcharts + Highcharts.chart('chartContainer', { + chart: { type: 'line' }, + title: { text: 'Comparativo por Sucursal' }, + xAxis: { + categories: categorias, + title: { text: 'Sucursal' } + }, + yAxis: { + title: { text: 'Monto' }, + labels: { + formatter: function () { + return '$' + Highcharts.numberFormat(this.value, 0); + } + } + }, + tooltip: { + headerFormat: '{series.name}
', + pointFormat: 'Sucursal: {point.category}
Valor: ${point.y:,.2f}' + }, + plotOptions: { + series: { marker: { enabled: true } } + }, + series: series + }); + + // 8) Mostrar el modal + $('#DivModalGrafica').modal('show'); + return false; + } + + function generarGrafica(gridId) { + var $grid = $('#' + gridId); + + // Encuentra las filas de encabezado (donde están los checkboxes) + var $headerRows = $grid.find('tr:has(th)'); + var $subHeader = $headerRows.length > 1 ? $headerRows.eq(1) : $headerRows.eq(0); + var $subThs = $subHeader.find('th'); + + // Buscar checkboxes marcados + var $checks = $grid.find('input.header-checkbox:checked'); + if ($checks.length === 0) { + alert('Por favor, seleccione al menos una columna para graficar.'); + return false; + } + + // Filas de datos + var $dataRows = $grid.find('tr').has('td'); + + // Categorías (eje X) + var categorias = $dataRows.map(function () { + return $(this).find('td').eq(0).text().trim(); + }).get(); + + // Construir series + var series = []; + $checks.each(function () { + var $chk = $(this); + var field = $chk.data('field'); + + // Buscar el índice de la columna que tiene ese data-field + var colIndex = -1; + $subThs.each(function (i) { + var $input = $(this).find('input.header-checkbox'); + if ($input.length && $input.data('field') === field) { + colIndex = i + 1; // +1 porque la primera columna es la de las categorías + } + }); + + if (colIndex === -1) return; // No encontrado, saltar + + var name = field.replace(/([a-z])([A-Z])/g, '$1 $2'); + var data = $dataRows.map(function () { + var txt = $(this).find('td').eq(colIndex).text().replace(/,/g, ''); + return parseFloat(txt) || 0; + }).get(); + + series.push({ name: name, data: data }); + }); + + // Título dinámico + var titulo = $grid.closest('.portlet').find('.caption-subject').text(); + var modalTitulo = document.getElementById('modalTitulo'); + if (modalTitulo) modalTitulo.innerText = 'Comparativo: ' + titulo; + + // Dibujar gráfica + Highcharts.chart('chartContainer', { + chart: { type: 'line' }, + title: { text: titulo }, // Usar el título dinámico + xAxis: { + categories: categorias, + title: { text: 'Categoría' } // Título genérico para el eje X + }, + yAxis: { + title: { text: 'Monto (MXN)' }, + labels: { + formatter: function () { + return '$' + Highcharts.numberFormat(this.value, 0); + } + } + }, + tooltip: { + headerFormat: '{series.name}
', + pointFormat: 'Categoría: {point.category}
Valor: ${point.y:,.2f}' + }, + plotOptions: { + series: { marker: { enabled: true } } + }, + series: series + }); + + $('#DivModalGrafica').modal('show'); + return false; + } + + diff --git a/General/Dashboard.aspx.vb b/General/Dashboard.aspx.vb index b3f4a34bc..5fe165fe6 100644 --- a/General/Dashboard.aspx.vb +++ b/General/Dashboard.aspx.vb @@ -373,50 +373,411 @@ Partial Class General_Dashboard Protected Sub gvResumenSucursales_RowCreated(sender As Object, e As GridViewRowEventArgs) If e.Row.RowType = DataControlRowType.Header Then - ' Limpiar celdas originales e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) - ' Crear primera fila de encabezado (grupos) - Dim headerRow As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) - ' Celda para "Sucursal" (ocupa 2 filas) Dim cellSucursal As New TableHeaderCell() cellSucursal.RowSpan = 2 - cellSucursal.Text = "Sucursal" - headerRow.Cells.Add(cellSucursal) + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Sucursal ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGraficaSucursales();") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) - ' Celda para "Año" (abarca 2 columnas) - Dim cellAño As New TableHeaderCell() - cellAño.ColumnSpan = 2 - cellAño.Text = "Año" - headerRow.Cells.Add(cellAño) + Dim cellAnio As New TableHeaderCell() + cellAnio.ColumnSpan = 2 + cellAnio.HorizontalAlign = HorizontalAlign.Center + cellAnio.Text = "Año" + headerRow1.Cells.Add(cellAnio) - ' Celda para "Mes" (abarca 2 columnas) Dim cellMes As New TableHeaderCell() cellMes.ColumnSpan = 2 + cellMes.HorizontalAlign = HorizontalAlign.Center cellMes.Text = "Mes" - headerRow.Cells.Add(cellMes) + headerRow1.Cells.Add(cellMes) - ' Añadir fila al GridView - Dim grid As GridView = DirectCast(sender, GridView) - grid.Controls(0).Controls.AddAt(0, headerRow) + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) - ' Crear segunda fila de encabezado (subtítulos) - Dim subHeaderRow As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) - - ' Subtítulos para "Año" - subHeaderRow.Cells.Add(New TableHeaderCell() With {.Text = "Venta"}) - subHeaderRow.Cells.Add(New TableHeaderCell() With {.Text = "Utilidad"}) - - ' Subtítulos para "Mes" - subHeaderRow.Cells.Add(New TableHeaderCell() With {.Text = "Venta"}) - subHeaderRow.Cells.Add(New TableHeaderCell() With {.Text = "Utilidad"}) - - grid.Controls(0).Controls.AddAt(1, subHeaderRow) + ' --- Fila 2 --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + headerRow2.Cells.Add(CreateSubHeaderCell("Venta", "chkVentaAnual", "VentaAnual")) + headerRow2.Cells.Add(CreateSubHeaderCell("Utilidad", "chkUtilidadAnual", "UtilidadAnual")) + headerRow2.Cells.Add(CreateSubHeaderCell("Venta", "chkVentaMensual", "VentaMensual")) + headerRow2.Cells.Add(CreateSubHeaderCell("Utilidad", "chkUtilidadMensual", "UtilidadMensual")) + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) End If End Sub + Protected Sub gvVentasPorSucursal_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Sucursal ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvVentasPorVendedor_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Vendedor ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvVentasPorClasificacion_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Clasificación ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvVentasPorMarca_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Marca ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvVentasPorPS_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("PS ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvVentasPorCliente_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Cliente ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvVentasPorProveedor_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Proveedor ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("Año", "chkAño", "Año")) + headerRow2.Cells.Add(CreateSubHeaderCell("Mes", "chkMes", "Mes")) + headerRow2.Cells.Add(CreateSubHeaderCell("Semana", "chkSemana", "Semana")) + headerRow2.Cells.Add(CreateSubHeaderCell("Día", "chkDia", "Dia")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvCarteraPorSucursal_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Sucursal ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("TotalCxC", "chkTotalCxC", "Total CxC")) + headerRow2.Cells.Add(CreateSubHeaderCell("Vencido", "chkVencido", "Vencido")) + headerRow2.Cells.Add(CreateSubHeaderCell("PorVencer", "chkPorVencer", "Por Vencer")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + Protected Sub gvCarteraPorVendedor_RowCreated(sender As Object, e As GridViewRowEventArgs) + If e.Row.RowType = DataControlRowType.Header Then + e.Row.Cells.Clear() + Dim grid As GridView = DirectCast(sender, GridView) + + ' --- Fila 1 --- + Dim headerRow1 As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Celda principal (Sucursal) + Dim cellSucursal As New TableHeaderCell() + cellSucursal.RowSpan = 2 + cellSucursal.VerticalAlign = VerticalAlign.Middle + cellSucursal.Controls.Add(New LiteralControl("Vendedor ")) + Dim hypGrafica As New HyperLink() + hypGrafica.NavigateUrl = "javascript:void(0);" + hypGrafica.Attributes.Add("onclick", "return generarGrafica('" & grid.ClientID & "');") + hypGrafica.CssClass = "grafica-icon" + hypGrafica.Controls.Add(New LiteralControl("")) + cellSucursal.Controls.Add(hypGrafica) + headerRow1.Cells.Add(cellSucursal) + + headerRow1.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(0, headerRow1) + + ' --- Fila 2 (Subheaders) --- + Dim headerRow2 As New GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal) + + ' Subheaders con checkboxes + headerRow2.Cells.Add(CreateSubHeaderCell("TotalCxC", "chkTotalCxC", "Total CxC")) + headerRow2.Cells.Add(CreateSubHeaderCell("Vencido", "chkVencido", "Vencido")) + headerRow2.Cells.Add(CreateSubHeaderCell("PorVencer", "chkPorVencer", "Por Vencer")) + + headerRow2.TableSection = TableRowSection.TableHeader + grid.Controls(0).Controls.AddAt(1, headerRow2) + End If + End Sub + + ''' + ''' Ahora emitimos HTML puro para el checkbox + label, + ''' así el label realmente dispara el toggle del input. + ''' + Private Function CreateSubHeaderCell(text As String, checkboxId As String, dataField As String) As TableHeaderCell + Dim cell As New TableHeaderCell() + cell.HorizontalAlign = HorizontalAlign.Center + + ' Construimos un pequeño bloque HTML con y