ALTER TABLE ITLANCTOEST ADD VRUNILANCTOANT FLOAT(126)
/

CREATE OR REPLACE PROCEDURE ATUALIZA_CUSTO_ABSORCAO
   (P_CDFILIAL     IN FILIAL.CDFILIAL%TYPE,
    P_DATACUSTO    IN FILIAL.DTULTATU%TYPE,
    P_ERRO         OUT VARCHAR)
AS
   V_VRCUSTOCONT   FLOAT; 
   V_QTTEMPOAPO    FLOAT; 
   V_COUNT         INTEGER;
   V_QTHRTOTAL     FLOAT;
BEGIN
   P_ERRO := 'N';
   /* Verifica contas contabeis associadas para calculo do custo */
   BEGIN
      SELECT SUM(ABS(VRSALDEMPR)) AS VRCUSTOCONT
        INTO V_VRCUSTOCONT
        FROM ATUCUSTPROD P, FILIAL F, SALDEMPR S
       WHERE P.CDFILIAL   = P_CDFILIAL
         AND F.CDFILIAL   = P.CDFILIAL
         AND S.CDEMPRESA  = F.CDEMPRESA
         AND S.CDCONTCTBL = P.CDCONTCTBL
         AND S.DTSALDEMPR = LAST_DAY(P_DATACUSTO);
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_VRCUSTOCONT := 0;
   END;
   /* Verifica se foi realizado o calculo do custo de absorcao */
   BEGIN
      SELECT COUNT(*)
        INTO V_COUNT
        FROM CUSTOABSORCAOPR
       WHERE CDFILIAL = P_CDFILIAL
         AND DTCUSTOABSORCAO = LAST_DAY(P_DATACUSTO);
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         V_COUNT := 0;
   END;
   IF (V_VRCUSTOCONT > 0) AND (V_COUNT = 0) THEN
      /* Tempo apontado referente as tarefas por habilidade (homem/hora) por produto em todas as
         ordens de producao (OP) conforme mes informado (tempo de producao) */
      FOR C_PROD IN (SELECT P.CDSUBPRODETA AS CDPRODUTO, SUM(P.QTPRACABADO) AS QTPRODUZIDA, NVL(SUM(QTHSPRODUZIDOPR),0) AS QTHSPRODUZIDOPR
                       FROM ORDPRODUCAO O, PRODACABADO P,
                            (SELECT O.CDFILIAL, O.NRORDPROD, O.NRSUBORDPROD, (A.DTFINREALAUD - A.DTINIREALAUD) * 24 AS QTHSPRODUZIDOPR
                               FROM ORDPRODUCAO O, AUDITORIA A, RECURETAPAOP R
                              WHERE O.CDFILIAL = P_CDFILIAL
                                AND A.CDFILIAL = O.CDFILIAL
                                AND A.NRORDPROD = O.NRORDPROD
                                AND A.NRSUBORDPROD = O.NRSUBORDPROD
                                AND A.IDORIGAUDIT = 'TAR'
                                AND R.CDFILIAL = A.CDFILIAL
                                AND R.NRAUDITORIA = A.NRAUDITORIA
                                AND R.IDRECURETAOP = 'H'
                                AND TO_CHAR(P_DATACUSTO, 'MM/YYYY') = TO_CHAR(A.DTINIREALAUD, 'MM/YYYY')
                                AND NOT A.DTFINREALAUD IS NULL) C
                      WHERE O.CDFILIAL = P_CDFILIAL
                        AND O.IDSITORDPROD = '3'
                        AND O.DTHRFIMREAOP BETWEEN P_DATACUSTO AND LAST_DAY(P_DATACUSTO)
                        AND P.CDFILIAL = O.CDFILIAL
                        AND P.NRORDPROD = O.NRORDPROD
                        AND P.NRSUBORDPROD = O.NRSUBORDPROD
                        AND O.CDFILIAL = C.CDFILIAL (+)
                        AND O.NRORDPROD = C.NRORDPROD (+)
                        AND O.NRSUBORDPROD = C.NRSUBORDPROD (+)
                      GROUP BY P.CDSUBPRODETA)
      LOOP
         INSERT INTO CUSTOABSORCAOPR
            (CDFILIAL, DTCUSTOABSORCAO, VRTOTRATEADO, CDPRODUTO, QTPRODUZIDA, QTHSPRODUZIDOPR, VRCUSTOABSORCAO)
         VALUES
            (P_CDFILIAL, LAST_DAY(P_DATACUSTO), V_VRCUSTOCONT, C_PROD.CDPRODUTO, C_PROD.QTPRODUZIDA, C_PROD.QTHSPRODUZIDOPR, 0);
      END LOOP;
      SELECT SUM(QTHSPRODUZIDOPR)
        INTO V_QTHRTOTAL
        FROM CUSTOABSORCAOPR
       WHERE CDFILIAL = P_CDFILIAL
         AND DTCUSTOABSORCAO = LAST_DAY(P_DATACUSTO);
      IF V_QTHRTOTAL > 0 THEN
      /* (Total de horas de producao do produto / total de horas * Valor total contabil) / qtde produzida do produto no periodo */
         UPDATE CUSTOABSORCAOPR
            SET VRCUSTOABSORCAO = ((QTHSPRODUZIDOPR / V_QTHRTOTAL) * VRTOTRATEADO) / QTPRODUZIDA
          WHERE CDFILIAL = P_CDFILIAL
            AND DTCUSTOABSORCAO = LAST_DAY(P_DATACUSTO);
         FOR C_CUSTOABSORCAO IN (SELECT CDFILIAL, CDPRODUTO, VRCUSTOABSORCAO
                                   FROM CUSTOABSORCAOPR
                                  WHERE CDFILIAL = P_CDFILIAL
                                    AND DTCUSTOABSORCAO = LAST_DAY(P_DATACUSTO)
                                  ORDER BY CDPRODUTO)
         LOOP
            FOR C_PRODACABADO IN (SELECT P.CDFILIAL, P.NRLANCESTQ, P.NRSEQUITEM, I.CDFILIMOVI, I.DTLANCMOVI
                                    FROM ORDPRODUCAO O, PRODACABADO P, ITLANCTOEST I
                                   WHERE O.CDFILIAL = C_CUSTOABSORCAO.CDFILIAL
                                     AND O.IDSITORDPROD = '3'
                                     AND O.DTHRFIMREAOP BETWEEN P_DATACUSTO AND LAST_DAY(P_DATACUSTO)
                                     AND P.CDFILIAL = O.CDFILIAL
                                     AND P.NRORDPROD = O.NRORDPROD
                                     AND P.NRSUBORDPROD = O.NRSUBORDPROD
                                     AND P.CDSUBPRODETA = C_CUSTOABSORCAO.CDPRODUTO
                                     AND I.CDFILIAL = P.CDFILIAL
                                     AND I.NRLANCESTQ = P.NRLANCESTQ
                                     AND I.NRSEQUITEM = P.NRSEQUITEM
                                   ORDER BY I.DTLANCMOVI)
            LOOP
               UPDATE ITLANCTOEST
                  SET VRUNILANCTO  = ROUND(VRUNILANCTO + C_CUSTOABSORCAO.VRCUSTOABSORCAO, 5),
                      VRTOTLANCTO  = ROUND(VRTOTLANCTO + (QTTOTLANCTO * C_CUSTOABSORCAO.VRCUSTOABSORCAO), 5),
                      VRLANCTOEST  = ROUND(VRLANCTOEST + C_CUSTOABSORCAO.VRCUSTOABSORCAO, 5),
                      VRLANCTOBRUT = ROUND(VRLANCTOBRUT + C_CUSTOABSORCAO.VRCUSTOABSORCAO, 5),
                      VRCUSTENTR   = ROUND(VRCUSTENTR + (QTTOTLANCTO * C_CUSTOABSORCAO.VRCUSTOABSORCAO), 5),
                      VRUNILANCTOANT = ROUND(VRUNILANCTO, 5)
                WHERE CDFILIAL   = C_PRODACABADO.CDFILIAL
                  AND NRLANCESTQ = C_PRODACABADO.NRLANCESTQ
                  AND NRSEQUITEM = C_PRODACABADO.NRSEQUITEM;
               ATUALIZA_ESTOQUE(C_PRODACABADO.CDFILIMOVI, C_PRODACABADO.DTLANCMOVI, TRUNC(SYSDATE), C_PRODACABADO.CDFILIAL, C_PRODACABADO.NRLANCESTQ);
            END LOOP;
         END LOOP;
      END IF;
   ELSE
      P_ERRO := 'S';
   END IF;
END;