CREATE OR REPLACE PROCEDURE CALCULA_QUANTIDADESM(
  P_CDFILIAL         IN     FILIAL.CDFILIAL%TYPE,
  P_CDCIA            IN     COMPANHIA.CDCIA%TYPE,
  P_NRVOO            IN     VOO.NRVOO%TYPE,
  P_CDTRECHO         IN     VOOTRECHO.CDTRECHO%TYPE,
  P_NRSERVICOCIAFILI IN     SERVPLANOM.NRSERVICOCIAFILI%TYPE,
  P_CDCLASSE         IN     CLASSE.CDCLASSE%TYPE,
  P_CDCICLO          IN     CICLOCIA.CDCICLO%TYPE,
  P_DTREF            IN     DATE,
  P_QTTOTPAX         IN     PREVISAOPAXM.QTTOTPAXAT%TYPE,
  P_IDPROPSERV       IN OUT SERVPLANOM.IDTIPSCBOSP%TYPE,
  P_QTSESOLICSP      OUT    SERVPLANOM.QTSESOLICSP%TYPE,
  P_QTSESBYPRSP      IN OUT SERVPLANOM.QTSESBYPRSP%TYPE,
  P_NRPROP           IN OUT FLOAT,
  P_VRPELOAD         IN OUT FLOAT,
  P_QTFIX            IN OUT FLOAT,
  P_QTSERVFAT        OUT    FLOAT
)
AS
  V_SGCIA           COMPANHIA.SGCIA%TYPE;  
  V_SGCLASSE        CLASSE.SGCLASSE%TYPE;
  V_TESTE           NUMBER;
  V_QTSERVICO       PROPSERVICOM.QTSERVICO%TYPE;
  V_QTSESOLICSP     SERVPLANOM.QTSESOLICSP%TYPE;
  V_IDPROPORCAO     VARCHAR2(1);
  V_QTPROPORCAO     FLOAT;
  V_QTPROPANTERIOR  FLOAT;
  V_DSSERVICOCIAFILI VARCHAR2(250);  
  V_IDCICLO VARCHAR2(20);
  V_SERVICO VARCHAR2(500);
  V_CONTADOR NUMBER;
  V_NRTABPRECO VARCHAR2(3);
  V_ITEM_TAB_PRECO NUMBER;
  V_NRSEQPRECO NUMBER;
  V_IDCALCPROPDLCOM VARCHAR2(1);
  V_IDTPPRECO VARCHAR2(1);
  V_IDSERVICO VARCHAR2(1);
  V_CDMANCIA VARCHAR2(4);
  V_IDVINCULOMANUAL VARCHAR2(1);
  V_IDPROPSUBSEMAM VARCHAR2(1);
  V_QTPROPSUBSEMAM_DIF VARCHAR2(1);
  V_QTPROPSUBSEMAM FLOAT;
  V_NRSERVICOCIAFILIMENU NUMBER;
  V_CDSUBGRU VARCHAR2(10);
  V_QTSUBGRU_VINCULADOS NUMBER;
  V_NUM_LOADINGS NUMBER;
  V_PROPORCAO_INFORMADA VARCHAR2(1);
  V_SERVICO_VINCULADO NUMBER;
  V_QTSERVICOS FLOAT;
  V_DSMANUAL VARCHAR2(2000);
  V_MANUAL VARCHAR2(2000); 
  V_MENU_APROVADO VARCHAR2(1);
  V_MENU_VIGENTE VARCHAR2(1);
  V_NRORG NUMBER;
  V_NRSEQSUBGRUSEMAM NUMBER;
  V_DESC_VOO VARCHAR2(50);
