![]() |
![]() |
![]() |
![]() |
![]() |
FTP | ![]() |
![]() |
CCD | ![]() |
![]() |
Buscar | ![]() |
![]() |
Trucos | ![]() |
![]() |
Trabajo | ![]() |
![]() |
Foros | ![]() |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
![]() |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
![]() Hola, nosotros trabajamos en c#, importamos el wsdl y este genera unas clases con los objetos y sus propiedades.
Para crear un registro de facturación, creamos un objeto y lo rellenamos. Para enviar ese registro, creamos otro objeto con todos los registros de facturación a enviar y lo enviamos directamente con las funciones que se generaron al importar el wsdl, pasándole el objeto para enviar. No creamos el XML a pelo, de hecho no haría falta serializar el objeto a XML, si no fuera para guardarlo (en fichero o en base de datos). Esto ya nos funciona pero hemos encontrado un caso que no funciona correctamente. El tema está en el campo FechaHoraHusoGenRegistro, al importar el wsdl ese campo se crea como un DateTime. En la documentación ese campo es una fecha en formato YYYY-MM-DDThh:mm:ssTZD (ej: 2024-01-01T19:20:30+01:00) (ISO 8601) Al rellenar la propiedad en el objeto le indicamos que ese DateTime tiene DateTimeKind.Local para indicar que la hora representada es la hora local. Para calcular la huella necesitamos esa fecha en formato de cadena y lo convertimos de forma que aparezca la información de la zona horaria. Hemos visto que estas dos operaciones, utilizan la configuración de la zona horaria del ordenador donde se ejecuta. Hasta aquí todo bien. En condiciones normales funciona perfectamente. El problema lo tenemos cuando hay un ordenador con una configuración de zona horaria y otro con otra configuración. Hemos visto que si el registro de facturación lo genera y lo envía el mismo ordenador, no hay problema. Pero si el registro de facturación lo genera un ordenador y lo envía otro (con configuración de zona horaria distinta) luego la factura es aceptada con errores y el error es de la huella. 2000 El cálculo de la huella suministrada es incorrecta. Puntualizar que en nuestro caso cada ordenador genera registros de facturación, se guardan en una BD central de un servidor, y en ese servidor hay un servicio que va enviando los RFs. Imaginamos que el error ocurre porque el tipo de datos DateTime de c# no tiene información del desplazamiento respecto UTC y mira la configuración de zona horaria del ordenador donde se ejecuta. Pensamos que la función para enviar el objeto, también utiliza esa configuración y depende del ordenador envía una cosa u otra. Por ejemplo desde un ordenador envía 2025-04-15T15:57:46+01:00 desde el otro envía 2025-04-15T15:57:46+02:00 Y claro cuando hacienda hace las validaciones y genera la huella, si la FechaHoraHusoGenRegistro no es la correcta, la huella cambia. Hemos estado haciendo varias pruebas y buscando varias posibilidades pero no hemos encontrado la forma de solucionarlo. Pensamos que tenemos varias opciones: 1. No permitir que varios ordenadores tengan distintas configuraciones de zona horaria. 2. Modificar las clases que se generan al importar el wsdl, cambiar el tipo del campo FechaHoraHusoGenRegistro para que sea una cadena y hacer el tratamiento nosotros del valor de la zona horaria 3. Para el envió, no trabajar con los objetos, sino utilizar una cadena con el XML y enviar ese string directamente haciendo un POST. (y controlar el valor de la zona horaria del campo). Seguramente haremos la opción 1, no se si algún cliente nuestro requerirá configuraciones distintas. Sobre la opción 2, no nos gusta demasiado porque cada vez que se actualice el wsdl se tendrá que volver a cambiar. Sobre la opción 3, pensamos que en general es mejor para nosotros trabajar con los objetos, para rellenarlos y para tratar las respuestas obtenidas. No se si alguno de vosotros trabaja en c# y se ha encontrado con este problema o si tenéis alguna otra idea para afrontar ese caso. Muchas gracias |
#2
|
|||
|
|||
nueva prueba
Hola, hemos seguido investigando y haciendo pruebas y tenemos otra opción, pero no tenemos claro que sea correcta.
Lo que hemos hecho ahora es al rellenar la propiedad de la fecha hora de generación, en el objeto le indicamos que ese DateTime tiene DateTimeKind.Utc para indicar que la hora representada es la hora UTC. Para calcular la huella ahora la cadena para representar FechaHoraHusoGenRegistro en formato ISO 8601 no tiene un +01:00 al final sino que tiene una Z. Luego tanto si envío ese registro de facturación desde un ordenador como desde otro con una configuración de zona horaria (huso) distinta, se envía el mismo valor y las facturas son aceptadas sin errores. Pero tenemos la duda sobre si la hora de generación que estamos informando es la correcta. Consultando por la web los datos de las facturas ya enviadas, tenemos Fecha de presentación: 16-04-2025 13:28:49 Fecha de generación del registro: 2025-04-16T12:24:36Z Estamos indicando la misma fecha y hora en los dos campos? (Los minutos y segundos varían un poco por el tiempo que he tardado entre generar el registro y enviar pero eso no me importa para este tema, solo la hora) Preguntando a la IA me ha contestado lo siguiente: Cita:
Como podéis ver no domino demasiado en temas de horas y husos horarios pero podría ser que sea correcto lo que me ha dicho. Por otra parte AEAT ha contestado como correcta pero no se si es que no lo valida o que. En la definición del campo FechaHoraHusoGenRegistro a parte de indicar el formato, también dice: Cita:
En algún otro post de este foro he visto alguien que también enviaba una Z en FechaHoraHusoGenRegistro pero no encuentro el mensaje ni se si es correcto. Vosotros que pensáis? Muchas gracias!! |
#3
|
|||
|
|||
las dos son las mismas fechashoras, lo que no indicas el huso horario, Z entiendo que es por hora "Zulú" que es la hora sin ningún huso horario (o +0), por lo que entiendo que se las traga ahora pero si quieren que le pasemos el huso horario te dará problemas en el futuro entiendo.
__________________
La religión es personal e intransferible. |
#4
|
|||
|
|||
Cita:
![]() |
#5
|
||||
|
||||
Cita:
En algunos casos (no en todos) no cogemos la hora del equipo, sino la del servidor (para el tema de Ley antifraude lo hemos usado en varios sitios).
__________________
Germán Estévez => Web/Blog Guía de estilo, Guía alternativa Utiliza TAG's en tus mensajes. Contactar con el Clubdelphi ![]() P.D: Más tiempo dedicado a la pregunta=Mejores respuestas. |
#6
|
|||
|
|||
Cita:
Nosotros también usamos la fecha y hora del servidor SQL server, y procuramos que ese servidor siempre esté en la hora exacta. No usamos la hora local del ordenador porque pueden estar fuera de hora y tampoco consultamos la hora de internet (ROA) a cada factura para evitar tantas consultas. Pero independientemente de esto, nos ocurre lo mencionado en el primer post. Porque esa fecha hora del servidor SQL, al pasarla a DateTime, no tiene el huso y luego depende de donde se utilice ese DateTime, genera una FechaHoraHusoGenRegistro distinta. Para coger la hora del servidor SQL primero usábamos la consulta Pero solo devuelve un DateTime (sin huso) Luego probamos con la consulta Que devuelve un DateTimeOffset, este tipo si que tiene una propiedad Offset con el desplazamiento de la hora respecto de la hora universal coordinada (UTC). Esto seria fantástico si en la clase de VeriFactu que se genera al importar el WSDL, el objeto FechaHoraHusoGenRegistro fuera DateTimeOffset, pero no lo es. Y estamos con el mismo problema Muchas gracias |
#7
|
|||
|
|||
Cita:
¿y no puedes crear una función en el Visual que te devuelva un string, con el formato que necesita Verifactu? si haciendo el "SYSDATETIMEOFFSET" obtienes algo como esto: "2025-04-16 16:44:01.6718891 +02:00" y Verifactu necesita algo como esto: "2025-04-16T16:44:01+02:00" entiendo que no sería difícil crear una función que haga la consulta, la ponga en el formato de Verifactu y la devuelva como string. Y si la haces y la pones aquí, ya la aprovecho yo ![]() ![]() |
#8
|
|||
|
|||
Venga... ya la hice yo, la pongo aquí que mañana es festivo y estoy de buenas
![]() Código:
Function ObtenerFechaHora() As String Dim retorno As String = "" '------------------------------------------- '1 - COGEMOS LA HORA DE INTERNET '------------------------------------------- Try ServicePointManager.SecurityProtocol = CType(3072, SecurityProtocolType) 'TLS 1.2 Dim webRequest As HttpWebRequest = CType(Net.WebRequest.Create("https://www2.roa.es/cgi-bin/horautc"), HttpWebRequest) webRequest.Method = "GET" Dim respuesta As HttpWebResponse = CType(webRequest.GetResponse(), HttpWebResponse) If respuesta.StatusCode = HttpStatusCode.OK Then Dim strmRespuesta As Stream = respuesta.GetResponseStream() Dim leeRespuesta As New StreamReader(strmRespuesta) Dim jsonRespuesta As String = leeRespuesta.ReadToEnd() Dim ticks As Long = Long.Parse(jsonRespuesta.Replace("\n", "")) Dim fechora As DateTime = Org.BouncyCastle.Utilities.Date.DateTimeUtilities.UnixMsToDateTime(ticks).ToLocalTime() retorno = fechora.ToString("yyyy-MM-dd'T'HH:mm:ssK") End If Catch Ex As Exception 'MsgBox(Ex.Message, MsgBoxStyle.OkOnly, "ObtenerFechaHora - Internet") End Try '------------------------------------------- '2 - COGEMOS LA HORA DEL SERVIDOR SQL '------------------------------------------- If retorno = "" Then Try Dim DAHora As New SqlDataAdapter Dim DSHora As New DataSet Dim SqlHora As String = "SELECT SYSDATETIMEOFFSET() AS FechaActual" DSHora.Reset() DAHora = New SqlDataAdapter(SqlHora, Conexion) DAHora.Fill(DSHora, "Hora") If DSHora.Tables("Hora").Rows.Count = 1 Then Dim RowHora As DataRow = DSHora.Tables("Hora").Rows(0) Dim fechora As DateTime = RowHora.Item("FechaActual").ToString retorno = fechora.ToString("yyyy-MM-dd'T'HH:mm:ssK") End If DAHora.Dispose() DSHora.Dispose() Catch Ex As Exception 'MsgBox(Ex.Message, MsgBoxStyle.OkOnly, "ObtenerFechaHora - Servidor") End Try End If '------------------------------------------- '2 - COGEMOS LA HORA DEL EQUIPO '------------------------------------------- If retorno = "" Then retorno = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ssK") End If Return retorno End Function Primero intenta cogerla de internet, si no es capaz del servidor sql y si no es capaz del equipo La primera puede dar error si no hay internet o no responde ROA... la segunda debería devolver siempre (si no hay conexión al servidor ya no va a funcionar la aplicación) Espero que te sirva! |
#9
|
|||
|
|||
Cita:
Si utilizo un string para almacenar la FechaHoraHusoGenRegistro al generar el registro, ya se guarda correctamente PERO, con las clases que se genera en Visual Studio al importar el WSDL, el campo no es string sino DateTime. Para utilizar ese string tendría que hacer una de las opciones 2 o 3 que comento en el primer post y que intento evitar ![]() Muchas gracias igualmente |
#10
|
|||
|
|||
Cita:
pues a mi usando el objeto me deja asignarle un campo string: Código:
CType(objectoFactEmitida.RegistroFactura(x).Item, RegistroFacturacionAltaType).FechaHoraHusoGenRegistro = Row.Item("FechaHoraHusoGenRegistro") CType(objectoFactEmitida.RegistroFactura(x).Item, RegistroFacturacionAltaType).TipoHuella = TipoHuellaType.Item01 CType(objectoFactEmitida.RegistroFactura(x).Item, RegistroFacturacionAltaType).Huella = Row.Item("HuellaVerifactu") |
#11
|
|||
|
|||
Cita:
En nuestro caso es DateTime y no puedo hacer esa asignación directa sin convertir. Al importar el WSDL dentro del fichero reference.cs genera el campo así: Código:
/// <remarks/> [System.Xml.Serialization.XmlElementAttribute(Order=25)] public System.DateTime FechaHoraHusoGenRegistro { get { return this.fechaHoraHusoGenRegistroField; } set { this.fechaHoraHusoGenRegistroField = value; this.RaisePropertyChanged("FechaHoraHusoGenRegistro"); } } Código:
<element name="FechaHoraHusoGenRegistro" type="dateTime" /> Gracias igualmente Última edición por rci fecha: Hace 2 Semanas a las 17:58:53. |
#12
|
|||
|
|||
a mi también me dice que es de tipo Date. Entiendo que a todo el mundo debería decirle lo mismo, porque estamos importando el mismo wsdl:
Código:
'''<remarks/> Public Property FechaHoraHusoGenRegistro() As Date Get Return Me.fechaHoraHusoGenRegistroField End Get Set Me.fechaHoraHusoGenRegistroField = value End Set End Property pero me traga cuando lo que le envío es un string: Código:
CType(objectoFactEmitida.RegistroFactura(x).Item, RegistroFacturacionAnulacionType).FechaHoraHusoGenRegistro = Row.Item("FechaHoraHusoGenRegistro") |
#13
|
|||
|
|||
Cita:
![]() Imagino que Visual Basic lo trata diferente que C# ![]() De todas formas también afecta a la hora de enviar. Si el objeto es DateTime, no tiene información del huso horario y coge la configuración del ordenador que envía, y aquí viene el problema si no es la misma que el ordenador que generó el registro de facturación. Gracias Última edición por rci fecha: Hace 2 Semanas a las 18:27:17. |
#14
|
||||
|
||||
Fechaora internet con uso horadio
Hola @rci, Prueba esto.
public System.DateTime(System.DateTime currentDateTime) { return new DateTime(currentDateTime.Year, currentDateTime.Month, currentDateTime.Day, currentDateTime.Hour, currentDateTime.Minute, currentDateTime.Second, DateTimeKind.Local); } Si la hora no es local la convierte a local.
__________________
Uno se alegra de ser útil. (Isaac Asimov) |
#15
|
||||
|
||||
Cita:
Osea que consultais la fecha hora al ordenador que hace el envio y la usais para generar el registro y la huella, asi seguro que es la misma, con unos segundos de diferencia. El ordenador que hace el envio a su vez la consulta con la base de datos o internet o lo que sea.
__________________
Uno se alegra de ser útil. (Isaac Asimov) |
#16
|
|||
|
|||
Cita:
![]() Pero esto solo crea un DateTime indicando que DateTimeKind es local, luego cuando el serializador o "quien" sea coge ese DateTime para obtener la fecha hora real con el huso, utiliza la configuración de la zona horaria del ordenador donde se ejecuta. y si no es el mismo que el que generó el registro de facturación, pues no indica la misma hora/huso. Cita:
![]() Pero gracias de todas formas. De momento he prohibido que haya configuraciones de zona horaria distintas en todos los ordenadores que ejecutan el programa con la misma base de datos. Si no encuentro otra solución lo dejaré así. Saludos |
#17
|
||||
|
||||
Cita:
A lo que me refiero es a que implementeis la funcion que consulta la hora solo en el ordenador que envia y que los demas se la pidan a el.
__________________
Uno se alegra de ser útil. (Isaac Asimov) |
#18
|
|||
|
|||
Cita:
Si, de esta forma también funcionaria, pero es un poco mas complicado. Lo tendré en cuenta. Gracias |
#19
|
|||
|
|||
Yo para obtener el valor de "FechaHoraHusoGenRegistro" en SQL Server uso:
select @ls_valor = left(convert(nvarchar(33), sysdatetimeoffset(), 126), 19) + right(convert(nvarchar(33), sysdatetimeoffset(), 126), 6) Saludos |
#20
|
|||
|
|||
Cita:
Muchas gracias por la respuesta FelixDL De esta forma se obtiene directamente una cadena, pero trabajando con objetos tengo el mismo problema |
![]() |
|
|
![]() |
||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Consultas por franja horaria | petercat | SQL | 2 | 17-04-2018 09:12:29 |
Obtener zona horaria en window 8 | ingabraham | Varios | 0 | 28-08-2013 17:53:04 |
como caambiar la zona horaria desde delphi | kurono | Varios | 4 | 19-08-2008 06:53:36 |
Zona Horaria | palets | API de Windows | 2 | 23-10-2006 19:44:57 |
Zona horaria | Genner | Varios | 1 | 17-04-2006 14:22:20 |
![]() |
|