Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 27-02-2025
afxe afxe is offline
Miembro
 
Registrado: jul 2004
Ubicación: Malaga-España
Posts: 291
Poder: 21
afxe Va por buen camino
Otra vez fallos de redondeos.

Hola grupo. Tengo FB 3.0 y dialect 3.

Hago una consulta para sacar la suma por bases imponibles, la cuota y el total de una factura a partir de los detalles que la componen:

Código SQL [-]

SELECT A.CODIGO, D.PORC_IVA, 
                 SUM(D.IMPORTE_VENTA)                      AS BASE,
                 SUM(D.IMPORTE_VENTA) * D.PORC_IVA/100      AS CUOTA_1,
                 round( SUM(D.IMPORTE_VENTA) * D.PORC_IVA/100, 2)       AS CUOTA_2,
                 round (SUM(D.IMPORTE_VENTA) * D.PORC_IVA/100 + sum(importe_venta), 2)   AS Total_Factura
FROM CAB_VENTAS A LEFT JOIN DET_MOVIMIENTOS D ON A.TIPO_DOCUMENTO = D.TIPO_CABECERA AND A.CODIGO = D.COD_CABECERA
where a.codigo = 939006
GROUP BY A.CODIGO, D.PORC_IVA

Y este es el resultado:
Código:
CODIGO	PORC_IVA	       BASE	          CUOTA_1	        CUOTA_2	   TOTAL_FACTURA
939006	10.000000	174.55	         17.455000         	17.450000	      192.010000
Podéis observar que CUOTA_2 no hace correctamente el redondeo, debería dar 17.46. IMPORTE_VENTA es un Numeric(15,2) y he probado todas las maneras de hacer el ROUND y CAST, incluso cambiado los campos a Double Precision.

He buscado por el foro pero no he encontrado una solución a esto, y creo que no debe ser el único que lucha con los redondeos. El problema es que me genera gran cantidad de descuadres en contabilización y totalizaciones. ¿Una ayudita?
__________________
Amar al mundo apasionadamente.
Responder Con Cita
  #2  
Antiguo 27-02-2025
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.874
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
A ver si esto te ayuda:
https://docwiki.embarcadero.com/RADS...nding_Routines

Hay otros redondeos en Delphi.

Si buscas en los foros también encontrarás hilos antiguos donde hemos hablado de esto.
__________________
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.
Responder Con Cita
  #3  
Antiguo 27-02-2025
afxe afxe is offline
Miembro
 
Registrado: jul 2004
Ubicación: Malaga-España
Posts: 291
Poder: 21
afxe Va por buen camino
Gracias Neftali.

Todas las operaciones en delphi están controladas. Los rendondeos los hace correctamente. El problema lo tengo en una vista de firebird, (CREATE VIEW) en SQL. La vista saca totalizada las bases, descuentos, cuotas de iva, cuotas de recargo y el total de la linea. Necesito que la vista saque correctamente el redondeo. Cuando hay un importe con #.#5 y le aplico un 10% de descuento, o un 10% de IVA, el redondeo lo hace como quiere, probad esto:

Código SQL [-]
select ROUND(174.55 * 10/100, 2) from rdb$database

Devuelve 17.45. No puedo usar las librerías de delphi en SQL. (bajo programa los redondeos están controlados, uso math.simpleRoundTo, o la funcion MyRound que copie de "Casimiro" ).

El problema lo tengo en las consultas estadísticas y ahora en contabilidad, que no me coincide la base + iva con el total. Antes tenía grabada la cuota de iva calculada por delphi.... un campo por cada base, porc_iva, cuota, porc_rec y recargo: con 3 tipos de IVA tenía 15 campos... lo quité cuando empezaron con el 5%, 2%, 7.5%.... demasiados campos inútiles a la larga.... ahora sólo tengo base_imponible y total_Factura. Cuando necesito el desglose de IVA lo saco de una VIEW.... EMPEZARON LOS PROBLEMAS. El total de la vista no coincide con el total factura.
__________________
Amar al mundo apasionadamente.

