SET DEFINE OFF;

DROP TABLE MOHISTORICOCRM_2201;

create or replace FUNCTION FUNC_ADD_BUSCA_PRECO_DATA_INI(
    p_config_209_filtrarGrupoEcon IN NUMBER,
    p_estabelecimento             IN NUMBER,
    p_data                        IN DATE,
    p_produto                     IN NUMBER,
    p_indicadorPropriedadePosseIt IN CHAR,
    p_pessoaParticipante          IN NUMBER,
    p_gerandoInventario           IN NUMBER
  )
  RETURN DATE
IS 
  v_data DATE;
BEGIN
  SELECT COALESCE(MAX(a.data),TO_DATE('01/01/1900','DD/MM/YYYY'))
  INTO v_data
  FROM (
    SELECT MAX(TRUNC(invEst.data)+1) data
    FROM MOINVENTARIOESTOQUEXITENS itemEst
    JOIN CAGRADESPRODUTO gradProd ON gradProd.gradeProduto = itemEst.gradeProduto
    JOIN MOINVENTARIOSESTOQUE invEst ON invEst.inventarioEstoque = itemEst.inventarioEstoque
    WHERE gradProd.produto = p_produto
    AND itemEst.indicadorPropriedadePosseItem = '' || CASE WHEN p_indicadorPropriedadePosseIt IS NULL OR p_indicadorPropriedadePosseIt = '' OR p_indicadorPropriedadePosseIt = ' ' THEN '0' ELSE p_indicadorPropriedadePosseIt END || ''
    AND itemEst.pessoaParticipante = p_pessoaParticipante
    AND TRUNC(invEst.data) <= (TRUNC(p_data) - CASE WHEN p_gerandoInventario = 1 THEN 1 ELSE 0 END)
    AND (p_estabelecimento = 0
      OR p_estabelecimento <> 0
      AND p_config_209_filtrarGrupoEcon = 0
      AND EXISTS (
        SELECT 1
        FROM PAESTABELECIMENTOS est
        JOIN PAESTABELECIMENTOS est2 ON est2.pessoaEstabelecimento = est.pessoaEstabelecimento
        WHERE est.estabelecimento = invEst.estabelecimento
        AND (est.estabelecimento = p_estabelecimento
          OR est2.estabelecimento = p_estabelecimento))
      OR p_estabelecimento <> 0
      AND p_config_209_filtrarGrupoEcon = 1
      AND EXISTS (
        SELECT 1
        FROM PAESTABELECIMENTOS est
        JOIN CAPESSOAS pessEst ON pessEst.pessoa = est.pessoaEstabelecimento
        JOIN CAPESSOAS pessEst2 ON pessEst2.grupoEconomico = pessEst.grupoEconomico
        JOIN PAESTABELECIMENTOS est2 ON est2.pessoaEstabelecimento = pessEst2.pessoa
        WHERE est.estabelecimento = invEst.estabelecimento
        AND (est.estabelecimento = p_estabelecimento
          OR est2.estabelecimento = p_estabelecimento)))
    UNION ALL
    SELECT /*+ RULE*/ MAX(TRUNC(itemEst.data)) data
    FROM MOESTOQUES itemEst
    JOIN CAGRADESPRODUTO gradProd ON gradProd.gradeProduto = itemEst.gradeProduto
    WHERE gradProd.produto = p_produto
    AND itemEst.indicadorPropriedadePosseItem = '' || CASE WHEN p_indicadorPropriedadePosseIt IS NULL OR p_indicadorPropriedadePosseIt = '' OR p_indicadorPropriedadePosseIt = ' ' THEN '0' ELSE p_indicadorPropriedadePosseIt END || ''
    AND itemEst.pessoaParticipante = p_pessoaParticipante
    AND itemEst.operacaoInternaEstoque = 1
    AND TRUNC(itemEst.data) <= TRUNC(p_data)
    AND (p_estabelecimento = 0
      OR p_estabelecimento <> 0
      AND p_config_209_filtrarGrupoEcon = 0
      AND EXISTS (
        SELECT 1
        FROM PAESTABELECIMENTOS est
        JOIN PAESTABELECIMENTOS est2 ON est2.pessoaEstabelecimento = est.pessoaEstabelecimento
        WHERE est.estabelecimento = itemEst.estabelecimento
        AND (est.estabelecimento = p_estabelecimento
          OR est2.estabelecimento = p_estabelecimento))
      OR p_estabelecimento <> 0
      AND p_config_209_filtrarGrupoEcon = 1
      AND EXISTS (
        SELECT 1
        FROM PAESTABELECIMENTOS est
        JOIN CAPESSOAS pessEst ON pessEst.pessoa = est.pessoaEstabelecimento
        JOIN CAPESSOAS pessEst2 ON pessEst2.grupoEconomico = pessEst.grupoEconomico
        JOIN PAESTABELECIMENTOS est2 ON est2.pessoaEstabelecimento = pessEst2.pessoa
        WHERE est.estabelecimento = itemEst.estabelecimento
        AND (est.estabelecimento = p_estabelecimento
          OR est2.estabelecimento = p_estabelecimento)))
  ) a;
  RETURN v_data;
END;

/

create or replace FUNCTION FUNC_ADD_BUSCA_ESTOQUE_PRODUTO(
    p_dataPosicaoEstoque          IN DATE,
    p_gradeProduto                IN NUMBER,
    p_estabelecimento             IN NUMBER,
    p_idInventarioEstoque         IN NUMBER,
    p_dataInventario              IN DATE,
    p_indicadorPropriedadePosseIt IN CHAR,
    p_pessoaParticipante          IN NUMBER,
    p_localEstoque                IN NUMBER,
    p_personalizacao              IN NUMBER,
    p_idLoteEstoque               IN NUMBER,
    p_idEnderecoEstoque           IN NUMBER,
    p_idNumeroSerie               IN NUMBER,
    p_gradProd_produto            IN NUMBER,
    p_prod_controleEstoque        IN NUMBER,
    p_documentoDesconsiderar      IN CHAR, -- D = Documento Fiscal, P = Pré-Documento
    p_idDocumentoDesconsiderar    IN NUMBER,
    p_estoqueFiscal               IN NUMBER)
  RETURN NUMBER
IS
  v_dataPosicaoEstoqueInicial DATE;
  v_quantidadeInventario      NUMBER (15,6);
  v_quantidadeEstoque         NUMBER (15,6);
  v_quantidadeDocFisc         NUMBER (15,6);
  v_quantidadePreDoc          NUMBER (15,6);
