Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Rafael Antonio X

trigger de inventário Oracle 10g XE.

Recommended Posts

Olá pessoal do imasters, é meu primeiro tópico aqui no forum.

 

Tenho a seguinte dúvida e gostaria de alguma solução, pois estou travado na parte do INVENTÁRIO

Tenho a lógica para a criação da trigger mas não consigo implementar.

 

 

A lógica da trigger inventário:

Segue a lógica que preciso transformar na trigger: (as linhas em vermelho é a lógica de buscar o saldo do mês anterior para compor o saldo inicial do mes que está sendo criado a partir da movimentação):

- Para cada movimentação de produto:
   - Buscar o saldo referente ao produto da movimentação e ano/mes igual a data da movimentação
   - Se não existir o saldo então
       - Cria o registro na tabela de saldo

- Busca o saldo referente ao mes/ano anterior ao mes/ano da movimentação

- Se exitir o saldo refente ao mes/ano anterior entao

- T_SALDO = T_SALDO_INICIAL + ENTRADAS - SAIDAS

- Senao

- T_SALDO = 0

- Saldo inicial do mes/ano igual a data de movimentação = T_SALDO

 

    - Se a movimentação for de entrada entao
           - SALDOS.ENTRADAS = SALDOS.ENTRADAS + MOVIMENTACAO.QUANTIDADE
       - Senao
           - SALDOS.SAIDAS = SALDOS.SAIDAS + MOVIMENTACAO.QUANTIDADE.
   - Senao
       - Se a movimentação for de entrada entao
           - SALDOS.ENTRADAS = SALDOS.ENTRADAS + MOVIMENTACAO.QUANTIDADE
       - Senao
           - SALDOS.SAIDAS = SALDOS.SAIDAS + MOVIMENTACAO.QUANTIDADE.
FimPara

 

 

Tenho as seguintes tabelas no banco:

 

Tabela Motivo

CREATE  TABLE Motivo(
id_motivo INT NOT NULL ,
descricao VARCHAR(40) NOT NULL,
tipo_motivo CHAR(1),
PRIMARY KEY (id_motivo));

Tabela Movimento

CREATE  TABLE Movimento(
id_movimento INT NOT NULL,
data_movimento DATE NOT NULL,
nota DECIMAL(9,2),
valor DECIMAL(9,2) NULL,
fornecedor INT,
cliente INT,
desconto DECIMAL(9,2),
situacao CHAR(1),
tipo CHAR(1),
endereco_estoque INT,
outrosvalores DECIMAL(9,2),
PRIMARY KEY (id_movimento),
FOREIGN KEY (fornecedor )
REFERENCES Fornecedor (id_fornecedor ),
FOREIGN KEY (motivo)
REFERENCES Motivo (id_motivo),
motivo INT NULL, 
FOREIGN KEY (cliente )
REFERENCES Cliente (id_cliente ),
FOREIGN KEY (endereco_estoque )
REFERENCES Endereco_estoque (id_endereco_estoque ));

 

Tabela ItemMovimento

CREATE  TABLE ItemMovimento (
id_itemmovimento INT NOT NULL ,
endereco_estoque INT,
movimento INT NOT NULL ,
produto INT NOT NULL, 
qtde INT NOT NULL, 
preco INT NOT NULL,
PRIMARY KEY (id_itemmovimento),
FOREIGN KEY (produto)
REFERENCES  Produto (id_produto),
FOREIGN KEY(movimento)
REFERENCES  Movimento (id_movimento));

 

Tabela Saldo

CREATE  TABLE Saldo(
id_saldo INT NOT NULL,
entradas INT,
saidas INT,
produto INT,
ano INT,
mes INT,
estoque INT,
endereco_estoque INT ,
PRIMARY KEY (id_saldo),
FOREIGN KEY (produto )
REFERENCES Produto (id_produto ),
FOREIGN KEY (endereco_estoque )
REFERENCES Endereco_estoque (id_endereco_estoque ));

 

Tabela Inventario

