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 @@
Cuenta:
-
+
Tipo:
@@ -110,12 +113,22 @@
-
+
Bancomer:
-
+
+
Bajio:
+
+
+
+
+
Scotia:
+
+
+
+
@@ -852,7 +865,7 @@
-
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}
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
que tengan
+ 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