BEGIN
  v_quantidadeInventario      := 0;
  v_quantidadeEstoque         := 0;
  v_quantidadeDocFisc         := 0;
  v_quantidadePreDoc          := 0;
  -- KIT / COMBO
  IF p_prod_controleEstoque IN (3,4) THEN
    -- Busca estoque do item filho com menor estoque
    SELECT COALESCE((
      SELECT MIN (TRUNC((FUNC_ADD_BUSCA_ESTOQUE_PRODUTO(
        p_dataPosicaoEstoque,
        kit.gradeProdutoFilho,
        p_estabelecimento,
        p_idInventarioEstoque,
        p_dataInventario,
        p_indicadorPropriedadePosseIt,
        p_pessoaParticipante,
        p_localEstoque,
        0,
        0,
        p_idEnderecoEstoque,
        0,
        gradProdFilho.produto,
        prodFilho.controleEstoque,
        p_documentoDesconsiderar,
        p_idDocumentoDesconsiderar,
        p_estoqueFiscal) / kit.quantidade), uniMedPai.casasDecimaisUnidadeMedida))
      FROM CAGRADEPRODUTOXKITSCOMBOS kit
      JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
      JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
      JOIN CAGRADESPRODUTO gradProdPai ON gradProdPai.gradeProduto = kit.gradeProduto
      JOIN CAPRODUTOS prodPai ON prodPai.produto = gradProdPai.produto
      JOIN SIUNIDADESMEDIDA uniMedPai ON uniMedPai.unidadeMedida = prodPai.unidadeMedida
      WHERE kit.gradeProduto = p_gradeProduto
      AND kit.ativo = 1
      AND kit.quantidade > 0
      AND prodFilho.controleEstoque IN (1,3,4,5,11,12)),0)
    INTO v_quantidadeEstoque
    FROM DUAL;
  -- DEMAIS PRODUTOS (EXCETO KIT / COMBO)
  ELSIF p_prod_controleEstoque IN (1,5,11,12) THEN
    -- v_dataPosicaoEstoqueInicial
    SELECT COALESCE((
      SELECT /*+ RULE*/ MAX (est.data)
        FROM MOESTOQUES est
        JOIN CAGRADESPRODUTO gradProd ON gradProd.gradeProduto = est.gradeProduto
        WHERE gradProd.produto = p_gradProd_produto
        AND est.estabelecimento = p_estabelecimento
        AND est.operacaoInternaEstoque = 1
        AND TRUNC(est.data) <= TRUNC (p_dataPosicaoEstoque)
        AND (p_idInventarioEstoque <= 0
		  OR TRUNC(est.data) > TRUNC(p_dataInventario))),
      CASE
        WHEN p_idInventarioEstoque > 0 AND NOT (p_dataInventario IS NULL)
        THEN TRUNC (p_dataInventario) + 1
        ELSE TO_DATE ('01/01/1900','DD/MM/YYYY')
      END)
    INTO v_dataPosicaoEstoqueInicial
    FROM DUAL;
    -- v_quantidadeInventario
    IF p_idInventarioEstoque > 0 THEN
      SELECT COALESCE((
        SELECT SUM (CASE WHEN p_estoqueFiscal = 1 THEN est.quantidadeFiscal ELSE est.quantidadeGerencial END)
        FROM MOINVENTARIOESTOQUEXITENS est
        JOIN PALOCAISESTOQUE locEst ON locEst.localEstoque = est.localEstoque
        JOIN CAGRADESPRODUTO gradProd ON gradProd.gradeProduto = est.gradeProduto
        WHERE est.inventarioEstoque = p_idInventarioEstoque
        AND est.gradeProduto = p_gradeProduto
        AND (p_indicadorPropriedadePosseIt IS NULL
		  OR p_indicadorPropriedadePosseIt = ' '
		  OR est.indicadorPropriedadePosseItem = '' || p_indicadorPropriedadePosseIt || '')
        AND (p_pessoaParticipante = 0
		  OR est.pessoaParticipante = p_pessoaParticipante)
        AND (p_localEstoque = 0
		  AND locEst.validoEstoqueTotal = 1
		  OR est.localEstoque = p_localEstoque)
        AND (p_personalizacao = 0
		  OR est.personalizacao = p_personalizacao)
        AND (p_idLoteEstoque = 0
		  OR est.idLoteEstoque = p_idLoteEstoque)
        AND (p_idEnderecoEstoque = 0
		  OR est.idEnderecoEstoque = p_idEnderecoEstoque)
        AND (p_idNumeroSerie = 0
		  OR est.idNumeroSerie = p_idNumeroSerie)),0)
      INTO v_quantidadeInventario
      FROM DUAL;
    ELSE
      v_quantidadeInventario := 0;
    END IF;
    -- v_quantidadeEstoque
    IF TRUNC (v_dataPosicaoEstoqueInicial) <= TRUNC (p_dataPosicaoEstoque) THEN
      SELECT COALESCE((
        SELECT SUM (est.quantidade * CASE WHEN est.entradaSaida = 'S' THEN (-1) ELSE 1 END)
        FROM MOESTOQUES est
        JOIN PALOCAISESTOQUE locEst ON locEst.localEstoque = est.localEstoque
        WHERE est.gradeProduto = p_gradeProduto
        AND est.estabelecimento = p_estabelecimento
        AND TRUNC(est.data) BETWEEN TRUNC (v_dataPosicaoEstoqueInicial) AND TRUNC (p_dataPosicaoEstoque)
        AND (p_indicadorPropriedadePosseIt IS NULL
		  OR p_indicadorPropriedadePosseIt = ' '
		  OR est.indicadorPropriedadePosseItem = '' || p_indicadorPropriedadePosseIt || '')
        AND (p_pessoaParticipante = 0
		  OR est.pessoaParticipante = p_pessoaParticipante)
        AND (p_localEstoque = 0
		  AND locEst.validoEstoqueTotal = 1
		  OR est.localEstoque = p_localEstoque)
         AND (p_personalizacao = 0
		  OR est.personalizacao = p_personalizacao)
       AND (p_idLoteEstoque = 0
		  OR est.idLoteEstoque = p_idLoteEstoque)
        AND (p_idEnderecoEstoque = 0
		  OR est.idEnderecoEstoque = p_idEnderecoEstoque)
        AND (p_idNumeroSerie = 0
		  OR est.idNumeroSerie = p_idNumeroSerie)
        AND (p_estoqueFiscal = 0
		  OR est.operacaoInternaEstoque <> 101)),0)
      INTO v_quantidadeEstoque
      FROM DUAL;
    ELSE
      v_quantidadeEstoque := 0;
    END IF;
    -- v_quantidadeDocFisc
    IF p_documentoDesconsiderar = 'D' AND p_idDocumentoDesconsiderar > 0 THEN
      SELECT COALESCE((
        SELECT SUM (est.quantidade * CASE WHEN est.entradaSaida = 'S' THEN (-1) ELSE 1 END)
        FROM MODOCFISCALXITENS itemDoc
        JOIN MODOCFISCALXESTOQUE docXEst ON docXEst.idItemDocFiscal = itemDoc.idItemDocFiscal
        JOIN MOESTOQUES est ON est.idEstoque = docXEst.idEstoque
        JOIN PALOCAISESTOQUE locEst ON locEst.localEstoque = est.localEstoque
        WHERE itemDoc.idDocumentoFiscal = p_idDocumentoDesconsiderar
        AND est.gradeProduto = p_gradeProduto
        AND est.estabelecimento = p_estabelecimento
        AND TRUNC(est.data) <= TRUNC (p_dataPosicaoEstoque)
        AND (p_indicadorPropriedadePosseIt IS NULL
		  OR p_indicadorPropriedadePosseIt = ' '
		  OR est.indicadorPropriedadePosseItem = '' || p_indicadorPropriedadePosseIt || '')
        AND (p_pessoaParticipante = 0
		  OR est.pessoaParticipante = p_pessoaParticipante)
        AND (p_localEstoque = 0
		  AND locEst.validoEstoqueTotal = 1
		  OR est.localEstoque = p_localEstoque)
        AND (p_personalizacao = 0
		  OR est.personalizacao = p_personalizacao)
        AND (p_idLoteEstoque = 0
		  OR est.idLoteEstoque = p_idLoteEstoque)
        AND (p_idEnderecoEstoque = 0
		  OR est.idEnderecoEstoque = p_idEnderecoEstoque)
        AND (p_idNumeroSerie = 0
		  OR est.idNumeroSerie = p_idNumeroSerie)
        AND (p_estoqueFiscal = 0
		  OR est.operacaoInternaEstoque <> 101)),0)
      INTO v_quantidadeDocFisc
      FROM DUAL;
    ELSE
      v_quantidadeDocFisc := 0;
    END IF;
    -- v_quantidadePreDoc
    IF p_documentoDesconsiderar = 'P' AND p_idDocumentoDesconsiderar > 0 THEN
      SELECT COALESCE((
        SELECT SUM (est.quantidade * CASE WHEN est.entradaSaida = 'S' THEN (-1) ELSE 1 END)
        FROM MOPREDOCUMXITENS itemDoc
        JOIN MOPREDOCUMXESTOQUE docXEst ON docXEst.idItemPreDocumento = itemDoc.idItemPreDocumento
        JOIN MOESTOQUES est ON est.idEstoque = docXEst.idEstoque
        JOIN PALOCAISESTOQUE locEst ON locEst.localEstoque = est.localEstoque
        WHERE itemDoc.preDocumento = p_idDocumentoDesconsiderar
        AND est.gradeProduto = p_gradeProduto
        AND est.estabelecimento = p_estabelecimento
        AND TRUNC(est.data) <= TRUNC (p_dataPosicaoEstoque)
        AND (p_indicadorPropriedadePosseIt IS NULL
		  OR p_indicadorPropriedadePosseIt = ' '
		  OR est.indicadorPropriedadePosseItem = '' || p_indicadorPropriedadePosseIt || '')
        AND (p_pessoaParticipante = 0
		  OR est.pessoaParticipante = p_pessoaParticipante)
        AND (p_localEstoque = 0
		  AND locEst.validoEstoqueTotal = 1
		  OR est.localEstoque = p_localEstoque)
        AND (p_personalizacao = 0
		  OR est.personalizacao = p_personalizacao)
        AND (p_idLoteEstoque = 0
		  OR est.idLoteEstoque = p_idLoteEstoque)
        AND (p_idEnderecoEstoque = 0
		  OR est.idEnderecoEstoque = p_idEnderecoEstoque)
        AND (p_idNumeroSerie = 0
		  OR est.idNumeroSerie = p_idNumeroSerie)
        AND (p_estoqueFiscal = 0
		  OR est.operacaoInternaEstoque <> 101)),0)
      INTO v_quantidadePreDoc
      FROM DUAL;
    ELSE
      v_quantidadePreDoc := 0;
    END IF;
  END IF;
  RETURN v_quantidadeInventario + v_quantidadeEstoque - v_quantidadeDocFisc - v_quantidadePreDoc;
