create or replace PROCEDURE COPIA_SERV_MENU_GRID
(
  P_CDFILIPROC IN VARCHAR2,
  P_CDFILIALORI IN VARCHAR2,
  P_CDCIAORI IN VARCHAR2,
  P_CDMANCIAORI IN VARCHAR2,
  P_NRLISTASERVORI IN VARCHAR2,
  P_NRPROXLISTASUBGRU IN VARCHAR2,  
  P_CDFILIALDES IN VARCHAR2,
  P_CDCIADES IN VARCHAR2,
  P_CDMANCIADES IN VARCHAR2,
  P_IMAGEMDEFAULT IN VARCHAR2,
  P_COPIA_IMAGEM IN VARCHAR2,
  P_SOBRESCREVER IN VARCHAR2,
  P_COPIA_PRODCIA IN VARCHAR2,
  P_COPIA_IT IN VARCHAR2,
  P_CDOPERADOR IN VARCHAR2,
  P_NRORG IN NUMBER DEFAULT 1,
  P_NRLISTAERROS OUT NUMBER
)
AS   
   V_SEQ VARCHAR2(20);
   V_MSGERRO VARCHAR2(2000);
   V_NRLISTA VARCHAR2(10);
   V_LISTACICLOS VARCHAR2(2000);
   V_IDSITUAPROPCIA VARCHAR2(30);
   V_NRSERVICOCIAFILI NUMBER;
   V_NRSERVICOCIAFILIDES NUMBER;
   V_EXISTE_NO_DESTINO NUMBER;      

   FUNCTION RETORNA_NUMERO_SERVICO(P_NRSERVICOCIAFILI NUMBER, P_CDCLASSE VARCHAR2) RETURN NUMBER
   AS      
      V_NOVO_SERVICO NUMBER;
      V_NRSERVICOGEN NUMBER;
      V_TXCOMENTASE VARCHAR2(500);
      V_CDPRODUTO VARCHAR2(10);
      V_CDSETOR VARCHAR2(4);      
      V_IDTIPMANUAL VARCHAR2(1);
      V_IDSERVESP VARCHAR2(1);
      V_IDFATSE VARCHAR2(1);
      V_DSSERVICOCIAFILI VARCHAR2(100);
      V_DSSERVICOCIAFILIING VARCHAR2(100);
      V_DSSERVICOCIAFILIESP VARCHAR2(100);      
      V_IDTPPRECO VARCHAR2(1);
      V_NRPADSERVICOM NUMBER;
      V_IDFATVENDADEVOL VARCHAR2(30);      
      V_EXISTE_SERVICO NUMBER;
      V_DSCLASSE VARCHAR2(30);
      V_EXISTE_CLASSECIA NUMBER;
   BEGIN
      /*Busca os dados do servico de origem*/
      SELECT SCF.NRSERVICOGEN, SCF.CDPRODUTO, SCF.CDSETOR, 
             SCF.TXCOMENTASE, SCF.IDTIPMANUAL, SCF.IDSERVESP, SCF.IDFATSE, 
             SCF.DSSERVICOCIAFILI, SCF.DSSERVICOCIAFILIING, SCF.DSSERVICOCIAFILIESP, SCF.IDTPPRECO, 
             SCF.NRPADSERVICOM, SCF.IDFATVENDADEVOL
        INTO V_NRSERVICOGEN, V_CDPRODUTO, V_CDSETOR,
             V_TXCOMENTASE, V_IDTIPMANUAL, V_IDSERVESP, V_IDFATSE,
             V_DSSERVICOCIAFILI, V_DSSERVICOCIAFILIING, V_DSSERVICOCIAFILIESP, V_IDTPPRECO,
             V_NRPADSERVICOM, V_IDFATVENDADEVOL
        FROM SERVICOCIAFILI SCF
       WHERE SCF.CDFILIAL = P_CDFILIALORI
         AND SCF.CDCIA = P_CDCIAORI
         AND SCF.NRSERVICOCIAFILI = P_NRSERVICOCIAFILI;

      IF P_CDFILIALORI = P_CDFILIALDES AND P_CDCIAORI = P_CDCIADES THEN
         /*Verifica se o servico ja e utilizado no menu*/
         SELECT COUNT(NRSERVICOCIAFILI)
           INTO V_EXISTE_SERVICO
           FROM SERVMANUALM
          WHERE CDFILIAL = P_CDFILIALDES
            AND CDCIA = P_CDCIADES
            AND CDMANCIA = P_CDMANCIADES
            AND NRSERVICOCIAFILI = P_NRSERVICOCIAFILI
            AND CDCLASSE = P_CDCLASSE;
         IF V_EXISTE_SERVICO > 0 THEN
            RETURN P_NRSERVICOCIAFILI;
         END IF;
      END IF;

      /* Verifica se existe um servico no menu com esse nome */
      SELECT MAX(S.NRSERVICOCIAFILI)
           INTO V_EXISTE_SERVICO
           FROM SERVMANUALM S 
                INNER JOIN SERVICOCIAFILI SCF ON SCF.CDFILIAL = S.CDFILIAL AND
                                                 SCF.CDCIA = S.CDCIA AND
                                                 SCF.NRSERVICOCIAFILI = S.NRSERVICOCIAFILI
          WHERE S.CDFILIAL = P_CDFILIALDES
            AND S.CDCIA = P_CDCIADES
            AND S.CDMANCIA = P_CDMANCIADES
            AND SCF.DSSERVICOCIAFILI = V_DSSERVICOCIAFILI
            AND S.CDCLASSE = P_CDCLASSE
          ORDER BY S.NRSERVICOCIAFILI;
      
      IF V_EXISTE_SERVICO IS NOT NULL THEN
         RETURN V_EXISTE_SERVICO;
      END IF;

      /*Verifica se na companhia existe um servico com o mesmo nome ATIVO*/
      SELECT MAX(NRSERVICOCIAFILI)
        INTO V_EXISTE_SERVICO
        FROM SERVICOCIAFILI
       WHERE CDFILIAL = P_CDFILIALDES
         AND CDCIA = P_CDCIADES
         AND DSSERVICOCIAFILI = V_DSSERVICOCIAFILI
         AND IDSITSERVICO = '1'
         AND IDTIPOSERVICO IN ('ITEMMENUGRID', 'AMBOS');
      IF V_EXISTE_SERVICO IS NULL THEN
         /*Verifica se na companhia existe um servico com o mesmo nome ATIVO*/
         SELECT MAX(NRSERVICOCIAFILI)
           INTO V_EXISTE_SERVICO
           FROM SERVICOCIAFILI
          WHERE CDFILIAL = P_CDFILIALDES
            AND CDCIA = P_CDCIADES
            AND DSSERVICOCIAFILI = V_DSSERVICOCIAFILI
            AND IDSITSERVICO = '2'
            AND IDTIPOSERVICO IN ('ITEMMENUGRID', 'AMBOS');
         IF V_EXISTE_SERVICO IS NULL THEN
            NOVO_CODIGO_NT('SERVICOCIAFILI', V_SEQ);
            V_NOVO_SERVICO := TO_NUMBER(V_SEQ);

            INSERT INTO SERVICOCIAFILI
            (CDFILIAL, CDCIA, NRSERVICOCIAFILI, NRSERVICOGEN, 
            CDPRODUTO, CDSETOR, IDSITSERVICO, TXCOMENTASE,
            IDTIPMANUAL, IDSERVESP, IDFATSE,
            DSSERVICOCIAFILI, DSSERVICOCIAFILIING, DSSERVICOCIAFILIESP,
            IDTPPRECO, NRPADSERVICOM, IDTIPOSERVICO, IDFATVENDADEVOL,
            NRORG, NRORGINCLUSAO, NRORGULTATU,
            CDOPERINCLUSAO, CDOPERULTATU,
            DTINCLUSAO, DTULTATU)
            VALUES
            (P_CDFILIALDES, P_CDCIADES, V_NOVO_SERVICO, V_NRSERVICOGEN,
            V_CDPRODUTO, V_CDSETOR, '1', V_TXCOMENTASE,
            V_IDTIPMANUAL, V_IDSERVESP, V_IDFATSE,
            V_DSSERVICOCIAFILI, V_DSSERVICOCIAFILIING, V_DSSERVICOCIAFILIESP,
            V_IDTPPRECO, V_NRPADSERVICOM, 'ITEMMENUGRID', V_IDFATVENDADEVOL,
            P_NRORG, P_NRORG, P_NRORG,
            P_CDOPERADOR, P_CDOPERADOR,
            SYSDATE, SYSDATE);
         END IF;
      END IF;

      IF V_EXISTE_SERVICO IS NOT NULL THEN
         V_NOVO_SERVICO := V_EXISTE_SERVICO;
      END IF;

      /*Verifica se a companhia esta vinculada a essa classe*/
      SELECT COUNT(1)
        INTO V_EXISTE_CLASSECIA
        FROM CLASSECIA
       WHERE CDFILIAL = P_CDFILIALDES
         AND CDCIA = P_CDCIADES
         AND CDCLASSE = P_CDCLASSE;

      IF V_EXISTE_CLASSECIA = 0 THEN
         SELECT MAX(DSCLASSE)
           INTO V_DSCLASSE
           FROM CLASSE 
          WHERE CDCLASSE = P_CDCLASSE;

         INSERT INTO CLASSECIA
         (CDFILIAL, CDCIA, CDCLASSE, DSCLASSECIA,DTULTATUCLAC,
          NRORG, NRORGINCLUSAO, NRORGULTATU,
          CDOPERINCLUSAO, CDOPERULTATU,
          DTINCLUSAO, DTULTATU, IDATIVO)
         VALUES
         (P_CDFILIALDES, P_CDCIADES, P_CDCLASSE, V_DSCLASSE, SYSDATE,
          P_NRORG, P_NRORG, P_NRORG,
          P_CDOPERADOR, P_CDOPERADOR,
          SYSDATE, SYSDATE, 'S');
      END IF;

      RETURN V_NOVO_SERVICO;
   END;