Última edición por afxe fecha: 27-02-2025 a las 14:00:22.
Responder Con Cita
  #4  
Antiguo 27-02-2025
chenech chenech is offline
Miembro
 
Registrado: dic 2013
Posts: 107
Poder: 12
chenech Va por buen camino
Prueba así a ver:
Código:
CAST(SUM(PVP * UNIDADES) AS NUMERIC(9, 2)) AS BASE, 
CAST(SUM((PVP * UNIDADES) * IVA / 100) AS NUMERIC(9, 2)) AS IMPIVA, 
CAST(CAST(SUM(PVP * UNIDADES) AS NUMERIC(9, 2)) + CAST(SUM((PVP * UNIDADES) * IVA / 100) AS NUMERIC(9, 2)) AS NUMERIC(9, 2)) AS TOTAL
Responder Con Cita
  #5  
Antiguo 27-02-2025
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.405
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Sería necesario saber exactamente qué datos tienes en ese campo, porque no me cuadra que no redondee correctamente, jamás tuve ese problema.
Responder Con Cita
  #6  
Antiguo 28-02-2025
Avatar de fjcg02
[fjcg02] fjcg02 is offline
Miembro Premium
 
Registrado: dic 2003
Ubicación: Zamudio
Posts: 1.414
Poder: 23
fjcg02 Va camino a la fama
Prueba esto....

Código SQL [-]
SELECT
TOT.CODIGO,
TOT.PORC_IVA,
TOT.BASE * TOT.PORC_IVA/100 AS CUOTA_1,
round( TOT.BASE * TOT.PORC_IVA/100, 2) AS CUOTA_2,
FROM
  (
    SELECT 
    A.CODIGO, 
    D.PORC_IVA, 
    SUM(D.IMPORTE_VENTA) AS BASE
    FROM CAB_VENTAS A LEFT JOIN DET_MOVIMIENTOS D ON A.TIPO_DOCUMENTO = D.TIPO_CABECERA AND A.CODIGO = D.COD_CABECERA
    where a.codigo = 939006
    GROUP BY A.CODIGO, D.PORC_IVA
   ) TOT

Saludos
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino -
Responder Con Cita
  #7  
Antiguo 28-02-2025
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.934
Poder: 26
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Cita:
Empezado por afxe Ver Mensaje
Código SQL [-]
select ROUND(174.55 * 10/100, 2) from rdb$database
Sqlite da 17.45, Postgres 17.46.

Esto es algo que hay considerar:

* No asumas que tipo de datos es un literal ('174.55') sin leer la documentación
* Hacer a ciegas ` AS NUMERIC(9, 2)` hace un `cast` que cuando es de `alto a bajo` es un `corte`. Osea es malo. No es redondear!
* Cuando tienes datos que se trabajan en multiples lenguajes/bd asegurare que *realmente* estan verdaderamente alineados. que son tipos realmente *equivalentes* en vez de ser *similares*. Fíjate en los docs que tengan los mismo exactos rangos.


Por ultimo, yo considero que siempre tienes que tener una UNICA fuente de LA VERDAD. O haces redondeos siempre en Firebird, o siempre en Delphi. En mi caso, yo guardo todo los datos calculados en la bd (ie: Los cálculos los hago siempre en Rust, en vez de en Postgres), ya que hay reglas dinámicas para determinar cuando se aplica o no los impuestos (antes o después de los descuentos por ejemplo), así que no puedo hacer cálculos simples en la bd:



Código SQL [-]
    price       DECIMAL NOT NULL DEFAULT 0,
    cost        DECIMAL NOT NULL DEFAULT 0,
    qty         DECIMAL NOT NULL DEFAULT 0,

    tax_percent   DECIMAL NOT NULL DEFAULT 0,
    tax_total   DECIMAL NOT NULL DEFAULT 0,

    discount_percent    DECIMAL NOT NULL DEFAULT 0,
    discount_value DECIMAL NOT NULL DEFAULT 0,

    sub_total   DECIMAL NOT NULL DEFAULT 0,
    total       DECIMAL NOT NULL DEFAULT 0,