END;

/

create or replace PROCEDURE ADD_GERA_TEMP_ESTOQUE (
  p_uniqueMachineID     IN VARCHAR2,
  p_contadorSessao      IN NUMBER,
  p_dataPosicaoEstoque  IN DATE,
  p_inEstabelecimentos  IN VARCHAR2,
  p_inLocaisEstoque     IN VARCHAR2,
  p_joinProdutos        IN VARCHAR2,
  p_andWhereProdutos    IN VARCHAR2,
  p_joinInventarios     IN VARCHAR2,
  p_andWhereInventarios IN VARCHAR2,
  p_joinMovimentos      IN VARCHAR2,
  p_andWhereMovimentos  IN VARCHAR2)
IS
BEGIN
  DELETE TEMPESTOQUE
  WHERE  uniqueMachineID = p_uniqueMachineID
  AND contadorSessao = p_contadorSessao;
  EXECUTE IMMEDIATE 'INSERT INTO TEMPESTOQUE (
    uniqueMachineID,
    contadorSessao,
    gradeProduto,
    estabelecimento,
    localEstoque,
    indicadorPropriedadePosseItem,
    pessoaParticipante,
    personalizacao,
    idLoteEstoque,
    idEnderecoEstoque,
    idNumeroSerie,
    quantidadeFiscal,
    quantidadeGerencial)
  WITH ESTABELECIMENTOS AS (
    SELECT
      a.estabelecimento,
      a.dataInventario,
      COALESCE ((
      SELECT MAX (inv.inventarioEstoque)
      FROM MOINVENTARIOSESTOQUE inv
      WHERE inv.estabelecimento = a.estabelecimento
      AND TRUNC (inv.data) = TRUNC(a.dataInventario)),0) inventarioEstoque
    FROM (
      SELECT
        est.estabelecimento,
        COALESCE(
          ( SELECT MAX(TRUNC(inv.data))
            FROM MOINVENTARIOSESTOQUE inv
            WHERE inv.estabelecimento = est.estabelecimento
            AND TRUNC (inv.data) <= ' || CASE WHEN  p_dataPosicaoEstoque IS NULL THEN 'TRUNC (SYSDATE)' ELSE 'TO_DATE(''' || TO_CHAR(p_dataPosicaoEstoque, 'DD/MM/YYYY') || ''', ''DD/MM/YYYY'')' END || '
          ),
          TO_DATE (''01/01/1900'',''DD/MM/YYYY'')) dataInventario
      FROM PAESTABELECIMENTOS est'
|| CASE
     WHEN p_inEstabelecimentos IS NULL OR p_inEstabelecimentos = ' ' OR p_inEstabelecimentos = '0'
     THEN ''
     WHEN INSTR(p_inEstabelecimentos,',') = 0
     THEN '
      WHERE est.estabelecimento = ' || TRIM(TO_CHAR(p_inEstabelecimentos))
     ELSE '
      WHERE INSTR('',' || RTRIM(p_inEstabelecimentos) || ','','','' || TRIM(TO_CHAR(est.estabelecimento)) || '','') > 0'
   END
|| ') a)
  SELECT
    ''' || CASE WHEN p_uniqueMachineID IS NULL OR p_uniqueMachineID = ' ' THEN ' ' ELSE RTRIM(p_uniqueMachineID) END || ''',
    ' || TO_CHAR(p_contadorSessao) || ',
    a.gradeProduto,
    a.estabelecimento,
    a.localEstoque,
    a.indicadorPropriedadePosseItem,
    a.pessoaParticipante,
    a.personalizacao,
    a.idLoteEstoque,
    a.idEnderecoEstoque,
    a.idNumeroSerie,
    SUM(a.quantidadeFiscal) quantidadeFiscal,
    SUM(a.quantidadeGerencial) quantidadeGerencial
  FROM (
    SELECT DISTINCT
      itemInv.inventarioEstoque id,
      itemInv.gradeProduto,
      est.estabelecimento,
      itemInv.localEstoque,
      itemInv.indicadorPropriedadePosseItem,
      itemInv.pessoaParticipante,
      itemInv.personalizacao,
      itemInv.idLoteEstoque,
      itemInv.idEnderecoEstoque,
      itemInv.idNumeroSerie,
      itemInv.quantidadeFiscal,
      itemInv.quantidadeGerencial
    FROM MOINVENTARIOESTOQUEXITENS itemInv
    JOIN ESTABELECIMENTOS est ON est.inventarioEstoque = itemInv.inventarioEstoque
    JOIN CAGRADESPRODUTO gradProd ON gradProd.gradeProduto = itemInv.gradeProduto
    JOIN CAPRODUTOS prod ON prod.produto = gradProd.produto'
|| CASE
     WHEN p_joinProdutos IS NULL OR p_joinProdutos = ' '
     THEN ''
     ELSE '
    ' || RTRIM(p_joinProdutos)
   END
|| CASE
     WHEN p_joinInventarios IS NULL OR p_joinInventarios = ' '
     THEN ''
     ELSE '
    ' || RTRIM(p_joinInventarios)
   END
|| '
    WHERE itemInv.inventarioEstoque > 0
    AND itemInv.gradeProduto > 0'
|| CASE
     WHEN p_inLocaisEstoque IS NULL OR p_inLocaisEstoque = ' ' OR p_inLocaisEstoque = '0'
     THEN ''
     WHEN INSTR(p_inLocaisEstoque,',') = 0
     THEN '
    AND itemInv.localEstoque = ' || TRIM(TO_CHAR(p_inLocaisEstoque))
     ELSE '
    AND INSTR('',' || RTRIM(p_inLocaisEstoque) || ','','','' || TRIM(TO_CHAR(itemInv.localEstoque)) || '','') > 0'
   END
|| CASE
     WHEN p_andWhereProdutos IS NULL OR p_andWhereProdutos = ' '
     THEN ''
     ELSE '
    ' || RTRIM(p_andWhereProdutos)
   END
|| '
    AND NOT (EXISTS(
      SELECT /*+ RULE*/ 1
      FROM MOESTOQUES mov
      JOIN CAGRADESPRODUTO gradProdMov ON gradProdMov.gradeProduto = mov.gradeProduto
      WHERE gradProdMov.produto = gradProd.produto
      AND mov.estabelecimento = est.estabelecimento
      AND mov.operacaoInternaEstoque = 1
      AND TRUNC(mov.data) BETWEEN TRUNC(est.dataInventario) + 1 AND ' || CASE WHEN  p_dataPosicaoEstoque IS NULL THEN 'TRUNC (SYSDATE)' ELSE 'TO_DATE(''' || TO_CHAR(p_dataPosicaoEstoque, 'DD/MM/YYYY') || ''', ''DD/MM/YYYY'')' END || '
      ))'
|| CASE
     WHEN p_andWhereInventarios IS NULL OR p_andWhereInventarios = ' '
     THEN ''
     ELSE '
    ' || RTRIM(p_andWhereInventarios)
   END
|| '
    UNION ALL
    SELECT DISTINCT
      mov.idEstoque id,
      mov.gradeProduto,
      mov.estabelecimento,
      mov.localEstoque,
      mov.indicadorPropriedadePosseItem,
      mov.pessoaParticipante,
      mov.personalizacao,
      mov.idLoteEstoque,
      mov.idEnderecoEstoque,
      mov.idNumeroSerie,
      CASE WHEN operacaoInternaEstoque = 101 THEN 0 ELSE mov.quantidade * CASE WHEN mov.entradaSaida = ''S'' THEN -1 ELSE 1 END END quantidadeFiscal,
      mov.quantidade * CASE WHEN mov.entradaSaida = ''S'' THEN -1 ELSE 1 END quantidadeGerencial
    FROM MOESTOQUES mov
    JOIN ESTABELECIMENTOS est ON est.estabelecimento = mov.estabelecimento
    JOIN CAGRADESPRODUTO gradProd ON gradProd.gradeProduto = mov.gradeProduto
    JOIN CAPRODUTOS prod ON prod.produto = gradProd.produto'
|| CASE
     WHEN p_joinProdutos IS NULL OR p_joinProdutos = ' '
     THEN ''
     ELSE '
   ' || RTRIM(p_joinProdutos)
   END
|| CASE
     WHEN p_joinMovimentos IS NULL OR p_joinMovimentos = ' '
     THEN ''
     ELSE '
    ' || RTRIM(p_joinMovimentos)
   END
|| '
    WHERE mov.idEstoque > 0
    AND mov.gradeProduto > 0'
|| CASE
     WHEN p_inLocaisEstoque IS NULL OR p_inLocaisEstoque = ' ' OR p_inLocaisEstoque = '0'
     THEN ''
     WHEN INSTR(p_inLocaisEstoque,',') = 0
     THEN '
    AND mov.localEstoque = ' || TRIM(TO_CHAR(p_inLocaisEstoque))
     ELSE '
    AND INSTR('',' || RTRIM(p_inLocaisEstoque) || ','','','' || TRIM(TO_CHAR(mov.localEstoque)) || '','') > 0'
   END
|| CASE
     WHEN p_andWhereProdutos IS NULL OR p_andWhereProdutos = ' '
     THEN ''
     ELSE '
    ' || RTRIM(p_andWhereProdutos)
   END
|| '
    AND TRUNC(mov.data) BETWEEN COALESCE(
      ( SELECT /*+ RULE*/ MAX (movIni.data)
        FROM MOESTOQUES movIni
        JOIN CAGRADESPRODUTO gradProdIni ON gradProdIni.gradeProduto = movIni.gradeProduto
        WHERE gradProdIni.produto = gradProd.produto
        AND movIni.estabelecimento = mov.estabelecimento
        AND movIni.operacaoInternaEstoque = 1
        AND TRUNC(movIni.data) BETWEEN
          CASE
            WHEN est.inventarioEstoque > 0 AND NOT (est.dataInventario IS NULL)
            THEN TRUNC (est.dataInventario) + 1
            ELSE TO_DATE (''01/01/1900'',''DD/MM/YYYY'')
          END
          AND ' || CASE WHEN  p_dataPosicaoEstoque IS NULL THEN 'TRUNC (SYSDATE)' ELSE 'TO_DATE(''' || TO_CHAR(p_dataPosicaoEstoque, 'DD/MM/YYYY') || ''', ''DD/MM/YYYY'')' END || '
      ),
      ( CASE
          WHEN est.inventarioEstoque > 0 AND NOT (est.dataInventario IS NULL)
          THEN TRUNC (est.dataInventario) + 1
          ELSE TO_DATE (''01/01/1900'',''DD/MM/YYYY'')
        END))
      AND ' || CASE WHEN  p_dataPosicaoEstoque IS NULL THEN 'TRUNC (SYSDATE)' ELSE 'TO_DATE(''' || TO_CHAR(p_dataPosicaoEstoque, 'DD/MM/YYYY') || ''', ''DD/MM/YYYY'')' END
|| CASE
     WHEN p_andWhereMovimentos IS NULL OR p_andWhereMovimentos = ' '
     THEN ''
     ELSE '
   ' || RTRIM(p_andWhereMovimentos)
   END
|| '
  ) a
  GROUP BY
    a.gradeProduto,
    a.estabelecimento,
    a.localEstoque,
    a.indicadorPropriedadePosseItem,
    a.pessoaParticipante,
    a.personalizacao,
    a.idLoteEstoque,
    a.idEnderecoEstoque,
    a.idNumeroSerie';
END ADD_GERA_TEMP_ESTOQUE;

/

create or replace PROCEDURE ADD_DOC_FISC_ITEM_EST_KIT(
    p_config_209_filtrarGrupoEcon  IN NUMBER,
    p_config_362_calcCustoPorGrade IN NUMBER,
    p_bufferIdEstoque              IN VARCHAR2,
    p_estabelecimentoAtivo         IN NUMBER,
    p_cab_modeloDocumento          IN NUMBER,
    p_cab_atualizaCustoMedio       IN NUMBER,
    p_cab_atualizaUltimaCompra     IN NUMBER,
    p_cab_entradaSaida             IN CHAR,
    p_cab_estabelecimento          IN NUMBER,
    p_cab_dataEmissao              IN DATE,
    p_cab_dataEntradaSaida         IN DATE,
    p_modDoc_geraTransferencia     IN NUMBER,
    p_modDoc_geraOperacaoEmTransit IN NUMBER,
    p_modDoc_transitoLocalEstoque  IN NUMBER,
    p_locEstTransito_indicProprPos IN CHAR,
    p_item_idItemDocFiscal         IN NUMBER,
    p_item_gradeProduto            IN NUMBER,
    p_item_localEstoque            IN NUMBER,
    p_item_pessoaParticipante      IN NUMBER,
    p_item_quantidade              IN NUMBER,
    p_item_valorCustoOperacao      IN NUMBER,
    p_item_observacoes             IN VARCHAR2,
    p_endEst_idEnderecoEstoqueDocF IN NUMBER,
    p_idEnderecoEstoque            IN NUMBER,
    p_locEst_indicProprPosseItem   IN CHAR,
    p_docTransf_estabelecEntrada   IN NUMBER,
    p_docTransf_estabelecSaida     IN NUMBER,
    r_bufferIdEstoque              OUT VARCHAR2)
IS  
  v_quantidadeNumerosSerie NUMBER;
  v_quantidadeRateioTotal  NUMBER;
  v_quantSaldoRateioTotal  NUMBER;
  v_valorSaldoRateioTotal  NUMBER;
  v_valorCustoManter       NUMBER;
  v_precoCustoKit          NUMBER;
  v_valorCustoKit          NUMBER;
  CURSOR c_kit IS 
    SELECT 
      kit.gradeProdutoFilho,
      kit.manterUltimoCusto,
      gradProdFilho.produto,
      prodFilho.controleEstoque,
      prodFilho.controlaNumeroSerie,
      ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida) quantidade
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida) > 0;
BEGIN
  r_bufferIdEstoque := p_bufferIdEstoque;
  IF p_cab_atualizaCustoMedio = 1 THEN
    SELECT COALESCE(SUM(ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida)),0)
    INTO v_quantidadeRateioTotal
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND kit.manterUltimoCusto = 0;
    SELECT ROUND((COALESCE(SUM(ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida)
      * FUNC_ADD_BUSCA_PRECO_ULT_CUSTO(
          p_config_209_filtrarGrupoEcon,
          p_config_362_calcCustoPorGrade,
          p_cab_estabelecimento,
          TO_DATE ('01/01/1900','DD/MM/YYYY'),
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END,
          0,
          gradProdFilho.produto,
          0,
          ' ',
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante)),0)),2)
    INTO v_valorCustoManter
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND kit.manterUltimoCusto = 1;
  ELSE
    v_quantidadeRateioTotal := 0;
    v_valorCustoManter      := 0;
  END IF;
  v_quantSaldoRateioTotal := v_quantidadeRateioTotal;
  v_valorSaldoRateioTotal := p_item_valorCustoOperacao - v_valorCustoManter;
  FOR kit IN c_kit
  LOOP  
    IF p_cab_atualizaCustoMedio = 1 AND kit.manterUltimoCusto = 1 THEN
      v_precoCustoKit := FUNC_ADD_BUSCA_PRECO_ULT_CUSTO(
          p_config_209_filtrarGrupoEcon,
          p_config_362_calcCustoPorGrade,
          p_cab_estabelecimento,
          TO_DATE ('01/01/1900','DD/MM/YYYY'),
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END,
          0,
          kit.produto,
          0,
          ' ',
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante);
      v_valorCustoKit := ROUND (kit.quantidade * v_precoCustoKit,2);
    ELSIF p_cab_atualizaCustoMedio = 1 AND p_item_valorCustoOperacao > v_valorCustoManter AND v_quantSaldoRateioTotal > kit.quantidade THEN
      v_valorCustoKit := ROUND((p_item_valorCustoOperacao - v_valorCustoManter) * kit.quantidade / v_quantidadeRateioTotal,2);
      v_precoCustoKit := ROUND(v_valorCustoKit / kit.quantidade,7);
      v_quantSaldoRateioTotal := v_quantSaldoRateioTotal - kit.quantidade;
      v_valorSaldoRateioTotal := v_valorSaldoRateioTotal - v_valorCustoKit;
    ELSIF p_cab_atualizaCustoMedio = 1 AND v_valorSaldoRateioTotal > 0 THEN
      v_valorCustoKit := v_valorSaldoRateioTotal;
      v_precoCustoKit := ROUND(v_valorCustoKit / kit.quantidade,7);
      v_quantSaldoRateioTotal := 0;
      v_valorSaldoRateioTotal := 0;
    ELSE
      v_precoCustoKit := 0;
      v_valorCustoKit := 0;
    END IF;
    IF kit.controleEstoque IN (3,4) THEN
      ADD_DOC_FISC_ITEM_EST_KIT(
        p_config_209_filtrarGrupoEcon,
        p_config_362_calcCustoPorGrade,
        r_bufferIdEstoque,
        p_estabelecimentoAtivo,
        p_cab_modeloDocumento,
        p_cab_atualizaCustoMedio,
        p_cab_atualizaUltimaCompra,
        p_cab_entradaSaida,
        p_cab_estabelecimento,
        p_cab_dataEmissao,
        p_cab_dataEntradaSaida,
        p_modDoc_geraTransferencia,
        p_modDoc_geraOperacaoEmTransit,
        p_modDoc_transitoLocalEstoque,
        p_locEstTransito_indicProprPos,
        p_item_idItemDocFiscal,
        kit.gradeProdutoFilho,
        p_item_localEstoque,
        p_item_pessoaParticipante,
        kit.quantidade,
        v_valorCustoKit,
        p_item_observacoes,
        p_endEst_idEnderecoEstoqueDocF,
        p_idEnderecoEstoque,
        p_locEst_indicProprPosseItem,
        p_docTransf_estabelecEntrada,
        p_docTransf_estabelecSaida,
        r_bufferIdEstoque);
    ELSIF kit.controleEstoque IN(1,5,11,12) THEN
      v_quantidadeNumerosSerie := 0;
      IF kit.controlaNumeroSerie > 0 THEN
        ADD_DOC_FISC_ITEM_EST_N_SERIE(
          r_bufferIdEstoque,
          p_estabelecimentoAtivo,
          p_cab_modeloDocumento,
          p_cab_atualizaCustoMedio,
          p_cab_atualizaUltimaCompra,
          p_cab_entradaSaida,
          p_cab_estabelecimento,
          p_cab_dataEmissao,
          p_cab_dataEntradaSaida,
          p_modDoc_geraTransferencia,
          p_modDoc_geraOperacaoEmTransit,
          p_modDoc_transitoLocalEstoque,
          p_locEstTransito_indicProprPos,
          p_item_idItemDocFiscal,
          kit.gradeProdutoFilho,
          0, -- p_item_idFormulaTinta
          0, -- p_item_personalizacao
          0, -- p_item_idLoteEstoque
          p_item_localEstoque,
          p_item_pessoaParticipante,
          v_precoCustoKit, -- p_item_precoCustoOperacao,
          0, -- p_item_precoCMV,
          p_item_observacoes,
          p_endEst_idEnderecoEstoqueDocF,
          p_idEnderecoEstoque,
          p_locEst_indicProprPosseItem,
          p_docTransf_estabelecEntrada,
          p_docTransf_estabelecSaida,
          r_bufferIdEstoque,
          v_quantidadeNumerosSerie);
      END IF;    
      IF kit.quantidade > v_quantidadeNumerosSerie THEN
        ADD_ESTOQUE_INSERE(
          r_bufferIdEstoque,
          p_estabelecimentoAtivo,
          p_cab_estabelecimento,
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END, --p_data
          kit.gradeProdutoFilho,
          p_cab_modeloDocumento,
          100, --p_cab_operacaoInternaEstoque
          p_cab_atualizaCustoMedio,
          p_cab_atualizaUltimaCompra,
          p_cab_entradaSaida,
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante,
          p_item_localEstoque,
          0, -- p_personalizacao
          0, -- p_idLoteEstoque
          p_idEnderecoEstoque,
          0, -- p_idNumeroSerie
          kit.quantidade - v_quantidadeNumerosSerie,
          v_precoCustoKit, -- p_precoCustoOperacao
          CASE WHEN v_quantidadeNumerosSerie = 0 THEN p_item_valorCustoOperacao WHEN kit.quantidade = 0 THEN 0 ELSE ROUND ((p_item_valorCustoOperacao * (kit.quantidade - v_quantidadeNumerosSerie) / (kit.quantidade - v_quantidadeNumerosSerie)), 2) END, -- p_totalCustoOperacao
          0, -- p_precoCMV
          0, -- p_valorCMV
          p_item_observacoes,
          0, -- p_idItemPreDocumento,
          p_item_idItemDocFiscal,
          0, -- p_idItemSeparacao,
          0, -- p_divergenciaBalanco,
          0, -- p_idItemDocTransferencia,
          r_bufferIdEstoque);
        IF p_modDoc_geraTransferencia = 1 AND p_modDoc_geraOperacaoEmTransit = 1 AND p_modDoc_transitoLocalEstoque > 0 AND p_docTransf_estabelecEntrada > 0 AND p_docTransf_estabelecSaida > 0 THEN
          ADD_ESTOQUE_INSERE(
            r_bufferIdEstoque, 
            p_estabelecimentoAtivo, 
            p_docTransf_estabelecSaida,
            CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END, --p_data
            kit.gradeProdutoFilho,
            p_cab_modeloDocumento,
            900,
            0,
            0,
            CASE WHEN p_cab_entradaSaida='S' THEN 'E' ELSE 'S' END,
            p_locEstTransito_indicProprPos,
            p_item_pessoaParticipante,
            p_modDoc_transitoLocalEstoque,
            0, -- p_personalizacao
            0, -- p_idLoteEstoque
            p_idEnderecoEstoque,
            0, -- p_idNumeroSerie
            kit.quantidade - v_quantidadeNumerosSerie,
            v_precoCustoKit, -- p_precoCustoOperacao
            CASE WHEN v_quantidadeNumerosSerie = 0 THEN p_item_valorCustoOperacao WHEN kit.quantidade = 0 THEN 0 ELSE ROUND ((p_item_valorCustoOperacao * (kit.quantidade - v_quantidadeNumerosSerie) / (kit.quantidade - v_quantidadeNumerosSerie)), 2) END, -- p_totalCustoOperacao
            0, -- p_precoCMV
            0, -- p_valorCMV
            p_item_observacoes,
            0, -- p_idItemPreDocumento,
            p_item_idItemDocFiscal,
            0, -- p_idItemSeparacao,
            0, -- p_divergenciaBalanco,
            0, -- p_idItemDocTransferencia,
            r_bufferIdEstoque);
        END IF;    
      END IF;    
    END IF;
  END LOOP;
