V10 RecursosGuías
RecursosGuías
Guías
Años | List of Articles

¿Cómo obtener valores de inventario mediante instrucciones SQL?

Última modificación el 03/05/2024

Además de los avances tecnológicos, la versión 10 del ERP PRIMAVERA aporta algunos cambios estructurales importantes, como:

  • La separación de Logística y Tesorería en los distintos módulos;
  • Una reestructuración completa del módulo de Inventario;

En este artículo vamos a explorar, utilizando algunos ejemplos, cómo obtener valores de inventario utilizando instrucciones SQL para comprender mejor cómo están estructuradas las tablas.

Los valores a obtener se refieren a:

  • Stocks
  • Costing
  • Valoraciones
  • Variaciones

En primer lugar, conviene saber que cualquier movimiento que integre en el módulo Inventario debe, obligatoriamente, ser registrado en la tabla INV_Origens. En esta tabla se registrará toda la información necesaria sobre el origen de cada movimiento:

  • Módulo y documento que lo originó;
  • Valores originales en la moneda de contabilización;
  • Cantidades originales en la unidad de contabilización.

Ejemplo 1: Movimientos de stock

Los movimientos de stock se registran en la tabla INV_Movimentosy la correcta ordenación de los registros se realiza mediante los campos Data y NumRegisto. El campo Data indica cuándo se produce el movimiento, mientras que el campo NumRegisto es un campo secuencial de tipo Identity. También hay otro campo que almacena la fecha en la que se registra realmente el movimiento, el campo DataIntegracao.

Ejemplo de obtención de un extracto de stocks para el artículo "A0001" de una empresa DEMO:

/* Movimentos de stock (INV_Movimentos) */
SELECT		orig.Documento, m.Data, m.DataIntegracao, m.NumRegisto, m.Artigo, m.Armazem, m.Localizacao, m.Lote, m.EstadoStock, m.TipoMovimento, orig.Transferencia
	,	m.Id, m.IdOrigem, orig.IdChave1, orig.IdChave2, orig.IdChave3
	,	orig.AplicaValorizacao

	--	Quantidade movimentada (unidade base)
	,	Quantidade			= FORMAT(m.Quantidade, '0.00')

	--	Stock
	,	Stock_Anterior			= FORMAT(m.Stock_Anterior, '0.00')
	,	Stock_Actual			= FORMAT(m.Stock_Actual, '0.00')
	,	StockArm_Anterior		= FORMAT(m.StockArm_Anterior, '0.00')
	,	StockArm_Actual			= FORMAT(m.StockArm_Actual, '0.00')
	,	StockLoc_Anterior		= FORMAT(m.StockLoc_Anterior, '0.00')
	,	StockLoc_Actual			= FORMAT(m.StockLoc_Actual, '0.00')
	,	StockLot_Anterior		= FORMAT(m.StockLot_Anterior, '0.00')
	,	StockLot_Actual			= FORMAT(m.StockLot_Actual, '0.00')
	,	StockArmLot_Anterior		= FORMAT(m.StockArmLot_Anterior, '0.00')
	,	StockArmLot_Actual		= FORMAT(m.StockArmLot_Actual, '0.00')
	,	StockLocLot_Anterior		= FORMAT(m.StockLocLot_Anterior, '0.00')
	,	StockLocLot_Actual		= FORMAT(m.StockLocLot_Actual, '0.00')

	--	Existência
	,	Existencias_Anterior		= FORMAT(m.Existencias_Anterior, '0.00')
	,	Existencias_Actual		= FORMAT(m.Existencias_Actual, '0.00')
	,	ExistenciasArm_Anterior		= FORMAT(m.ExistenciasArm_Anterior, '0.00')
	,	ExistenciasArm_Actual		= FORMAT(m.ExistenciasArm_Actual, '0.00')
	,	ExistenciasLoc_Anterior		= FORMAT(m.ExistenciasLoc_Anterior, '0.00')
	,	ExistenciasLoc_Actual		= FORMAT(m.ExistenciasLoc_Actual, '0.00')
	,	ExistenciasGrpCst_Anterior	= FORMAT(m.ExistenciasGrpCst_Anterior, '0.00')
	,	ExistenciasGrpCst_Actual	= FORMAT(m.ExistenciasGrpCst_Actual, '0.00')
	,	ExistenciasLot_Anterior		= FORMAT(m.ExistenciasLot_Anterior, '0.00')
	,	ExistenciasLot_Actual		= FORMAT(m.ExistenciasLot_Actual, '0.00')
	,	ExistenciasArmLot_Anterior	= FORMAT(m.ExistenciasArmLot_Anterior, '0.00')
	,	ExistenciasArmLot_Actual	= FORMAT(m.ExistenciasArmLot_Actual, '0.00')
	,	ExistenciasLocLot_Anterior	= FORMAT(m.ExistenciasLocLot_Anterior, '0.00')
	,	ExistenciasLocLot_Actual	= FORMAT(m.ExistenciasLocLot_Actual, '0.00')
	,	ExistenciasGrpCstLot_Anterior	= FORMAT(m.ExistenciasGrpCstLot_Anterior, '0.00')
	,	ExistenciasGrpCstLot_Actual	= FORMAT(m.ExistenciasGrpCstLot_Actual, '0.00')
