This commit is contained in:
2025-05-24 00:46:54 -07:00
32 changed files with 1465 additions and 236 deletions

View File

@@ -39,8 +39,8 @@
<table width="100%">
<tr>
<td>Tipo Reporte:</td>
<td>
<asp:DropDownList ID="DdlTipoReporte" CssClass="form-control input-sm select2me" runat="server">
<td colspan="2">
<asp:DropDownList ID="DdlTipoReporte" CssClass="form-control input-sm select2me" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DdlTipoReporte_SelectedIndexChanged">
<asp:ListItem Text="Catálogo Cuentas" Value="1"></asp:ListItem>
<asp:ListItem Text="Balanza Comprobación" Value="2"></asp:ListItem>
</asp:DropDownList>
@@ -54,21 +54,30 @@
<td>Periodo: </td>
<td>
<asp:DropDownList ID="DdlPeriodo" CssClass="form-control input-sm select2me" runat="server">
<asp:ListItem Text="Enero" Value="1"></asp:ListItem>
<asp:ListItem Text="Febrero" Value="2"></asp:ListItem>
<asp:ListItem Text="Marzo" Value="3"></asp:ListItem>
<asp:ListItem Text="Abril" Value="4"></asp:ListItem>
<asp:ListItem Text="Mayo" Value="5"></asp:ListItem>
<asp:ListItem Text="Junio" Value="6"></asp:ListItem>
<asp:ListItem Text="Julio" Value="7"></asp:ListItem>
<asp:ListItem Text="Agosto" Value="8"></asp:ListItem>
<asp:ListItem Text="Septiembre" Value="9"></asp:ListItem>
<asp:ListItem Text="Enero" Value="01"></asp:ListItem>
<asp:ListItem Text="Febrero" Value="02"></asp:ListItem>
<asp:ListItem Text="Marzo" Value="03"></asp:ListItem>
<asp:ListItem Text="Abril" Value="04"></asp:ListItem>
<asp:ListItem Text="Mayo" Value="05"></asp:ListItem>
<asp:ListItem Text="Junio" Value="06"></asp:ListItem>
<asp:ListItem Text="Julio" Value="07"></asp:ListItem>
<asp:ListItem Text="Agosto" Value="08"></asp:ListItem>
<asp:ListItem Text="Septiembre" Value="09"></asp:ListItem>
<asp:ListItem Text="Octubre" Value="10"></asp:ListItem>
<asp:ListItem Text="Noviembre" Value="11"></asp:ListItem>
<asp:ListItem Text="Diciembre" Value="12"></asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr id="trTipoEnvio" runat="server" visible="false">
<td>Tipo Envío:</td>
<td colspan="2">
<asp:DropDownList ID="DdlTipoEnvío" CssClass="form-control input-sm select2me" runat="server">
<asp:ListItem Text="Normal" Value="N"></asp:ListItem>
<asp:ListItem Text="Complementaria" Value="C"></asp:ListItem>
</asp:DropDownList>
</td>
</tr>
</table>
<hr />

View File

