--sintaxis de tablas
--MAE = maestra (encabezado)
--DET = detalle
--ej. mae_boleta_Venta : guarda encabezados de las boletas de venta
--det_boleta_venta : guarda las lineas de detalle de las boletas de venta
--sintaxis para los campos de cada tabla
--InicialesDeNombreDeTabla_DescripcionCampo
--ej. mps_id_producto_servicio
--mps viene de la tabla Mae_Producto_Servicio
--sintaxis del procedimiento almacenado (sp_tipo_nombre)
--tipos de procedimientos almacenados
--sel : seleccion
--ins : insercion
--del : delete
-- he estado realizando las pruebas con los 2 primeros parametros en 0
-- y con distintas fechas de inicio y final
alter PROCEDURE [dbo].[sp_SEL_InfoVentasPorProducto]
@IdProducto numeric, --parametro recibido para filtrar por un producto en especifico, cuando no se filtra recibe un 0
@IdCategoria numeric, --parametro recibido para filtrar por una categoria de producto en especifico, cuando no se filtra recibe un 0
@FechasDesde datetime, --parametro recibido desde el formulario para filtrar las ventas (fecha inicio)
@FechasHasta datetime --parametro recibido desde el formulario para filtrar las ventas (fecha final)
AS
declare @MontoBoletas decimal (26,8) --variable que almacena el monto total neto de boletas de venta por producto
declare @CantidadProductoBOV numeric --variable almacena cantidad vendida de productos en boleta
--los montos netos deben ser calculados, ya que los precios de venta se almacenan con iva
set @FechasHasta = dateadd(dd,1,@FechasHasta)
--los documentos de venta cuentan con un descuento general (encabezado) y un descuento por linea de detalle
--los siguientes 2 updates de las tablas mae_boleta_venta (encabezado boleta) y det_boleta_venta (glosa detalle
-- de boleta) calculan el factor de descuento del encabezado que le corresponde a cada detalle para saber
-- realmente a cuanto se vendio el producto efectivamente
--solo por asegurarme vuelvo a calcular el subtotal bruto de la boleta, correspondiente al total con descuento mas el descuento
update mae_boleta_venta
set mbv_subtotal_bruto = mbv_total + mbv_monto_descuento
--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,
--el subtotal de la boleta corresponde a la suma de todos los totales de las lineas o tuplas del detalle de la boleta
--el total de la linea, corresponde a el subtotal de la linea menos el descuento de la linea
--el subtotal de la linea corresponde a la cantidad vendida por el valor unitario bruto de producto
--procedo a calcular el factor que le corresponde a cada linea por descuento general de boleta
update det_boleta_venta
set dbv_descuento_encabezado = mae_boleta_venta.mbv_monto_descuento / mae_boleta_venta.mbv_subtotal_bruto
from det_boleta_venta
join mae_boleta_venta
on det_boleta_venta.dbv_id_boleta_venta = mae_boleta_venta.mbv_id_boleta_venta
where mbv_subtotal_bruto > 0
----------------------------------------------------------------------------------
IF(@IdCategoria=0 AND @IdProducto > 0) --si no se ingreso categoria de producto y si se ingreso id de producto en formulario
BEGIN
--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
set @MontoBoletas = (SELECT sum(((D.dbv_total*100)/(b.mbv_porcentaje_iva + 100))* (1 - isnull(d.dbv_descuento_encabezado,0)))
FROM MAE_BOLETA_VENTA B --tabla maestra de la boleta (encabezado)
JOIN DET_BOLETA_VENTA D --tabla detalles de boleta (almacena todas las lineas de productos vendidos)
ON (B.mbv_id_boleta_venta = D.dbv_id_boleta_venta)
JOIN MAE_PRODUCTO_SERVICIO P
ON (P.mps_id_producto_SErvicio = D.dbv_id_producto_servicio)
WHERE (D.dbv_id_producto_servicio = @IdProducto OR @IdProducto=0) --filtro segun el id de producto ingresado
AND (B.mbv_fecha>=@FechasDesde AND B.mbv_fecha<=@FechasHasta) --filtro segun rango de fechas ingresadas
AND (P.mps_id_categoria_producto_servicio = @IdCategoria OR @IdCategoria=0) --filtro segun id de categorias de producto ingresado
AND B.mbv_nula = 0) --selecciono solo las boletas que no son nulas
set @CantidadProductoBOV = (SELECT SUM(D.dbv_cantidad) --sumo la cantidad de productos en el detalle y la asigno a la variable
FROM MAE_BOLETA_VENTA B
JOIN DET_BOLETA_VENTA D
ON (B.mbv_id_boleta_venta = D.dbv_id_boleta_venta)
JOIN MAE_PRODUCTO_SERVICIO P
ON (P.mps_id_producto_SErvicio = D.dbv_id_producto_servicio)
WHERE (D.dbv_id_producto_servicio = @IdProducto OR @IdProducto=0) --filtro segun el id de producto ingresado
AND (B.mbv_fecha>=@FechasDesde AND B.mbv_fecha<=@FechasHasta) --filtro segun rango de fechas ingresado
AND (p.mps_id_categoria_producto_servicio = @IdCategoria OR @IdCategoria=0) --filtro segun el id de categoria de producto ingresado
AND B.mbv_nula = 0) --selecciono solo las boletas que no son nulas
if(@MontoBoletas is null) --si el monto de las boletas es nulo le asigno un 0
set @MontoBoletas = 0
if(@CantidadProductoBOV is null) --si la cantidad de productos en boleta es nulo le asigno un 0
set @MontoBoletas = 0
SELECT
MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio AS IdProducto, --id producto para manejo interno de consultas (llave primaria)
MAE_PRODUCTO_SERVICIO.mps_descripcion AS NombreProducto, --el nombre del producto p ej.: 'Coca Cola'
MAE_PRODUCTO_SERVICIO.mps_codigo_barra AS CodigoProducto, --codigo producto manejado por usuario de sw (codigo barras)
isnull(@MontoBoletas,0) AS MontoBoletas,
isnull(@MontoFacturas,0) AS MontoFacturas,
isnull(@MontoNotaCreditoVenta,0) AS MontoNotaCreditoVenta,
isnull(@MontoTotalVentas,0) AS MontoTotalVentas,
isnull(@CantidadProducto,0) as Cantidad,
isnull(mps_precio_venta,0) as PrecioVenta --precio bruto unitario del producto
FROM MAE_PRODUCTO_SERVICIO --table donde se guardan todos los datos que corresponden al producto
WHERE
(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
---que hace que el informe liste todos los productos y no un producto especifico
(MAE_PRODUCTO_SERVICIO.mps_id_categoria_producto_servicio=@IdCategoria OR @IdCategoria=0) --y que este en la categoria ingresada o que no filtre categorias
END
IF(@IdCategoria>=0 AND @IdProducto=0) --si no me ingresaron id de producto y me ingresaron o no un id de categoria de producto
BEGIN
declare @TotalProdCat numeric -- variable para almecenar la cantidad de tuplas en #TempIdProd
declare @Contador numeric --contador para recorrer la tabla #TempIdProd
declare @IdProd numeric --variable auxiliar para filtr
declare @PrecioVenta numeric --almacena el precio del producto
CREATE TABLE #TempVentasProd ( --tabla temporal para almacenar los detalles de la venta del producto
IdProducto numeric, --pk del producto
NombreProducto varchar(55), --descripcion del producto
CodigoProducto varchar(55), --codigo de barras del producto
MontoBoletas decimal(26,8), -- monto neto vendido del producto en boletas
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)
Cantidad numeric, --cantidad vendida del producto correspondiente entre boletas, facturas y notas de credito.
PrecioVenta numeric --precio unitario bruto del producto
)
CREATE TABLE #TempIdProd --almacena id o pk de los productos vendidos
(
id int IDENTITY (1, 1), --genero un id autoincremental para poder usarlo como identificador de lineas
IdProd numeric, --campo para guardar el id del producto encontrado
)
INSERT #TempIdProd --guarda los id de los productos vendidos
SELECT DISTINCT DET_BOLETA_VENTA.dbv_id_producto_servicio --trae las distintas pk de producto en detalles de boleta
FROM MAE_PRODUCTO_SERVICIO --desde la tabla maestra de productos
JOIN DET_BOLETA_VENTA --unida con el detalle de la boleta de venta (productos vendidos)
ON MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio = DET_BOLETA_VENTA.dbv_id_producto_servicio
JOIN MAE_BOLETA_VENTA --y unida con la cabecera de la boleta donde se vendio el producto
ON DET_BOLETA_VENTA.dbv_id_boleta_venta = MAE_BOLETA_VENTA.mbv_id_boleta_venta
WHERE (DET_BOLETA_VENTA.dbv_id_producto_servicio = @IdProducto OR @IdProducto=0) --donde el id del producto este en el detalle de la boleta
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
AND (MAE_PRODUCTO_SERVICIO.mps_id_categoria_producto_servicio = @IdCategoria OR @IdCategoria=0) --y que el producto este en la categoria seleccionada
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)
set @TotalProdCat= (Select count(*) from #TempIdProd) --total de lineas en tabla temporal #TempIdProd
set @Contador=1
--mientras el contador sea menor a la cantidad total de registros en #TempIdProd
WHILE (@Contador <= @TotalProdCat) --recorre la tabla temporal #TempIdProd
BEGIN
--extrae el id de producto correspondiente a la linea segun indique el contador
set @IdProd = (Select IdProd from #TempIdProd where id=@Contador)
--asigno el neto de la suma de las lineas de detalle de la boleta sin el descuento que corresponde por el encabezado
--a la variable '@MontoBoletas'
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
*(1- isnull(d.dbv_descuento_encabezado,0))) --calcula el valor segun lo que le corresponde de descuento por el encabezado de la boleta
FROM DET_BOLETA_VENTA D --tabla que almacena los detalles de la boleta de venta
JOIN MAE_BOLETA_VENTA b --unida a la tabla del encabezado de boleta de venta
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
WHERE (D.dbv_id_producto_servicio = @IdProd) --y filtro segun el id del producto ...
AND (b.mbv_fecha>=@FechasDesde AND b.mbv_fecha<=@FechasHasta) -- ...segun el rango de fechas ingresados...
AND b.mbv_nula = 0) --...y que la boleta no este anulada.
--asigno la cantidad de productos
set @CantidadProductoBOV = (SELECT SUM(DET_BOLETA_VENTA.dbv_cantidad) --suma la cantidad de productos vendidos segun lo que indica la linea de detalle
FROM DET_BOLETA_VENTA --detalle de boleta de venta
join MAE_BOLETA_VENTA --unido con el encabezado
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
WHERE (DET_BOLETA_VENTA.dbv_id_producto_servicio = @IdProd) --filtrado por el producto que me ingresaron a traves de formulario
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
AND mbv_nula = 0 ) --donde la boleta no hata sido anulada
if(@MontoBoletas is null)
begin
set @MontoBoletas = 0 --si el monto de boletas es nulo le asigno un 0
end
if(@CantidadProductoBOV is null)
begin
set @CantidadProductoBOV = 0 --y si la cantidad es nula asigno un 0
end
set @MontoTotalVentas = @MontoBoletas -- se asigna a @MontoTotalVentas todo lo que se vendio del producto entre
--boletas, facturas y notas de credito.. en este caso solo lo mostrare con boletas para q veas una consulta mas corta
set @CantidadProducto = @CantidadProductoBOV -- se asigna el total de productos vendidos (en este caso solo boletas por lo explicado anteriormente)
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
FROM MAE_PRODUCTO_SERVICIO -- de la tabla maestra de productos
WHERE mps_id_producto_servicio=@IdProd) --donde el id del producto sea igual al almacenado en la tabla temporal
INSERT #TempVentasProd --guarda los montos de venta segun el producto
SELECT
MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio, --pk de producto
MAE_PRODUCTO_SERVICIO.mps_descripcion, --nombre de producto
MAE_PRODUCTO_SERVICIO.mps_codigo_barra, --codigo de producto
isnull(@MontoBoletas,0) AS MontoBoletas, --monto vendido del producto en boletas (neto)
isnull(@MontoTotalVentas,0) AS MontoTotalVentas, --monto total vendido del producto (neto)
isnull(@CantidadProducto,0) as Cantidad, --cantidad de productos vendidos
isnull(@PrecioVenta,0) as PrecioVenta --precio unitario de venta de producto (bruto)
FROM MAE_PRODUCTO_SERVICIO
WHERE (MAE_PRODUCTO_SERVICIO.mps_id_producto_servicio = @IdProd) --filtra segun el id que se este filtrando entre los productos vendidos
set @Contador = @Contador + 1 --suma 1 al contador para poder avanzar una tupla en #TempIdProd
END
SELECT DISTINCT * --selecciona los distintos registros que se guardaron en la tabla y con eso genera el informe
FROM #TempVentasProd
DROP TABLE #TempIdProd --borra la tabla temporal
DROP TABLE #TempVentasProd --bora la tbla temporal que almacena el informe (quedo cargado en grilla del formulario)
END