Relatório de Saldos e Movimentação
-
Introdução
O objetivo desse manual é documentar tudo o que envolve o processo do cálculo mas de uma forma mais técnica, para facilitar os testes do suporte ou futuras correções de bugs pelo desenvolvimento.
A forma como é calculado os Saldos e Movimentações dos produtos foi alterada. Anteriormente o relatório calculava toda a movimentação no momento da impressão, o que gerava lentidão quando o cliente possuía uma base de dados muito grande.
A partir de agora os saldos serão calculados diariamente, evitando que o relatório tenha uma gama de dados grande para processar.
Onde ficam armazenados os saldos?
Os saldos e movimentações serão armazenados na tabela
SaldosEstoqueque contém num único registro todas as movimentações do produto no dia, como: saldo anterior, entradas, saídas, ajustes e vendas.Por exemplo:
SELECT * FROM SaldosEstoqueResultado:
idSaldosEstoque salEmpresa salProduto salDataMovimento salSaldoAnterior 38705 1 1059 27/12/2016 0,00 salEntradas salSaidas salAjusteMais salAjusteMenos salVendas 300,00 0,00 0,00 0,00 0,00A rotina que calcula os saldos e armazena na tabela
SaldosEstoqueé a spdbo.spc_mov_processa_saldos_estoque.sql.Quem executa a rotina de cálculo?
Quem executa a sp é o AutomatizeGO, através do plugin
SaldoEstoque.dll.O processamento é feito a cada 1 hora e filtrará somente movimentos que foram alterados a mais de meia hora, isso para evitar rodar a rotina com o cliente ainda digitando um movimento.
O resultado da execução do AutomatizeGO pode ser verificada no log do mesmo em:
C:\Arquivos de Programas\Automatize\log\AutomatizeGO\.Exemplo:
Caso o processamento ocorra com sucesso:
28/11 14:39:13,807 [30] INFO AutomatizeGo.ServiceGo - Info plugin AutomatizeGo.Plugins.SaldoEstoque, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: EXEC SALDO ESTOQUEAbaixo um exemplo caso ocorra um problema:
28/11 14:04:26,034 [6] INFO AutomatizeGo.ServiceGo - Info plugin AutomatizeGo.Plugins.SaldoEstoque, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: NÃO ENCONTRADO TABELA E SP DE PROCESSAMENTO DO SALDONote que o erro foi
"NÃO ENCONTRADO TABELA E...". Para esse erro ocorrer, uma das seguintes situações deve ter ocorrido:- A tabela
SaldosEstoquenão existir no banco; - A sp
dbo.spc_mov_processa_saldos_estoque.sqlnão exista; - O campo
MovimentoProdutoItem.mpiSaldoProcessadonão exista (abaixo esse campo é explicado); - O campo
MovimentoProdutoItemComposicao.mpcSaldoProcessadonão exista (abaixo esse campo é explicado).
Na primeira execução, caso a tabela
SaldosEstoqueesteja vazia, a sp irá recalcular toda a movimentação de todos os produtos e armazenar nela. Sendo assim, para fins de teste, caso haja a necessidade de se recalcular tudo novamente, basta apagar a tabela da seguinte forma:truncate table SaldosEstoqueO procedimento pode demorar um pouco (em alguns testes com bases grandes, menos de 3 minutos) dependendo da quantidade de movimentos do cliente, então é necessário verificar o log do AutomatizeGO se a mensagem
"EXEC SALDO ESTOQUE"foi apresentada ou algum outro erro.Em que momento serão calculados os saldos dos produtos?
O saldo é calculado nas seguintes situações:
- logo na primeira execução do plugin do AutomatizeGO ao ver que a tabela
SaldosEstoqueestá vazia - Ao alterar a situação do movimento
- Ao excluir um movimento
- Ao incluir um produto no movimento
- Ao alterar a quantidade de um produto dentro de um movimento
- Ao excluir um produto do movimento
Para permitir esses monitoramentos foram criados os seguintes gatilhos (triggers):
- dbo.tu_MovimentoProduto.sql
- é disparado quando houver alteração na situação do movimento.
- um registro será criado na tabela temporária
TmpSaldosEstoquepara que o AutomatizeGO processe essa alteração.
- um registro será criado na tabela temporária
- é disparado quando houver alteração na situação do movimento.
- dbo.td_MovimentoProduto.sql
- é disparado quando houver exclusão do movimento
- da mesma foram um registro será criado na tabela temporária
TmpSaldosEstoquepara que o AutomatizeGO processe essa exclusão.
- da mesma foram um registro será criado na tabela temporária
- é disparado quando houver exclusão do movimento
- dbo.tu_MovimentoProdutoItem.sq
- é disparado ao alterar a quantidade de um produto dentro do movimento.
- os campos
MovimentoProdutoItem.mpiSaldoProcessadoeMovimentoProdutoItemComposicao.mpcSaldoProcessadoserão setados para 0 (zero), para que o AutomatizeGO processe a alteração
- os campos
- é disparado ao alterar a quantidade de um produto dentro do movimento.
- dbo.td_MovimentoProdutoItem.sql
- é disparado excluir um produto do movimento.
- um registro será criado na tabela temporária
TmpSaldosEstoquepara cada produto e cada composição, para que o AutomatizeGO processe essa alteração.
- um registro será criado na tabela temporária
- é disparado excluir um produto do movimento.
Cliente possui centralização, como funciona?
A rotina de cálculo irá rodar nas filiais e, na central caso essa esteja indicada no campo
Node.NodeDest(abaixo).Após rodar a sp na filial os registros da tabela
SaldosEstoquesão enviados para a central para permitir visualizar nela o relatório de Saldos e Movimentação da filial.Nunca os dados serão enviados da central para as filiais ou de uma filial para outra.
Não é possível visualizar o relatório de uma filial estando na outra. Por exemplo, a filial 1 não conseguirá ver da 2 e vice-versa. Na central será possível ver das duas filiais.
Bom, se a rotina sempre vai rodar nas filiais, então em que situação ela rodará também na central?
Para isso teremos que verificar a tabela
Nodena central.Exemplo de central que irá rodar:
select * from nodeResultado:
KEY = corp nodeDest = 4Exemplo de central que não irá rodar:
select * from nodeResultado:
KEY = corp nodeDest = NULLPosso testar o cálculo sem que seja pelo AutomatizeGO?
Sim, como o AutomatizeGO irá rodar o cálculo dos saldos a cada 1 hora, talvez seja conveniente utilizar o script abaixo.
Não esqueça de trocar a filial no início do script, caso necessário:
SET NOCOUNT ON DECLARE @idEmpresa int set @idempresa = 1 -- << TROQUE A FILIAL AQUI >> -- se não tem registro na tabela então ja recalcula tudo pela primeira vez if NOT exists(select top 1 1 from SaldosEstoque) BEGIN print 'Primeiro recalculo' exec spc_mov_processa_saldos_estoque @idempresa=@idEmpresa, @dataInicial='01/01/2000' UPDATE MovimentoProdutoItem SET mpiSaldoProcessado = 1 UPDATE MovimentoProdutoItemComposicao SET mpcSaldoProcessado = 1 RETURN END -- exclui os temporarios processados delete from TmpSaldosEstoque where saeProcessado = 1 -- PROCURA pelos registros não processados do movimento para executar a spc_mov_processa_saldos_estoque DECLARE @curEmpresa int, @curProduto int, @curDt smalldatetime , @curIdMpi int, @curIdMpc int, @curProcessado bit, @curidTmpSaldos int , @msgerro varchar(2000) DECLARE @TBPROC TABLE ( idEmpresa int, prod int, dt datetime, idMpi int, idMpc int, sysInc datetime, processado bit, idTmpSaldos int ) INSERT INTO @TBPROC (idEmpresa, prod, dt, idMpi, idMpc, sysInc, processado, idTmpSaldos) SELECT DISTINCT idEmpresa = mvpEmpresa , prod = MPI.mpiProduto , Dt = CAST(FLOOR(CAST(MVP.mvpData AS FLOAT)) AS DATETIME) --retira a hora da data , IDMPI = idMovimentoProdutoItem , null , isnull(mpi.sysRegistro, mpi.sysInc) , 0 , null FROM MovimentoProdutoItem MPI INNER JOIN MovimentoProduto MVP ON MVP.idMovimentoProduto = MPI.mpiMovimentoProduto where MVP.mvpEmpresa = @idEmpresa and isnull(MPI.mpiSaldoProcessado,0) = 0 and (IsNull(MVP.mvpSituacao, 0) in (0,9)) UNION ALL -- composição SELECT DISTINCT idEmpresa = mvpEmpresa , MPC.mpcProduto , Dt = CAST(FLOOR(CAST(MVP.mvpData AS FLOAT)) AS DATETIME) , null , idMovimentoProdutoItemComposicao , isnull(mpi.sysRegistro, mpi.sysInc) , 0 , null FROM MovimentoProdutoItemComposicao MPC INNER JOIN MovimentoProdutoItem MPI ON MPI.idMovimentoProdutoItem = MPC.mpcMovimentoProdutoItem INNER JOIN MovimentoProduto MVP ON MVP.idMovimentoProduto = MPI.mpiMovimentoProduto where MVP.mvpEmpresa = @idEmpresa and isnull(MPC.mpcSaldoProcessado,0) = 0 and (IsNull(MVP.mvpSituacao, 0) in (0,9)) UNION ALL SELECT DISTINCT saeEmpresa , saeProduto , CAST(FLOOR(CAST(saeData AS FLOAT)) AS DATETIME) , null , null , sysInc , 0 , idTmpSaldosEstoque FROM TmpSaldosEstoque WHERE saeProcessado = 0 and saeEmpresa = @idEmpresa ORDER BY idEmpresa, prod, dt select * from @TBPROC -- DEFINE UM CURSOR DINAMICO PORQUE VOU ALTERAR OS DADOS DA COLUNA -- PROCESSADO E QUERO QUE REFLITA NOS PROCESSAMENTOS SEGUINTES DECLARE curMov CURSOR LOCAL DYNAMIC FOR SELECT idEmpresa , prod , dt , processado FROM @TBPROC --WHERE (sysInc is null or sysInc < dateadd(minute, -30, current_timestamp)) -- pega somente o que foi modificado a mais de 30min -- -- ABRE O CURSOR E PERCORRE OS MOVIMENTOS -- OPEN curMov FETCH NEXT FROM curMov INTO @curEmpresa, @curProduto, @curDt, @curProcessado WHILE @@FETCH_STATUS = 0 BEGIN --print 'Processa?: ' + cast( @curProduto as varchar) + ' | ' + convert(varchar(12), @curDt, 103) + ' > ' + CAST(@curProcessado as varchar) if @curProcessado = 0 begin --print 'Calculando...' begin try exec dbo.spc_mov_processa_saldos_estoque @idEmpresa = @curEmpresa , @DataInicial = @curDt , @DataFinal = null , @idProduto = @curProduto end try begin catch SET @MSGErro = 'Erro processando salods: ' + ERROR_MESSAGE()+' /L:' + cast(error_line() as varchar) RAISERROR(@MSGErro, 16, 1) GOTO SAIR end catch -- a spc_mov_processa_saldos_estoque processa todos os movimentos -- do produto a partir de uma data, então se existe mais algum -- registro do produto com uma data superior a @curDt, vou marcar como processado UPDATE MovimentoProdutoItem SET mpiSaldoProcessado = 1 WHERE IDMovimentoProdutoItem IN ( SELECT idMpi FROM @TBProc WHERE idEmpresa = @curEmpresa and prod = @curProduto and dt >= @curDt ) --composição UPDATE MovimentoProdutoItemComposicao SET mpcSaldoProcessado = 1 WHERE idMovimentoProdutoItemComposicao IN ( SELECT idMpc FROM @TBProc WHERE idEmpresa = @curEmpresa and prod = @curProduto and dt >= @curDt ) -- temporaria com os excluidos UPDATE TmpSaldosEstoque SET saeProcessado = 1 WHERE idTmpSaldosEstoque IN ( SELECT idTmpSaldos FROM @TBProc WHERE idEmpresa = @curEmpresa and prod = @curProduto and dt >= @curDt ) UPDATE @TBPROC SET processado = 1 WHERE idEmpresa = @curEmpresa and prod = @curProduto and dt >= @curDt end FETCH NEXT FROM curMov INTO @curEmpresa, @curProduto, @curDt, @curProcessado END SAIR: CLOSE curMov DEALLOCATE curMovConsiderações finais
Qual versão do AutomatizeGO que possui o plugin
SaldoEstoque.dll?A partir da 5.0.6.
Migrado da wiki (
saldos_e_movimentacoes). Última edição em 01/12/2017; autores: cassol. - A tabela
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Cadastrar Login