CREATE OR REPLACE
PROCEDURE SPED_ECF_BLOCOL_DEMONSTRATIVO(
   P_CDEMPRESA IN EMPRESA.CDEMPRESA%TYPE,
   P_ANO IN VARCHAR,
   P_NRSEQARQMAG IN VARCHAR,
   P_NRORDEMATUAL IN NUMBER,
   P_NRORDENACAO OUT NUMBER)
IS
   V_LINHA VARCHAR2(4000);
   V_NRORDREGARQ NUMBER;
   V_COUNT NUMBER;
   V_INDICADORMOV VARCHAR2(01);
   V_DATAINICIAL DATE;
   V_DATAFINAL DATE;
   V_DATASALDO DATE;
   V_TEMP VARCHAR2(12);
   V_MES VARCHAR2(02);
   V_DTPERIODO DATE;
   V_INSEREL200 VARCHAR2(01);
   V_INSEREL030 VARCHAR2(01);
   V_TIPOVALOR VARCHAR2(01);

   V_VRTEMP NUMBER;

   /* FUNCAO PARA TRAZER O SALDO DE UMA DETERMINADA CONTA, SEJA COMUM OU ANTES DO ENCERRAMENTO */
   FUNCTION VALOR_SALDO(P_CONTA IN VARCHAR,
                        P_DATASALDO IN DATE) RETURN NUMBER
   IS
      V_RESULT NUMBER;
   BEGIN
      V_RESULT := 0;
      BEGIN
         /* SALDO COMUM */
         SELECT VALOR
           INTO V_RESULT
           FROM (SELECT NVL(ABS(SUM(ROUND(S.VRSALDEMPR, 2))), 0) VALOR
                   FROM SALDEMPR S
                  WHERE S.CDCONTCTBL = P_CONTA
                    AND S.CDEMPRESA = P_CDEMPRESA
                    AND S.DTSALDEMPR = P_DATASALDO
                    AND NOT EXISTS (SELECT 1
                                      FROM LANCCONT L
                                     WHERE L.CDEMPRESA = S.CDEMPRESA
                                       AND L.CDCONTCTBL LIKE S.CDCONTCTBL ||'%'
                                       AND L.IDLANCINTE IN ('T', 'F')
                                       AND L.DTLANCCONT = LAST_DAY(P_DATASALDO))
                 HAVING NVL(ABS(SUM(ROUND(S.VRSALDEMPR, 2))), 0) > 0

                  UNION

                 /* SALDO ANTES DOS ENCERRAMENTOS */
                 SELECT NVL(ABS(SUM(ROUND(S.VRSALDOTRANSF, 2))), 0) VALOR
                   FROM SALDOTRANSF S
                  WHERE S.CDCONTCTBL = P_CONTA
                    AND S.CDEMPRESA = P_CDEMPRESA
                    AND S.DTSALDOTRANSF = P_DATASALDO
                    AND EXISTS (SELECT 1
                                  FROM LANCCONT L
                                 WHERE L.CDEMPRESA = S.CDEMPRESA
                                   AND L.CDCONTCTBL LIKE S.CDCONTCTBL ||'%'
                                   AND L.IDLANCINTE IN ('T', 'F')
                                   AND L.DTLANCCONT = LAST_DAY(P_DATASALDO))
                 HAVING NVL(ABS(SUM(ROUND(S.VRSALDOTRANSF, 2))), 0) > 0) X
           WHERE VALOR <> 0;
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
            V_RESULT := 0;
      END;
      RETURN V_RESULT;
   END;

   /* FUNCAO PARA SOMAR OS LANCAMENTOS CONTABEIS DE UMA DETERMINADA CONTA CONTABIL */
   FUNCTION SOMA_LANCAMENTOS(P_CONTA IN VARCHAR,
                             P_DATAINI IN DATE,
                             P_DATAFIN IN DATE) RETURN NUMBER
   IS
      V_RESULT NUMBER;
   BEGIN
      V_RESULT := 0;
      BEGIN
         SELECT NVL(ABS(SUM(ROUND(L.VRLANCAMENT, 2))), 0)
           INTO V_RESULT
           FROM LANCCONT L, CONTCTBL CC
          WHERE L.CDEMPRESA = P_CDEMPRESA
            AND L.DTLANCCONT BETWEEN P_DATAINI AND P_DATAFIN
            AND L.CDCONTCTBL = CC.CDCONTCTBL
            AND CC.IDTIPOCONT = 'A'
            AND CC.CDCONTCTBL LIKE P_CONTA||'%'
            AND CC.IDCONTCCUS <> 'R'
            AND NOT EXISTS (SELECT 1
                              FROM LANCLOTE LL
                             WHERE LL.CDEMPRESA = L.CDEMPRESA
                               AND LL.NRLANCDEFI = L.NRLANCCONT
                               AND L.DTLANCCONT = P_DATAFIN
                               AND L.IDLANCINTE IN ('T', 'F'))
         HAVING NVL(ABS(SUM(ROUND(L.VRLANCAMENT, 2))), 0) > 0;
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
            V_RESULT := 0;
      END;
      RETURN V_RESULT;
   END;
