create view vwcentro_negocio_ccusto (
ID,
CENTRO_NEGOCIO_ID,
CCUSTO_ID
)
as
select
    c.*
from tbcentro_negocio_ccusto c, tbcentro_negocio j
where j.id = c.centro_negocio_id
and j.status = 1
;

SET TERM ^ ;

CREATE OR ALTER procedure SPU_RATEAMENTO_CONTABIL (
    ANO integer,
    MES integer,
    GRUPO_RATEAMENTO integer,
    ESTABELECIMENTO integer)
returns (
    OLT_CCUSTO varchar(10),
    OLT_VALOR numeric(18,8),
    OLT_FAMILIA varchar(300),
    OLT_CONTA varchar(30))
as
declare variable DATA1 date;
declare variable DATA2 date;
declare variable CONTA varchar(30);
declare variable VALOR_ORIGEM integer;
declare variable REGRA_RATEAMENTO integer;
declare variable RATEAMENTO_GRUPO integer;
declare variable CCUSTO varchar(10);
declare variable VALOR numeric(18,8);
declare variable PERC numeric(18,8);
declare variable TIPO_ID integer;
declare variable TIPO_CUSTO integer;
declare variable ID integer;
declare variable CCONTABIL_DEBITO varchar(20);
begin

  :DATA1 = cast('01.'||mes||'.'||ano as date);
  :DATA2 = cast(FN_END_OF_MONTH(:DATA1) as date);

  --exception "..." :DATA2;

  --remove despesas de ccusto/conta, para poder atualizalas
  delete from TBDESPESA_HISTORICO d where d.ano = :ANO and d.mes = :MES and d.tipo > 4 AND D.grupo_rateamento = :GRUPO_RATEAMENTO;


    if(GRUPO_RATEAMENTO = 2)then
    begin
        ---valor com origem calculada nas variacoes de estoque
        for
            select
                CCUSTO,
                CONTA,
                VALOR,
                fn_calc_precision(VALOR,TOTAL,'/') as PERC
            from(
                select
                    CCUSTO,
                    CONTA,
                    VALOR,
                    sum(VALOR) over() as TOTAL
                from(
                    select
                        e.ccusto,
                        e.conta,
                        sum(e.valor) as VALOR
                    from TBMOVCONTABIL_DRE e
                    where e.ano = :ANO
                    and e.mes = :MES
                    group by 1,2
               )
            ) where  TOTAL <> 0
        into
            :CCUSTO,
            :CONTA,
            :VALOR,
            :PERC
        do
        begin
            :olt_ccusto = CCUSTO;
            :olt_valor  = VALOR;
        
            TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
        
            if(TIPO_CUSTO <> 3)then
            begin
                update tbrateamento_historico h set
                  h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:VALOR,0)),
                  h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':0:'||coalesce(:VALOR,0))
                where h.ano = :ano
                and h.mes = :mes
                and h.rateamento_grupo = :RATEAMENTO_GRUPO
                and replace(h.ccusto,'*','') = :CCUSTO;
            end else
            begin
              INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO) VALUES (:CONTA, :CCUSTO, :VALOR, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO);
            end
        
            insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), :PERC ,  :GRUPO_RATEAMENTO, 3, 0);
        
            suspend;
        end
    end

  for
    select
        ID,
        CONTA,
        VALOR_ORIGEM,
        REGRA_RATEAMENTO,
        RATEAMENTO_GRUPO,
        TIPO_ID
    from tbrateamento_conta_contabil c
    where c.rateamento_grupo = :GRUPO_RATEAMENTO
  into
     :ID,
     :CONTA,
     :VALOR_ORIGEM,
     :REGRA_RATEAMENTO,
     :RATEAMENTO_GRUPO,
     :TIPO_ID
  do
  begin

     --valor pelo lancamento contabil
     if(:VALOR_ORIGEM = 2)then
     begin
        for
            select
                CCUSTO,
                VALOR,
                fn_calc_precision(VALOR,TOTAL,'/') as PERC
            from(
                select
                    CCUSTO,
                    VALOR,
                    sum(VALOR) over() as TOTAL
                from(
                    select
                        iif(m.ccusto = '','11', coalesce(m.ccusto,'11')) as ccusto,
                        SUM(fn_calc_precision(a.VALOR,fn_calc_precision(coalesce(m.percentual,100),100,'/'),'*') * iif(a.natureza = 'C', -1, 1)) as VALOR
                    from tbmovcontabil a left join tbrateamento_movcontabil m on m.movcontabil_id = a.id
                    where a.conta = :CONTA
                      and a.tipolanc <> 'E'
                      and a.data between :DATA1 and :DATA2
                    group by 1
                )
            ) where  TOTAL <> 0
        into
            :CCUSTO,
            :VALOR,
            :PERC
        do
        begin
            :olt_ccusto = CCUSTO;
            :olt_valor  = VALOR;

            TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);

            if(TIPO_CUSTO <> 3)then
            begin
                update tbrateamento_historico h set
                  h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:VALOR,0)),
                  h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':0:'||coalesce(:VALOR,0))
                where h.ano = :ano
                and h.mes = :mes
                and h.rateamento_grupo = :RATEAMENTO_GRUPO
                and replace(h.ccusto,'*','') = :CCUSTO;
            end else
            begin
              INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO) VALUES (:CONTA, :CCUSTO, :VALOR, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO);
            end

            insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), :PERC ,  :RATEAMENTO_GRUPO, 3, 0);

            suspend;
        end
     end

     --valor pelo lancamento estoque
     if(:VALOR_ORIGEM = 1)then
     begin
        for
            select
                CENTRO_DE_CUSTO,
                CUSTO_MEDIO,
                --(CUSTO_MEDIO) / sum(CUSTO_MEDIO) over() as PERC
                fn_calc_precision(custo_medio, sum(CUSTO_MEDIO) over(),'/') as PERC
            from(
                Select
                    A.CENTRO_DE_CUSTO,
                    Sum(Cast(A.Quantidade as double precision) *
                    (Select First 1 Cast(S.Custo_Medio as double precision) From TbEstoque_Saldo_Diario S
                     Where S.Estabelecimento_Codigo = A.Estabelecimento_Codigo
                       and S.Data = A.Data
                       and S.Produto_Codigo = A.Produto_Codigo
                       and S.Localizacao_Codigo = A.Localizacao_Codigo)) Custo_Medio
                From TbEstoque_Transacao_Item A, TbProduto P, TBOperacao O,  tbproduto_operacao_contabil c
                Where A.Estabelecimento_Codigo = :estabelecimento
                  and A.Produto_Codigo = P.Codigo
                  and A.DATA BETWEEN :Data1 and :Data2
                  AND A.tipo = 'S'
                  AND P.codigo = c.produto_id
                  and c.conta_contabil = :CONTA
                  and O.Codigo = A.Operacao_Codigo
                  and O.GGF = '1'
                  and p.inventario = 1
                Group by 1
            )
        into
            :CCUSTO,
            :VALOR,
            :PERC
        do
        begin
            :olt_ccusto  = CCUSTO;
            :olt_valor   = VALOR;
            :olt_familia = '';
            :olt_conta   = CONTA;

            TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);

            if(TIPO_CUSTO <> 3)then
            begin
                update tbrateamento_historico h set
                  h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:VALOR,0)),
                  h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':0:'||coalesce(:VALOR,0))
                where h.ano = :ano
                and h.mes = :mes
                and h.rateamento_grupo = :RATEAMENTO_GRUPO
                and replace(h.ccusto,'*','') = :CCUSTO;
            end else
            begin
              INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :VALOR, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO, 0);
            end

           insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), :PERC,  :RATEAMENTO_GRUPO, 3, 0);
           suspend;
        end

     end

     --valor pelo lancamento contabil
     if(:VALOR_ORIGEM = 4 or :VALOR_ORIGEM = 6)then
     begin

        for
            SELECT
               IIF(:VALOR_ORIGEM = 4,
               (
            select
               SUM(VALOR * iif(a.natureza = 'C', -1, 1))
            from tbmovcontabil a
            where a.conta = :CONTA
              and a.tipolanc <> 'E'
              and a.data between :DATA1 and :DATA2
                ),(
               select
                   SUM(VALOR * iif(a.natureza = 'C', -1, 1))
                from tbmovcontabil a
                where a.conta = :CONTA
                  AND A.CODORIGEM = 'NFE'
                  and a.data between :DATA1 and :DATA2
              )
           ) AS VALOR FROM rdb$database
        into
            :VALOR
        do
        begin

            
            --rateamento fixo
            if(:TIPO_ID < 1000)then
            begin
                for
                    select
                       ccusto,
                       fn_calc_precision(fn_calc_precision(valor, 1.00000,'*'), TOTAL,'/')  as PERC
                    from(
                        select
                            ccusto,
                            sum(valor) as valor,
                            max(TOTAL) as TOTAL
                        from(
                            select
                               iif(codigo2 is null, ccusto , codigo2) as ccusto,
                               valor,
                               sum(valor) over() as TOTAL
                            from(
                                select
                                    c.ccusto,
                                    c.valor,
                                    (select first 1 h.ccusto from  tbrateamento_historico h where h.rateamento_grupo = :RATEAMENTO_GRUPO and h.ano = :ano and h.mes = :mes and c.ccusto like replace(replace(h.ccusto||'*','**','*'),'*','%')) as codigo2
                                from tbrateamento_tipo t, TBRATEAMENTO_TIPO_DETALHE c
                                where c.tipo_id = :TIPO_ID
                                and t.id = c.tipo_id
                                and :DATA1 between t.data_inicial and coalesce(t.data_final,'31.12.3000')
                            )
                        ) group by ccusto
                    )
                    /*
                    select
                        ccusto,
                        cast(((valor * 1.00000) / TOTAL) as numeric(18,8)) as PERC
                    from(
                        select
                            c.ccusto,
                            c.valor,
                            sum(c.valor) over() as TOTAL
                        from TBRATEAMENTO_TIPO_DETALHE c, tbrateamento_tipo t
                        where c.tipo_id = :TIPO_ID
                        and t.id = c.tipo_id
                        and :DATA1 between t.data_inicial and coalesce(t.data_final,'31.12.3000')
                    )
                    */
                into
                   :CCUSTO,
                   :PERC
                do
                begin
                    :olt_ccusto = CCUSTO;
    
                    --:olt_valor  =  cast(( cast(VALOR as numeric(18,0)) * PERC) as numeric(18,8));
                    --:olt_valor  =  cast((cast(VALOR as numeric(18,4)) * cast(PERC as numeric(18,4))) as numeric(18,8));
                    :olt_valor = fn_calc_precision(VALOR, PERC, '*');
    
                    :olt_familia = '';
                    :olt_conta   = CONTA;
        
                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
                    if(TIPO_CUSTO <> 3)then
                    begin
                        update tbrateamento_historico h set
                          h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:olt_valor,0)),
                          h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':'||cast(:PERC as numeric(18,8))||':'||coalesce(:olt_valor,0))
                        where h.ano = :ano
                        and h.mes = :mes
                        and h.rateamento_grupo = :RATEAMENTO_GRUPO
                        and replace(h.ccusto,'*','') = :CCUSTO;
                    end else
                    begin
                      INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :olt_valor, :ANO, :MES, 6, :PERC, :GRUPO_RATEAMENTO,0);
                    end

                    insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), cast(:PERC as numeric(18,4)),  :RATEAMENTO_GRUPO, 3,0);

                    suspend;
                end
            end

            --rateamento colaborador
            if(:TIPO_ID = 1001)then
            begin
                for
                    select
                        CODIGO,
                        sum(TOTAL)
                    from(
                        select
                            codigo,
                            fn_calc_precision(PESO, TOTAL,'/') as TOTAL
                        from(
                            select
                                codigo,
                                PESO,
                                sum(PESO) over() as TOTAL
                                --((PESO * 1.00000000) / sum(PESO) over()) as TOTAL
                                --fn_calc_precision(fn_calc_precision(PESO,1.00000000,'*'), sum(PESO) over(),'/') as TOTAL
                            from(
                        
                                select
                                   iif(i.codigo2 is null, i.codigo , i.codigo2) as codigo,
                                   descricao,
                                   PESO
                                from(
                                    select
                                
                                        j.codigo,
                                        j.descricao,
                                        (select first 1 h.ccusto from  tbrateamento_historico h where h.rateamento_grupo = :RATEAMENTO_GRUPO and h.ano = :ano and h.mes = :mes and j.codigo like replace(replace(h.ccusto||'*','**','*'),'*','%')) as codigo2,
                                        count(c.pessoal_nome) as PESO
                                    
                                    from tbcolaborador c, tbcentro_de_custo j
                                    
                                    where c.situacao = '1'
                                    and j.codigo = c.centro_de_custo_codigo
                                    
                                    group by 1,2,3
                                ) i
                            )
                        )
                    ) group by 1
                into
                   :CCUSTO,
                   :PERC
                do
                begin

                    :olt_ccusto = CCUSTO;
    
                    --:olt_valor  =  cast((cast(VALOR as numeric(18,4)) * cast(PERC as numeric(18,4))) as numeric(18,8));
                    :olt_valor = fn_calc_precision(VALOR, PERC, '*');

    
                    :olt_familia = '';
                    :olt_conta   = CONTA;
        
                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
                    if(TIPO_CUSTO <> 3)then
                    begin
                        update tbrateamento_historico h set
                          h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:olt_valor,0)),
                          h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':'||cast(:PERC as numeric(18,8))||':'||coalesce(:olt_valor,0))
                        where h.ano = :ano
                        and h.mes = :mes
                        and h.rateamento_grupo = :RATEAMENTO_GRUPO
                        and replace(h.ccusto,'*','') = replace(:CCUSTO,'*','');
                    end else
                    begin
                      INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :olt_valor, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO,0);
                    end

                    insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), cast(:PERC as numeric(18,8)),  :RATEAMENTO_GRUPO, 2, 0);

                    suspend;
                end
            end

            --rateamento colaborador/transporte
            if(:TIPO_ID = 1004)then
            begin

                for
                    select
                        CCusto,
                        fn_calc_precision(Colaboradores, total,'/') as PERC
                    from (
                        select
                            iif(codigo2 is null, CCusto , codigo2) as CCusto,
                            sum(Colaboradores) as Colaboradores,
                            max(total) as total
                        from(
                            select
                                CCusto,
                                Colaboradores,
                                sum(Colaboradores) over() as total,
                               ( select first 1 h.ccusto from  tbrateamento_historico h where h.rateamento_grupo = :RATEAMENTO_GRUPO and h.ano = :ano and h.mes = :mes and y.ccusto like replace(replace(h.ccusto||'*','**','*'),'*','%')) as codigo2
                        from(
                                Select A.CCusto,
                                       Count(A.Colaborador_Id) Colaboradores
                                  From TbFolPag_Detalhe A, TbFolPag_Verba B
                                 Where A.Verba_Codigo = B.Codigo
                                   and B.Natureza in ('C','D')
                                   and B.CODIGO = 1498
                                   and A.Ano = :ANO
                                   and A.Mes = :MES
                                Group by 1
                            ) y where Colaboradores > 0
                        ) x Group by 1
                    )
                into
                   :CCUSTO,
                   :PERC
                do
                begin
                    :olt_ccusto = CCUSTO;
    
                    --:olt_valor  =  cast((cast(VALOR as numeric(18,0)) * PERC) as numeric(18,8));
                    --:olt_valor  =  cast((cast(VALOR as numeric(18,4)) * cast(PERC as numeric(18,4))) as numeric(18,8));
                    :olt_valor = fn_calc_precision(VALOR, PERC, '*');
    
                    :olt_familia = '';
                    :olt_conta   = CONTA;
        
                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
                    if(TIPO_CUSTO <> 3)then
                    begin
                        update tbrateamento_historico h set
                          h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:olt_valor,0)),
                          h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':'||cast(:PERC as numeric(18,8))||':'||coalesce(:olt_valor,0))
                        where h.ano = :ano
                        and h.mes = :mes
                        and h.rateamento_grupo = :RATEAMENTO_GRUPO
                        and replace(h.ccusto,'*','') = :CCUSTO;
                    end else
                    begin
                      INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :olt_valor, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO,0);
                    end

                    insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), cast(:PERC as numeric(18,8)),  :RATEAMENTO_GRUPO, 2, 0);

                    suspend;
                end
            end

            --rateamento colaborador/refeicao
            if(:TIPO_ID = 1005)then
            begin
                for select
                            CCusto,
                            fn_calc_precision(fn_calc_precision(Colaboradores,1.00000000,'*'), total,'/') as PERC
                        from(
                            select
                                CCusto,
                                Colaboradores,
                                sum(Colaboradores) over() total
                                --(Colaboradores * 1.00000000) / sum(Colaboradores) over() PERC
                                --fn_calc_precision(fn_calc_precision(Colaboradores,1.00000000,'*'), sum(Colaboradores) over(),'/') as PERC
                            from(
                                Select A.CCusto,
                                       Count(A.Colaborador_Id) Colaboradores
                                  From TbFolPag_Detalhe A, TbFolPag_Verba B
                                 Where A.Verba_Codigo = B.Codigo
                                   and B.Natureza in ('C','D')
                                   and B.CODIGO = 209
                                   and A.Ano = :ANO
                                   and A.Mes = :MES
                            Group by 1
                            ) where Colaboradores > 0
                        )
                into
                   :CCUSTO,
                   :PERC
                do
                begin
                    :olt_ccusto = CCUSTO;
    
                    --:olt_valor  =  cast((cast(VALOR as numeric(18,0)) * PERC) as numeric(18,8));
                    --:olt_valor  =  cast((cast(VALOR as numeric(18,4)) * cast(PERC as numeric(18,4))) as numeric(18,8));
                    :olt_valor    = fn_calc_precision(VALOR, PERC, '*');
    
                    :olt_familia = '';
                    :olt_conta   = CONTA;
        
                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
                    if(TIPO_CUSTO <> 3)then
                    begin
                        update tbrateamento_historico h set
                          h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:olt_valor,0)),
                          h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':'||cast(:PERC as numeric(18,8))||':'||coalesce(:olt_valor,0))
                        where h.ano = :ano
                        and h.mes = :mes
                        and h.rateamento_grupo = :RATEAMENTO_GRUPO
                        and replace(h.ccusto,'*','') = :CCUSTO;
                    end else
                    begin
                      INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :olt_valor, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO,0);
                    end

                    insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), cast(:PERC as numeric(18,8)),  :RATEAMENTO_GRUPO, 2, 0);

                    suspend;
                end
            end

            --rateamento para setores do corte
            if(:TIPO_ID = 1006)then
            begin
                for select
                        CCUSTO,
                        fn_calc_precision(1.00000000, total,'/') as PERC
                    from(
                        select
                            CCUSTO,
                            count(CCUSTO) over() as total
                            --1.000000 / count(CCUSTO) over() as PERC
                            --fn_calc_precision(1.00000000, sum(CCUSTO) over(),'/') as PERC
                        from(
                        select DISTINCT CC.CODIGO CCUSTO, 1 PESO
                        from tbcentro_de_custo cc, tbponto_cartao pc
                        where cc.codigo = pc.ccusto
                          and pc.data between :DATA1 and :DATA2
                          and cc.ct = 'BH'
                        )
                    )
                into
                   :CCUSTO,
                   :PERC
                do
                begin
                    :olt_ccusto = CCUSTO;
    
                    --:olt_valor  =  cast((VALOR * PERC) as numeric(18,8));
                    :olt_valor = fn_calc_precision(VALOR, PERC, '*');
    
                    :olt_familia = '';
                    :olt_conta   = CONTA;

                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
                    if(TIPO_CUSTO <> 3)then
                    begin
                        update tbrateamento_historico h set
                          h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:olt_valor,0)),
                          h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':'||cast(:PERC as numeric(18,8))||':'||coalesce(:olt_valor,0))
                        where h.ano = :ano
                        and h.mes = :mes
                        and h.rateamento_grupo = :RATEAMENTO_GRUPO
                        and replace(h.ccusto,'*','') = :CCUSTO;
                    end else
                    begin
                      INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :olt_valor, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO,0);
                    end

                    insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), cast(:PERC as numeric(18,8)),  :RATEAMENTO_GRUPO, 3, 0);

                    suspend;
                end
            end

            --rateamento pelo percentual de faturamento das familias
            if(:TIPO_ID = 1007)then
            begin
                for
                    select
                        CCUSTO_ID,
                        fn_calc_precision(VALOR, TOTAL, '/') as PERCENTUAL
                    from(
                        select
                            CCUSTO_ID,
                            VALOR,
                            sum(VALOR) over() as TOTAL
                        from(
                            select
                                c.ccusto_id,
                                sum(f.faturamento) as VALOR
                            from TBFAMILIA_FATURAMENTO f, tbcentro_negocio_familia n, vwcentro_negocio_ccusto c
                            where f.ano = :ANO
                            and f.mes = :MES
                            and n.familia_id = f.familia_id
                            and c.centro_negocio_id = n.centro_negocio_id
                            group by 1
                        )
                    )
                into
                   :CCUSTO,
                   :PERC
                do
                begin
                    :olt_ccusto = CCUSTO;
    
                    :olt_valor = fn_calc_precision(VALOR, PERC, '*');
    
                    :olt_familia = '';
                    :olt_conta   = CONTA;

                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
                    if(TIPO_CUSTO <> 3)then
                    begin
                        update tbrateamento_historico h set
                          h.ACUMULADO_CONTA = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:olt_valor,0)),
                          h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':'||cast(:PERC as numeric(18,8))||':'||coalesce(:olt_valor,0))
                        where h.ano = :ano
                        and h.mes = :mes
                        and h.rateamento_grupo = :RATEAMENTO_GRUPO
                        and replace(h.ccusto,'*','') = :CCUSTO;
                    end else
                    begin
                      INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CONTA, :CCUSTO, :olt_valor, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO,0);
                    end

                    insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CONTA, :CCUSTO,coalesce(:olt_valor,0), cast(:PERC as numeric(18,8)),  :RATEAMENTO_GRUPO, 3, 0);

                    suspend;
                end
            end

        end
     end

     --valor pelo lancamento contabil do imobilizado
     if(:TIPO_ID = 1002)then
     begin
        for
                select
                    CCUSTO,
                    CCONTABIL_DEBITO,
                    VALOR,
                    fn_calc_precision(VALOR,sum(VALOR) over(),'/') as PERC
                from(
                     SELECT
                        I.CCUSTO,
                        t.CCONTABIL_DEBITO,
                        SUM(ID.VALOR) as VALOR
                      FROM TBIMOBILIZADO_DEPRECIACAO ID,
                           TBIMOBILIZADO_ITEM II,
                           TBIMOBILIZADO I,
                           tbimobilizado_tipo T,
                          (SELECT FIRST 1 CAST('01.' || CAST(:MES AS INTEGER) || '.' || CAST(:ANO AS INTEGER) AS DATE) DATA FROM TBTURNO T) D
                    
                    WHERE
                        ID.DATA BETWEEN FN_START_OF_MONTH(D.DATA) AND FN_END_OF_MONTH(D.DATA)
                    AND II.ID = ID.IMOBILIZADO_ITEM_ID
                    AND I.ID  = II.IMOBILIZADO_ID
                    AND T.id = i.tipo_id
                    and T.tipo_gasto = 1
                    and t.CCONTABIL_DEBITO = :CONTA
                    group by 1,2
                )
        into
            :CCUSTO,
            :CCONTABIL_DEBITO,
            :VALOR,
            :PERC
        do
        begin
            :olt_ccusto = CCUSTO;
            :olt_valor  = VALOR;
            :olt_conta  = :CONTA;

            TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:CCUSTO,'*','')),0);
    
            if(TIPO_CUSTO <> 3)then
            begin
                update tbrateamento_historico h set
                  h.ACUMULADO_CONTA  = (coalesce(h.ACUMULADO_CONTA,0) + coalesce(:VALOR,0)),
                  h.valor_composicao = (coalesce(h.valor_composicao,'') || ' + '||:CONTA||':0:'||coalesce(:VALOR,0))
                where h.ano = :ano
                and h.mes = :mes
                and h.rateamento_grupo = :RATEAMENTO_GRUPO
                and replace(h.ccusto,'*','') = :CCUSTO;
            end else
            begin
              INSERT INTO TBDESPESA_HISTORICO (CONTA, CCUSTO, VALOR, ANO, MES, TIPO, PERCENTUAL, GRUPO_RATEAMENTO, servico) VALUES (:CCONTABIL_DEBITO, :CCUSTO, :VALOR, :ANO, :MES, 6, :PERC, :RATEAMENTO_GRUPO,0);
            end

            insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, servico) values(:ano, :mes,:CCONTABIL_DEBITO, :CCUSTO,coalesce(:VALOR,0), :PERC,  :RATEAMENTO_GRUPO, 2, 0);

            suspend;
        end

     end

  end

  --rateamentos recebidos em c. de custo filhos
  for

      select
        CCUSTO,

        coalesce((
            select
                sum(d.valor)
            from TBRATEAMENTO_DETALHE d
            where replace(d.ccusto ,'*','') like replace(replace(rc.ccusto||'*' ,'**','*'),'*','%')
            and d.ano  =  rc.ano
            and d.mes  =  rc.mes
            and d.tipo > 1
            and d.grupo_rateamento = rc.rateamento_grupo
        ),0) as VALOR

      from
      TBRATEAMENTO_HISTORICO rc
      where rc.RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO
      and rc.ano = :ANO
      and rc.mes = :MES

      order by rc.abrangencia, rc.ordem ascending

   into
      :CCUSTO,
      :VALOR
   do
   begin

        update tbrateamento_historico h set
          h.ACUMULADO_CONTA  = coalesce(:VALOR,0),
          h.valor_composicao = coalesce(h.valor_composicao,'') || ' + rateamento filhos'
        where h.ano = :ano
        and h.mes = :mes
        and h.rateamento_grupo = :GRUPO_RATEAMENTO
        and h.ccusto = :CCUSTO;

   end