END ADD_DOC_FISC_ITEM_EST_KIT;

/

create or replace PROCEDURE ADD_PRE_DOC_ITEM_EST_KIT(
    p_config_209_filtrarGrupoEcon  IN NUMBER,
    p_config_362_calcCustoPorGrade IN NUMBER,
    p_bufferIdEstoque              IN VARCHAR2,
    p_estabelecimentoAtivo         IN NUMBER,
    p_cab_modeloDocumento          IN NUMBER,
    p_cab_atualizaCustoMedio       IN NUMBER,
    p_cab_atualizaUltimaCompra     IN NUMBER,
    p_cab_entradaSaida             IN CHAR,
    p_cab_estabelecimento          IN NUMBER,
    p_cab_dataEmissao              IN DATE,
    p_cab_dataEntradaSaida         IN DATE,
    p_modDoc_geraTransferencia     IN NUMBER,
    p_modDoc_geraOperacaoEmTransit IN NUMBER,
    p_modDoc_transitoLocalEstoque  IN NUMBER,
    p_locEstTransito_indicProprPos IN CHAR,
    p_item_idItemPreDocumento      IN NUMBER,
    p_item_gradeProduto            IN NUMBER,
    p_item_localEstoque            IN NUMBER,
    p_item_pessoaParticipante      IN NUMBER,
    p_item_quantidade              IN NUMBER,
    p_item_valorCustoOperacao      IN NUMBER,
    p_item_observacoes             IN VARCHAR2,
    p_endEst_idEnderecoEstoquePreD IN NUMBER,
    p_idEnderecoEstoque            IN NUMBER,
    p_locEst_indicProprPosseItem   IN CHAR,
    p_docTransf_estabelecEntrada   IN NUMBER,
    p_docTransf_estabelecSaida     IN NUMBER,
    r_bufferIdEstoque              OUT VARCHAR2)