CREATE  TABLE Inventario (
id_inventario INT NOT NULL ,
data DATE NULL ,
obs VARCHAR(50),
produto INT ,
PRIMARY KEY (id_inventario) ,
FOREIGN KEY (produto )
REFERENCES Produto (id_produto ));

 

A trigger atualiza saldo:

Trigger está funcionando e foi implementada pelo meu amigo: David Pagliotto.

CREATE OR REPLACE TRIGGER ALTERA_ESTOQUE
AFTER INSERT OR UPDATE OR DELETE ON ITEMMOVIMENTO FOR EACH ROW
DECLARE
CURSOR C_TIPO_MOVIMENTO(P_ID_MOVIMENTO INTEGER) IS
 SELECT TIPO_MOTIVO
   FROM MOVIMENTO M,
	 MOTIVO MT
  WHERE M.MOTIVO = MT.ID_MOTIVO
    AND M.ID_MOVIMENTO = P_ID_MOVIMENTO;

 V_TIPO_MOVIMENTO   C_TIPO_MOVIMENTO%ROWTYPE;
BEGIN
IF (DELETING) THEN
	OPEN C_TIPO_MOVIMENTO(:OLD.MOVIMENTO);
   FETCH C_TIPO_MOVIMENTO INTO V_TIPO_MOVIMENTO;
   CLOSE C_TIPO_MOVIMENTO;
ELSE
	OPEN C_TIPO_MOVIMENTO(:NEW.MOVIMENTO);
   FETCH C_TIPO_MOVIMENTO INTO V_TIPO_MOVIMENTO;
   CLOSE C_TIPO_MOVIMENTO;
END IF;

IF (INSERTING) THEN
	IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN
		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) - :NEW.QTDE
		 WHERE PRODUTO = :NEW.PRODUTO;
	ELSE
		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE
		 WHERE PRODUTO = :NEW.PRODUTO;
	END IF;
ELSIF (DELETING) THEN
	IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN
		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) + :OLD.QTDE
		 WHERE PRODUTO = :OLD.PRODUTO;
	ELSE
		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) - :OLD.QTDE
		 WHERE PRODUTO = :OLD.PRODUTO;
	END IF;
ELSE
	IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN
		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) + :OLD.QTDE
		 WHERE PRODUTO = :NEW.PRODUTO;

		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) - :NEW.QTDE
		 WHERE PRODUTO = :NEW.PRODUTO;
	ELSE
		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) - :OLD.QTDE
		 WHERE PRODUTO = :NEW.PRODUTO;

		UPDATE SALDO 
		   SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE
		 WHERE PRODUTO = :NEW.PRODUTO;
	END IF;
END IF;
END;

 

Alguem se dispõe em me ajudar?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não endenti, a trigger publicada não funciona, a lógica dela não faz o que se pede ?

 

Qual o problema ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá. a trigger SALDO está funcionando na atualização da tabela saldo.

 

O unico problema é de não conseguir acrescentar a lógica do inventário a ela.

Gostaria de saber como criar uma unica trigger que use a trigger saldo com a lógica da trigger inventário. Unindo assim INVENTÁRIO COM SALDO.

 

Caso não seja possivel poderia tranformar a lógica da trigger inventário em código Trigger para oracle.

Compartilhar este post


Link para o post
Compartilhar em outros sites

A questão é montar as consultas com base na definição usando o plsql

 

- Para cada movimentação de produto:

 