BEGIN
  IF P_CDFILIALORI = P_CDFILIALDES AND
      P_CDCIAORI = P_CDCIADES AND
      P_CDMANCIAORI = P_CDMANCIADES THEN
      RETURN;
  END IF;
  /* Como a novo codigo executa um commit, 
     foi acrescentado o parametro P_NRPROXLISTASUBGRU
     para ser utilizado quando essa procedure for chamada a partir de outra 
  */
  IF P_NRPROXLISTASUBGRU IS NULL THEN
     NOVO_CODIGO_NT('LISTA', V_SEQ);
     V_NRLISTA := SUBSTR(V_SEQ, -10);
  ELSE
     V_NRLISTA := P_NRPROXLISTASUBGRU;
  END IF;

  /*
  Verifica se o status do manual de destino
  */
  SELECT MAX(IDSITUAPROPCIA)
    INTO V_IDSITUAPROPCIA
    FROM MANUALCIAM
   WHERE CDFILIAL = P_CDFILIALDES
     AND CDCIA = P_CDCIADES
     AND CDMANCIA = P_CDMANCIADES;

  /*Operacao bloqueada. Manual de destino ja esta em proposta ou reprovado.*/
  IF V_IDSITUAPROPCIA NOT IN ('E', 'A') THEN
     RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00046' || 'APPERRMSGEND' , TRUE);
  END IF;


  P_NRLISTAERROS := NULL;  

  IF P_NRLISTAERROS IS NOT NULL THEN
    RETURN;
  END IF;

  /* insere todos os servicos do manual de origem no manual de destino (que ainda nao existam no destino) */
  FOR CUR_SERV IN
   (     
     SELECT S.NRSERVICOCIAFILI, S.CDCLASSE, SCF.DSSERVICOCIAFILI, CL.SGCLASSE
       FROM SERVMANUALM S
            INNER JOIN LISTA L ON L.NRLISTA = P_NRLISTASERVORI AND
                                 S.NRSERVICOCIAFILI = TO_NUMBER(SUBSTR(L.CDLISTA, 1, INSTR(L.CDLISTA, '|') - 1)) AND
                                 S.CDCLASSE = SUBSTR(L.CDLISTA, INSTR(L.CDLISTA, '|') + 1, 20)
           INNER JOIN SERVICOCIAFILI SCF ON SCF.CDFILIAL = S.CDFILIAL AND
                                            SCF.CDCIA = S.CDCIA AND
                                            SCF.NRSERVICOCIAFILI = S.NRSERVICOCIAFILI
           INNER JOIN CLASSE CL ON CL.CDCLASSE = S.CDCLASSE
     WHERE S.CDFILIAL = P_CDFILIALORI
       AND S.CDCIA    = P_CDCIAORI
       AND S.CDMANCIA = P_CDMANCIAORI
       AND S.NRORG    = P_NRORG
    ) LOOP

    V_NRSERVICOCIAFILIDES := RETORNA_NUMERO_SERVICO(CUR_SERV.NRSERVICOCIAFILI, CUR_SERV.CDCLASSE);

    SELECT COUNT(1)
      INTO V_EXISTE_NO_DESTINO
      FROM SERVMANUALM
     WHERE CDFILIAL = P_CDFILIALDES
       AND CDCIA = P_CDCIADES
       AND CDMANCIA = P_CDMANCIADES
       AND NRSERVICOCIAFILI = V_NRSERVICOCIAFILIDES
       AND CDCLASSE = CUR_SERV.CDCLASSE;   


    IF V_EXISTE_NO_DESTINO > 0 THEN
       IF P_SOBRESCREVER = 'S' THEN

          /*Servicos nao podem ser sobrescritos em menu aprovados*/
          IF V_IDSITUAPROPCIA = 'A' THEN
             /*Operacao bloqueada. Servico $param[0] ja esta cadastrado no menu grid de destino e o mesmo se encontra aprovado.*/
             RAISE_APPLICATION_ERROR(-20501, 'APPERRMSGSTR' || 'APP-00082'|| '$$' || CUR_SERV.DSSERVICOCIAFILI || ' - ' || CUR_SERV.SGCLASSE || 'APPERRMSGEND' , TRUE);
          END IF;

          EXCLUI_SERVICO_MENUGRID(P_CDFILIALDES, P_CDCIADES, P_CDMANCIADES, 
                                  V_NRSERVICOCIAFILIDES,CUR_SERV.CDCLASSE, P_NRORG);
       ELSE
          CONTINUE; -- Pula para o proximo servico
       END IF;
    END IF;

    INSERT INTO SERVMANUALM
       (CDFILIAL,CDCIA,CDMANCIA,NRSERVICOCIAFILI,CDCLASSE,
        NRORG, DTINCLUSAO, CDOPERINCLUSAO, DTULTATU, NRORGINCLUSAO, NRORGULTATU, CDOPERULTATU, IDATIVO)
    VALUES
       (P_CDFILIALDES,P_CDCIADES,P_CDMANCIADES,V_NRSERVICOCIAFILIDES,CUR_SERV.CDCLASSE,
        P_NRORG,SYSDATE,P_CDOPERADOR,SYSDATE,P_NRORG,P_NRORG,P_CDOPERADOR,'S');
    
    /* Cria lista para importacao de servicos no manual de destino */
    INSERT INTO LISTA
    (NRLISTA, CDLISTA, NRORG)
    SELECT V_NRLISTA, CDSUBGRU || '|' || TO_CHAR(NRSEQSUBGRUSEMAM), P_NRORG
      FROM
    (
    SELECT CDSUBGRU, NRSEQSUBGRUSEMAM, ROW_NUMBER() OVER(PARTITION BY CDSUBGRU
                                 ORDER BY TO_CHAR(DTINIVGSUMA,'YYYYMMDD') DESC, TO_CHAR(DTFIMVGSUMA,'YYYYMMDD') DESC, NRSEQSUBGRUSEMAM DESC) AS ORDEM
          FROM SUBGRUSEMAM
         WHERE CDFILIAL = P_CDFILIALORI
           AND CDCIA = P_CDCIAORI
           AND CDMANCIA = P_CDMANCIAORI
           AND NRSERVICOCIAFILI = CUR_SERV.NRSERVICOCIAFILI
           AND CDCLASSE = CUR_SERV.CDCLASSE
    )
    WHERE ORDEM = 1;

    V_LISTACICLOS := 'TODOS';

    COPIA_SUBGRU_SERV_MENU_GRID(P_CDFILIPROC, P_CDFILIALORI, P_CDCIAORI, P_CDMANCIAORI,
                                CUR_SERV.NRSERVICOCIAFILI, CUR_SERV.CDCLASSE,
                                V_NRLISTA, V_LISTACICLOS,
                                P_CDFILIALDES, P_CDCIADES, P_CDMANCIADES,
                                V_NRSERVICOCIAFILIDES, CUR_SERV.CDCLASSE, P_IMAGEMDEFAULT, P_COPIA_IMAGEM,
                                P_SOBRESCREVER, P_COPIA_PRODCIA,
                                P_COPIA_IT, P_CDOPERADOR, NULL, NULL, 'N', P_NRORG, P_NRLISTAERROS);

    DELETE FROM LISTA WHERE NRLISTA = V_NRLISTA;
  END LOOP;
END;
/