IS  
  v_quantidadeNumerosSerie NUMBER;
  v_quantidadeRateioTotal  NUMBER;
  v_quantSaldoRateioTotal  NUMBER;
  v_valorSaldoRateioTotal  NUMBER;
  v_valorCustoManter       NUMBER;
  v_precoCustoKit          NUMBER;
  v_valorCustoKit          NUMBER;
  CURSOR c_kit
  IS 
    SELECT 
      kit.gradeProdutoFilho,
      kit.manterUltimoCusto,
      gradProdFilho.produto,
      prodFilho.controleEstoque,
      prodFilho.controlaNumeroSerie,
      ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida) quantidade
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida) > 0;
BEGIN
  r_bufferIdEstoque := p_bufferIdEstoque;
  IF p_cab_atualizaCustoMedio = 1 THEN
    SELECT COALESCE(SUM(ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida)),0)
    INTO v_quantidadeRateioTotal
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND kit.manterUltimoCusto = 0;
    SELECT ROUND((COALESCE(SUM(ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida)
      * FUNC_ADD_BUSCA_PRECO_ULT_CUSTO(
          p_config_209_filtrarGrupoEcon,
          p_config_362_calcCustoPorGrade,
          p_cab_estabelecimento,
          TO_DATE ('01/01/1900','DD/MM/YYYY'),
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END,
          0,
          gradProdFilho.produto,
          0,
          ' ',
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante)),0)),2)
    INTO v_valorCustoManter
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND kit.manterUltimoCusto = 1;
  ELSE
    v_quantidadeRateioTotal := 0;
    v_valorCustoManter      := 0;
  END IF;
  v_quantSaldoRateioTotal := v_quantidadeRateioTotal;
  v_valorSaldoRateioTotal := p_item_valorCustoOperacao - v_valorCustoManter;
  FOR kit IN c_kit
  LOOP  
    IF p_cab_atualizaCustoMedio = 1 AND kit.manterUltimoCusto = 1 THEN
      v_precoCustoKit := FUNC_ADD_BUSCA_PRECO_ULT_CUSTO(
          p_config_209_filtrarGrupoEcon,
          p_config_362_calcCustoPorGrade,
          p_cab_estabelecimento,
          TO_DATE ('01/01/1900','DD/MM/YYYY'),
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END,
          0,
          kit.produto,
          0,
          ' ',
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante);
      v_valorCustoKit := ROUND (kit.quantidade * v_precoCustoKit,2);
    ELSIF p_cab_atualizaCustoMedio = 1 AND p_item_valorCustoOperacao > v_valorCustoManter AND v_quantSaldoRateioTotal > kit.quantidade THEN
      v_valorCustoKit := ROUND((p_item_valorCustoOperacao - v_valorCustoManter) * kit.quantidade / v_quantidadeRateioTotal,2);
      v_precoCustoKit := ROUND(v_valorCustoKit / kit.quantidade,7);
      v_quantSaldoRateioTotal := v_quantSaldoRateioTotal - kit.quantidade;
      v_valorSaldoRateioTotal := v_valorSaldoRateioTotal - v_valorCustoKit;
    ELSIF p_cab_atualizaCustoMedio = 1 AND v_valorSaldoRateioTotal > 0 THEN
      v_valorCustoKit := v_valorSaldoRateioTotal;
      v_precoCustoKit := ROUND(v_valorCustoKit / kit.quantidade,7);
      v_quantSaldoRateioTotal := 0;
      v_valorSaldoRateioTotal := 0;
    ELSE
      v_precoCustoKit := 0;
      v_valorCustoKit := 0;
    END IF;
    IF kit.controleEstoque IN (3,4) THEN
      ADD_PRE_DOC_ITEM_EST_KIT(
        p_config_209_filtrarGrupoEcon,
        p_config_362_calcCustoPorGrade,
        r_bufferIdEstoque,
        p_estabelecimentoAtivo,
        p_cab_modeloDocumento,
        p_cab_atualizaCustoMedio,
        p_cab_atualizaUltimaCompra,
        p_cab_entradaSaida,
        p_cab_estabelecimento,
        p_cab_dataEmissao,
        p_cab_dataEntradaSaida,
        p_modDoc_geraTransferencia,
        p_modDoc_geraOperacaoEmTransit,
        p_modDoc_transitoLocalEstoque,
        p_locEstTransito_indicProprPos,
        p_item_idItemPreDocumento,
        kit.gradeProdutoFilho,
        p_item_localEstoque,
        p_item_pessoaParticipante,
        kit.quantidade,
        v_valorCustoKit,
        p_item_observacoes,
        p_endEst_idEnderecoEstoquePreD,
        p_idEnderecoEstoque,
        p_locEst_indicProprPosseItem,
        p_docTransf_estabelecEntrada,
        p_docTransf_estabelecSaida,
        r_bufferIdEstoque);
    ELSIF kit.controleEstoque IN(1,5,11,12) THEN
      v_quantidadeNumerosSerie := 0;
      IF kit.controlaNumeroSerie > 0 THEN
        ADD_PRE_DOC_ITEM_EST_N_SERIE(
          r_bufferIdEstoque,
          p_estabelecimentoAtivo,
          p_cab_modeloDocumento,
          p_cab_atualizaCustoMedio,
          p_cab_atualizaUltimaCompra,
          p_cab_entradaSaida,
          p_cab_estabelecimento,
          p_cab_dataEmissao,
          p_cab_dataEntradaSaida,
          p_modDoc_geraTransferencia,
          p_modDoc_geraOperacaoEmTransit,
          p_modDoc_transitoLocalEstoque,
          p_locEstTransito_indicProprPos,
          p_item_idItemPreDocumento,
          kit.gradeProdutoFilho,
          0, -- p_item_idFormulaTinta
          0, -- p_item_personalizacao
          0, -- p_item_idLoteEstoque
          p_item_localEstoque,
          p_item_pessoaParticipante,
          v_precoCustoKit, -- p_item_precoCustoOperacao,
          0, -- p_item_precoCMV,
          p_item_observacoes,
          p_endEst_idEnderecoEstoquePreD,
          p_idEnderecoEstoque,
          p_locEst_indicProprPosseItem,
          p_docTransf_estabelecEntrada,
          p_docTransf_estabelecSaida,
          r_bufferIdEstoque,
          v_quantidadeNumerosSerie);
      END IF;    
      IF kit.quantidade > v_quantidadeNumerosSerie THEN
        ADD_ESTOQUE_INSERE(
          r_bufferIdEstoque,
          p_estabelecimentoAtivo,
          p_cab_estabelecimento,
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END, --p_data
          kit.gradeProdutoFilho,
          p_cab_modeloDocumento,
          101, --p_cab_operacaoInternaEstoque
          p_cab_atualizaCustoMedio,
          p_cab_atualizaUltimaCompra,
          p_cab_entradaSaida,
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante,
          p_item_localEstoque,
          0, -- p_personalizacao
          0, -- p_idLoteEstoque
          p_idEnderecoEstoque,
          0, -- p_idNumeroSerie
          kit.quantidade - v_quantidadeNumerosSerie,
          v_precoCustoKit, -- p_precoCustoOperacao
          CASE WHEN v_quantidadeNumerosSerie = 0 THEN p_item_valorCustoOperacao WHEN kit.quantidade = 0 THEN 0 ELSE ROUND ((p_item_valorCustoOperacao * (kit.quantidade - v_quantidadeNumerosSerie) / (kit.quantidade - v_quantidadeNumerosSerie)), 2) END, -- p_totalCustoOperacao
          0, -- p_precoCMV
          0, -- p_valorCMV
          p_item_observacoes,
          p_item_idItemPreDocumento,
          0, -- p_idItemDocFiscal,
          0, -- p_idItemSeparacao,
          0, -- p_divergenciaBalanco,
          0, -- p_idItemDocTransferencia,
          r_bufferIdEstoque);
        IF p_modDoc_geraTransferencia = 1 AND p_modDoc_geraOperacaoEmTransit = 1 AND p_modDoc_transitoLocalEstoque > 0 AND p_docTransf_estabelecEntrada > 0 AND p_docTransf_estabelecSaida > 0 THEN
          ADD_ESTOQUE_INSERE(
            r_bufferIdEstoque, 
            p_estabelecimentoAtivo, 
            p_docTransf_estabelecSaida,
            CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END, --p_data
            kit.gradeProdutoFilho,
            p_cab_modeloDocumento,
            900,
            0,
            0,
            CASE WHEN p_cab_entradaSaida='S' THEN 'E' ELSE 'S' END,
            p_locEstTransito_indicProprPos,
            p_item_pessoaParticipante,
            p_modDoc_transitoLocalEstoque,
            0, -- p_personalizacao
            0, -- p_idLoteEstoque
            p_idEnderecoEstoque,
            0, -- p_idNumeroSerie
            kit.quantidade - v_quantidadeNumerosSerie,
            v_precoCustoKit, -- p_precoCustoOperacao
            CASE WHEN v_quantidadeNumerosSerie = 0 THEN p_item_valorCustoOperacao WHEN kit.quantidade = 0 THEN 0 ELSE ROUND ((p_item_valorCustoOperacao * (kit.quantidade - v_quantidadeNumerosSerie) / (kit.quantidade - v_quantidadeNumerosSerie)), 2) END, -- p_totalCustoOperacao
            0, -- p_precoCMV
            0, -- p_valorCMV
            p_item_observacoes,
            p_item_idItemPreDocumento,
            0, -- p_idItemDocFiscal,
            0, -- p_idItemSeparacao,
            0, -- p_divergenciaBalanco,
            0, -- p_idItemDocTransferencia,
            r_bufferIdEstoque);
        END IF;    
      END IF;    
    END IF;
  END LOOP;
