SET TERM ^ ;

CREATE OR ALTER PROCEDURE SP_MOVIMENTA_ESTOQUE (
    P_CODGRUPO VARCHAR(16),
    P_CODPRODUTO VARCHAR(30),
    P_QUANTIDADE FLOAT,
    P_TIPO CHAR(1), -- E=Entrada, S=Saída
    P_NUMEROVENDA INTEGER DEFAULT NULL,
    P_VALORUNITITEM FLOAT DEFAULT NULL,
    P_VALORTOTALITEM FLOAT DEFAULT NULL,
    P_OBSERVACAO VARCHAR(54) DEFAULT NULL
)
RETURNS (
    MSGRETORNO VARCHAR(255)
)
AS
DECLARE VARIABLE V_BAIXAR CHAR(1);
DECLARE VARIABLE V_QTDEATUAL FLOAT;
DECLARE VARIABLE V_PERMESTNEGATIVO CHAR(1);
DECLARE VARIABLE V_CODMOVIMENTO INTEGER;
DECLARE VARIABLE V_QTDEBAIXAR FLOAT;
DECLARE VARIABLE V_CODGRUPOEXTRA VARCHAR(16);
DECLARE VARIABLE V_CODPRODUTOEXTRA VARCHAR(30);
BEGIN
    MSGRETORNO = NULL;

    -- Verifica se o produto baixa estoque
    SELECT BAIXAR FROM CADPRODUTOSCOMP
    WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO
    INTO :V_BAIXAR;

    IF (V_BAIXAR IS NULL) THEN
    BEGIN
        MSGRETORNO = 'Produto não encontrado';
        SUSPEND;
        EXIT;
    END

    IF (V_BAIXAR <> 'S') THEN
    BEGIN
        MSGRETORNO = 'Produto não controla estoque';
        SUSPEND;
        EXIT;
    END

    -- Verifica permissão para estoque negativo
    SELECT FIRST 1 PERMESTNEGATIVO FROM CUSTOMIZACAO INTO :V_PERMESTNEGATIVO;

    -- Obtém o saldo atual
    SELECT QTDEATUAL FROM CADPRODUTOS
    WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO
    INTO :V_QTDEATUAL;

    -- Validação de estoque insuficiente (somente na SAÍDA)
    IF ((:P_TIPO = 'S') AND (V_PERMESTNEGATIVO <> 'S') AND (V_QTDEATUAL < :P_QUANTIDADE)) THEN
    BEGIN
        MSGRETORNO = 'Estoque insuficiente. Qtde Atual: ' || CAST(V_QTDEATUAL AS VARCHAR(20)) || ' | Qtde Solicitada: ' || CAST(:P_QUANTIDADE AS VARCHAR(20));
        SUSPEND;
        EXIT;
    END

    -- Atualização de estoque
    IF (:P_TIPO = 'E') THEN
        UPDATE CADPRODUTOS SET QTDEATUAL = COALESCE(QTDEATUAL,0) + :P_QUANTIDADE
        WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO;
    ELSE IF (:P_TIPO = 'S') THEN
        UPDATE CADPRODUTOS SET QTDEATUAL = COALESCE(QTDEATUAL,0) - :P_QUANTIDADE
        WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO;

    -- MOVESTOQUE (cabeçalho)
    SELECT FIRST 1 CODMOVIMENTO FROM MOVESTOQUE
    WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO AND TIPO = :P_TIPO
    INTO :V_CODMOVIMENTO;

    IF (V_CODMOVIMENTO IS NULL) THEN
    BEGIN
        V_CODMOVIMENTO = GEN_ID(GEN_CODMOVESTOQUE,1);
        INSERT INTO MOVESTOQUE (CODMOVIMENTO, CODGRUPO, CODPRODUTO, DESCRICAO, TIPO, OBSERVACAO)
        VALUES (:V_CODMOVIMENTO, :P_CODGRUPO, :P_CODPRODUTO, '', :P_TIPO, :P_OBSERVACAO);
    END

    -- MOVESTOQUEITENS (principal)
    INSERT INTO MOVESTOQUEITENS (CODMOVIMENTO, NUMEROVENDA, DATAMOV, QTDEMOV, QTDEATUAL, VALORUNITITEM, VALORTOTALITEM, OBSERVACAO)
    VALUES (:V_CODMOVIMENTO, :P_NUMEROVENDA, CURRENT_DATE, :P_QUANTIDADE,
            (SELECT QTDEATUAL FROM CADPRODUTOS WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO),
            :P_VALORUNITITEM, :P_VALORTOTALITEM, :P_OBSERVACAO);

    -- Controle de BAIXA EXTRA
    FOR SELECT CODGRUPOEXTRA, CODPRODUTOEXTRA, QTDEBAIXAR
        FROM CADPRODUTOSBAIXAEXTRA
        WHERE CODGRUPO = :P_CODGRUPO AND CODPRODUTO = :P_CODPRODUTO
    INTO :V_CODGRUPOEXTRA, :V_CODPRODUTOEXTRA, :V_QTDEBAIXAR
    DO
    BEGIN
        IF (:P_TIPO = 'E') THEN
            UPDATE CADPRODUTOS SET QTDEATUAL = COALESCE(QTDEATUAL,0) + (:P_QUANTIDADE * :V_QTDEBAIXAR)
            WHERE CODGRUPO = :V_CODGRUPOEXTRA AND CODPRODUTO = :V_CODPRODUTOEXTRA;
        ELSE IF (:P_TIPO = 'S') THEN
            UPDATE CADPRODUTOS SET QTDEATUAL = COALESCE(QTDEATUAL,0) - (:P_QUANTIDADE * :V_QTDEBAIXAR)
            WHERE CODGRUPO = :V_CODGRUPOEXTRA AND CODPRODUTO = :V_CODPRODUTOEXTRA;

        INSERT INTO MOVESTOQUEITENS (CODMOVIMENTO, NUMEROVENDA, DATAMOV, QTDEMOV, QTDEATUAL, VALORUNITITEM, VALORTOTALITEM, OBSERVACAO)
        VALUES (:V_CODMOVIMENTO, :P_NUMEROVENDA, CURRENT_DATE,
                CASE WHEN :P_TIPO = 'E' THEN (:P_QUANTIDADE * :V_QTDEBAIXAR) ELSE -(:P_QUANTIDADE * :V_QTDEBAIXAR) END,
                (SELECT QTDEATUAL FROM CADPRODUTOS WHERE CODGRUPO = :V_CODGRUPOEXTRA AND CODPRODUTO = :V_CODPRODUTOEXTRA),
                :P_VALORUNITITEM, :P_VALORTOTALITEM, 'BAIXA EXTRA - ' || COALESCE(:P_OBSERVACAO, ''));
    END

    MSGRETORNO = NULL;
    SUSPEND;
END

SET TERM ^ ;