FROM		INV_Movimentos	m	WITH(NOLOCK)
INNER JOIN	INV_Origens	orig	WITH(NOLOCK)	ON m.IdOrigem = orig.Id
WHERE		m.Artigo	= 'A0001'
ORDER BY	m.Data, m.NumRegisto

Las cantidades de stock actuales pueden obtenerse ahora de la tabla INV_ValoresActuaisStock, como se muestra en este ejemplo:

/* Quantidades atuais de stock (INV_ValoresActuaisStock) */
SELECT		Artigo, Armazem, Localizacao, Lote, EstadoStock, DataStock

	--	Stock actual na localização (unidade base)
	,	Stock = FORMAT(Stock, '0.00')

	--	Identificador do último movimento que originou o stock atual
	,	IdMovimentoStock

	--	Identificador do registo
	,	Id

FROM		INV_ValoresActuaisStock WITH(NOLOCK)
WHERE		Artigo = 'A0001'
ORDER BY	Armazem, Localizacao, Lote

Ejemplo 2 - Movimientos de costing

Los movimientos de costing se registran en la tabla INV_Custeio y, como en el ejemplo anterior, la correcta ordenación de los registros se realiza por los campos Data y NumRegisto. El campo Data indica cuándo se produce el movimiento, el campo NumRegisto es un campo secuencial del tipo Identity. Existe también otro campo que almacena la fecha en la que se registra realmente el movimiento, el campo DataIntegracao.

Ejemplo de obtención de un extracto de costes para el artículo "A0001" de una empresa DEMO:

