• Viernes 19 de Abril de 2024, 22:35

Autor Tema:  montos erroneos en informe ventas por producto  (Leído 1375 veces)

NICOWEZ

  • Nuevo Miembro
  • *
  • Mensajes: 1
    • Ver Perfil
montos erroneos en informe ventas por producto
« en: Lunes 2 de Marzo de 2009, 22:45 »
0
resulta que tengo un software que genera variados informes de las ventas que este mismo realiza...


informe de ventas por cliente, ventas por vendedor, ventas anuales y ventas por producto.

en este ultimo me entrega datos erroneos, especificamente un valor mas alto al correspondiente.

les dejo el procedimiento almacenado que genera ese informe

estructura de las tablas
img220.imageshack.us/img220/4199/estructuratablas.th.png


editado codigo comentado y resumido solo a boletas de venta
Código: Text
  1.  
  2.    
  3. --sintaxis de tablas
  4. --MAE = maestra (encabezado)
  5. --DET = detalle
  6. --ej. mae_boleta_Venta : guarda encabezados de las boletas de venta
  7. --det_boleta_venta : guarda las lineas de detalle de las boletas de venta
  8.  
  9. --sintaxis para los campos de cada tabla
  10. --InicialesDeNombreDeTabla_DescripcionCampo
  11. --ej. mps_id_producto_servicio
  12. --mps viene de la tabla Mae_Producto_Servicio
  13.  
  14. --sintaxis del procedimiento almacenado (sp_tipo_nombre)
  15. --tipos de procedimientos almacenados
  16. --sel : seleccion
  17. --ins : insercion
  18. --del : delete
  19.  
  20. -- he estado realizando las pruebas con los 2 primeros parametros en 0
  21. -- y con distintas fechas de inicio y final
  22.  
  23. alter PROCEDURE [dbo].[sp_SEL_InfoVentasPorProducto]      
  24.      
  25.     @IdProducto numeric, --parametro recibido para filtrar por un producto en especifico, cuando no se filtra recibe un 0    
  26.     @IdCategoria numeric, --parametro recibido para filtrar por una categoria de producto en especifico, cuando no se filtra recibe un 0        
  27.     @FechasDesde datetime, --parametro recibido desde el formulario para filtrar las ventas (fecha inicio)    
  28.     @FechasHasta datetime  --parametro recibido desde el formulario para filtrar las ventas (fecha final)      
  29.      
  30. AS      
  31.      
  32.      
  33. declare @MontoBoletas  decimal (26,8)   --variable que almacena el monto total neto de boletas de venta por producto
  34. declare @CantidadProductoBOV numeric  --variable almacena cantidad vendida de productos en boleta        
  35.  
  36. --los montos netos deben ser calculados, ya que los precios de venta se almacenan con iva
  37.    
  38. set @FechasHasta = dateadd(dd,1,@FechasHasta)      
  39.      
  40.  
  41. --los documentos de venta cuentan con un descuento general (encabezado) y un descuento por linea de detalle
  42. --los siguientes 2 updates de las tablas mae_boleta_venta (encabezado boleta) y det_boleta_venta (glosa detalle
  43. -- de boleta) calculan el factor de descuento del encabezado que le corresponde a cada detalle para saber
  44. -- realmente a cuanto se vendio el producto efectivamente
  45.  
  46. --solo por asegurarme vuelvo a calcular el subtotal bruto de la boleta, correspondiente al total con descuento mas el descuento
  47. update mae_boleta_venta  
  48. set mbv_subtotal_bruto = mbv_total + mbv_monto_descuento  
  49.  
  50. --el descuento de encabezado es un factor que se calcula dividiendo el monto de descuento general de la boleta por el subtotal de la boleta,
  51. --el subtotal de la boleta corresponde a la suma de todos los totales de las lineas o tuplas del detalle de la boleta
  52. --el total de la linea, corresponde a el subtotal de la linea menos el descuento de la linea
  53. --el subtotal de la linea corresponde a la cantidad vendida por el valor unitario bruto de producto
  54.  
  55. --procedo a calcular el factor que le corresponde a cada linea por descuento general de boleta
  56. update det_boleta_venta  
  57. set dbv_descuento_encabezado = mae_boleta_venta.mbv_monto_descuento / mae_boleta_venta.mbv_subtotal_bruto  
  58. from det_boleta_venta  
  59. join mae_boleta_venta  
  60. on det_boleta_venta.dbv_id_boleta_venta = mae_boleta_venta.mbv_id_boleta_venta  
  61. where mbv_subtotal_bruto > 0  
  62.  
  63.  
  64. ----------------------------------------------------------------------------------    
  65. IF(@IdCategoria=0 AND @IdProducto > 0)     --si no se ingreso categoria de producto y si se ingreso id de producto en formulario
  66. BEGIN      
  67.    
  68. --asigno al monto de las boletas el neto de la suma de los detalles con el descuento por encabezado y ya aplicado mediante el calculo
  69. set @MontoBoletas = (SELECT  sum(((D.dbv_total*100)/(b.mbv_porcentaje_iva + 100))* (1 - isnull(d.dbv_descuento_encabezado,0)))  
  70.       FROM MAE_BOLETA_VENTA B --tabla maestra de la boleta (encabezado)      
  71.      JOIN DET_BOLETA_VENTA D  --tabla detalles de boleta (almacena todas las lineas de productos vendidos)    
  72.      ON (B.mbv_id_boleta_venta = D.dbv_id_boleta_venta)      
  73.      JOIN MAE_PRODUCTO_SERVICIO P      
  74.      ON (P.mps_id_producto_SErvicio = D.dbv_id_producto_servicio)      
  75.      WHERE (D.dbv_id_producto_servicio = @IdProducto OR @IdProducto=0)  --filtro segun el id de producto ingresado    
  76.      AND (B.mbv_fecha>=@FechasDesde AND B.mbv_fecha<=@FechasHasta)     --filtro segun rango de fechas ingresadas  
  77.                     AND  (P.mps_id_categoria_producto_servicio = @IdCategoria OR @IdCategoria=0) --filtro segun id de categorias de producto ingresado    
  78.      AND B.mbv_nula = 0)    --selecciono solo las boletas que no son nulas  
  79.    
  80.      
  81. set @CantidadProductoBOV = (SELECT SUM(D.dbv_cantidad)   --sumo la cantidad de productos en el detalle y la asigno a la variable    
  82.        FROM MAE_BOLETA_VENTA B      
  83.        JOIN DET_BOLETA_VENTA D      
  84.        ON (B.mbv_id_boleta_venta = D.dbv_id_boleta_venta)      
  85.        JOIN MAE_PRODUCTO_SERVICIO P      
  86.        ON (P.mps_id_producto_SErvicio = D.dbv_id_producto_servicio)      
  87.        WHERE (D.dbv_id_producto_servicio = @IdProducto OR @IdProducto=0) --filtro segun el id de producto ingresado      
  88.               AND (B.mbv_fecha>=@FechasDesde AND B.mbv_fecha<=@FechasHasta) --filtro segun rango de fechas ingresado      
  89.                             AND  (p.mps_id_categoria_producto_servicio = @IdCategoria OR @IdCategoria=0) --filtro segun el id de categoria de producto ingresado      
  90.        AND B.mbv_nula = 0) --selecciono solo las boletas que no son nulas      
  91.      
  92.      
  93. if(@MontoBoletas is null)   --si el monto de las boletas es nulo le asigno un 0
  94.  set @MontoBoletas = 0      
  95.      
  96. if(@CantidadProductoBOV is null)      --si la cantidad de productos en boleta es nulo le asigno un 0
  97.  set @MontoBoletas = 0            
  98.      
  99. SELECT      
  100. MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio AS IdProducto, --id producto para manejo interno de consultas (llave primaria)    
  101. MAE_PRODUCTO_SERVICIO.mps_descripcion AS NombreProducto, --el nombre del producto p ej.: 'Coca Cola'    
  102. MAE_PRODUCTO_SERVICIO.mps_codigo_barra AS CodigoProducto, --codigo producto manejado por usuario de sw  (codigo barras)  
  103. isnull(@MontoBoletas,0) AS MontoBoletas,      
  104. isnull(@MontoFacturas,0) AS MontoFacturas,      
  105. isnull(@MontoNotaCreditoVenta,0) AS MontoNotaCreditoVenta,      
  106. isnull(@MontoTotalVentas,0) AS MontoTotalVentas,      
  107. isnull(@CantidadProducto,0) as Cantidad,      
  108. isnull(mps_precio_venta,0) as PrecioVenta --precio bruto unitario del producto      
  109. FROM MAE_PRODUCTO_SERVICIO    --table donde se guardan todos los datos que corresponden al producto  
  110. WHERE      
  111. (MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio = @IdProducto or @IdProducto=0) AND  --que el id del producto sea igual al que me ingresaron o el parametro venga en 0 lo
  112.                                                                                     ---que hace que el informe liste todos los productos y no un producto especifico    
  113. (MAE_PRODUCTO_SERVICIO.mps_id_categoria_producto_servicio=@IdCategoria OR @IdCategoria=0) --y que este en la categoria ingresada o que no filtre categorias      
  114.        
  115.      
  116. END      
  117.      
  118.      
  119. IF(@IdCategoria>=0 AND @IdProducto=0)  --si no me ingresaron id de producto y me ingresaron o no un id de categoria de producto  
  120. BEGIN      
  121.      
  122. declare @TotalProdCat numeric   -- variable para almecenar la cantidad de tuplas en #TempIdProd
  123. declare @Contador numeric  --contador para recorrer la tabla  #TempIdProd  
  124. declare @IdProd numeric   --variable auxiliar para filtr        
  125. declare @PrecioVenta numeric  --almacena el precio del producto    
  126.      
  127.      
  128. CREATE TABLE #TempVentasProd    (  --tabla temporal para almacenar los detalles de la venta del producto      
  129.  IdProducto numeric,   --pk del producto    
  130.  NombreProducto varchar(55),      --descripcion del producto
  131.  CodigoProducto varchar(55),     --codigo de barras del producto
  132.  MontoBoletas decimal(26,8),      -- monto neto vendido del producto en boletas
  133.  MontoTotalVentas decimal (26,8),   -- monto neto vendido del producto incluye facturas, notas de credito y boletas (en este caso es irrelevante xq solo mostrate la consulta que tiene q ver con las boletas)  
  134.  Cantidad numeric,  --cantidad vendida del producto correspondiente entre boletas, facturas y notas de credito.    
  135.  PrecioVenta numeric  --precio unitario bruto del producto    
  136. )      
  137.      
  138.  CREATE TABLE #TempIdProd --almacena id o pk de los productos vendidos      
  139.  (        
  140.   id int IDENTITY (1, 1),      --genero un id autoincremental para poder usarlo como identificador de lineas
  141.   IdProd numeric,        --campo para guardar el id del producto encontrado
  142.  )      
  143.      
  144.      
  145.      
  146.      
  147.        
  148.      
  149.      
  150.  INSERT #TempIdProd     --guarda los id de los productos vendidos
  151.  SELECT DISTINCT DET_BOLETA_VENTA.dbv_id_producto_servicio  --trae las distintas pk de producto en detalles de boleta  
  152.  FROM MAE_PRODUCTO_SERVICIO --desde la tabla maestra de productos
  153.  JOIN DET_BOLETA_VENTA --unida con el detalle de la boleta de venta (productos vendidos)
  154.  ON MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio = DET_BOLETA_VENTA.dbv_id_producto_servicio
  155.  JOIN MAE_BOLETA_VENTA --y unida con la cabecera de la boleta donde se vendio el producto
  156.  ON DET_BOLETA_VENTA.dbv_id_boleta_venta = MAE_BOLETA_VENTA.mbv_id_boleta_venta
  157.  WHERE (DET_BOLETA_VENTA.dbv_id_producto_servicio = @IdProducto OR @IdProducto=0) --donde el id del producto este en el detalle de la boleta          
  158.  AND (MAE_BOLETA_VENTA.mbv_fecha>=@FechasDesde AND MAE_BOLETA_VENTA.mbv_fecha<=@FechasHasta) --y la boleta haya sido generada en el rango de fecha ingresado por usuario        
  159.  AND  (MAE_PRODUCTO_SERVICIO.mps_id_categoria_producto_servicio = @IdCategoria OR @IdCategoria=0) --y que el producto este en la categoria seleccionada
  160.  AND mbv_nula = 0    --donde la boleta no este anulada (mbv_nula es un bit donde 0 significa que la boleta no ha sido anulada)      
  161.            
  162.      
  163.  set @TotalProdCat= (Select count(*) from #TempIdProd) --total de lineas en tabla temporal #TempIdProd    
  164.  set @Contador=1      
  165.    
  166. --mientras el contador sea menor a la cantidad total de registros en  #TempIdProd  
  167.   WHILE (@Contador <= @TotalProdCat)   --recorre la tabla temporal #TempIdProd  
  168.   BEGIN      
  169.      
  170.    --extrae  el id de producto correspondiente a la linea segun indique el contador  
  171.    set @IdProd = (Select IdProd from #TempIdProd where id=@Contador)      
  172.      
  173. --asigno el neto de la suma de las lineas de detalle de la boleta sin el descuento que corresponde por el encabezado
  174. --a la variable '@MontoBoletas'
  175.    set @MontoBoletas = (SELECT sum(((D.dbv_total*100)/(b.mbv_porcentaje_iva + 100)) --el neto de la suma de las lineas de detalle de la boleta
  176.                                 *(1- isnull(d.dbv_descuento_encabezado,0)))   --calcula el valor segun lo que le corresponde de descuento por el encabezado de la boleta
  177.          FROM DET_BOLETA_VENTA  D    --tabla que almacena los detalles de la boleta de venta
  178.          JOIN MAE_BOLETA_VENTA b       --unida a la tabla del encabezado de boleta de venta
  179.          ON (b.mbv_id_boleta_Venta = D.dbv_id_boleta_venta)      --las uno por su clave primaria y foranea respectivamente correspondiente al id interno de la boleta de venta
  180.          WHERE (D.dbv_id_producto_servicio = @IdProd)    --y filtro segun el id del producto  ...
  181.          AND (b.mbv_fecha>=@FechasDesde AND b.mbv_fecha<=@FechasHasta)   --  ...segun el rango de fechas ingresados...
  182.          AND b.mbv_nula = 0)      --...y que la boleta no este anulada.
  183.    
  184.    
  185.    
  186. --asigno la cantidad de productos    
  187.    set @CantidadProductoBOV = (SELECT SUM(DET_BOLETA_VENTA.dbv_cantidad)  --suma la cantidad de productos vendidos segun lo que indica la linea de detalle    
  188.           FROM DET_BOLETA_VENTA --detalle de boleta de venta
  189.             join MAE_BOLETA_VENTA   --unido con el encabezado
  190.             on  DET_BOLETA_VENTA.dbv_id_boleta_venta = MAE_BOLETA_VENTA.mbv_id_boleta_venta --a traves de la clave primaria del encabezado de la boleta de venta    
  191.           WHERE (DET_BOLETA_VENTA.dbv_id_producto_servicio = @IdProd) --filtrado por el producto que me ingresaron a traves de formulario            
  192.           AND (MAE_BOLETA_VENTA.mbv_fecha>=@FechasDesde AND MAE_BOLETA_VENTA.mbv_fecha<=@FechasHasta)  --y que haya sido vendido en el rango de fechas indicado por el usuario    
  193.           AND mbv_nula = 0 ) --donde la boleta no hata sido anulada    
  194.      
  195.    if(@MontoBoletas is null)      
  196.             begin      
  197.     set @MontoBoletas = 0  --si el monto de boletas es nulo le asigno un 0    
  198.    end      
  199.  
  200.    if(@CantidadProductoBOV is null)      
  201.             begin      
  202.     set @CantidadProductoBOV = 0   --y si la cantidad es nula asigno un 0  
  203.    end      
  204.      
  205.      
  206.    set @MontoTotalVentas = @MontoBoletas    --  se asigna a @MontoTotalVentas todo lo que se vendio del producto entre
  207.                                             --boletas, facturas y notas de credito.. en este caso solo lo mostrare con boletas para q veas una consulta mas corta
  208.      
  209.    set @CantidadProducto = @CantidadProductoBOV  -- se asigna el total de productos vendidos (en este caso solo boletas por lo explicado anteriormente)    
  210.      
  211.  
  212.      
  213.    set @PrecioVenta = (SELECT isnull(mps_precio_venta,0) -- consulta el precio unitario bruto de venta del producto, y si es nulo le asigna un 0      
  214.         FROM MAE_PRODUCTO_SERVICIO   -- de la tabla maestra de productos    
  215.         WHERE mps_id_producto_servicio=@IdProd)      --donde el id del producto sea igual al almacenado en la tabla temporal
  216.      
  217.      
  218.    
  219.    INSERT #TempVentasProd     --guarda los montos de venta segun el producto
  220.    SELECT      
  221.    MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio,  --pk de producto    
  222.    MAE_PRODUCTO_SERVICIO.mps_descripcion,      --nombre de producto
  223.    MAE_PRODUCTO_SERVICIO.mps_codigo_barra,       --codigo de producto
  224.    isnull(@MontoBoletas,0) AS MontoBoletas,     --monto vendido del producto en boletas    (neto)
  225.    isnull(@MontoTotalVentas,0) AS MontoTotalVentas,  --monto total vendido del producto    (neto)
  226.             isnull(@CantidadProducto,0) as Cantidad, --cantidad de productos vendidos      
  227.             isnull(@PrecioVenta,0) as PrecioVenta     --precio unitario de venta de producto (bruto)
  228.    FROM MAE_PRODUCTO_SERVICIO      
  229.    WHERE (MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio = @IdProd)     --filtra segun el id que se este filtrando entre los productos vendidos
  230.          
  231.      
  232.    set @Contador = @Contador + 1    --suma 1 al contador para poder avanzar una tupla en  #TempIdProd
  233.      
  234.   END      
  235.      
  236.      
  237.      
  238.  SELECT DISTINCT *     --selecciona los distintos registros que se guardaron en la tabla y con eso genera el informe  
  239.  FROM #TempVentasProd      
  240.      
  241.  DROP TABLE #TempIdProd   --borra la tabla temporal  
  242.  DROP TABLE #TempVentasProd --bora la tbla temporal que almacena el informe (quedo cargado en grilla del formulario)    
  243.      
  244.      
  245. END      
  246.      
  247.  
  248.  

Pantallazos de Software
img216.imageshack.us/img216/9055/informeclientes.th.png

img213.imageshack.us/img213/7987/informevendedor.th.png

img216.imageshack.us/img216/5647/informeproductos.th.png

espero que me puedan ayudar... me he craneado bastante con esto y no se como arreglarlo..

saludos.. y gracias de antemano