create or replace PROCEDURE CALCULA_QTDE_PESSOA(
   P_NRLISTA VARCHAR2, /*lista de cdfilial||cdservfili das unidades e servicos selecionados na lista*/
   P_CDOPERADOR VARCHAR2 /*cdoperador logado*/,
   P_CDPRATOINI VARCHAR2,/*PRATO INICIO DO INTERVALO*/
   P_CDPRATOFIM VARCHAR2, /*PRATO FIM DO INTERVALO*/
   P_IDTIPOEXPORTACAO VARCHAR2, /*ACRESCENTAR OU SOBREPOR*/
   P_IDTIPORECEITA VARCHAR2, /*PLS; P = PADRAO; L = LOCAL; S = SERVICO; QUEM NAO FOR SELECIONADO, SUBSTITUI POR X, EX: XLS, OU PXS, OU PLX, OU XXS, OU PXX, OU XLX, OU PXX*/
   P_VRQTDEPESSOA FLOAT DEFAULT NULL/*QUANTIDADE POR PESSOA, SE FOR NULL ENTAO VAI CALCULAR, SE TIVER PREENCHIDO ENTAO VAI USAR O VALOR FIXO*/
)
AS
   V_QTDEPRODUTO FLOAT(126);
   V_PESOPRATO FLOAT(126);
   V_UNIDADE_PADRAO VARCHAR2(10);