end
^

SET TERM ; ^

SET TERM ^ ;

CREATE OR ALTER procedure SPU_RATEAMENTO_DETALHADO (
    ANO integer,
    MES integer,
    GRUPO_RATEAMENTO integer,
    ESTABELECIMENTO_ID integer)
returns (
    RET_CCUSTO_PAI varchar(10),
    RET_CCUSTO_FILHO varchar(10),
    RET_PERC numeric(18,8),
    RET_VALOR numeric(18,8),
    RET_REGRA integer,
    RET_SETORES integer,
    RET_COLABORADORES integer,
    RET_LOG1 varchar(300),
    RET_LOG2 varchar(300),
    RET_ACUMULADO_CONTA numeric(18,8),
    RET_REG1 integer,
    RET_REG2 integer,
    RET_REG3 integer,
    RET_REG4 numeric(18,8),
    TIPO_CUSTO integer,
    RATEAMENTO_VERTICAL integer,
    RATEAMENTO_HORIZONTAL integer)
as
declare variable CCUSTO varchar(10);
declare variable PERC_RATEAMENTO numeric(18,8);
declare variable REGRA_RATEAMENTO integer;
declare variable ABRANGENCIA integer;
declare variable VALOR numeric(18,8);
declare variable ABSORVIDO numeric(18,8);
declare variable T_COLABORADORES numeric(18,8);
declare variable V_ID integer;
declare variable V_CCUSTO varchar(10);
declare variable V_COLABORADORES integer;
declare variable TEMP numeric(18,9);
declare variable T_SETORES integer;
declare variable PERC_RATEIO numeric(18,8);
declare variable ACUMULADO_CONTA numeric(18,8);
declare variable TIPO_ID integer;
declare variable TOTAL_REGRA_RATEADO numeric(18,8);
declare variable TOTAL_REGRA_ABSORVIDO numeric(18,8);
declare variable TOTAL_REGRA numeric(18,8);
declare variable V_PERC_ABSORCAO numeric(15,4);
declare variable VL_RATEAR numeric(18,8);
declare variable OG_RATEAR varchar(20);
declare variable PR_RATEAR numeric(15,6);
declare variable SV_RATEAR integer;
declare variable V_PERC numeric(18,8);
begin

   TEMP = (select sum(valor) from SPU_RATEAMENTO_HISTORICO(:ano, :mes, :GRUPO_RATEAMENTO, :ESTABELECIMENTO_ID));

   --limpa o absorvido
   update TBRATEAMENTO_HISTORICO rc set rc.absorvido = 0, rc.nivel_absolvicao = 0, VALOR_COMPOSICAO = '', ACUMULADO_CONTA = 0
      where rc.RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO
      and rc.ano = :ano
      and rc.mes = :mes;

   TEMP = (select sum(olt_valor) from SPU_RATEAMENTO_CONTABIL(:ano, :mes, :GRUPO_RATEAMENTO, :ESTABELECIMENTO_ID));

   --passa do centro de custo mais abrangente ate o menos abrangente rateando o valor
   for

      select
        CCUSTO,
        VALOR,
        ACUMULADO_CONTA,
        REGRA_RATEAMENTO,
        PERC_RATEAMENTO,
        ABRANGENCIA,
        TIPO_ID,
        RATEAMENTO_VERTICAL,
        RATEAMENTO_HORIZONTAL
      from
      TBRATEAMENTO_HISTORICO rc
      where rc.RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO
      and rc.ano = :ANO
      and rc.mes = :MES

      order by rc.abrangencia, rc.ordem ascending

   into
        :CCUSTO,
        :VALOR,
        :ACUMULADO_CONTA,
        :REGRA_RATEAMENTO,
        :PERC_RATEAMENTO,
        :ABRANGENCIA,
        :TIPO_ID,
        :RATEAMENTO_VERTICAL,
        :RATEAMENTO_HORIZONTAL
   do
   begin

         if(:TIPO_ID < 1000)then
         begin

            --total usando o tipo de regra para ccustos que serao rateados
            TOTAL_REGRA_RATEADO = coalesce((
                                            select
                                                sum(c.valor)
                                            from TBRATEAMENTO_TIPO_DETALHE c, tbrateamento_tipo t, TBRATEAMENTO_HISTORICO rc
                                        
                                            where rc.RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO
                                            and rc.abrangencia < 9999
                                            and rc.abrangencia > :ABRANGENCIA
                                            and rc.ano = :ANO
                                            and rc.mes = :MES
                                            and rc.STOP_PROPAG = 0
                                            and (c.ccusto = rc.ccusto or c.ccusto like replace(replace(rc.ccusto||'*','**','*'),'*','%'))
                                            and c.tipo_id = :TIPO_ID
                                            and t.id = c.tipo_id
                                            and cast('01.'||:MES||'.'||:ANO as date) between t.data_inicial and coalesce(t.data_final,'31.12.3000')
                                            and iif(:RATEAMENTO_VERTICAL = 1, true, false)

                                        ),0);

            --total usando o tipo de regra para ccustos que só absorvem
            TOTAL_REGRA_ABSORVIDO = coalesce((
                                                select
                                                    sum(c.valor)
                                                from TBRATEAMENTO_TIPO_DETALHE c, tbrateamento_tipo t, TBRATEAMENTO_HISTORICO rc
                                                where rc.RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO
                                                and rc.ccusto in (select distinct
                                                                        a.ccusto
                                                                    from TBRATEAMENTO_ABSORCAO a
                                                                    where a.ccusto_absorcao = :CCUSTO
                                                                    and a.rateamento_grupo = :GRUPO_RATEAMENTO
                                                                 )
                                                and rc.ano = :ANO
                                                and rc.mes = :MES
                                                and rc.STOP_PROPAG = 0
                                                and c.ccusto = rc.ccusto
                                                and c.tipo_id = :TIPO_ID
                                                and t.id = c.tipo_id
                                                and cast('01.'||:MES||'.'||:ANO as date) between t.data_inicial and coalesce(t.data_final,'31.12.3000')
                                                and iif(:rateamento_horizontal = 1, true, false)
                                            ),0);
        end

       for
            select
                valor,
                origem,
                servico
            from(
                select
                    sum(t.valor) as valor,
                    t.origem,
                    t.servico,
                    1 as add_salario
                from TBRATEAMENTO_DETALHE t
                where t.ano = :ano
                and t.mes = :mes
                and t.ccusto like replace(:CCUSTO,'*','%')
                and t.grupo_rateamento = :GRUPO_RATEAMENTO
    
                group by t.origem, t.servico
    
                union
    
                select
                    SALARIO,
                    '31100400001' as origem,
                    0 servico,
                    iif(:GRUPO_RATEAMENTO = 1, 1, 0) as add_salario
                from SPC_SALARIO_CCUSTO_V2(:ANO, :MES, :ESTABELECIMENTO_ID, :CCUSTO)

            ) where add_salario = 1
       into
            :VL_RATEAR,
            :OG_RATEAR,
            :SV_RATEAR
       do begin

            :VALOR            = :VL_RATEAR;
            :ACUMULADO_CONTA  = 0;
            :ABSORVIDO        = 0;

            :SV_RATEAR = coalesce(SV_RATEAR,0);

            if(TIPO_ID = 1007)then
            begin

                for
                    select
                        CCUSTO_ID,
                        fn_calc_precision(VALOR, TOTAL, '/') as PERCENTUAL
                    from(
                        select
                            CCUSTO_ID,
                            VALOR,
                            sum(VALOR) over() as TOTAL
                        from(
                            select
                                c.ccusto_id,
                                sum(f.faturamento) as VALOR
                            from TBFAMILIA_FATURAMENTO f, tbcentro_negocio_familia n, vwcentro_negocio_ccusto c, tbcentro_negocio j
                            where f.ano = :ANO
                            and f.mes = :MES
                            and n.familia_id = f.familia_id
                            and c.centro_negocio_id = n.centro_negocio_id
                            and j.id = c.centro_negocio_id
                            and j.status = 1
                            group by 1
                        )
                    )
                into
                   :V_CCUSTO,
                   :V_PERC
                do
                begin
                    TEMP = 0;
                    RET_LOG1 = '';
                    RET_LOG2 = '';

                    PERC_RATEIO = V_PERC;

                    TEMP = FN_CALC_PRECISION(PERC_RATEAMENTO,100.0000,'/');
                    TEMP = FN_CALC_PRECISION(VALOR , TEMP,'*');
                    TEMP = FN_CALC_PRECISION(V_PERC, TEMP,'*');

                    TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:V_CCUSTO,'*','')),0);
                
                    if(TIPO_CUSTO <> 3)then
                    begin
            
                        UPDATE TBRATEAMENTO_HISTORICO set ABSORVIDO = (coalesce(ABSORVIDO,0) + :TEMP)
                        where ANO = :ano
                        and MES = :MES
                        and CCUSTO = :V_CCUSTO
                        and RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO;
            
                         --adiciona o detalhamento
                         insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, colaboradores, TIPO_RATEAMENTO, CCUSTO_ORIGEM, SERVICO) values(:ano, :mes, :og_ratear, coalesce(:V_CCUSTO,''),:TEMP, :PERC_RATEIO,  :GRUPO_RATEAMENTO, 1, :V_COLABORADORES, :TIPO_ID, coalesce(:ccusto,''), :SV_RATEAR);
            
                     end else
                     begin
                        if(:GRUPO_RATEAMENTO = 2)then
                        begin
                            insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, colaboradores, TIPO_RATEAMENTO, CCUSTO_ORIGEM, SERVICO) values(:ano, :mes, :og_ratear, coalesce(:V_CCUSTO,''),:TEMP, :PERC_RATEIO,  :GRUPO_RATEAMENTO, 1, :V_COLABORADORES, :TIPO_ID, coalesce(:ccusto,''), :SV_RATEAR);
                        end
                     end
            
                     RET_PERC  = PERC_RATEIO;
                     RET_VALOR = TEMP;
                     RET_COLABORADORES = V_COLABORADORES;
                     RET_REGRA = REGRA_RATEAMENTO;
                     RET_CCUSTO_PAI = CCUSTO;
                     RET_CCUSTO_FILHO = V_CCUSTO;
                     RET_SETORES =  (T_SETORES);
                     RET_ACUMULADO_CONTA = :ACUMULADO_CONTA;

                end

            end else
            begin

                --if(:OG_RATEAR = '32100100001')then
                --begin
                --    exception "..." '32100100001 - '||:CCUSTO;
                --end

                --ccusto que recebem o rateamento
                for
                    select distinct
                        ID,
                        CCUSTO,
                        COLABORADORES,
                        --PERC_ABSORCAO,
                        iif(PERC_ABSORCAO > 0 and COLABORADORES > 0, ((PERC_ABSORCAO * 1.000000) / (sum(iif(COLABORADORES > 0, PERC_ABSORCAO, 0)) over())) * 100.0000, 0) as PERC_ABSORCAO,
                        sum(COLABORADORES) over() as  TCOLABORADORES,
                        sum(iif(COLABORADORES > 0, 1,0)) over() as SETORES
                    from (

                       select
                
                            ID,
                            CCUSTO,
                            COLABORADORES,
                            0 as PERC_ABSORCAO
                            from
                            TBRATEAMENTO_HISTORICO rc
                            where rc.RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO
                            and rc.abrangencia > :ABRANGENCIA and rc.abrangencia < 9999
                            and rc.ano = :ANO
                            and rc.mes = :MES
                            and rc.STOP_PROPAG = 0
                            and iif(:RATEAMENTO_VERTICAL = 1, true, false)
                
                        union
                            
                        select
                            ID,
                            CCUSTO,
                            coalesce((select COLABORADORES from SPC_SALARIO_CCUSTO_DRE(:ANO, :MES, :ESTABELECIMENTO_ID, rc.ccusto)),0) as COLABORADORES,
                            PERC_ABSORCAO
                            from
                            TBRATEAMENTO_ABSORCAO rc
                            where rc.ccusto_absorcao  = :CCUSTO
                            and iif(:rateamento_horizontal = 1, true, false)
                            and rc.rateamento_grupo = :GRUPO_RATEAMENTO
                
                    )
                
                into
                    :V_ID,
                    :V_CCUSTO,
                    :V_COLABORADORES,
                    :V_PERC_ABSORCAO,
                    :T_COLABORADORES,
                    :T_SETORES
                do
                begin
                
                    TEMP = 0;
                    RET_LOG1 = '';
                    RET_LOG2 = '';
                
                    --rateamento por colaborador
                     if(TIPO_ID = 1001)then
                     begin
                        if(T_COLABORADORES > 0 and V_COLABORADORES > 0)then
                        begin

                          PERC_RATEIO = FN_CALC_PRECISION(V_COLABORADORES, T_COLABORADORES, '/');
                          TEMP = FN_CALC_PRECISION(PERC_RATEAMENTO,100.0000,'/');
                          TEMP = FN_CALC_PRECISION((VALOR + ACUMULADO_CONTA + ABSORVIDO),TEMP,'*');
                          TEMP = FN_CALC_PRECISION(PERC_RATEIO, TEMP,'*');

                        end
                     end

                     --rateamento fixo
                     if(TIPO_ID = 1003 and (V_COLABORADORES > 0 or V_PERC_ABSORCAO > 0))then
                     begin
                
                          if(V_PERC_ABSORCAO > 0)then
                          begin

                             PERC_RATEIO = FN_CALC_PRECISION(V_PERC_ABSORCAO, 100.0000, '/');
                             TEMP = FN_CALC_PRECISION(PERC_RATEAMENTO,100.0000,'/');
                             TEMP = FN_CALC_PRECISION((VALOR + ACUMULADO_CONTA + ABSORVIDO),TEMP,'*');
                             TEMP = FN_CALC_PRECISION(PERC_RATEIO, TEMP,'*');

                          end else
                          begin
                              if(T_SETORES > 0)then
                              begin

                                 PERC_RATEIO = FN_CALC_PRECISION(FN_CALC_PRECISION(100.0000 , T_SETORES,'/'), 100.0000, '/');
                                 TEMP = FN_CALC_PRECISION(PERC_RATEAMENTO,100.0000,'/');
                                 TEMP = FN_CALC_PRECISION((VALOR + ACUMULADO_CONTA + ABSORVIDO), TEMP,'*');
                                 TEMP = FN_CALC_PRECISION(PERC_RATEIO, TEMP, '*');

                              end
                          end
                     end
                
                     RET_REG1 = null;
                     RET_REG2 = null;
                     RET_REG3 = null;
                     RET_REG4 = null;
                
                     if(TIPO_ID < 1000)then
                     begin
                
                        --total usando a regra
                        TOTAL_REGRA = coalesce((select
                                                sum(c.valor)
                                            from TBRATEAMENTO_TIPO_DETALHE c, tbrateamento_tipo t
                                        
                                            where (c.ccusto = :V_CCUSTO or c.ccusto like replace(replace(:V_CCUSTO||'*','**','*'),'*','%'))
                                            and c.tipo_id = :TIPO_ID
                                            and t.id = c.tipo_id
                                            and cast('01.'||:MES||'.'||:ANO as date) between t.data_inicial and coalesce(t.data_final,'31.12.3000')),0);
                
                
                        RET_REG1 = cast(coalesce(TOTAL_REGRA,0) * 10000 as numeric(18,0));
                        RET_REG2 = cast(coalesce(TOTAL_REGRA_RATEADO,0) * 10000 as numeric(18,0));
                        RET_REG3 = cast(coalesce(TOTAL_REGRA_ABSORVIDO,0) * 10000 as numeric(18,0));
                
                        RET_REG4 = (RET_REG2 + RET_REG3);
                
                        if(RET_REG4 > 0)then
                        begin

                            PERC_RATEIO = FN_CALC_PRECISION(FN_CALC_PRECISION(RET_REG1,1.0000,'*'), RET_REG4, '/');
                            TEMP        = FN_CALC_PRECISION(PERC_RATEAMENTO,100.0000,'/');
                            TEMP        = FN_CALC_PRECISION((VALOR + ACUMULADO_CONTA + ABSORVIDO),TEMP,'*');
                            TEMP        = FN_CALC_PRECISION(PERC_RATEIO, TEMP,'*');

                        end
                
                     end
                    
                     TEMP = coalesce(TEMP,0);
                     PERC_RATEIO = coalesce(PERC_RATEIO,0);
                     PERC_RATEIO = cast(:PERC_RATEIO as numeric(18,8));
                    
                    if(
                        ((TIPO_ID = 1001 or TIPO_ID = 1003 or TIPO_ID = 1006) and V_COLABORADORES > 0) or
                        (TIPO_ID <> 1001 and TIPO_ID <> 1003 and TIPO_ID <> 1006)
                    )then
                    begin
                
                
                        TIPO_CUSTO = coalesce((select c.tipo_custo from tbcentro_de_custo c where c.codigo = replace(:V_CCUSTO,'*','')),0);
                
                        if(TIPO_CUSTO <> 3)then
                        begin
                
                            if( coalesce((select k.id from TBRATEAMENTO_HISTORICO k where k.ano = :ano and k.mes = :mes and k.ccusto = :V_CCUSTO and k.rateamento_grupo = :GRUPO_RATEAMENTO),0) = 0 )then
                            begin
            
                               INSERT INTO TBRATEAMENTO_HISTORICO (
                                    ANO, 
                                    MES, 
                                    CCUSTO, 
                                    RATEAMENTO_GRUPO, 
                                    COLABORADORES,
                                    VALOR,
                                    ACUMULADO_CONTA,
                                    REGRA_RATEAMENTO,
                                    PERC_RATEAMENTO,
                                    TIPO_ID,
                                    STOP_PROPAG
                                ) VALUES (
                                    :ANO,
                                    :MES,
                                    :V_CCUSTO,
                                    :GRUPO_RATEAMENTO,
                                    :V_COLABORADORES,
                                    0,
                                    0,
                                    0,
                                    0,
                                    0,
                                    0
                                );
            
                            end
            
                            UPDATE TBRATEAMENTO_HISTORICO set ABSORVIDO = (coalesce(ABSORVIDO,0) + :TEMP)
                            where ANO = :ano
                            and MES = :MES
                            and CCUSTO = :V_CCUSTO
                            and RATEAMENTO_GRUPO = :GRUPO_RATEAMENTO;

                            --adiciona o detalhamento
                            insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, colaboradores, TIPO_RATEAMENTO, CCUSTO_ORIGEM, SERVICO) values(:ano, :mes, :og_ratear, coalesce(:V_CCUSTO,''),:TEMP, :PERC_RATEIO,  :GRUPO_RATEAMENTO, 1, :V_COLABORADORES, :TIPO_ID, coalesce(:ccusto,''), :SV_RATEAR);
                
                         end else
                         begin
                            if(:GRUPO_RATEAMENTO = 2)then
                            begin
                                insert into TBRATEAMENTO_DETALHE (ano, mes, origem, CCUSTO, valor, rateamento, grupo_rateamento, tipo, colaboradores, TIPO_RATEAMENTO, CCUSTO_ORIGEM, SERVICO) values(:ano, :mes, :og_ratear, coalesce(:V_CCUSTO,''),:TEMP, :PERC_RATEIO,  :GRUPO_RATEAMENTO, 1, :V_COLABORADORES, :TIPO_ID, coalesce(:ccusto,''), :SV_RATEAR);
                            end
                         end
                
                         RET_PERC  = PERC_RATEIO;
                         RET_VALOR = TEMP;
                         RET_COLABORADORES = V_COLABORADORES;
                         RET_REGRA = REGRA_RATEAMENTO;
                         RET_CCUSTO_PAI = CCUSTO;
                         RET_CCUSTO_FILHO = V_CCUSTO;
                         RET_SETORES =  (T_SETORES);
                         RET_ACUMULADO_CONTA = :ACUMULADO_CONTA;
                
                     suspend;
                   end
                
                end

            end
       end
   end