BEGIN

  V_PROPORCAO_INFORMADA := P_IDPROPSERV;

  SELECT MAX(SGCIA) INTO V_SGCIA FROM COMPANHIA WHERE CDCIA = P_CDCIA;

  V_DESC_VOO := V_SGCIA || '-' || P_NRVOO;

  SELECT MAX(IDSERVICO), MAX(SCF.DSSERVICOCIAFILI), MAX(CL.SGCLASSE), MAX(CI.IDCICLO), MAX(SCF.IDTPPRECO)
    INTO V_IDSERVICO, V_DSSERVICOCIAFILI, V_SGCLASSE, V_IDCICLO, V_IDTPPRECO
    FROM SERVCICLO SC
         INNER JOIN SERVICOCIAFILI SCF ON SCF.CDFILIAL = SC.CDFILIAL AND
                                          SCF.CDCIA = SC.CDCIA AND
                                          SCF.NRSERVICOCIAFILI = SC.NRSERVICOCIAFILI
         INNER JOIN SERVICOGEN SG ON SG.NRSERVICOGEN = SCF.NRSERVICOGEN                                          
         INNER JOIN CLASSE CL ON CL.CDCLASSE = SC.CDCLASSE
         INNER JOIN CICLO CI ON CI.CDCICLO = SC.CDCICLO
   WHERE (SC.CDFILIAL = P_CDFILIAL) AND
         (SC.CDCIA = P_CDCIA) AND
         (SC.NRSERVICOCIAFILI = P_NRSERVICOCIAFILI) AND
         (SC.CDCLASSE = P_CDCLASSE) AND
         (SC.CDCICLO = P_CDCICLO);

  V_SERVICO := V_DSSERVICOCIAFILI||'$$'||V_SGCLASSE||'$$'||V_IDCICLO;  


  SELECT MAX(IDVINCULOMANUAL)
    INTO V_IDVINCULOMANUAL
    FROM CIAFILI
   WHERE CDFILIAL = P_CDFILIAL
     AND CDCIA = P_CDCIA;

  --Se a proporcao nao foi informada ou foi informada e tem que ler da tabela de precos
  IF V_PROPORCAO_INFORMADA IS NULL OR P_IDPROPSERV = '3' THEN

    BEGIN
      SELECT COUNT(*), MAX(NRTABPRECO)
      INTO V_TESTE, V_NRTABPRECO
      FROM TABPRECOSEM
      WHERE (CDFILIAL = P_CDFILIAL) AND
            (CDCIA    = P_CDCIA   ) AND
            (P_DTREF BETWEEN DTINIVIGTAB AND DTFIMVIGTAB);
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
       V_TESTE := NULL;
    END;
    IF (NVL(V_TESTE, 0) < 1) THEN
       --Sem tabela de preco ativa na data
       RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00043' || '$$' || V_SGCIA|| '$$' ||TO_CHAR(P_DTREF, 'DD/MM/YYYY') || 'APPERRMSGEND', TRUE);
    END IF;

    IF (V_TESTE > 1) THEN
         -- Mais de uma tabela de preco ativa para a companhia
       RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00009' || '$$' ||V_SGCIA || 'APPERRMSGEND', TRUE);
    END IF;

    SELECT COUNT(P.NRSEQPRECO),MIN(P.NRSEQPRECO),
             MAX(P.IDPROPORCAO), MAX(P.QTPROPORCAO), MAX(P.CDMANCIA), MAX(NRORG)
      INTO V_ITEM_TAB_PRECO,V_NRSEQPRECO,
           V_IDPROPORCAO, V_QTPROPORCAO, V_CDMANCIA, V_NRORG
      FROM PRECOSECIAM P
     WHERE (P.CDFILIAL   = P_CDFILIAL  ) AND
           (P.CDCIA      = P_CDCIA     ) AND
           (P.NRTABPRECO = V_NRTABPRECO) AND
           (P.NRSERVICOCIAFILI  = P_NRSERVICOCIAFILI ) AND
           (P.CDCLASSE  = P_CDCLASSE ) AND
           (P.CDCICLO   = P_CDCICLO ) AND
           (P_DTREF BETWEEN P.DTINIVIGSE AND P.DTFIMVIGSE);
    IF (V_ITEM_TAB_PRECO > 1) THEN
       --Mais de um preco para o item
       RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00010'|| '$$' || V_SERVICO || '$$' || V_DESC_VOO || 'APPERRMSGEND', TRUE);
    END IF;

    IF (V_ITEM_TAB_PRECO = 0) THEN
       --Item sem preco
       RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00008'|| '$$' || V_SERVICO || '$$' || V_DESC_VOO || 'APPERRMSGEND', TRUE);
    END IF;    
    
  END IF;  

  -- Pega a proporcao do cadastro da tabela de preco, se ela nao foi informada
  IF P_IDPROPSERV IS NULL THEN
     P_IDPROPSERV := TO_CHAR(GET_PROPORCAO_ITEMFAT(P_CDFILIAL, P_CDCIA, V_NRTABPRECO, P_NRSERVICOCIAFILI, P_CDCLASSE, P_CDCICLO, V_NRSEQPRECO, P_DTREF, V_NRORG, 'S', 'S'));
     V_QTPROPORCAO := GET_PROPORCAO_ITEMFAT(P_CDFILIAL, P_CDCIA, V_NRTABPRECO, P_NRSERVICOCIAFILI, P_CDCLASSE, P_CDCICLO, V_NRSEQPRECO, P_DTREF, V_NRORG, 'N', 'S');
  ELSE
     V_QTPROPORCAO := CASE WHEN P_IDPROPSERV = '2' THEN P_NRPROP
                           WHEN P_IDPROPSERV = '4' THEN P_VRPELOAD
                           WHEN P_IDPROPSERV = '5' THEN P_QTFIX
                      END;
  END IF;
  
  IF P_IDPROPSERV = '1' THEN
     IF P_QTTOTPAX IS NULL OR (P_QTTOTPAX = 0)  THEN
        RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00003' || '$$' || V_SERVICO || 'APPERRMSGEND', TRUE);

        /*{'Geracao interrompida. O servico '||
        V_CDSERVICO||' - '||V_DSSERVICO||' do voo '||V_SGCIA||' - '||P_NRVOO||
        ' pertence a classe '||V_SGCLASSE||' mas a quantidade de passageiros desta classe nao foi informada. '||
        'Verifique a previsao de passageiros informada para esta classe e tente novamente.', True);*/
     END IF;

     P_QTSESOLICSP := P_QTTOTPAX;
  END IF;

  IF P_IDPROPSERV = '2' THEN /* PROPORCIONAL FIXA */
    IF (V_QTPROPORCAO IS NULL) OR (V_QTPROPORCAO = 0) THEN
      RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00004' || '$$' || V_SERVICO || 'APPERRMSGEND', TRUE);

      /*Geracao interrompida. O servico '||
      V_CDSERVICO||' - '||V_DSSERVICO||' do voo '||V_SGCIA||' - '||P_NRVOO||
      ' possui proporcao fixa, mas o valor da proporcao nao se encontra cadastrado. '||
      'Verifique a funcao Ambiente - Cadastros - Configuracao de Servicos e tente novamente.'*/
    END IF;

    /* Alterado para sempre arredondar para cima quando o valor for
       menor que 1 e maior que 0. */
    /*V_QTSESOLICSP := (P_QTTOTPAX/P_NRPROPAXSE);
    IF (V_QTSESOLICSP > 0) AND (V_QTSESOLICSP < 1) THEN
      P_QTSESOLICSP := 1;
    ELSE
      P_QTSESOLICSP := ROUND(V_QTSESOLICSP);
    END IF;*/

    /* Alterado dia 24/01/2001 por Leonardo Monteiro
       conforme solicitacao 4255 para sempre arredondar para cima. */
    P_QTSESOLICSP := CEIL(P_QTTOTPAX/V_QTPROPORCAO);

    P_QTSESBYPRSP := CEIL(P_QTSESBYPRSP/V_QTPROPORCAO);
  END IF;

  IF P_IDPROPSERV = '3' THEN /* PROPORCIONAL VARIAVEL */
    /*So pega tabela do menu grid se nao for Handling, se o vinculo for obrigatorio*/
    IF (V_IDSERVICO NOT IN ('3', '5')) AND V_IDVINCULOMANUAL = 'S' THEN

      /*Busca o subgrupo vinculado atualmente com o item de faturamento*/
      SELECT MAX(SG.NRSERVICOCIAFILI), MAX(SG.CDSUBGRU), MAX(SG.NRSEQSUBGRUSEMAM)
        INTO V_SERVICO_VINCULADO, V_CDSUBGRU, V_NRSEQSUBGRUSEMAM
        FROM SUBGRUTABPRECOM S 
             INNER JOIN SUBGRUSEMAM SG ON SG.CDFILIAL = S.CDFILIAL AND
                                          SG.CDCIA = S.CDCIA AND
                                          SG.CDMANCIA = S.CDMANCIA AND
                                          SG.NRSERVICOCIAFILI = S.NRSERVICOCIAFILI AND
                                          SG.CDCLASSE = S.CDCLASSE AND
                                          SG.CDSUBGRU = S.CDSUBGRU AND
                                          SG.NRSEQSUBGRUSEMAM = S.NRSEQSUBGRUSEMAM
       WHERE S.CDFILIAL = P_CDFILIAL
         AND S.CDCIA = P_CDCIA
         AND S.NRTABPRECO = V_NRTABPRECO
         AND S.NRSERVICOCIAFILIPRECO = P_NRSERVICOCIAFILI
         AND S.CDCLASSE = P_CDCLASSE
         AND S.CDCICLO = P_CDCICLO
         AND S.NRSEQPRECO = V_NRSEQPRECO
         AND (P_DTREF BETWEEN SG.DTINIVGSUMA AND SG.DTFIMVGSUMA);

      SELECT COUNT(QTSUBGRUPO)
        INTO V_TESTE
        FROM PROPSUBGRUSE
       WHERE (CDFILIAL  = P_CDFILIAL ) AND
             (CDCIA     = P_CDCIA    ) AND          
             (CDMANCIA = V_CDMANCIA) AND
             (NRSERVICOCIAFILI = V_SERVICO_VINCULADO) AND
             (CDCLASSE  = P_CDCLASSE ) AND
             (CDSUBGRU  = V_CDSUBGRU ) AND
             (NRSEQSUBGRUSEMAM = V_NRSEQSUBGRUSEMAM) AND             
             (P_QTTOTPAX BETWEEN QTPAXDE AND QTPAXATE);
    ELSE    
      SELECT COUNT(QTSERVICO)
      INTO   V_TESTE
      FROM   PROPORCAOPRECO
      WHERE (CDFILIAL  = P_CDFILIAL ) AND
            (CDCIA     = P_CDCIA    ) AND          
            (NRSERVICOCIAFILI = P_NRSERVICOCIAFILI) AND
            (CDCLASSE  = P_CDCLASSE ) AND
            (CDCICLO   = P_CDCICLO  ) AND
            (NRTABPRECO = V_NRTABPRECO) AND
            (NRSEQPRECO = V_NRSEQPRECO) AND
            (P_QTTOTPAX BETWEEN QTPAXDE AND QTPAXATE);

    END IF;
    /*Se existe tabela de proporcao variavel*/
    IF (V_TESTE <> 0) THEN
      IF (V_IDSERVICO NOT IN ('3', '5')) AND V_IDVINCULOMANUAL = 'S' THEN
         SELECT MAX(QTSUBGRUPO)
           INTO V_QTSERVICO
           FROM PROPSUBGRUSE
           WHERE (CDFILIAL  = P_CDFILIAL ) AND
                 (CDCIA     = P_CDCIA    ) AND          
                 (CDMANCIA = V_CDMANCIA) AND
                 (NRSERVICOCIAFILI = V_SERVICO_VINCULADO) AND
                 (CDCLASSE  = P_CDCLASSE ) AND
                 (CDSUBGRU  = V_CDSUBGRU ) AND
                 (NRSEQSUBGRUSEMAM = V_NRSEQSUBGRUSEMAM) AND
                 (P_QTTOTPAX BETWEEN QTPAXDE AND QTPAXATE);
      ELSE  
         SELECT MAX(QTSERVICO)
           INTO V_QTSERVICO
           FROM PROPORCAOPRECO
           WHERE (CDFILIAL  = P_CDFILIAL ) AND
                 (CDCIA     = P_CDCIA    ) AND
                 (NRSERVICOCIAFILI = P_NRSERVICOCIAFILI) AND
                 (CDCLASSE  = P_CDCLASSE ) AND
                 (CDCICLO   = P_CDCICLO  ) AND
                 (NRTABPRECO = V_NRTABPRECO) AND
                 (NRSEQPRECO = V_NRSEQPRECO) AND
                 (P_QTTOTPAX BETWEEN QTPAXDE AND QTPAXATE);
      END IF;
    ELSE
      V_QTSERVICO   := NULL;
    END IF;
    IF (V_QTSERVICO IS NOT NULL) THEN
      P_QTSESOLICSP := V_QTSERVICO;
    ELSE
      RAISE_APPLICATION_ERROR(-20502, 'APPERRMSGSTR' || 'APP-00005' || '$$' || V_SERVICO || '$$' || TO_CHAR(P_QTTOTPAX) || 'APPERRMSGEND', TRUE);

      /*Geracao interrompida. O servico '||
      V_CDSERVICO||' - '||V_DSSERVICO||' do voo '||V_SGCIA||' - '||P_NRVOO||
      ' possui Proporcao Variavel, mas nao  se encontra configurado na Proporcao de Servico por Passageiro. '||
      'Altere seu tipo de proporcao na funcao Ambiente - Cadastros - Configuracao de Servicos ou configure este servico.'*/
    END IF;
  END IF;

  IF P_IDPROPSERV = '4' THEN /* LOADING */
    IF (V_QTPROPORCAO IS NULL) OR (V_QTPROPORCAO = 0) THEN
      RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00006' || '$$' || V_SERVICO || 'APPERRMSGEND', TRUE);

      /*Geracao interrompida. O servico '||
      V_CDSERVICO||' - '||V_DSSERVICO||' do voo '||V_SGCIA||' - '||P_NRVOO||
      ' possui proporcao do tipo Loading, mas o valor percentual do Loading nao se encontra cadastrado. '||
      'Verifique a funcao Ambiente - Cadastros - Configuracao de Servicos e tente novamente.', */
    END IF;

    /* Alterado para sempre arredondar para cima quando o valor for
    menor que 1 e maior que 0. */
    P_QTSESOLICSP := ((P_QTTOTPAX * V_QTPROPORCAO)/100);
    IF (P_QTSESOLICSP > 0) AND (P_QTSESOLICSP < 1) THEN
      P_QTSESOLICSP := 1;
    ELSE
      P_QTSESOLICSP := ROUND(P_QTSESOLICSP);
    END IF;

    P_QTSESBYPRSP := ((P_QTSESBYPRSP * V_QTPROPORCAO)/100);
    IF (P_QTSESBYPRSP > 0) AND (P_QTSESBYPRSP < 1) THEN
      P_QTSESBYPRSP := 1;
    ELSE
      P_QTSESBYPRSP := ROUND(P_QTSESBYPRSP);
    END IF;
  END IF;

  IF P_IDPROPSERV = '5' THEN /* QUANTIDADE FIXA */
    /*Utiliza a proporcao */
    P_QTFIX := NVL(P_QTFIX, 0);
    V_QTPROPORCAO := CASE WHEN P_QTFIX > 0 THEN P_QTFIX ELSE V_QTPROPORCAO END;
    IF (V_QTPROPORCAO  IS NULL) OR (V_QTPROPORCAO = 0) THEN /* PARA NAO GRAVAR VALOR NULO */
      RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00007' || '$$' || V_SERVICO || 'APPERRMSGEND', TRUE);

      /*Geracao interrompida. O servico '||
      V_CDSERVICO||' - '||V_DSSERVICO||' do voo '||V_SGCIA||' - '||P_NRVOO||
      ' possui Quantidade Fixa, mas o valor desta nao se encontra cadastrado ou possui valor zero. '||
      'Verifique a funcao Ambiente - Cadastros - Configuracao de Servicos e tente novamente.'*/
    END IF;
    P_QTSESOLICSP  := 0;
  END IF;

  P_NRPROP := CASE WHEN P_IDPROPSERV = '2' THEN V_QTPROPORCAO ELSE 0 END;      
  P_VRPELOAD := CASE WHEN P_IDPROPSERV = '4' THEN V_QTPROPORCAO ELSE 0 END;      
  P_QTFIX := CASE WHEN P_IDPROPSERV = '5' THEN V_QTPROPORCAO ELSE 0 END;

  P_QTSERVFAT := 0;
  IF (V_IDTPPRECO = '2') and     /* PRECO TOTAL */
     ((P_QTFIX+P_QTSESOLICSP) > 0) THEN
     P_QTSERVFAT := 1;
  ELSE
     P_QTSERVFAT := P_QTFIX + P_QTSESOLICSP;
  END IF;

END;
/