A própria definição da trigger (for each row before insert or update in <tabela>

 

- Buscar o saldo referente ao produto da movimentação e ano/mes igual a data da movimentação

- Se não existir o saldo então

 

select entradas,saidas
into v_entradas,v_saidas
from saldo
where ...

 

if v_saidas is null then
 ...

 

 

 

No mais é realmente tentar montar a trigger.

Compartilhar este post


Link para o post
Compartilhar em outros sites

A questão é montar as consultas com base na definição usando o plsql

 

 

 

A própria definição da trigger (for each row before insert or update in <tabela>

 

 

 

select entradas,saidas
into v_entradas,v_saidas
from saldo
where ...

 

if v_saidas is null then
 ...

 

 

 

No mais é realmente tentar montar a trigger.

 

Como seria?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ficou assim mas está com erro por que toda hora cria uma nova id eu gostaria de criar id só quando dar entrada no proximo mês

 

CREATE OR REPLACE TRIGGER ALTERA_ESTOQUE

AFTER INSERT OR UPDATE OR DELETE ON ITEMMOVIMENTO FOR EACH ROW

DECLARE

CURSOR C_TIPO_MOVIMENTO(P_ID_MOVIMENTO INTEGER) IS

SELECT TIPO_MOTIVO

FROM MOVIMENTO M,

MOTIVO MT

WHERE M.MOTIVO = MT.ID_MOTIVO

AND M.ID_MOVIMENTO = P_ID_MOVIMENTO;

 

V_TIPO_MOVIMENTO C_TIPO_MOVIMENTO%ROWTYPE;

V_MES_SALDO INTEGER;

V_QTD INTEGER;

BEGIN

SELECT MAX(MES) INTO V_MES_SALDO

FROM SALDO

WHERE ANO = TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY'))

AND PRODUTO = :NEW.PRODUTO;

 

IF TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) <= V_MES_SALDO THEN

 

IF (DELETING) THEN

OPEN C_TIPO_MOVIMENTO(:OLD.MOVIMENTO);

FETCH C_TIPO_MOVIMENTO INTO V_TIPO_MOVIMENTO;

CLOSE C_TIPO_MOVIMENTO;

ELSE

OPEN C_TIPO_MOVIMENTO(:NEW.MOVIMENTO);

FETCH C_TIPO_MOVIMENTO INTO V_TIPO_MOVIMENTO;

CLOSE C_TIPO_MOVIMENTO;

END IF;

 

IF (INSERTING) THEN

IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) - :NEW.QTDE

WHERE PRODUTO = :NEW.PRODUTO;

ELSE

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE

WHERE PRODUTO = :NEW.PRODUTO;

END IF;

ELSIF (DELETING) THEN

IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) + :OLD.QTDE

WHERE PRODUTO = :OLD.PRODUTO;

ELSE

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) - :OLD.QTDE

WHERE PRODUTO = :OLD.PRODUTO;

END IF;

ELSE

IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) + :OLD.QTDE

WHERE PRODUTO = :NEW.PRODUTO;

 

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) - :NEW.QTDE

WHERE PRODUTO = :NEW.PRODUTO;

ELSE

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) - :OLD.QTDE

WHERE PRODUTO = :NEW.PRODUTO;

 

UPDATE SALDO

SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE

WHERE PRODUTO = :NEW.PRODUTO

AND MES = TO_NUMBER(TO_CHAR(SYSDATE, 'MM'))

AND ANO = TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY'));

IF SQL%ROWCOUNT = 0 THEN -- NÃO ACHOU NADA

INSERT

INTO SALDO(ID_SALDO,

PRODUTO,

MES,

ANO,

ESTOQUE,

ENDERECO_ESTOQUE)

VALUES (SQ_SALDO.NEXTVAL,

:NEW.PRODUTO,

TO_NUMBER(TO_CHAR(SYSDATE, 'MM')),

TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')),

V_QTD,

:NEW.ENDERECO_ESTOQUE);

END IF;

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uma forma de fazer algo assim

 

BEGIN
...
UPDATE SALDO 
SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE
WHERE PRODUTO = :NEW.PRODUTO
AND MES = TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) 
AND ANO = TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY'));
IF SQL%ROWCOUNT = 0 THEN -- NÃO ACHOU NADA
 INSERT 
 INTO SALDO(ID_SALDO, 
            PRODUTO, 
            MES, 
            ANO, 
            ESTOQUE, 
            NDERECO_ESTOQUE)
 VALUES (SQ_SALDO.NEXTVAL, 
         :NEW.PRODUTO, 
         TO_NUMBER(TO_CHAR(SYSDATE, 'MM')), 
         TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')),
         V_QTD,
         :NEW.ENDERECO_ESTOQUE);
END IF;
...
END;

 

Ou seja tenta atualizar e se não conseguir insere;

 