@@ -1,9 +1,20 @@
Option Explicit On
Option Strict On
Imports System.Data
Imports System.IO
Imports Extensiones
Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Xml
Imports System.Xml.Xsl
Imports System.Data
Imports CrystalDecisions.Web
Imports DocumentFormat.OpenXml.Wordprocessing
Imports Org.BouncyCastle.Asn1
Imports Org.BouncyCastle.Tls.Crypto.Impl
Partial Class Contabilidad_ContabilidadElectronica
Inherits ClsPaginas
@@ -91,11 +102,11 @@ Partial Class Contabilidad_ContabilidadElectronica
If UsuarioActual.Empresa.TipoContabilidad = 1 Then
Dim objconta As New ClsContabilidad
If objconta.GetCuentas(-1, "-1", -1, UsuarioActual.CveEmpresa) Then
DtCuentas = objconta.DtResultados
DtCuentas = objconta.DtResultados.FiltraParametros("CodigoSAT <> ''")
End If
objconta.Dispose()
Else
Dim ObjConpaq As New ClsContPAQi(UsuarioActual.Empresa)
Dim ObjConpaq As New ClsContPAQi(UsuarioActual.Empresa)
If ObjConpaq.GetCuentasElectronica(MinFecha, FechaF) Then
DtCuentas = ObjConpaq.DtResultados
End If
@@ -108,14 +119,11 @@ Partial Class Contabilidad_ContabilidadElectronica
'CABECERA
Str.Append("<?xml version=""1.0"" encoding=""UTF-8""?>")
Str.Append("<catalogocuentas:Catalogo xsi:schemaLocation=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogoCuentas/CatalogoCuentas_1_3.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Version=""1.3"" ")
Str.Append("<catalogocuentas:Catalogo xsi:schemaLocation=""http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogoCuentas http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogoCuentas/CatalogoCuentas_1_3.xsd"" Version=""1.3"" ")
Str.AppendFormat("RFC=""{0}"" ", UsuarioActual.Empresa.RFC)
Str.AppendFormat("Mes=""{0}"" ", DdlPeriodo.SelectedValue)
Str.AppendFormat("Mes=""{0}"" ", DdlPeriodo.SelectedValue.PadLeft(2, "0"c))
Str.AppendFormat("Anio=""{0}"" ", DdlEjercicio.SelectedValue)
Str.AppendFormat("Sello=""{0}"" ", "123")
Str.AppendFormat("noCertificado=""{0}"" ", "123")
Str.AppendFormat("Certificado=""{0}"" ", "1234567890")
Str.Append("xmlns:catalogocuentas=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogoCuentas"">")
Str.Append("xmlns:catalogocuentas=""http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogoCuentas"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">")
'DETALLES
For Each Dr As DataRow In DtCuentas.Rows
@@ -126,7 +134,7 @@ Partial Class Contabilidad_ContabilidadElectronica
Str.AppendFormat("Desc=""{0}"" ", HttpUtility.HtmlEncode(Dr("Nombre").ToString))
Str.AppendFormat("SubCtaDe=""{0}"" ", Dr("CodigoPadre").ToString)
Str.AppendFormat("Nivel=""{0}"" ", Dr("Nivel").ToString)
Str.AppendFormat("Natur=""{0}"" ", Dr("Tipo").ToString)
Str.AppendFormat("Natur=""{0}"" ", If(Dr("Tipo").ToString.Contiene("A", "C", "D", "G", "H"), "D", "A")) 'Atributo requerido para expresar la naturaleza de la cuenta o subcuenta. (D - Deudora, A - Acreedora). ( Activo = D ) ( Pasivo = A ) ( Capital = A ) ( Ingreso = A ) ( Costo = D ) ( Gasto = D ) ( Resultado Integral de Financiamiento = D y/o A ) ( Cuentas de orden = D y/o A ). Existen cuentas de Activo, Pasivo y Capital que por su naturaleza pueden presentarse de manera Deudora o Acreedora.
Else
Str.AppendFormat("CodAgrup=""{0}"" ", Dr("CodAgrup").ToString)
Str.AppendFormat("NumCta=""{0}"" ", Dr("NumCta").ToString)
@@ -147,31 +155,113 @@ Partial Class Contabilidad_ContabilidadElectronica
ArchivoCuentas = $"{UsuarioActual.Empresa.Ruta}/ContabilidadElectronica/{ UsuarioActual.Empresa.RFC}{DdlEjercicio.SelectedValue}{DdlPeriodo.SelectedValue.PadLeft(2, "0"c)}CT.xml"
'SOBREESCRIBE
If System.IO.File.Exists(ArchivoCuentas) Then
System.IO.File.Delete(ArchivoCuentas)
End If
If System.IO.File.Exists(ArchivoCuentas) Then System.IO.File.Delete(ArchivoCuentas)
Dim fs As FileStream = File.Create(ArchivoCuentas)
Dim info As Byte() = New UTF8Encoding(True).GetBytes(Str.ToString)
fs.Write(info, 0, info.Length)
fs.Close()
Dim Archivo As New System.IO.FileInfo(ArchivoCuentas)
'DESCARGA XML
Dim DescargaZIP As Ionic.Zip.ZipFile = New Ionic.Zip.ZipFile()
If IO.File.Exists(ArchivoCuentas) Then
DescargaZIP.AddFile(ArchivoCuentas, "")
End If
DescargaZIP.Save(Response.OutputStream)
Response.AddHeader("content-Disposition", String.Format("attachment; filename={0}{1}{2}CT.zip", UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
Response.ContentType = "application/zip"
Response.End()
'Dim DescargaZIP As Ionic.Zip.ZipFile = New Ionic.Zip.ZipFile()
'If IO.File.Exists(ArchivoCuentas) Then DescargaZIP.AddFile(ArchivoCuentas, "")
'generar el sello
'SellarXML(Str.ToString, ArchivoCuentas, 1)
'DescargaZIP.Save(Response.OutputStream)
'Response.AddHeader("content-Disposition", String.Format("attachment; filename={0}{1}{2}CT.zip", UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
'Response.ContentType = "application/zip"
'Response.End()
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.ClearContent()
HttpContext.Current.Response.ContentType = "application/xml"
HttpContext.Current.Response.AppendHeader("Content-disposition", String.Format("attachment; filename={0}", Archivo.Name))
HttpContext.Current.Response.AddHeader("Content-Length", Archivo.Length.ToString())
HttpContext.Current.Response.TransmitFile(ArchivoCuentas)
'HttpContext.Current.Response.Flush()
HttpContext.Current.Response.End()
Archivo = Nothing
End If
End Sub
Private Function SellarXML(xmltexto As String, ArchivoCuentas As String, Opcion As Integer) As String
Dim ArchivoLLave As String = $"{UsuarioActual.Empresa.Ruta}Certificados\{UsuarioActual.Empresa.ArchivoKey}"
Dim Archivopfx As String = $"{UsuarioActual.Empresa.Ruta}Certificados\{UsuarioActual.Empresa.FielPFX }"
Dim Clavepfx As String = UsuarioActual.Empresa.FielPassword
Dim xsltPath As String
Select Case Opcion
Case 1
xsltPath = $"{AppDomain.CurrentDomain.BaseDirectory}Temp\CatalogoCuentas_1_3.xslt"
Case 2
xsltPath = $"{AppDomain.CurrentDomain.BaseDirectory}Temp\BalanzaComprobacion_1_3.xslt"
End Select
If Not File.Exists(ArchivoLLave) Then
Alert("El archivo de llave privada no existe", TipoMensaje.MsgError)
End If
' 1. Cargar y transformar el XML para obtener la Cadena Original
Dim originalCadena As String = GenerarCadenaOriginal(xmltexto, xsltPath)
' 2. Cargar tu certificado PFX (incluye la clave privada)
Dim cert As New X509Certificate2(Archivopfx, Clavepfx, X509KeyStorageFlags.MachineKeySet)
' 3. Firmar la cadena con SHA256
Dim selloBytes As Byte()
Using rsa As RSA = cert.GetRSAPrivateKey()
selloBytes = rsa.SignData(
Encoding.UTF8.GetBytes(originalCadena),
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1)
End Using
Dim selloBase64 As String = Convert.ToBase64String(selloBytes)
' 4. Obtener el certificado (público) en Base64 y el número de certificado
Dim certBase64 As String = Convert.ToBase64String(cert.RawData)
Dim noCertificado As String = cert.GetSerialNumberString()
' 5. Insertar atributos en el XML
Dim xmlDoc As New XmlDocument()
xmlDoc.PreserveWhitespace = True ' conserva espacios y saltos
xmlDoc.LoadXml(xmltexto)
Dim root As XmlElement = xmlDoc.DocumentElement
root.SetAttribute("Sello", selloBase64)
root.SetAttribute("noCertificado", noCertificado)
root.SetAttribute("certificado", certBase64)
' 6. Guardar archivo sellado
Dim StrFinal As String = xmlDoc.OuterXml
Dim fs As FileStream = File.Create(ArchivoCuentas)
Dim info As Byte() = New UTF8Encoding(True).GetBytes(StrFinal)
fs.Write(info, 0, info.Length)
fs.Close()
'xmlDoc.Save(ArchivoCuentas)
Return StrFinal
End Function
''' <summary>
''' Aplica el XSLT para generar la Cadena Original según SAT.
''' </summary>
Function GenerarCadenaOriginal(xmlContenido As String, xsltFile As String) As String
' Carga la transformación XSLT
Dim xslt As New XslCompiledTransform()
xslt.Load(xsltFile)
' Prepara un StringReader sobre el contenido del XML
Using sr As New StringReader(xmlContenido),
xr As XmlReader = XmlReader.Create(sr),
sw As New StringWriter()
' Ejecuta la transformación
xslt.Transform(xr, Nothing, sw)
' Devuelve la cadena original (trim para quitar saltos extra)
Return sw.ToString().Trim()
End Using
End Function
Private Sub GeneraBalanza()
Dim FechaI As Date = String.Format("01/{0}/{1}", DdlPeriodo.SelectedValue.PadLeft(2, "0"c), DdlEjercicio.SelectedValue).ToDate
Dim FechaF As Date = FechaI.LastDayOfMonth
@@ -186,10 +276,10 @@ Partial Class Contabilidad_ContabilidadElectronica
If DtCuentas IsNot Nothing Then
Dim Deudor As Decimal = DtCuentas.SUM("SaldoAD")
Dim Acreedor As Decimal = DtCuentas.SUM("SaldoAA")
If Deudor <> Acreedor Then
Alert("los Saldos Actuales no cuadran.", TipoMensaje.MsgError)
Exit Sub
End If
'If Deudor <> Acreedor Then
' Alert("los Saldos Actuales no cuadran.", TipoMensaje.MsgError)
' Exit Sub
'End If
End If
Else
Dim ObjConpaq As New ClsContPAQi(UsuarioActual.Empresa)
@@ -204,24 +294,25 @@ Partial Class Contabilidad_ContabilidadElectronica
'CABECERA
Str.Append("<?xml version=""1.0"" encoding=""UTF-8""?>")
Str.Append("<BCE:Balanza xsi:schemaLocation=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion/BalanzaComprobacion_1_3.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Version=""1.3"" ")
Str.Append("<bnc:Balanza ")
Str.Append("xmlns:bnc =""http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion"" ")
Str.Append("xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" ")
Str.Append("xsi:schemaLocation=""http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion/BalanzaComprobacion_1_3.xsd"" ")
Str.Append("Version=""1.3"" ")
Str.AppendFormat("RFC=""{0}"" ", UsuarioActual.Empresa.RFC)
Str.AppendFormat("Mes=""{0}"" ", DdlPeriodo.SelectedValue)
Str.AppendFormat("Mes=""{0}"" ", DdlPeriodo.SelectedValue.PadLeft(2, "0"c))
Str.AppendFormat("Anio=""{0}"" ", DdlEjercicio.SelectedValue)
Str.AppendFormat("TipoEnvio=""{0}"" ", "C")
Str.AppendFormat("FechaModBal=""{0}"" ", FechaF.ToString("yyyy-MM-dd"))
Str.AppendFormat("Sello=""{0}"" ", "123")
Str.AppendFormat("noCertificado=""{0}"" ", "123")
Str.AppendFormat("Certificado=""{0}"" ", "1234567890")
Str.Append("xmlns:BCE=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion"">")
Str.AppendFormat("TipoEnvio=""{0}"" ", DdlTipoEnvío.SelectedValue)
'SOLO CUANDO ES COMPLEMENTARIA
If DdlTipoEnvío.SelectedValue = "C" Then Str.AppendFormat("FechaModBal=""{0}""", FechaF.ToString("yyyy-MM-dd"))
Str.AppendFormat(">")
'DETALLES
For Each Dr As DataRow In DtCuentas.Rows
Str.Append("<BCE:Ctas ")
For Each Dr As DataRow In DtCuentas.FiltraParametros("Codigo <> ''").Rows
Str.Append("<bnc:Ctas ")
If UsuarioActual.Empresa.TipoContabilidad = 1 Then
Str.AppendFormat("NumCta=""{0}"" ", Dr("Codigo").ToString)
Str.AppendFormat("NumCta=""{0}"" ", Dr("Codigo").ToString.Replace("-", ""))
Str.AppendFormat("SaldoIni=""{0}"" ", Dr("SaldoInicial").ToString)
Str.AppendFormat("Debe=""{0}"" ", Dr("Cargos").ToString)
Str.AppendFormat("Haber=""{0}"" ", Dr("Abonos").ToString)
@@ -236,12 +327,10 @@ Partial Class Contabilidad_ContabilidadElectronica
Str.Append("/>")
Next
DtCuentas.Dispose()
'FIN
Str.Append("</BCE:Balanza>")
Str.Append("</bnc:Balanza>")
'GUARDA ARHIVO
ArchivoBalanza = Server.MapPath(String.Format("~/Empresas/{0}/ContabilidadElectronica/{1}{2}{3}BN.xml", UsuarioActual.CveEmpresa, UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
@@ -251,30 +340,50 @@ Partial Class Contabilidad_ContabilidadElectronica
'SOBREESCRIBE
If System.IO.File.Exists(ArchivoBalanza) Then System.IO.File.Delete(ArchivoBalanza)
Dim fs As FileStream = File.Create(ArchivoBalanza)
Dim info As Byte() = New UTF8Encoding(True).GetBytes(Str.ToString)
fs.Write(info, 0, info.Length)
fs.Close()
Dim Archivo As New System.IO.FileInfo(ArchivoBalanza)
'DESCARGA XML
Dim DescargaZIP As Ionic.Zip.ZipFile = New Ionic.Zip.ZipFile()
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.ClearContent()
HttpContext.Current.Response.ContentType = "application/xml"
HttpContext.Current.Response.AppendHeader("Content-disposition", String.Format("attachment; filename={0}", Archivo.Name))
HttpContext.Current.Response.AddHeader("Content-Length", Archivo.Length.ToString())
HttpContext.Current.Response.TransmitFile(ArchivoBalanza)
'HttpContext.Current.Response.Flush()
HttpContext.Current.Response.End()
Archivo = Nothing
If IO.File.Exists(ArchivoBalanza) Then
DescargaZIP.AddFile(ArchivoBalanza, "")
End If
''SOBREESCRIBE
'If System.IO.File.Exists(ArchivoBalanza) Then System.IO.File.Delete(ArchivoBalanza)
''DESCARGA XML
'Dim DescargaZIP As Ionic.Zip.ZipFile = New Ionic.Zip.ZipFile()
''generar el sello
'SellarXML(Str.ToString, ArchivoBalanza, 2)
DescargaZIP.Save(Response.OutputStream)
Response.AddHeader("content-Disposition", String.Format("attachment; filename={0}{1}{2}BN.zip", UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
Response.ContentType = "application/zip"
Response.End()
'If IO.File.Exists(ArchivoBalanza) Then
' DescargaZIP.AddFile(ArchivoBalanza, "")
'End If
'DescargaZIP.Save(Response.OutputStream)
'Response.AddHeader("content-Disposition", String.Format("attachment; filename={0}{1}{2}BN.zip", UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
'Response.ContentType = "application/zip"
'Response.End()
End If
End Sub
#End Region
Protected Sub DdlTipoReporte_SelectedIndexChanged(sender As Object, e As EventArgs)
If DdlTipoReporte.SelectedValue = "1" Then
trTipoEnvio.Visible = False
ElseIf DdlTipoReporte.SelectedValue = "2" Then
trTipoEnvio.Visible = True
End If
End Sub
End Class