end
^

SET TERM ; ^


SET TERM ^ ;

CREATE OR ALTER function FN_DRE_LANCAMENTOS_RAT (
    CCUSTO varchar(20),
    ID integer,
    CONTA varchar(20),
    ANO integer,
    MES integer,
    TIPO integer,
    NATUREZA_SERVICO varchar(10),
    USAR_REGRA_COMERCIAL integer = 0,
    USAR_REGRA_SERVICOS integer = 0,
    SQL blob sub_type 0 segment size 80 = '0',
    TIPO2 integer = 0)
returns numeric(15,4)
AS
declare variable valor numeric(15,4);
declare variable v1 numeric(15,4);
declare variable v2 numeric(15,4);
declare variable v3 numeric(15,4);
declare variable extra numeric(15,4);
begin
   V1 = 0;
   V2 = 0;
   V3 = 0;

   if(USAR_REGRA_COMERCIAL = 0 and (TIPO = 1 or TIPO = 3))then
   begin

        V1 = coalesce((
            select
                cast(sum(h.valor) as numeric(15,4))as valor
            from TBRATEAMENTO_DETALHE h, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c , TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND  c.ccusto_id like :CCUSTO) b
            where h.ano     = :ANO
            and   h.mes     = :MES
            and   h.origem  = :CONTA
            and   h.SERVICO = 0
            and   h.grupo_rateamento = 2
            and   h.ccusto like b.CCUSTO
            /*
            and (
                h.ccusto like '21%' or
                h.ccusto like '22%' or
                h.ccusto like '61%' or
                h.ccusto like '97%'
            )*/
    
        ),0) * -1;

   end

   if(USAR_REGRA_SERVICOS = 0 and (TIPO = 2 or TIPO = 3))then
   begin
       V2 = coalesce((
                /*
                select
                    sum(h.valor * iif(:NATUREZA_SERVICO = 'D', -1, 1))
                from TBDESPESA_HISTORICO h
                where h.ano     = :ANO
                and   h.mes     = :MES
                and   h.conta   = :CONTA
                and   h.SERVICO = 1
                and   h.grupo_rateamento = 2
                */

                select
                    sum(h.valor * iif(:NATUREZA_SERVICO = 'D', -1, 1))
                from TBRATEAMENTO_DETALHE h, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c , TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND  c.ccusto_id like :CCUSTO) b
                where h.ano     = :ANO
                and   h.mes     = :MES
                and   h.origem  = :CONTA
                and   h.SERVICO = 1
                and   h.grupo_rateamento = 2
                and   h.ccusto like b.CCUSTO
                    
            ),0);
   end

   if(USAR_REGRA_COMERCIAL = 1 and (TIPO = 1 or TIPO = 3))then
   begin
       :SQL = replace(:SQL,':MES'     ,:MES   );
       :SQL = replace(:SQL,':ANO'     ,:ANO   );
       :SQL = replace(:SQL,':CONTA'   ,:CONTA );
       :SQL = replace(:SQL,':CCUSTO'  , ''''||fn_replace(:CCUSTO,'%|*','','|')||'''');
       :SQL = replace(:SQL,'''''''''' , '''''');

       --exception "..." :SQL;

       :V1  = FN_EXECUTE_CALC_V3('coalesce(('||:SQL||'),0)') * iif(:NATUREZA_SERVICO = 'D', -1, 1);
   end

   if(USAR_REGRA_SERVICOS = 1 and (TIPO = 2 or TIPO = 3))then
   begin
       :SQL = replace(:SQL,':MES'    ,:MES   );
       :SQL = replace(:SQL,':ANO'    ,:ANO   );
       :SQL = replace(:SQL,':CONTA'  ,:CONTA );
       :SQL = replace(:SQL,':CCUSTO' , ''''||fn_replace(:CCUSTO,'%|*','','|')||'''');
       :SQL = replace(:SQL,'''''''''' , '''''');

       --exception "..." :SQL;

       :V2  = FN_EXECUTE_CALC_V3('coalesce(('||:SQL||'),0)') * iif(:NATUREZA_SERVICO = 'D', -1, 1);
   end

   EXTRA = 0;

   if(TIPO = 1 or TIPO = 3)then
   begin
        EXTRA = EXTRA +  coalesce((
                select sum(iif(m.tipo = 'D', m.valor * -1, m.valor))
                from tbdre_gerencial_ajuste m, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c , TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND  c.ccusto_id like :CCUSTO) b
                where m.ano      = :ANO
                and m.mes        = :MES
                and m.conta      = :CONTA
                and m.comercial  = 1
                and m.tipo_conta = 1
                and m.ccusto like b.CCUSTO
            ),0);

        EXTRA = EXTRA +  coalesce((
                select sum(iif(m.tipo = 'D', m.valor * -1, m.valor))
                from tbdre_gerencial_ajuste m, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c , TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND  c.ccusto_id like :CCUSTO) b
                where m.ano      = :ANO
                and m.mes        = :MES
                and m.conta      = :ID
                and m.comercial  = 1
                and m.tipo_conta = 2
                and m.ccusto like b.CCUSTO
            ),0);
   end

   if(TIPO = 2 or TIPO = 3)then
   begin
        EXTRA = EXTRA + coalesce((
                select sum(iif(m.tipo = 'D', m.valor * -1, m.valor))
                from tbdre_gerencial_ajuste m, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c , TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND  c.ccusto_id like :CCUSTO) b
                where m.ano      = :ANO
                and m.mes        = :MES
                and m.conta      = :CONTA
                and m.servicos   = 1
                and m.tipo_conta = 1 
                and m.ccusto like b.CCUSTO
            ),0);

        EXTRA = EXTRA +  coalesce((
                select sum(iif(m.tipo = 'D', m.valor * -1, m.valor))
                from tbdre_gerencial_ajuste m, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c, TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND c.ccusto_id like :CCUSTO) b
                where m.ano      = :ANO
                and m.mes        = :MES
                and m.conta      = :ID
                and m.servicos   = 1
                and m.tipo_conta = 2
                and m.ccusto like b.CCUSTO
            ),0);
   end

   if(TIPO2 > 0)then
   begin

        EXTRA = EXTRA + coalesce((
                select sum(iif(m.tipo = 'D', m.valor * -1, m.valor))
                from tbdre_gerencial_ajuste m, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c, TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND c.ccusto_id like :CCUSTO) b
                where m.ano        = :ANO
                and m.mes          = :MES
                and m.conta        = :CONTA
                and m.consolidado  = 1
                and m.tipo_conta   = 1
                and m.ccusto like b.CCUSTO
            ),0);

        EXTRA = EXTRA +  coalesce((
                select sum(iif(m.tipo = 'D', m.valor * -1, m.valor))
                from tbdre_gerencial_ajuste m, (select distinct c.ccusto_id||'%' as CCUSTO from vwcentro_negocio_ccusto c, TBCENTRO_NEGOCIO A where A.id = C.centro_negocio_id AND A.status = 1 AND c.ccusto_id like :CCUSTO) b
                where m.ano       = :ANO
                and m.mes         = :MES
                and m.conta       = :ID
                and m.consolidado = 1
                and m.tipo_conta  = 2
                and m.ccusto like b.CCUSTO
            ),0);
   end

   VALOR = coalesce(V1,0) + coalesce(V2,0) + coalesce(V3,0) + coalesce(EXTRA,0);

   --exception "..." coalesce(V1,0)||' | '||coalesce(V2,0)||' | '||coalesce(V3,0)||' | '||coalesce(EXTRA,0);

   return VALOR;
end
^

SET TERM ; ^