BEGIN

   /*SE MARCOU RECEITA PADRAO VAI PERCORRER AS RECEITAS PADRAO SEM USAR A LISTA DE FILIAL E SERVICO*/
   IF SUBSTR(P_IDTIPORECEITA, 1,1) = 'P' THEN
      /*LOOP TRAZENDO APENAS PRATOS PADRAO QUE EXISTE RECEITA PADRAO. OBS: PRATO LOCAL NAO PODE TER RECEITA PADRAO POR ISSO ESTE LOOP SO TRAS CDFILAUXPRAT = P*/
      FOR C_PADRAO IN (SELECT DISTINCT R.CDPRATO, R.CDFILAUXPRAT, PR.IDATIVO, PR.QTPADRAOPRAT AS QTDEPADRAO, P.SGUNIDADE AS UNIDADE_PRATO
                         FROM RECEPADR R LEFT JOIN PRATPADR PR ON PR.CDPRATO = R.CDPRATO AND PR.CDFILAUXPRAT = R.CDFILAUXPRAT
                                         INNER JOIN PRATO P ON P.CDFILAUXPRAT = R.CDFILAUXPRAT AND P.CDPRATO = R.CDPRATO
                        WHERE (P.CDPRATO BETWEEN P_CDPRATOINI AND P_CDPRATOFIM||'Z') AND (P.CDFILAUXPRAT = 'P')
      )LOOP
         V_PESOPRATO := 0;
         /*SE A OPCAO FOR SOBREPOR OU SE A OPCAO FOR ACRESCENTAR E MINHA RECEITA ESTA VAZIA ENTAO ENTRA NO IF*/
         IF C_PADRAO.QTDEPADRAO IS NULL OR P_IDTIPOEXPORTACAO = 'SOBREPOR' THEN
            /*SE O PARAMETRO DE QTDE POR PESSOA VEIO VAZIO ENTAO EU VOU TER QUE CALCULAR*/
            IF P_VRQTDEPESSOA IS NULL THEN
               FOR C_REC IN (SELECT R.CDPRODUTO, QTPRODPRAT AS QTPRODUTO, R.SGUNIDADE AS UNIDADE_RECEITA, P.SGUNIDADE AS UNIDADE_PRODUTO
                               FROM RECEPADR R INNER JOIN PRODUTO P ON R.CDPRODUTO = P.CDPRODUTO
                              WHERE R.CDFILAUXPRAT = C_PADRAO.CDFILAUXPRAT AND R.CDPRATO = C_PADRAO.CDPRATO  
               )LOOP
                  V_UNIDADE_PADRAO := NVL(C_REC.UNIDADE_RECEITA, C_REC.UNIDADE_PRODUTO);
                  /*SE A UNIDADE DO PRODUTO NA RECEITA OU DO PRODUTO FOR DIFERENTE DA UNIDADE PADRAO, CONVERTE O PRODUTO PARA A UNIDADE DO PRATO*/
                  IF V_UNIDADE_PADRAO <> C_PADRAO.UNIDADE_PRATO THEN
                     V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, C_REC.QTPRODUTO,NVL(C_REC.UNIDADE_RECEITA, C_REC.UNIDADE_PRODUTO), C_PADRAO.UNIDADE_PRATO);
                     /*SE NAO EXISTIR CONVERSAO DA UNIDADE DA RECEITA PARA UNIDADE DO PRATO ENTAO CONVERTE A UNIDADE DA RECEITA PARA A UNIDADE DE ESTOQUE DO PRODUTO E ENTAO CONVERTE DE NOVO PARA A UNIDADE DO PRATO*/
                     IF V_UNIDADE_PADRAO <> C_REC.UNIDADE_PRODUTO AND V_QTDEPRODUTO = 0 THEN
                        V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, C_REC.QTPRODUTO, V_UNIDADE_PADRAO, C_REC.UNIDADE_PRODUTO);
                        V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, V_QTDEPRODUTO, C_REC.UNIDADE_PRODUTO, C_PADRAO.UNIDADE_PRATO);
                     END IF;
                  ELSE
                     V_QTDEPRODUTO := C_REC.QTPRODUTO;
                  END IF;
                  V_PESOPRATO := V_PESOPRATO + V_QTDEPRODUTO;
               END LOOP;
            ELSE
               V_PESOPRATO := P_VRQTDEPESSOA;
            END IF;
            /*SE NAO EXISTE REGISTRO DE PRATOPADRAO ENTAO VAI INSERIR UM NOVO REGISTRO*/
            IF C_PADRAO.IDATIVO IS NULL THEN
               INSERT INTO PRATPADR (CDFILAUXPRAT, CDPRATO, QTPADRAOPRAT, CDOPERINCLUSAO) VALUES (C_PADRAO.CDFILAUXPRAT, C_PADRAO.CDPRATO, ROUND(V_PESOPRATO,5), P_CDOPERADOR);
            ELSE
               UPDATE PRATPADR
                  SET QTPADRAOPRAT = ROUND(V_PESOPRATO,5),
                      CDOPERULTATU = P_CDOPERADOR,
                      DTULTATU = SYSDATE
                WHERE CDFILAUXPRAT = C_PADRAO.CDFILAUXPRAT AND
                      CDPRATO = C_PADRAO.CDPRATO;
            END IF;
         END IF;
      END LOOP;
   END IF;

   /*SE MARCOU RECEITA LOCAL VAI PERCORRER AS RECEITAS LOCAIS USANDO A FILIAL DA LISTA DE FILIAL E SERVICO*/
   IF SUBSTR(P_IDTIPORECEITA, 2,1) = 'L' THEN
      /*LOOP TRAZENDO PRATOS PADRAO OU LOCAIS QUE EXISTE RECEITA LOCAL*/
      FOR C_LOCAL IN (SELECT DISTINCT R.CDPRATO, R.CDFILAUXPRAT, R.CDFILIAL, PR.IDATIVO, PR.QTPADRAOFILI AS QTDEPADRAO, P.SGUNIDADE AS UNIDADE_PRATO
                        FROM RECEFILI R INNER JOIN (SELECT DISTINCT SUBSTR(CDLISTA,1,4) AS CDFILIAL FROM LISTA WHERE NRLISTA = P_NRLISTA) L ON L.CDFILIAL = R.CDFILIAL
                                        LEFT JOIN PRATFILI PR ON PR.CDPRATO = R.CDPRATO AND PR.CDFILAUXPRAT = R.CDFILAUXPRAT AND PR.CDFILIAL = R.CDFILIAL
                                        INNER JOIN PRATO P ON P.CDPRATO = R.CDPRATO AND P.CDFILAUXPRAT = R.CDFILAUXPRAT
                       WHERE (R.CDPRATO BETWEEN P_CDPRATOINI AND P_CDPRATOFIM||'Z') AND (R.CDFILAUXPRAT = 'P' OR R.CDFILAUXPRAT = L.CDFILIAL)
      )LOOP
         V_PESOPRATO := 0;
         /*SE A OPCAO FOR SOBREPOR OU SE A OPCAO FOR ACRESCENTAR E MINHA RECEITA ESTA VAZIA ENTAO ENTRA NO IF*/
         IF C_LOCAL.QTDEPADRAO IS NULL OR P_IDTIPOEXPORTACAO = 'SOBREPOR' THEN
            /*SE O PARAMETRO DE QTDE POR PESSOA VEIO VAZIO ENTAO EU VOU TER QUE CALCULAR*/
            IF P_VRQTDEPESSOA IS NULL THEN
               FOR C_REC IN (SELECT R.CDFILIAL, R.CDPRODUTO, QTPRODRECLOC AS QTPRODUTO, R.SGUNIDADE AS UNIDADE_RECEITA, P.SGUNIDADE AS UNIDADE_PRODUTO
                               FROM RECEFILI R INNER JOIN PRODUTO P ON R.CDPRODUTO = P.CDPRODUTO
                              WHERE R.CDFILAUXPRAT = C_LOCAL.CDFILAUXPRAT AND R.CDPRATO = C_LOCAL.CDPRATO AND R.CDFILIAL = C_LOCAL.CDFILIAL 
               )LOOP
                  V_UNIDADE_PADRAO := NVL(C_REC.UNIDADE_RECEITA, C_REC.UNIDADE_PRODUTO);
                  /*SE A UNIDADE DO PRODUTO NA RECEITA OU DO PRODUTO FOR DIFERENTE DA UNIDADE PADRAO, CONVERTE O PRODUTO PARA A UNIDADE DO PRATO*/
                  IF V_UNIDADE_PADRAO <> C_LOCAL.UNIDADE_PRATO THEN
                     V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, C_REC.QTPRODUTO,NVL(C_REC.UNIDADE_RECEITA, C_REC.UNIDADE_PRODUTO), C_LOCAL.UNIDADE_PRATO);
                     /*SE NAO EXISTIR CONVERSAO DA UNIDADE DA RECEITA PARA UNIDADE DO PRATO ENTAO CONVERTE A UNIDADE DA RECEITA PARA A UNIDADE DE ESTOQUE DO PRODUTO E ENTAO CONVERTE DE NOVO PARA A UNIDADE DO PRATO*/
                     IF V_UNIDADE_PADRAO <> C_REC.UNIDADE_PRODUTO AND V_QTDEPRODUTO = 0 THEN
                        V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, C_REC.QTPRODUTO, V_UNIDADE_PADRAO, C_REC.UNIDADE_PRODUTO);
                        V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, V_QTDEPRODUTO, C_REC.UNIDADE_PRODUTO, C_LOCAL.UNIDADE_PRATO);
                     END IF;
                  ELSE
                     V_QTDEPRODUTO := C_REC.QTPRODUTO;
                  END IF;
                  V_PESOPRATO := V_PESOPRATO + V_QTDEPRODUTO;
               END LOOP;
            ELSE
               V_PESOPRATO := P_VRQTDEPESSOA;
            END IF;
            /*SE NAO EXISTE REGISTRO DE PRATFILI ENTAO VAI INSERIR UM NOVO REGISTRO*/
            IF C_LOCAL.IDATIVO IS NULL THEN
               INSERT INTO PRATFILI (CDFILAUXPRAT, CDPRATO, CDFILIAL, QTPADRAOFILI, CDOPERINCLUSAO) VALUES (C_LOCAL.CDFILAUXPRAT, C_LOCAL.CDPRATO, C_LOCAL.CDFILIAL, ROUND(V_PESOPRATO,5), P_CDOPERADOR);
            ELSE
               UPDATE PRATFILI
                  SET QTPADRAOFILI = ROUND(V_PESOPRATO,5),
                      CDOPERULTATU = P_CDOPERADOR,
                      DTULTATU = SYSDATE
                WHERE CDFILAUXPRAT = C_LOCAL.CDFILAUXPRAT AND
                      CDPRATO = C_LOCAL.CDPRATO AND
                      CDFILIAL = C_LOCAL.CDFILIAL;
            END IF;
         END IF;
      END LOOP;
   END IF;

   /*SE MARCOU RECEITA POR SERVICO VAI PERCORRER AS RECEITAS POR SERVICO USANDO A LISTA DE FILIAL E SERVICO*/
   IF SUBSTR(P_IDTIPORECEITA, 3,1) = 'S' THEN
      /*LOOP TRAZENDO PRATOS PADRAO OU LOCAIS QUE EXISTE RECEITA POR SERVICO*/
      FOR C_SERV IN (SELECT DISTINCT R.CDPRATO, R.CDFILAUXPRAT, R.CDFILIAL, R.CDSERVFILI, PR.IDATIVO, PR.QTPADRAOSERV AS QTDEPADRAO, P.SGUNIDADE AS UNIDADE_PRATO
                        FROM RECESERV R INNER JOIN LISTA L ON NRLISTA = P_NRLISTA AND R.CDFILIAL = SUBSTR(L.CDLISTA, 1,4) AND R.CDSERVFILI = SUBSTR(L.CDLISTA,5,5)
                                        LEFT JOIN PRATSERV PR ON PR.CDPRATO = R.CDPRATO AND PR.CDFILAUXPRAT = R.CDFILAUXPRAT AND PR.CDFILIAL = R.CDFILIAL AND PR.CDSERVFILI = R.CDSERVFILI
                                        INNER JOIN PRATO P ON P.CDPRATO = R.CDPRATO AND P.CDFILAUXPRAT = R.CDFILAUXPRAT
                       WHERE (R.CDPRATO BETWEEN P_CDPRATOINI AND P_CDPRATOFIM||'Z') AND (R.CDFILAUXPRAT = 'P' OR R.CDFILAUXPRAT = SUBSTR(L.CDLISTA, 1,4))
      )LOOP
         V_PESOPRATO := 0;
         /*SE A OPCAO FOR SOBREPOR OU SE A OPCAO FOR ACRESCENTAR E MINHA RECEITA ESTA VAZIA ENTAO ENTRA NO IF*/
         IF C_SERV.QTDEPADRAO IS NULL OR P_IDTIPOEXPORTACAO = 'SOBREPOR' THEN
            /*SE O PARAMETRO DE QTDE POR PESSOA VEIO VAZIO ENTAO EU VOU TER QUE CALCULAR*/
            IF P_VRQTDEPESSOA IS NULL THEN
               FOR C_REC IN (SELECT R.CDFILIAL, R.CDSERVFILI, R.CDPRODUTO, QTPRODRECSER AS QTPRODUTO, R.SGUNIDADE AS UNIDADE_RECEITA, P.SGUNIDADE AS UNIDADE_PRODUTO
                               FROM RECESERV R INNER JOIN PRODUTO P ON R.CDPRODUTO = P.CDPRODUTO
                              WHERE R.CDFILAUXPRAT = C_SERV.CDFILAUXPRAT AND R.CDPRATO = C_SERV.CDPRATO AND R.CDFILIAL = C_SERV.CDFILIAL AND R.CDSERVFILI = C_SERV.CDSERVFILI
               )LOOP
                  V_UNIDADE_PADRAO := NVL(C_REC.UNIDADE_RECEITA, C_REC.UNIDADE_PRODUTO);
                  /*SE A UNIDADE DO PRODUTO NA RECEITA OU DO PRODUTO FOR DIFERENTE DA UNIDADE PADRAO, CONVERTE O PRODUTO PARA A UNIDADE DO PRATO*/
                  IF V_UNIDADE_PADRAO <> C_SERV.UNIDADE_PRATO THEN
                     V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, C_REC.QTPRODUTO,NVL(C_REC.UNIDADE_RECEITA, C_REC.UNIDADE_PRODUTO), C_SERV.UNIDADE_PRATO);
                     /*SE NAO EXISTIR CONVERSAO DA UNIDADE DA RECEITA PARA UNIDADE DO PRATO ENTAO CONVERTE A UNIDADE DA RECEITA PARA A UNIDADE DE ESTOQUE DO PRODUTO E ENTAO CONVERTE DE NOVO PARA A UNIDADE DO PRATO*/
                     IF V_UNIDADE_PADRAO <> C_REC.UNIDADE_PRODUTO AND V_QTDEPRODUTO = 0 THEN
                        V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, C_REC.QTPRODUTO, V_UNIDADE_PADRAO, C_REC.UNIDADE_PRODUTO);
                        V_QTDEPRODUTO := CONVERTE_UNIDADE_PRODUTO(C_REC.CDPRODUTO, V_QTDEPRODUTO, C_REC.UNIDADE_PRODUTO, C_SERV.UNIDADE_PRATO);
                     END IF;
                  ELSE
                     V_QTDEPRODUTO := C_REC.QTPRODUTO;
                  END IF;
                  V_PESOPRATO := V_PESOPRATO + V_QTDEPRODUTO;
               END LOOP;
            ELSE
               V_PESOPRATO := P_VRQTDEPESSOA;
            END IF;
            /*SE NAO EXISTE REGISTRO DE PRATFILI ENTAO VAI INSERIR UM NOVO REGISTRO*/
            IF C_SERV.IDATIVO IS NULL THEN
               INSERT INTO PRATSERV (CDFILAUXPRAT, CDPRATO, CDFILIAL, CDSERVFILI, QTPADRAOSERV, CDOPERINCLUSAO) VALUES (C_SERV.CDFILAUXPRAT, C_SERV.CDPRATO, C_SERV.CDFILIAL, C_SERV.CDSERVFILI, ROUND(V_PESOPRATO,5), P_CDOPERADOR);
            ELSE
               UPDATE PRATSERV
                  SET QTPADRAOSERV = ROUND(V_PESOPRATO,5),
                      CDOPERULTATU = P_CDOPERADOR,
                      DTULTATU = SYSDATE
                WHERE CDFILAUXPRAT = C_SERV.CDFILAUXPRAT AND
                      CDPRATO = C_SERV.CDPRATO AND
                      CDFILIAL = C_SERV.CDFILIAL AND
                      CDSERVFILI = C_SERV.CDSERVFILI;
            END IF;
         END IF;
      END LOOP;
   END IF;
   COMMIT;
END;
/