END ADD_PRE_DOC_ITEM_EST_KIT;

/

create or replace PROCEDURE ADD_ESTOQUE_KIT(
    p_config_209_filtrarGrupoEcon  IN NUMBER,
    p_config_362_calcCustoPorGrade IN NUMBER,
    p_bufferIdEstoque              IN VARCHAR2,
    p_estabelecimentoAtivo         IN NUMBER,
    p_cab_modeloDocumento          IN NUMBER,
    p_cab_operacaoInternaEstoque   IN NUMBER,
    p_cab_atualizaCustoMedio       IN NUMBER,
    p_cab_atualizaUltimaCompra     IN NUMBER,
    p_cab_entradaSaida             IN CHAR,
    p_cab_estabelecimento          IN NUMBER,
    p_cab_dataEmissao              IN DATE,
    p_cab_dataEntradaSaida         IN DATE,
    p_modDoc_geraTransferencia     IN NUMBER,
    p_modDoc_geraOperacaoEmTransit IN NUMBER,
    p_modDoc_transitoLocalEstoque  IN NUMBER,
    p_locEstTransito_indicProprPos IN CHAR,
    p_item_gradeProduto            IN NUMBER,
    p_item_localEstoque            IN NUMBER,
    p_item_pessoaParticipante      IN NUMBER,
    p_item_quantidade              IN NUMBER,
    p_item_valorCustoOperacao      IN NUMBER,
    p_item_observacoes             IN VARCHAR2,
    p_idEnderecoEstoque            IN NUMBER,
    p_locEst_indicProprPosseItem   IN CHAR,
    p_idItemPreDocumento           IN NUMBER,
    p_idItemDocFiscal              IN NUMBER,
    p_idItemSeparacao              IN NUMBER,
    p_divergenciaBalanco           IN NUMBER,
    p_idItemDocTransferencia       IN NUMBER,
    p_docTransf_estabelecEntrada   IN NUMBER,
    p_docTransf_estabelecSaida     IN NUMBER,
    r_bufferIdEstoque              OUT VARCHAR2)
