Calculando impostos com MaFisIni, MaFisAdd, MaFisRet e MaFisEnd – Maratona AdvPL e TL++ 336

Nesse vídeo demonstraremos a utilização das funções MaFisIni, MaFisAdd, MaFisRet e MaFisEnd, que servem para calcular impostos conforme parametrizações do sistema (TES, Produtos, Clientes, Fornecedores, etc).

Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:

//Bibliotecas
#Include "Totvs.ch"

/*/{Protheus.doc} User Function zExe336
Cálcula os impostos de um pedido ou documento
@type Function
@author Atilio
@since 12/03/2023
@see https://tdn.totvs.com/pages/releaseview.action?pageId=605868324 e https://tdn.totvs.com/pages/releaseview.action?pageId=605867908
@obs 

    Função MaFisIni
    Parâmetros
        01 - Codigo Cliente/Fornecedor
        02 - Loja do Cliente/Fornecedor
        03 - C:Cliente , F:Fornecedor
        04 - Tipo da NF
        05 - Tipo do Cliente/Fornecedor
        06 - Relacao de Impostos que suportados no arquivo
        07 - Tipo de complemento
        08 - Permite Incluir Impostos no Rodape .T./.F.
        09 - Alias do Cadastro de Produtos - ("SBI" P/ Front Loja)
        10 - Nome da rotina que esta utilizando a funcao
    Retorno
        Função não tem retorno

    Função MaFisAdd
    Parâmetros
        01 - Codigo do Produto
        02 - Codigo do TES
        03 - Quantidade
        04 - Preco Unitario
        05 - Desconto
        06 - Numero da NF Original  ( Devolucao/Benef )
        07 - Serie da NF Original  ( Devolucao/Benef )
        08 - RecNo da NF Original no arq SD1/SD2
        09 - Valor do Frete do Item
        10 - Valor da Despesa do item
        11 - Valor do Seguro do item
        12 - Valor do Frete Autonomo
        13 - Valor da Mercadoria
        14 - Valor da Embalagem
        15 - RecNo do SB1
        16 - RecNo do SF4
    Retorno
        Função não tem retorno

    Função MaFisRet
    Parâmetros
        Posição do item (ou vazio se for do documento)
        Nome do valor a ser buscado
    Retorno
        Retorna o valor pesquisado

    Função MaFisEnd
    Parâmetros
        Função não tem parâmetros
    Retorno
        Função não tem retorno

    **** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/

User Function zExe336()
    Local aArea     := FWGetArea()
    Local aAreaBkp
    Local cPedido   := FWInputBox("Digite um número de pedido:")
    Local cMensagem := ""

    DbSelectArea("SC5")
    SC5->(DbSetOrder(1)) // Filial + Pedido
    DbSelectArea("SC6")
    SC6->(DbSetOrder(1)) // Filial + Pedido + Item + Produto
    DbSelectArea("SB1")
    SB1->(DbSetOrder(1)) // Filial + Produto

    //Posicionar na SC5 com MsSeek antes desse trecho
    If SC5->(MsSeek(FWxFilial("SC5") + cPedido))
    
        MaFisIni(;
            SC5->C5_CLIENTE,;                        // 01 - Codigo Cliente/Fornecedor
            SC5->C5_LOJACLI,;                        // 02 - Loja do Cliente/Fornecedor
            Iif(SC5->C5_TIPO $ "D;B", "F", "C"),;    // 03 - C:Cliente , F:Fornecedor
            SC5->C5_TIPO,;                           // 04 - Tipo da NF
            SC5->C5_TIPOCLI,;                        // 05 - Tipo do Cliente/Fornecedor
            MaFisRelImp("MT100", {"SF2", "SD2"}),;   // 06 - Relacao de Impostos que suportados no arquivo
            ,;                                       // 07 - Tipo de complemento
            ,;                                       // 08 - Permite Incluir Impostos no Rodape .T./.F.
            "SB1",;                                  // 09 - Alias do Cadastro de Produtos - ("SBI" P/ Front Loja)
            "MATA461";                               // 10 - Nome da rotina que esta utilizando a funcao
        )

        //Enquanto houver itens
        SC6->(MsSeek(FWxFilial('SC6') + SC5->C5_NUM))
        aAreaBkp := SC6->(FWGetArea())
        nItAtu := 0
        While ! SC6->(EoF()) .And. SC6->C6_NUM == SC5->C5_NUM
            nItAtu++
        
            //Adiciona o item nos tratamentos de impostos
            SB1->(MsSeek(FWxFilial("SB1")+SC6->C6_PRODUTO))
            nQtdPeso := SB1->B1_PESO
            MaFisAdd(;
                SC6->C6_PRODUTO,;    // 01 - Codigo do Produto                    ( Obrigatorio )
                SC6->C6_TES,;        // 02 - Codigo do TES                        ( Opcional )
                SC6->C6_QTDVEN,;     // 03 - Quantidade                           ( Obrigatorio )
                SC6->C6_PRCVEN,;     // 04 - Preco Unitario                       ( Obrigatorio )
                SC6->C6_VALDESC,;    // 05 - Desconto
                SC6->C6_NFORI,;      // 06 - Numero da NF Original                ( Devolucao/Benef )
                SC6->C6_SERIORI,;    // 07 - Serie da NF Original                 ( Devolucao/Benef )
                0,;                  // 08 - RecNo da NF Original no arq SD1/SD2
                0,;                  // 09 - Valor do Frete do Item               ( Opcional )
                0,;                  // 10 - Valor da Despesa do item             ( Opcional )
                0,;                  // 11 - Valor do Seguro do item              ( Opcional )
                0,;                  // 12 - Valor do Frete Autonomo              ( Opcional )
                SC6->C6_VALOR,;      // 13 - Valor da Mercadoria                  ( Obrigatorio )
                0,;                  // 14 - Valor da Embalagem                   ( Opcional )
                SB1->(RecNo()),;     // 15 - RecNo do SB1
                0;                   // 16 - RecNo do SF4
            )

            MaFisLoad("IT_VALMERC", SC6->C6_VALOR, nItAtu)                
            MaFisAlt("IT_PESO", nQtdPeso, nItAtu)
                
            SC6->(DbSkip())
        EndDo
                    
        //Altera dados do cabeçalho
        MaFisAlt("NF_FRETE", SC5->C5_FRETE)
        MaFisAlt("NF_SEGURO", SC5->C5_SEGURO)
        MaFisAlt("NF_DESPESA", SC5->C5_DESPESA) 
        MaFisAlt("NF_AUTONOMO", SC5->C5_FRETAUT)
        If SC5->C5_DESCONT > 0
            MaFisAlt("NF_DESCONTO", Min(MaFisRet(, "NF_VALMERC")-0.01, SC5->C5_DESCONT+MaFisRet(, "NF_DESCONTO")) )
        EndIf
        If SC5->C5_PDESCAB > 0
            MaFisAlt("NF_DESCONTO", A410Arred(MaFisRet(, "NF_VALMERC")*SC5->C5_PDESCAB/100, "C6_VALOR") + MaFisRet(, "NF_DESCONTO"))
        EndIf
            
        //Agora reposiciona nos itens para poder pegar os dados
        FWRestArea(aAreaBkp)
        nItAtu    := 0
        nTotalST  := 0
        nTotIPI   := 0
        nValorTot := 0
        While ! SC6->(EoF()) .And. SC6->C6_NUM == SC5->C5_NUM                
            nItAtu++
        
            //Pega os valores
            nBasICM    := MaFisRet(nItAtu, "IT_BASEICM")
            nValICM    := MaFisRet(nItAtu, "IT_VALICM")
            nValIPI    := MaFisRet(nItAtu, "IT_VALIPI")
            nAlqICM    := MaFisRet(nItAtu, "IT_ALIQICM")
            nAlqIPI    := MaFisRet(nItAtu, "IT_ALIQIPI")
            nValSol    := (MaFisRet(nItAtu, "IT_VALSOL") / SC6->C6_QTDVEN) 
            nBasSol    := MaFisRet(nItAtu, "IT_BASESOL")
            nPrcUniSol := SC6->C6_PRCVEN + nValSol
            nTotSol    := nPrcUniSol * SC6->C6_QTDVEN
            nTotalST   += MaFisRet(nItAtu, "IT_VALSOL")
            nTotIPI    += nValIPI
            nValorTot  += SC6->C6_VALOR
                
            SC6->(DbSkip())
        EndDo
        nTotFrete := MaFisRet(, "NF_FRETE")
        nTotVal := MaFisRet(, "NF_TOTAL")
        MaFisEnd()

        //Monta a mensagem e exibe
        cMensagem := "Pedido " + SC5->C5_NUM + CRLF + CRLF
        cMensagem += "Total ST:    " + cValToChar(nTotalST)  + CRLF
        cMensagem += "Total IPI:   " + cValToChar(nTotIPI)   + CRLF
        cMensagem += "Total Frete: " + cValToChar(nTotFrete) + CRLF
        cMensagem += "Total Valor: " + cValToChar(nTotVal)   + CRLF
        ShowLog(cMensagem)
    EndIf

    FWRestArea(aArea)
Return

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

4 Responses

  1. Arthur Pedroti disse:

    Como faria para usar o MaFisAdd junto com a TES Inteligente?

    • Bom dia Arthur, tudo joia?

      Infelizmente nunca precisei fazer uso das MaFis* junto de TES inteligente, então vou ficar devendo um exemplo pronto desse cenário.

      Mas de antemão, se os dados já estiverem gravados na SC6, a TES inteligente já foi acionada (caso do nosso exemplo, que estamos usando SC6->C6_TES).

      Agora caso você queira simular sem os dados estarem gravados, ai o que você poderia fazer é tentar simular o gatilho 1 do campo C6_OPER que usa a função MaTesInt para encontrar a TES Inteligente.

      Com isso, você joga o conteúdo em uma variável, tipo cTes e usa ela no lugar da SC6->C6_TES.

      Um grande abraço.

  2. Gabriel Martins disse:

    Boa tarde, e quanto ao cálculo do DIFAL, teria algum exemplo de como faria ele utilizando o MafisRet?

    Utilizamos o IT_DIFAL porém não bateu com o valor que queríamos.

    • Bom dia Gabriel, tudo joia?

      Infelizmente nunca precisei buscar o DIFAL usando as MaFis*. Pesquisando aqui em exemplos de clientes que já atendi, vi referências para IT_DIFAL e NF_PPDIFAL.

      Se eu conseguir um tempo, tentarei fazer alguns testes de estresse na rotina para simular um DIFAL ai eu atualizo o artigo.

      Tenha uma ótima e abençoada quarta feira.

      Um grande abraço.

Deixe uma resposta

Terminal de Informação