/* Movimentos de custeio (INV_Custeio) */
SELECT		TipoLancamento			= case m.TipoLancamentoCusteio when 1 then 'ENC' when 2 then 'DES' when 3 then 'VPT' else 'Normal' end
	,	orig.Documento, m.Data, m.DataIntegracao, m.NumRegisto, m.Artigo, m.GrupoCustos, m.Lote, m.TipoMovimento, orig.Transferencia, m.TransferenciaValor

	--	Quantidade movimentada
	,	Quantidade			= FORMAT(m.Quantidade, '0.00')
		
	--	Valores movimentados na moeda base
	,	ValorUnitarioMBase		= FORMAT(m.ValorUnitarioMBase, '0.00')
	,	ValorAdicionalMBase		= FORMAT(m.ValorAdicionalMBase, '0.00')
	,	ValorAbaterMBase		= FORMAT(m.ValorAbaterMBase, '0.00')
		
	--	Valores movimentados na moeda alternativa
	,	ValorUnitarioMAlt		= FORMAT(m.ValorUnitarioMAlt, '0.00')
	,	ValorAdicionalMAlt		= FORMAT(m.ValorAdicionalMAlt, '0.00')
	,	ValorAbaterMAlt			= FORMAT(m.ValorAbaterMAlt, '0.00')
		
	--	Valores de custeio na moeda base
	,	CustoGrpCstMBase_Anterior	= FORMAT(m.CustoGrpCstMBase_Anterior, '0.00')
	,	CustoGrpCstMBase_Actual		= FORMAT(m.CustoGrpCstMBase_Actual, '0.00')
	,	CustoGrpCstLotMBase_Anterior	= FORMAT(m.CustoGrpCstLotMBase_Anterior, '0.00')
	,	CustoGrpCstLotMBase_Actual	= FORMAT(m.CustoGrpCstLotMBase_Actual, '0.00')
		
	--	Valores de custeio na moeda alternativa
	,	CustoGrpCstMAlt_Anterior	= FORMAT(m.CustoGrpCstMAlt_Anterior, '0.00')
	,	CustoGrpCstMAlt_Actual		= FORMAT(m.CustoGrpCstMAlt_Actual, '0.00')
	,	CustoGrpCstLotMAlt_Anterior	= FORMAT(m.CustoGrpCstLotMAlt_Anterior, '0.00')
	,	CustoGrpCstLotMAlt_Actual	= FORMAT(m.CustoGrpCstLotMAlt_Actual, '0.00')
		
	--	Valores originais movimentados na moeda base
	,	ValorUnitarioOrigMBase		= FORMAT(m.ValorUnitarioOrigMBase, '0.00')
	,	ValorAdicionalOrigMBase		= FORMAT(m.ValorAdicionalOrigMBase, '0.00')
	,	ValorAbaterOrigMBase		= FORMAT(m.ValorAbaterOrigMBase, '0.00')
		
	--	Valores originais movimentados na moeda alteranativa
	,	ValorUnitarioOrigMAlt		= FORMAT(m.ValorUnitarioOrigMAlt, '0.00')
	,	ValorAdicionalOrigMAlt		= FORMAT(m.ValorAdicionalOrigMAlt, '0.00')
	,	ValorAbaterOrigMAlt		= FORMAT(m.ValorAbaterOrigMAlt, '0.00')
		
	--	Id's associados ao registo
	,	m.Id, m.IdMovimentoCusteioOrig, m.IdOrigem, m.IdMovimentoStock, m.IdValorizacao, orig.IdChave1, orig.IdChave2				
		
	--	Valores relacionados
	,	orig.AplicaValorizacao
	,	orig.ValorUnitario, orig.ValorAdicional, orig.ValorAbater
	,	orig.ActualizaPCU

FROM		INV_Custeio	m	WITH(NOLOCK)	
INNER JOIN	INV_Origens	orig	WITH(NOLOCK)	ON m.IdOrigem = orig.Id
WHERE		m.Artigo	= 'A0001'
ORDER BY	m.Data, m.NumRegisto

Los valores actuales del costing pueden obtenerse ahora de la tabla INV_ValoresActuaisCusteio, como se muestra en este ejemplo:

/* Valores atuais de custeio (INV_ValoresActuaisCusteio) */
SELECT		Artigo, GrupoCustos, Lote

	--	Valores de custeio na moeda base				
	,	CustoGrpCstMBase	= FORMAT(CustoGrpCstMBase, '0.00')						
	,	CustoGrpCstLotMBase	= FORMAT(CustoGrpCstLotMBase, '0.00')

	--	Valores de custeio na moeda alteranativa
	,	CustoGrpCstMAlt		= FORMAT(CustoGrpCstMAlt, '0.00')						
	,	CustoGrpCstLotMAlt	= FORMAT(CustoGrpCstLotMAlt, '0.00')

	--	Data do valor de custeio
	,	DataCusteio

FROM		INV_ValoresActuaisCusteio WITH(NOLOCK) 
WHERE		Artigo = 'A0001'
ORDER BY	DataCusteio

Ejemplo 3: Valoración de los movimientos de salida

A cualquier movimiento de salida de stock se aplica una valoración y se le asigna el valor de coste en la fecha de dicho movimiento (CMVMC). Esta valoración se aplica a cualquier movimiento de salida, a excepción del movimiento de salida de un traslado a una localización perteneciente al mismo grupo de costes.

El siguiente ejemplo muestra cómo obtener las valoraciones de todos los movimientos de salida para el artículo "A0001" en una empresa DEMO. Este ejemplo combina otras tablas, como INV_Movimentosque dará el movimiento de salida propiamente dicho, y INV_Custeioque relaciona la valoración con el movimiento de costing del que se extrae el coste.