SQL%ROWCOUNT retorna o número de linhas afetadas pelo update.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ficou assim, etá criando nova id sem gravar a quantidade no saldo.

Acho q seria melhor se eu separar por mês...

Assim: se for o mês atual 11 continua gravando na mesma id gerada no mês 11 IF TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) >= V_MES_SALDO THEN

 

se nao

se for mes 12 IF TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) <= V_MES_SALDO THEN

cria-se uma nova id.

 

CREATE OR REPLACE TRIGGER ALTERA_ESTOQUE
AFTER INSERT OR UPDATE OR DELETE ON ITEMMOVIMENTO FOR EACH ROW
DECLARE
CURSOR C_TIPO_MOVIMENTO(P_ID_MOVIMENTO INTEGER) IS
 SELECT TIPO_MOTIVO
   FROM MOVIMENTO M,
	 MOTIVO MT
  WHERE M.MOTIVO = MT.ID_MOTIVO
    AND M.ID_MOVIMENTO = P_ID_MOVIMENTO;

 V_TIPO_MOVIMENTO   C_TIPO_MOVIMENTO%ROWTYPE;
 V_MES_SALDO 		 INTEGER;
 V_QTD				 INTEGER;
BEGIN
 SELECT MAX(MES) INTO V_MES_SALDO
   FROM SALDO
  WHERE ANO = TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY'))
    AND PRODUTO = :NEW.PRODUTO;

  IF TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) <= V_MES_SALDO THEN

	IF (DELETING) THEN
		OPEN C_TIPO_MOVIMENTO(:OLD.MOVIMENTO);
	   FETCH C_TIPO_MOVIMENTO INTO V_TIPO_MOVIMENTO;
	   CLOSE C_TIPO_MOVIMENTO;
	ELSE
		OPEN C_TIPO_MOVIMENTO(:NEW.MOVIMENTO);
	   FETCH C_TIPO_MOVIMENTO INTO V_TIPO_MOVIMENTO;
	   CLOSE C_TIPO_MOVIMENTO;
	END IF;

	IF (INSERTING) THEN
		IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN
			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) - :NEW.QTDE
			 WHERE PRODUTO = :NEW.PRODUTO;
		ELSE
			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE
			 WHERE PRODUTO = :NEW.PRODUTO;
		END IF;
	ELSIF (DELETING) THEN
		IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN
			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) + :OLD.QTDE
			 WHERE PRODUTO = :OLD.PRODUTO;
		ELSE
			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) - :OLD.QTDE
			 WHERE PRODUTO = :OLD.PRODUTO;
		END IF;
	ELSE
		IF UPPER(V_TIPO_MOVIMENTO.TIPO_MOTIVO) = 'S' THEN
			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) + :OLD.QTDE
			 WHERE PRODUTO = :NEW.PRODUTO;

			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) - :NEW.QTDE
			 WHERE PRODUTO = :NEW.PRODUTO;
		ELSE
			UPDATE SALDO 
			   SET ESTOQUE = NVL(ESTOQUE, 0) - :OLD.QTDE
			 WHERE PRODUTO = :NEW.PRODUTO;

			UPDATE SALDO 
SET ESTOQUE = NVL(ESTOQUE, 0) + :NEW.QTDE
WHERE PRODUTO = :NEW.PRODUTO
AND MES = TO_NUMBER(TO_CHAR(SYSDATE, 'MM')) 
AND ANO = TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY'));
IF SQL%ROWCOUNT = 0 THEN -- NÃO ACHOU NADA
 INSERT 
 INTO SALDO(ID_SALDO, 
            PRODUTO, 
            MES, 
            ANO, 
            ESTOQUE, 
            NDERECO_ESTOQUE)
 VALUES (SQ_SALDO.NEXTVAL, 
         :NEW.PRODUTO, 
         TO_NUMBER(TO_CHAR(SYSDATE, 'MM')), 
         TO_NUMBER(TO_CHAR(SYSDATE, 'YYYY')),
         V_QTD,
         :NEW.ENDERECO_ESTOQUE);
END IF;

END;

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.