BEGIN
   /* PROCEDURE RESPONSAVEL POR GERAR AS INFORMACOES REFERENTES AO CABECALHO DOS DEMONSTRATIVOS CONTABEIS */

   V_DATAINICIAL := TO_DATE('01/01/'||P_ANO);
   V_DATAFINAL := TO_DATE('31/12/'||P_ANO);
   V_NRORDREGARQ := P_NRORDEMATUAL;

   BEGIN
      SELECT '|L001'||'|'|| /* NOME DO REGISTRO */
              '0'   ||'|'   /* INDICADOR DE MOVIMENTO
                               0- BLOCO COM DADOS INFORMADOS
                               1- BLOCO SEM DADOS INFORMADOS */
        INTO V_LINHA
        FROM DUAL;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_LINHA := NULL;
   END;

   V_NRORDREGARQ := V_NRORDREGARQ + 1;
   INSERT INTO ARQMAGNETICO
      (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
   VALUES
      (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);

   BEGIN
      SELECT FORMAAPUR
        INTO V_TEMP
        FROM REG0010_ECF
       WHERE CDEMPRESA = P_CDEMPRESA;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_TEMP := NULL;
   END;

   IF V_TEMP = 'A' THEN /* QUANDO E ANUAL, OBRIGATORIAMENTE, DEVE SER FEITO UM REGISTRO CONTENDO O SOMATORIO DO ANO */
      BEGIN
         SELECT '|L030'         ||'|'|| /* NOME DO REGISTRO */
                '0101'||P_ANO   ||'|'|| /* DATA INICIAL DO PERIODO */
                '3112'||P_ANO   ||'|'|| /* DATA FINAL DO PERIODO */
                'A00'           ||'|'   /* PERIODO DE APURACAO.
                                           NO CASO DE APURACAO ANUAL, E OBRIGATORIO O REGISTRO A00 */
           INTO V_LINHA
           FROM DUAL;
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
            V_LINHA := NULL;
      END;
      V_NRORDREGARQ := V_NRORDREGARQ + 1;
      INSERT INTO ARQMAGNETICO
         (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
      VALUES
         (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);

      V_NRORDREGARQ := V_NRORDREGARQ + 1;
      INSERT INTO ARQMAGNETICO
         (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
      VALUES
         (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), '|L200|1|', P_NRSEQARQMAG);

      /* REGISTRO ANUAL, OBRIGATORIO,  PARA TODOS OS MESES DO ANO */
      FOR C_L210 IN (
         SELECT R.CDREGL210,
                R.NRSEQREGL210 NRSEQUENCIAL,
                R.DSREGL210 DSREGL210
           FROM REGL210ECF R
          ORDER BY 1) LOOP
         V_VRTEMP := 0;
         FOR C_CONTAS IN
            (SELECT C.CDCONTCTBL, C.IDTIPO
               FROM CONTL210ECF C
              WHERE C.NRSEQREGL210 = C_L210.NRSEQUENCIAL) LOOP
            IF C_CONTAS.IDTIPO = 'S' THEN
               V_VRTEMP := V_VRTEMP + VALOR_SALDO(C_CONTAS.CDCONTCTBL, V_DATAFINAL); /* SALDO DO MES */
            ELSIF C_CONTAS.IDTIPO = 'A' THEN
               V_VRTEMP := V_VRTEMP + VALOR_SALDO(C_CONTAS.CDCONTCTBL, V_DATAINICIAL-1); /* SALDO ANTERIOR */
            ELSIF C_CONTAS.IDTIPO = 'L' THEN
               V_VRTEMP := V_VRTEMP + SOMA_LANCAMENTOS(C_CONTAS.CDCONTCTBL, V_DATAINICIAL, V_DATAFINAL); /* LANCAMENTOS */
            END IF;
         END LOOP;

         IF V_VRTEMP <> 0 THEN
            SELECT '|L210'                               ||'|'|| /* REGISTRO */
                   LTRIM(TO_CHAR(C_L210.CDREGL210))  ||'|'|| /* CODIGO PADRAO DA RECEITA */
                   C_L210.DSREGL210                  ||'|'|| /* DESCRICAO PADRAO DA RECEITA */
                   REPLACE(LTRIM(TO_CHAR(ABS(SUM(ROUND(V_VRTEMP, 2))), '9999999999990.00')), '.', ',') ||'|' AS LINHA /* VALOR DO CODIGO */
              INTO V_LINHA
              FROM DUAL;
             V_NRORDREGARQ := V_NRORDREGARQ + 1;
             INSERT INTO ARQMAGNETICO
                (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
             VALUES
                (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);
         END IF;
      END LOOP;

      /* ESTE CAMPO E CONCATENADO, SAO 12 CARACTERES QUE REPRESENTAM OS 12 MESES DO ANO.
         E NECESSARIO IR DE CARACTER A CARACTER PRA VERIFICAR QUAL MES FOI UTILIZADO
         A FORMA "BALANCO/SUSPENSAO" */
      BEGIN
         SELECT MESBALRED
           INTO V_TEMP
           FROM REG0010_ECF
          WHERE CDEMPRESA = P_CDEMPRESA;
      EXCEPTION
         WHEN NO_DATA_FOUND THEN
            V_TEMP := NULL;
      END;

      /* O REGISTRO DEVE SER GERADO TODO MES QUE ESTA MARCADO COMO BALANCO SUSPENSAO */
      V_COUNT := 1;
      WHILE V_COUNT <= 12 LOOP
         IF SUBSTR(V_TEMP, V_COUNT, 1) = 'B' THEN
            V_DATAINICIAL := TO_DATE('01/'||LPAD(TO_CHAR(V_COUNT),2,'0')||'/'||P_ANO);
            V_DATAFINAL := LAST_DAY(TO_DATE('01/'||LPAD(TO_CHAR(V_COUNT),2,'0')||'/'||P_ANO));
            V_MES := LPAD(TO_CHAR(V_COUNT),2,'0');
            
            V_INSEREL200 := 'S';
            V_INSEREL030 := 'S';
            FOR C_L200 IN
               (SELECT '|L200|1|' AS LINHA
                  FROM DUAL) LOOP
               FOR C_L210 IN (
                  SELECT R.CDREGL210,
                         R.NRSEQREGL210 NRSEQUENCIAL,
                         R.DSREGL210
                    FROM REGL210ECF R
                   ORDER BY 1) LOOP
                  V_VRTEMP := 0;
                  FOR C_CONTAS IN
                     (SELECT C.CDCONTCTBL, C.IDTIPO
                        FROM CONTL210ECF C
                       WHERE C.NRSEQREGL210 = C_L210.NRSEQUENCIAL) LOOP
                     IF C_CONTAS.IDTIPO = 'S' THEN
                        V_VRTEMP := V_VRTEMP + VALOR_SALDO(C_CONTAS.CDCONTCTBL, V_DATAFINAL); /* SALDO DO MES */
                     ELSIF C_CONTAS.IDTIPO = 'A' THEN
                        V_VRTEMP := V_VRTEMP + VALOR_SALDO(C_CONTAS.CDCONTCTBL, V_DATAINICIAL-1); /* SALDO ANTERIOR */
                     ELSIF C_CONTAS.IDTIPO = 'L' THEN
                        V_VRTEMP := V_VRTEMP + SOMA_LANCAMENTOS(C_CONTAS.CDCONTCTBL, V_DATAINICIAL, V_DATAFINAL); /* LANCAMENTOS */
                     END IF;
                  END LOOP;

                  IF V_VRTEMP <> 0 THEN
                     /* INSERE O REGISTRO PAI DO L200, O REGISTRO L030.
                        ESTE REGISTRO DEVE SER INSERIDO SOMENTE SE EXISTIR O L200 E O L210,
                        PORQUE SENAO ELE FICARA SEM REGISTROS FILHOS */
                     IF V_INSEREL030 = 'S' THEN
                        BEGIN
                           SELECT '|L030'                       ||'|'|| /* NOME DO REGISTRO */
                           '0101'||P_ANO                        ||'|'|| /* DATA INICIAL DO PERIODO */
                           TO_CHAR(V_DATAFINAL, 'DDMMYYYY')     ||'|'|| /* DATA FINAL DO PERIODO */
                                  'A'||V_MES                    ||'|'   /* PERIODO DE APURACAO */
                             INTO V_LINHA
                             FROM DUAL;
                        EXCEPTION
                           WHEN NO_DATA_FOUND THEN
                              V_LINHA := NULL;
                        END;

                        V_NRORDREGARQ := V_NRORDREGARQ + 1;
                        INSERT INTO ARQMAGNETICO
                           (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
                        VALUES
                           (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);
                        V_INSEREL030 := 'N';
                     END IF;

                     IF V_INSEREL200 = 'S' THEN
                        /* INSERE O CABECALHO DO REGISTRO L210, O REGISTRO L200 */
                        V_NRORDREGARQ := V_NRORDREGARQ + 1;
                        INSERT INTO ARQMAGNETICO
                           (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
                        VALUES
                           (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), C_L200.LINHA, P_NRSEQARQMAG);

                        V_INSEREL200 := 'N';
                     END IF;

                     SELECT '|L210'                           ||'|'|| /* REGISTRO */
                            LTRIM(TO_CHAR(C_L210.CDREGL210))  ||'|'|| /* CODIGO PADRAO DA RECEITA */
                            C_L210.DSREGL210                  ||'|'|| /* DESCRICAO PADRAO DA RECEITA */
                            REPLACE(LTRIM(TO_CHAR(ABS(SUM(ROUND(V_VRTEMP, 2))), '9999999999990.00')), '.', ',') ||'|' AS LINHA /* VALOR DO CODIGO */
                       INTO V_LINHA
                       FROM DUAL;
                      V_NRORDREGARQ := V_NRORDREGARQ + 1;
                      INSERT INTO ARQMAGNETICO
                         (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
                      VALUES
                         (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);
                  END IF;
               END LOOP;
               V_INSEREL200 := 'S';
            END LOOP;
         END IF;
         V_COUNT := V_COUNT + 1;
      END LOOP;
   ELSE
      /* Rotina de apuracao Trimestral */
      V_COUNT := 1;
      V_DATAINICIAL := TO_DATE('01/'||LPAD(TO_CHAR(V_COUNT),2,'0')||'/'||P_ANO);
      V_DATAFINAL := LAST_DAY(ADD_MONTHS(V_DATAINICIAL, 2));
      WHILE V_COUNT <= 4 LOOP
         IF SUBSTR(V_TEMP, V_COUNT, 1) = 'R' THEN
            V_MES := LPAD(TO_CHAR(V_COUNT),2,'0');
            V_INSEREL030 := 'S';
            V_INSEREL200 := 'S';
            FOR C_L200 IN
               (SELECT '|L200|1|' AS LINHA
                  FROM DUAL) LOOP
               FOR C_L210 IN (
                  SELECT R.CDREGL210,
                         R.NRSEQREGL210 NRSEQUENCIAL,
                         R.DSREGL210
                    FROM REGL210ECF R
                   ORDER BY 1) LOOP
                  V_VRTEMP := 0;
                  FOR C_CONTAS IN
                     (SELECT C.CDCONTCTBL, C.IDTIPO
                        FROM CONTL210ECF C
                       WHERE C.NRSEQREGL210 = C_L210.NRSEQUENCIAL) LOOP
                     IF C_CONTAS.IDTIPO = 'S' THEN
                        V_VRTEMP := V_VRTEMP + VALOR_SALDO(C_CONTAS.CDCONTCTBL, V_DATAFINAL); /* SALDO DO MES */
                     ELSIF C_CONTAS.IDTIPO = 'A' THEN
                        V_VRTEMP := V_VRTEMP + VALOR_SALDO(C_CONTAS.CDCONTCTBL, V_DATAINICIAL-1); /* SALDO ANTERIOR */
                     ELSIF C_CONTAS.IDTIPO = 'L' THEN
                        V_VRTEMP := V_VRTEMP + SOMA_LANCAMENTOS(C_CONTAS.CDCONTCTBL, V_DATAINICIAL, V_DATAFINAL); /* LANCAMENTOS */
                     END IF;
                  END LOOP;

                  IF V_VRTEMP <> 0 THEN
                     /* INSERE O REGISTRO PAI DO L200, O REGISTRO L030.
                        ESTE REGISTRO DEVE SER INSERIDO SOMENTE SE EXISTIR O L200 E O L210,
                        PORQUE SENAO ELE FICARA SEM REGISTROS FILHOS */
                     IF V_INSEREL030 = 'S' THEN
                        BEGIN
                           SELECT '|L030'                       ||'|'|| /* NOME DO REGISTRO */
                           '0101'||P_ANO                        ||'|'|| /* DATA INICIAL DO PERIODO */
                           TO_CHAR(V_DATAFINAL, 'DDMMYYYY')     ||'|'|| /* DATA FINAL DO PERIODO */
                                  'A'||V_MES                    ||'|'   /* PERIODO DE APURACAO */
                             INTO V_LINHA
                             FROM DUAL;
                        EXCEPTION
                           WHEN NO_DATA_FOUND THEN
                              V_LINHA := NULL;
                        END;

                        V_NRORDREGARQ := V_NRORDREGARQ + 1;
                        INSERT INTO ARQMAGNETICO
                           (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
                        VALUES
                           (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);
                     END IF;

                     IF V_INSEREL200 = 'S' THEN
                        /* INSERE O CABECALHO DO REGISTRO L210, O REGISTRO L200 */
                        V_NRORDREGARQ := V_NRORDREGARQ + 1;
                        INSERT INTO ARQMAGNETICO
                           (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
                        VALUES
                           (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), C_L200.LINHA, P_NRSEQARQMAG);

                        V_INSEREL200 := 'N';
                     END IF;

                     SELECT '|L210'                           ||'|'|| /* REGISTRO */
                            LTRIM(TO_CHAR(C_L210.CDREGL210))  ||'|'|| /* CODIGO PADRAO DA RECEITA */
                            C_L210.DSREGL210                  ||'|'|| /* DESCRICAO PADRAO DA RECEITA */
                            REPLACE(LTRIM(TO_CHAR(ABS(SUM(ROUND(V_VRTEMP, 2))), '9999999999990.00')), '.', ',') ||'|' AS LINHA /* VALOR DO CODIGO */
                       INTO V_LINHA
                       FROM DUAL;
                      V_NRORDREGARQ := V_NRORDREGARQ + 1;
                      INSERT INTO ARQMAGNETICO
                         (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
                      VALUES
                         (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);
                  END IF;
               END LOOP;
               V_INSEREL200 := 'S';
            END LOOP;
         END IF;
         V_DATAINICIAL := ADD_MONTHS(V_DATAINICIAL, 3);
         V_DATAFINAL := LAST_DAY(ADD_MONTHS(V_DATAFINAL, 3));
         V_COUNT := V_COUNT + 1;
      END LOOP;
   END IF;

   BEGIN
      SELECT '|L990'             ||'|'||  /* NOME DO REGISTRO */
             TO_CHAR(COUNT(*)+1) ||'|'    /* QUANTIDADE DE REGISTROS DO BLOCO J */
        INTO V_LINHA
        FROM ARQMAGNETICO
       WHERE NRSEQARQMAG = P_NRSEQARQMAG
         AND SUBSTR(DSREGARQMAG, 2, 1) = 'L';
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_LINHA := NULL;
   END;

   V_NRORDREGARQ := V_NRORDREGARQ + 1;
   INSERT INTO ARQMAGNETICO
     (NRORDREGARQ, DSREGARQMAG, NRSEQARQMAG)
   VALUES
     (LPAD(TO_CHAR(V_NRORDREGARQ),10,'0'), V_LINHA, P_NRSEQARQMAG);

   P_NRORDENACAO := V_NRORDREGARQ;
END;
/