CREATE OR REPLACE
PROCEDURE SEMANAL_RECORRENTE_DTENTR
  (P_CDFILIAL     IN VARCHAR2,
   P_CDPERIENTR   IN VARCHAR2,
   P_DTINICIAL    IN DATE,
   P_NRMESES      IN NUMBER,
   P_DTPROCESSA   IN DATE) IS
   V_CONTA        NUMBER;
   V_INTERVALO    NUMBER;
   V_DIENTREGA    NUMBER;
   V_AUXDIENTREGA NUMBER;
   V_AUX          NUMBER;
   V_CONTAUXI     NUMBER;

   V_MINENTREGA   VARCHAR2(2);
   V_MAXENTREGA   VARCHAR2(2);


   V_IDDOMPERIREC   CHAR(1);
   V_IDSEGPERIREC   CHAR(1);
   V_IDTERPERIREC   CHAR(1);
   V_IDQUAPERIREC   CHAR(1);
   V_IDQUIPERIREC   CHAR(1);
   V_IDSEXPERIREC   CHAR(1);
   V_IDSABPERIREC   CHAR(1);
   V_EXISTECALECOMP CHAR(1);
   V_SOMENTEDIAUTIL CHAR(1);

   V_DTMAXENTREGA DATE;
   V_DTAUX        DATE;
   V_DTAUX2       DATE;
   V_DTORIGINAL   DATE;
   VDATAPROX      DATE;
   V_DTINI_N_FERI DATE;
   V_DTFIN_N_FERI DATE;
   V_PERFILPROD_SITENTR VARCHAR2(1); -- Parametro que define se atrasa (A) ou adianta (D) a entrega do produto
