V10 RecursosGuias
RecursosGuias
Guias
Voltar | Lista de artigos

Como obter valores de inventário através de instruções SQL?

Última alteração a 29/09/2021

Além dos avanços tecnológicos , a versão 10 do ERP PRIMAVERA traz algumas mudanças estruturais importantes, tais como:

  • A separação da Logística e Tesouraria nos diferentes módulos;
  • Uma completa reestruturação do módulo de Inventário;

Neste artigo vamos explorar, através de alguns exemplos, como obter valores de inventário recorrendo a instruções de SQL de forma a perceber melhor como estão estruturadas as tabelas.

Os valores a obter referem-se a:

  • Stocks
  • Custeio
  • Valorizações
  • Variações

Antes de mais, convém saber que todo e qualquer movimento que integre no módulo de Inventário tem, obrigatoriamente, que ser registado na tabela INV_Origens. Nesta tabela ficará registada toda a informação necessária referente à origem de cada movimento:

  • Módulo e documento que lhe deu origem;
  • Valores originais na moeda de lançamento;
  • Quantidades originais na unidade de lançamento.

Exemplo 1: Movimentos de stock

Os movimentos de stock ficam registados na tabela INV_Movimentos, sendo que a correta ordenação dos registos faz-se pelos campos Data e NumRegisto. O campo Data indica quando ocorre o movimento, enquanto que o campo NumRegisto é um campo sequencial do tipo Identity. Existe ainda outro campo que guarda a data em que efetivamente o movimento é registado, o campo DataIntegracao.

Exemplo da obtenção de um extrato de stocks para o artigo "A0001" de uma 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

As quantidades atuais de stock podem ser agora obtidas a partir da tabela INV_ValoresActuaisStock, como mostrado neste exemplo:

/* 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

Exemplo 2 - Movimentos de custeio

Os movimentos de custeio ficam registados na tabela INV_Custeio e, tal como no exemplo anterior, a correta ordenação dos registos faz-se pelos campos Data e NumRegisto. O campo Data indica quando ocorre o movimento, o campo NumRegisto é um campo sequencial do tipo Identity. Existe ainda outro campo que guarda a data em que efetivamente o movimento é registado, o campo DataIntegracao.

Exemplo da obtenção de um extrato de custos para o artigo "A0001" de uma 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

Os valores atuais de custeio podem ser agora obtidos a partir da tabela INV_ValoresActuaisCusteio, como mostrado neste exemplo:

/* 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

Exemplo 3: Valorização dos movimentos de saída

A qualquer movimento de saída de stock é aplicado uma valorização, sendo-lhe atribuído o valor de custo à data desse mesmo movimento (CMVMC). Esta valorização é aplicada a qualquer movimento de saída excetuando o movimento de saída de uma transferência para uma localização pertencente ao mesmo grupo de custos.

O seguinte exemplo mostra a obtenção das valorizações para todos os movimentos de saída do artigo "A0001" numa empresa DEMO. Este exemplo junta outras tabelas, tais como a INV_Movimentos, que irá dar o próprio movimento de saída e a INV_Custeio, que relaciona a valorização com o movimento de custeio do qual é extraído o custo.

/* Valorizações dos movimentos de saída (INV_Valorizacoes) */
SELECT		[Doc.]		= 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

Exemplo 4: Variações de custeio associadas às valorizações

As variações que ocorrem no custo médio têm de ser refletidas nas valorizações aplicadas aos documentos de saída. Estas valorizações, uma vez aplicadas, não voltam a ser alteradas, apenas são acrescentadas as variações, tanto positivas como negativas.

Estas variações ficam registadas na tabela INV_Variacoes. O exemplo seguinte mostra como obter todas as variações aplicadas aos movimentos de saída do artigo "A0001".

/* Variações de custeio associadas às valorizações (INV_Variacoes) */
SELECT	--	Documento, data e grupo de custos de referência
		[Doc.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
Adicionar aos favoritos ou partilhar este artigo
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!
Artigos Relacionados
Começar a Usar Como criar um projeto de integração com Visual Studio? Como criar um projeto de extensibilidade de interface (PEX) com Visual Studio? Como criar um projeto de extensibilidade de API (Motor) com Visual Studio? Como criar separadores do utilizador com Visual Studio?