/* Valorizações dos movimentos de saída (INV_Valorizacoes) */
SELECT		[/av_]		= orig.Documento, orig.Transferencia, v.Data, v.DataValor, v.Quantidade

	--	Valor de custo na moeda base
	,	CustoMBase	= FORMAT(v.CustoMBase, '0.00')

	--	Valor de custo na moeda alternativa
	,	CustoMAlt	= FORMAT(v.CustoMAlt, '0.00')

	--	Grupo de custos
	,	GrupoCustos	= c.GrupoCustos

	--	Documento valorizado
	,	[Doc. Valor]	= isnull(origc.Documento, '')

	--	Identificador do movimento de saída de stock a ser valorizado
	,	v.IdMovimentoStock

	--	Identificador do movimento de custeio a valorizar o movimento de saída
	,	v.IdMovimentoCusteio

	--	Outros identificadores
	,	v.IdCustoPadrao, v.IdOrigem, v.Id

FROM		INV_Valorizacoes	v	WITH(NOLOCK) 
INNER JOIN	INV_Origens		orig	WITH(NOLOCK)	ON v.IdOrigem = orig.Id
INNER JOIN	INV_Movimentos		m	WITH(NOLOCK)	ON v.IdMovimentoStock = m.id		
LEFT JOIN	INV_Custeio		c	WITH(NOLOCK)	ON v.IdMovimentoCusteio = c.Id
LEFT JOIN	INV_Origens		origc	WITH(NOLOCK)	ON c.IdOrigem = origc.id
WHERE		m.Artigo = 'A0001'
ORDER BY	v.Data, m.NumRegisto

Ejemplo 4: Variaciones del costing asociadas a las valoraciones

Las variaciones que se producen en el coste medio deben reflejarse en las valoraciones aplicadas a los documentos de salida. Estas valoraciones, una vez aplicadas, no se vuelven a modificar, solo se añaden las variaciones, tanto positivas como negativas.

Estas variaciones se registran en la tabla INV_Variacoes. El siguiente ejemplo muestra cómo obtener todas las variaciones aplicadas a los movimientos de salida del artículo "A0001".

/* Variações de custeio associadas às valorizações (INV_Variacoes) */ SELECT -- Documento, data e grupo de custos de referência
		[/av_Ref.]				= origref.Documento, r.DataRef, GrupoCustosRef = cstref.GrupoCustos
		
	--	Documento, data e grupo de custos da variação
	,	[Doc.Var.] = origvar.Documento, r.DataVariacao
		
	--	Documento, data e grupo de custos da valorização
	,	[Doc.Val.] = origval.Documento, DataValorizacao = val.Data, GrupoCustosVal = cstvar.GrupoCustos

	--	Valor da variação na moeda base
	,	ValorMBase = FORMAT(r.ValorMBase, '0.00')
		
	--	Valor da variação na moeda alternativa
	,	ValorMAlt = FORMAT(r.ValorMAlt, '0.00')
		
	--	Identificador do movimento de custeio de referência (ex: VFA)
	,	r.IdCusteioRef
		
	--	Identificador do movimento de custeio que provoca a variação (ex: VPT/ENC/DES)
	,	r.IdCusteioVariacao
		
	--	Identificador da valorização
	,	r.IdValorizacao
	,	r.Id

FROM		INV_Variacoes		r	WITH(NOLOCK) 
INNER JOIN	INV_Custeio		cstref	WITH(NOLOCK)	ON r.IdCusteioRef = cstref.Id
INNER JOIN	INV_Origens		origref	WITH(NOLOCK)	ON cstref.IdOrigem = origref.Id
INNER JOIN	INV_Custeio		cstvar	WITH(NOLOCK)	ON r.IdCusteioVariacao = cstvar.Id
INNER JOIN	INV_Origens		origvar	WITH(NOLOCK)	ON cstvar.IdOrigem = origvar.Id
LEFT JOIN	INV_Valorizacoes	val	WITH(NOLOCK)	ON r.IdValorizacao = val.Id
LEFT JOIN	INV_Movimentos		movval	WITH(NOLOCK)	ON val.IdMovimentoStock = movval.Id
INNER JOIN	INV_Origens		origval	WITH(NOLOCK)	ON val.IdOrigem = origval.Id
WHERE		cstref.Artigo = 'A0001'
ORDER BY	r.DataVariacao, val.Data
Bookmark or share this article
Esta página foi útil?
Obrigado pelo seu voto.

login para deixar a sua opinião.

Obrigado pelo seu feedback. Iremos analisá-lo para continuarmos a melhorar!