IS
  v_quantidadeRateioTotal NUMBER;
  v_quantSaldoRateioTotal NUMBER;
  v_valorSaldoRateioTotal NUMBER;
  v_valorCustoManter      NUMBER;
  v_precoCustoKit         NUMBER;
  v_valorCustoKit         NUMBER;
  CURSOR c_kit IS 
    SELECT 
      kit.gradeProdutoFilho,
      kit.manterUltimoCusto,
      gradProdFilho.produto,
      prodFilho.controleEstoque,
      ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida) quantidade
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida) > 0;
BEGIN
  r_bufferIdEstoque := p_bufferIdEstoque;
  
  IF p_cab_atualizaCustoMedio = 1 THEN
    SELECT COALESCE(SUM(ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida)),0)
    INTO v_quantidadeRateioTotal
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND kit.manterUltimoCusto = 0;
    SELECT ROUND((COALESCE(SUM(ROUND(p_item_quantidade * kit.quantidade, uniFilho.casasDecimaisUnidadeMedida)
      * FUNC_ADD_BUSCA_PRECO_ULT_CUSTO(
          p_config_209_filtrarGrupoEcon,
          p_config_362_calcCustoPorGrade,
          p_cab_estabelecimento,
          TO_DATE ('01/01/1900','DD/MM/YYYY'),
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END,
          0,
          gradProdFilho.produto,
          0,
          ' ',
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante)),0)),2)
    INTO v_valorCustoManter
    FROM CAGRADEPRODUTOXKITSCOMBOS kit 
    JOIN CAGRADESPRODUTO gradProdFilho ON gradProdFilho.gradeProduto = kit.gradeProdutoFilho
    JOIN CAPRODUTOS prodFilho ON prodFilho.produto = gradProdFilho.produto
    JOIN SIUNIDADESMEDIDA uniFilho ON uniFilho.unidadeMedida = prodFilho.unidadeMedida
    WHERE kit.gradeProduto = p_item_gradeProduto
    AND kit.ativo = 1
    AND kit.manterUltimoCusto = 1;
  ELSE
    v_quantidadeRateioTotal := 0;
    v_valorCustoManter      := 0;
  END IF;
  v_quantSaldoRateioTotal := v_quantidadeRateioTotal;
  v_valorSaldoRateioTotal := p_item_valorCustoOperacao - v_valorCustoManter;
  FOR kit IN c_kit
  LOOP
    IF p_cab_atualizaCustoMedio = 1 AND kit.manterUltimoCusto = 1 THEN
      v_precoCustoKit := FUNC_ADD_BUSCA_PRECO_ULT_CUSTO(
          p_config_209_filtrarGrupoEcon,
          p_config_362_calcCustoPorGrade,
          p_cab_estabelecimento,
          TO_DATE ('01/01/1900','DD/MM/YYYY'),
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END,
          0,
          kit.produto,
          0,
          ' ',
          p_locEst_indicProprPosseItem,
          p_item_pessoaParticipante);
      v_valorCustoKit := ROUND (kit.quantidade * v_precoCustoKit,2);
    ELSIF p_cab_atualizaCustoMedio = 1 AND p_item_valorCustoOperacao > v_valorCustoManter AND v_quantSaldoRateioTotal > kit.quantidade THEN
      v_valorCustoKit := ROUND((p_item_valorCustoOperacao - v_valorCustoManter) * kit.quantidade / v_quantidadeRateioTotal,2);
      v_precoCustoKit := ROUND(v_valorCustoKit / kit.quantidade,7);
      v_quantSaldoRateioTotal := v_quantSaldoRateioTotal - kit.quantidade;
      v_valorSaldoRateioTotal := v_valorSaldoRateioTotal - v_valorCustoKit;
    ELSIF p_cab_atualizaCustoMedio = 1 AND v_valorSaldoRateioTotal > 0 THEN
      v_valorCustoKit := v_valorSaldoRateioTotal;
      v_precoCustoKit := ROUND(v_valorCustoKit / kit.quantidade,7);
      v_quantSaldoRateioTotal := 0;
      v_valorSaldoRateioTotal := 0;
    ELSE
      v_precoCustoKit := 0;
      v_valorCustoKit := 0;
    END IF;
    IF kit.controleEstoque IN (3,4) THEN
      ADD_ESTOQUE_KIT(
        p_config_209_filtrarGrupoEcon,
        p_config_362_calcCustoPorGrade,
        r_bufferIdEstoque,
        p_estabelecimentoAtivo,
        p_cab_modeloDocumento,
        p_cab_operacaoInternaEstoque,
        p_cab_atualizaCustoMedio,
        p_cab_atualizaUltimaCompra,
        p_cab_entradaSaida,
        p_cab_estabelecimento,
        p_cab_dataEmissao,
        p_cab_dataEntradaSaida,
        p_modDoc_geraTransferencia,
        p_modDoc_geraOperacaoEmTransit,
        p_modDoc_transitoLocalEstoque,
        p_locEstTransito_indicProprPos,
        kit.gradeProdutoFilho,
        p_item_localEstoque,
        p_item_pessoaParticipante,
        kit.quantidade,
        v_valorCustoKit,
        p_item_observacoes,
        p_idEnderecoEstoque,
        p_locEst_indicProprPosseItem,
        p_idItemPreDocumento,
        p_idItemDocFiscal,
        p_idItemSeparacao,
        p_divergenciaBalanco,
        p_idItemDocTransferencia,
        p_docTransf_estabelecEntrada,
        p_docTransf_estabelecSaida,
        r_bufferIdEstoque);
    ELSIF kit.controleEstoque IN(1,5,11,12) THEN
      ADD_ESTOQUE_INSERE(
        r_bufferIdEstoque, 
        p_estabelecimentoAtivo, 
        p_cab_estabelecimento,
        CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END, --p_data
        kit.gradeProdutoFilho,
        p_cab_modeloDocumento,
        p_cab_operacaoInternaEstoque,
        p_cab_atualizaCustoMedio,
        p_cab_atualizaUltimaCompra,
        p_cab_entradaSaida,
        p_locEst_indicProprPosseItem,
        p_item_pessoaParticipante,
        p_item_localEstoque,
        0, -- p_personalizacao
        0, -- p_idLoteEstoque
        p_idEnderecoEstoque,
        0, -- p_idNumeroSerie
        kit.quantidade,
        v_precoCustoKit, -- p_precoCustoOperacao
        v_valorCustoKit, -- p_totalCustoOperacao
        0, -- p_precoCMV
        0, -- p_valorCMV
        p_item_observacoes,
        p_idItemPreDocumento,
        p_idItemDocFiscal,
        p_idItemSeparacao,
        p_divergenciaBalanco,
        p_idItemDocTransferencia,
        r_bufferIdEstoque);
      IF p_modDoc_geraTransferencia = 1 AND p_modDoc_geraOperacaoEmTransit = 1 AND p_modDoc_transitoLocalEstoque > 0 AND p_docTransf_estabelecEntrada > 0 AND p_docTransf_estabelecSaida > 0 THEN
        ADD_ESTOQUE_INSERE(
          r_bufferIdEstoque, 
          p_estabelecimentoAtivo, 
          p_docTransf_estabelecSaida,
          CASE WHEN p_cab_dataEntradaSaida IS NULL OR p_cab_dataEntradaSaida < p_cab_dataEmissao THEN p_cab_dataEmissao ELSE p_cab_dataEntradaSaida END, --p_data
          kit.gradeProdutoFilho,
          p_cab_modeloDocumento,
          900,
          0,
          0,
          CASE WHEN p_cab_entradaSaida='S' THEN 'E' ELSE 'S' END,
          p_locEstTransito_indicProprPos,
          p_item_pessoaParticipante,
          p_modDoc_transitoLocalEstoque,
          0, -- p_personalizacao
          0, -- p_idLoteEstoque
          p_idEnderecoEstoque,
          0, -- p_idNumeroSerie
          kit.quantidade,
          v_precoCustoKit, -- p_precoCustoOperacao
          v_valorCustoKit, -- p_totalCustoOperacao
          0, -- p_precoCMV
          0, -- p_valorCMV
          p_item_observacoes,
          p_idItemPreDocumento,
          p_idItemDocFiscal,
          p_idItemSeparacao,
          p_divergenciaBalanco,
          p_idItemDocTransferencia,
          r_bufferIdEstoque);
      END IF;    
    END IF;
  END LOOP;
END ADD_ESTOQUE_KIT;

/

INSERT INTO SIPERSONALIZACOESCAMPOS (personalizacaoCampo, ordenacao, descricao, ativo, subcategoriaPersonalCampo, tipoCampo, mascara, exibirCampo, tipoArquivo, alteraTipoCampo, alteraExibirCampo, visivelSugestao, modificavelSugestao, obrigatorioSugestao, nomeCampoSugestao, conteudoSugestao, tabelaSistema, observacoes) VALUES (220, 20003031, 'Estabelecimento Faturamento', 1, 20003, 'N', '4', 'P', 0, 0, 0, 1, 1, 0, 'Estabelecimento Faturamento', ' ', 'PAESTABELECIMENTOS', ' ');

COMMIT;

INSERT INTO SIVERSOESSISTEMA (idVersaoSistema, versaoAplicativo, dataLiberacaoVersao, possuiConversaoTabelas, atualizada, dataAtualizacaoVersao, observacoes) VALUES (2022001008, '2022.1.8', sysdate, 1, 1, sysdate, ' ');

COMMIT;

--exec dbms_utility.compile_schema('ADDERI');
--exec dbms_stats.gather_schema_stats('ADDERI');

/*
*/