BEGIN
   V_DTINI_N_FERI := P_DTINICIAL - 7;
   V_DTFIN_N_FERI := P_DTINICIAL + 7;

   IF P_DTINICIAL > P_DTPROCESSA THEN
      DELETE FROM CALECOMP
      WHERE CDFILIAL   = P_CDFILIAL
        AND CDPERIENTR = P_CDPERIENTR
        AND DTENTREGA BETWEEN P_DTINICIAL AND TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY');
   ELSE
      DELETE FROM CALECOMP
      WHERE CDFILIAL   = P_CDFILIAL
        AND CDPERIENTR = P_CDPERIENTR
        AND DTENTREGA BETWEEN P_DTPROCESSA AND TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY');
   END IF;

   SELECT COUNT(*), MIN(DIENTREGA), MAX(DIENTREGA)
   INTO V_CONTA, V_MINENTREGA, V_MAXENTREGA
   FROM DIASENTR D
   WHERE D.CDPERIENTR = P_CDPERIENTR;
   V_EXISTECALECOMP := 'S';
   SELECT
      NVL(MAX(IDDOMPERIREC),'N'),
      NVL(MAX(IDSEGPERIREC),'N'),
      NVL(MAX(IDTERPERIREC),'N'),
      NVL(MAX(IDQUAPERIREC),'N'),
      NVL(MAX(IDQUIPERIREC),'N'),
      NVL(MAX(IDSEXPERIREC),'N'),
      NVL(MAX(IDSABPERIREC),'N'),
      NVL(MAX(IDDIANUTIL),'S')
   INTO
      V_IDDOMPERIREC,
      V_IDSEGPERIREC,
      V_IDTERPERIREC,
      V_IDQUAPERIREC,
      V_IDQUIPERIREC,
      V_IDSEXPERIREC,
      V_IDSABPERIREC,
      V_SOMENTEDIAUTIL
   FROM DIASENTR, PERIENTR
   WHERE DIASENTR.CDPERIENTR = P_CDPERIENTR
     AND DIASENTR.DIENTREGA  = V_MINENTREGA
     AND PERIENTR.CDPERIENTR = DIASENTR.CDPERIENTR;

   V_INTERVALO := 7 * V_CONTA;

   SELECT NVL(MAX(IDSITUENTREGA), 'A')
     INTO V_PERFILPROD_SITENTR
     FROM PERFILPROD PFP
    WHERE PFP.CDFILIAL   = P_CDFILIAL
      AND PFP.CDPERIENTR = P_CDPERIENTR
      AND NVL(PFP.IDSITUENTREGA, 'A') = 'D';

   IF V_CONTA > 0 THEN
      SELECT
         MAX(DTENTREGA)
      INTO
         V_DTMAXENTREGA
      FROM
         CALECOMP
      WHERE CALECOMP.CDFILIAL   = P_CDFILIAL
        AND CALECOMP.CDPERIENTR = P_CDPERIENTR
        AND CALECOMP.DTENTREGA <= P_DTINICIAL
        AND CALECOMP.CDFILIAL   = P_CDFILIAL
        AND NOT EXISTS (SELECT 1
                        FROM FERICOMP
                        WHERE FERICOMP.CDFILIAL   = CALECOMP.CDFILIAL
                          AND FERICOMP.DTFERICOMP BETWEEN V_DTINI_N_FERI AND V_DTFIN_N_FERI);
      IF V_DTMAXENTREGA IS NULL THEN
         SELECT
            MAX(DTENTREGA)
         INTO
            V_DTMAXENTREGA
         FROM
            CALECOMP
         WHERE CALECOMP.CDPERIENTR = P_CDPERIENTR
           AND CALECOMP.DTENTREGA <= P_DTINICIAL
           AND NOT EXISTS (SELECT 1
                           FROM FERICOMP
                           WHERE FERICOMP.CDFILIAL   = CALECOMP.CDFILIAL
                             AND FERICOMP.DTFERICOMP BETWEEN V_DTINI_N_FERI AND V_DTFIN_N_FERI);
      END IF;
      IF V_DTMAXENTREGA IS NULL THEN
         V_EXISTECALECOMP := 'N';
         V_DTMAXENTREGA := TO_DATE('01/01'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY');
      END IF;

      V_AUXDIENTREGA := NULL;
      WHILE (V_AUXDIENTREGA IS NULL) LOOP
         SELECT
            TO_NUMBER(TO_CHAR(V_DTMAXENTREGA, 'D'))
         INTO
            V_DIENTREGA
         FROM
            DUAL;
         SELECT MAX(DIENTREGA)
         INTO V_AUXDIENTREGA
         FROM DIASENTR
         WHERE CDPERIENTR = P_CDPERIENTR AND
              ((DECODE(NVL(IDDOMPERIREC,'N'), 'S', 1, 8) = V_DIENTREGA)
            OR (DECODE(NVL(IDSEGPERIREC,'N'), 'S', 2, 8) = V_DIENTREGA)
            OR (DECODE(NVL(IDTERPERIREC,'N'), 'S', 3, 8) = V_DIENTREGA)
            OR (DECODE(NVL(IDQUAPERIREC,'N'), 'S', 4, 8) = V_DIENTREGA)
            OR (DECODE(NVL(IDQUIPERIREC,'N'), 'S', 5, 8) = V_DIENTREGA)
            OR (DECODE(NVL(IDSEXPERIREC,'N'), 'S', 6, 8) = V_DIENTREGA)
            OR (DECODE(NVL(IDSABPERIREC,'N'), 'S', 7, 8) = V_DIENTREGA));
         IF V_AUXDIENTREGA IS NULL THEN
            IF V_EXISTECALECOMP = 'N' THEN
               V_DTMAXENTREGA := V_DTMAXENTREGA + 1;
            ELSE
               V_DTMAXENTREGA := V_DTMAXENTREGA - 1;
            END IF;
         END IF;
      END LOOP;

      IF V_EXISTECALECOMP = 'S' THEN
         IF V_AUXDIENTREGA > TO_NUMBER(V_MINENTREGA) THEN
            V_AUX := V_AUXDIENTREGA - TO_NUMBER(V_MINENTREGA);
            V_DTMAXENTREGA := V_DTMAXENTREGA - (7 * V_AUX);
         END IF;
      END IF;

      WHILE TO_NUMBER(TO_CHAR(V_DTMAXENTREGA, 'D')) > 1 LOOP
         V_DTMAXENTREGA := V_DTMAXENTREGA - 1;
      END LOOP;

      V_DTAUX := V_DTMAXENTREGA;
      FOR C_SEMANA IN
         (SELECT
             DIASENTR.DIENTREGA,
             NVL(DIASENTR.IDDOMPERIREC,'N') IDDOMPERIREC,
             NVL(DIASENTR.IDSEGPERIREC,'N') IDSEGPERIREC,
             NVL(DIASENTR.IDTERPERIREC,'N') IDTERPERIREC,
             NVL(DIASENTR.IDQUAPERIREC,'N') IDQUAPERIREC,
             NVL(DIASENTR.IDQUIPERIREC,'N') IDQUIPERIREC,
             NVL(DIASENTR.IDSEXPERIREC,'N') IDSEXPERIREC,
             NVL(DIASENTR.IDSABPERIREC,'N') IDSABPERIREC
          FROM DIASENTR
          WHERE DIASENTR.CDPERIENTR = P_CDPERIENTR
          ORDER BY DIASENTR.DIENTREGA
          )
      LOOP
         IF C_SEMANA.IDDOMPERIREC = 'S' THEN
            V_DTAUX2     := V_DTAUX;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         IF C_SEMANA.IDSEGPERIREC = 'S' THEN
            V_DTAUX2 := V_DTAUX+1;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         IF C_SEMANA.IDTERPERIREC = 'S' THEN
            V_DTAUX2 := V_DTAUX+2;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         IF C_SEMANA.IDQUAPERIREC = 'S' THEN
            V_DTAUX2 := V_DTAUX+3;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         IF C_SEMANA.IDQUIPERIREC = 'S' THEN
            V_DTAUX2 := V_DTAUX+4;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         IF C_SEMANA.IDSEXPERIREC = 'S' THEN
            V_DTAUX2 := V_DTAUX+5;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         IF C_SEMANA.IDSABPERIREC = 'S' THEN
            V_DTAUX2 := V_DTAUX+6;
            WHILE (V_DTAUX2 <= TO_DATE('31/12'||TO_CHAR(P_DTINICIAL,'YYYY'), 'DD/MM/YYYY')) LOOP
               V_DTORIGINAL := V_DTAUX2;
               IF V_DTAUX2 >= P_DTINICIAL THEN
                  /*- CALCULA UMA DATA DE ENTREGA ANTERIOR A UMA DATA NAO UTIL -*/
                  IF (V_SOMENTEDIAUTIL = 'S') THEN
                     V_CONTAUXI := 1;
                     WHILE (V_CONTAUXI > 0) LOOP
                       SELECT COUNT(*) INTO V_CONTAUXI
                       FROM FERICOMP
                       WHERE
                       CDFILIAL   = P_CDFILIAL AND
                       DTFERICOMP = V_DTAUX2;
                       IF (V_CONTAUXI > 0) THEN
                          IF NVL(V_PERFILPROD_SITENTR, 'A') <> 'D' THEN
                             V_DTAUX2 := V_DTAUX2 - 1;
                          ELSE
                             V_DTAUX2 := V_DTAUX2 + 1;
                          END IF;
                       END IF;
                     END LOOP;
                  END IF;
                  IF V_DTAUX2 >= P_DTPROCESSA THEN
                     INSERT INTO CALECOMP
                     (CDFILIAL, CDPERIENTR, DTENTREGA, DTANTPROXENT)
                     (SELECT
                         P_CDFILIAL, P_CDPERIENTR, V_DTAUX2, V_DTAUX2
                      FROM DUAL
                      WHERE NOT EXISTS (SELECT 1
                                        FROM CALECOMP
                                        WHERE CDFILIAL     = P_CDFILIAL AND
                                              CDPERIENTR   = P_CDPERIENTR AND
                                              DTENTREGA    = V_DTAUX2));
                  END IF;
               END IF;
               V_DTAUX2 := V_DTORIGINAL;
               V_DTAUX2 := V_DTAUX2 + V_INTERVALO;
            END LOOP;
         END IF;
         V_DTAUX := V_DTAUX + 7;
      END LOOP;
      VDATAPROX := NULL;
      FOR C_ANTPROXENTR IN
         (SELECT ROWID AS LINHA, C.*
             FROM CALECOMP C
          WHERE CDFILIAL   = P_CDFILIAL
            AND CDPERIENTR = P_CDPERIENTR
            AND DTENTREGA >= P_DTPROCESSA
          ORDER BY DTENTREGA DESC)
      LOOP
          IF VDATAPROX IS NULL THEN
              VDATAPROX := C_ANTPROXENTR.DTENTREGA;
          ELSE
              UPDATE CALECOMP
                 SET DTANTPROXENT = VDATAPROX - 1
               WHERE ROWID = C_ANTPROXENTR.LINHA;
               VDATAPROX := C_ANTPROXENTR.DTENTREGA;
          END IF;
      END LOOP;
   END IF;
   COMMIT;
END;
/