Y nunca hago `ROUND` en la bd, porque eso es en mi opinion 'presentacional', ósea, es algo que se configura similar a cual idioma y cual símbolo de moneda se usa. Todo es exacto en la bd (nota como yo no pongo un corte de cuantos decimales aquí, que es un problema el día que tengas que manejar varios países. Japón por ejemplo no usa decimales!) y a la hora de `reportes` se toma esa decisión.
__________________
El malabarista.

Última edición por mamcx fecha: 28-02-2025 a las 15:27:34.
Responder Con Cita
  #8  
Antiguo 03-03-2025
afxe afxe is offline
Miembro
 
Registrado: jul 2004
Ubicación: Malaga-España
Posts: 291
Poder: 21
afxe Va por buen camino
Cita:
Empezado por fjcg02 Ver Mensaje
Prueba esto....

Código SQL [-]
SELECT
TOT.CODIGO,
TOT.PORC_IVA,
TOT.BASE * TOT.PORC_IVA/100 AS CUOTA_1,
round( TOT.BASE * TOT.PORC_IVA/100, 2) AS CUOTA_2,
FROM
  (
    SELECT 
    A.CODIGO, 
    D.PORC_IVA, 
    SUM(D.IMPORTE_VENTA) AS BASE
    FROM CAB_VENTAS A LEFT JOIN DET_MOVIMIENTOS D ON A.TIPO_DOCUMENTO = D.TIPO_CABECERA AND A.CODIGO = D.COD_CABECERA
    where a.codigo = 939006
    GROUP BY A.CODIGO, D.PORC_IVA
   ) TOT

Saludos
Sigue sin funcionar....
__________________
Amar al mundo apasionadamente.
Responder Con Cita
  #9  
Antiguo 03-03-2025
afxe afxe is offline
Miembro
 
Registrado: jul 2004
Ubicación: Malaga-España
Posts: 291
Poder: 21
afxe Va por buen camino
Cita:
Empezado por mamcx Ver Mensaje
Sqlite da 17.45, Postgres 17.46.

Por ultimo, yo considero que siempre tienes que tener una UNICA fuente de LA VERDAD. O haces redondeos siempre en Firebird, o siempre en Delphi. En mi caso, yo guardo todo los datos calculados en la bd (ie: Los cálculos los hago siempre en Rust, en vez de en Postgres), ya que hay reglas dinámicas para determinar cuando se aplica o no los impuestos (antes o después de los descuentos por ejemplo), así que no puedo hacer cálculos simples en la bd:

Y nunca hago `ROUND` en la bd, porque eso es en mi opinion 'presentacional', ósea, es algo que se configura similar a cual idioma y cual símbolo de moneda se usa. Todo es exacto en la bd (nota como yo no pongo un corte de cuantos decimales aquí, que es un problema el día que tengas que manejar varios países. Japón por ejemplo no usa decimales!) y a la hora de `reportes` se toma esa decisión.
Supongo que tienes razón, tendré que totalizar en delphi cada vez que necesite las totalizaciones o crear nuevas tablas para grabar esas totalizaciones y no penalizar en tiempo. Tenía un Store Procedure (proc_totaliza_cab_ventas) que me devolvía una tabla con los totales por bases (bases, descuento, cuotas de iva, cuotas de recargo y total). Obtenía la información bastante rápido... pero con esos descuadres de céntimos. A currar....

Gracias a todos por vuestro interés.
__________________
Amar al mundo apasionadamente.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Problema con redondeos en doubles briast OOP 3 05-04-2012 11:10:16
Redondeos y no redondeos vivamotos C++ Builder 6 12-06-2010 00:29:48
Redondeos con Firebird 2.0 Jose_T Firebird e Interbase 12 19-01-2007 19:57:02
problemas con float y redondeos wonder boy Firebird e Interbase 17 27-12-2005 20:59:06
Problemas con Redondeos AGAG4 Varios 4 14-11-2005 23:38:44


La franja horaria es GMT +2. Ahora son las 16:32:33.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi