OCA / l10n-brazil

Localização brasileira oficial do Odoo.
https://odoo-community.org/psc-teams/brazil-66
GNU Affero General Public License v3.0
245 stars 246 forks source link

[14.0][l10n_br_account] erros de calculo de totais de impostos #2346

Closed rvalyi closed 1 year ago

rvalyi commented 1 year ago

Basicamente o merge para corrigir os totais de impostos nas faturas https://github.com/OCA/l10n-brazil/pull/2303 acabou criando e revelando um novo problema como eu comentei aqui:

https://github.com/OCA/l10n-brazil/pull/2303#issuecomment-1426532806

O problema é que dentro do create nativo do account.move.line é chamado o método _get_fields_onchange_subtotal_model as vezes em cima de um recordset vazio (por isso o sufixo _model) e dai dentro da nova implementação de https://github.com/OCA/l10n-brazil/pull/2303 o self.price_total não é definido (cast para zero então) https://github.com/OCA/l10n-brazil/pull/2303#discussion_r1073615797 e isso ferra os calculos. No inicio eu tinha testado de forma superficial no Runboat, mas botando um test explicito no PR para as contabilizações das remessas, o problema acabou se confirmando dentro dos proprios testes do repo https://github.com/OCA/l10n-brazil/pull/2338

Uma saida seria de pegar esse price_total pelo metodo _get_price_total_and_subtotal_model. que tb aceita um record set vazio (sufixo _model). So que atualmente para esse ultimo calcular as taxas correctamente è preciso passar varios parametros fiscais pelo context, assim como é feito no método @api.multi correspondante: https://github.com/OCA/l10n-brazil/blob/8148c41403805c237fbfa9686623ce7514a13125/l10n_br_account/models/account_invoice_line.py#L290 (eu imagino que o @renatonlima fez isso para não alterar a assinatura do metodo ja que não seria chamado com os parametros adicionais a partir do codigo do account.move.line nativo).

Ai a gente poderia então pensar em enfiar esses valores no context no inicio do create para achar elas de volta nesse _get_price_total_and_subtotal_model localizado. Porem não é tão simples porque o create è na verdade um @api.create_multi e ai não rola ter um contexto unico para todas linhas com esses parametros talvez diferentes... E eu realmente acredito que é super importante conserver esse @api.create_multi para as account.move.line... Na verdade, como esse _get_price_total_and_subtotal_model ja esta sendo chamando dentro do create nativo do account.move.line sem esse contexto, ja deve ter varios erros do tipo que devem ter passado batidos até agora...

Uma saida seria de enfiar os valores no contexto dentro de uma lista e usar o tipo de gambiarra que eu fiz aqui para a remessa para indexar cada linha account.move.line e pegar os parametros das taxas certinhos para cada linha: https://github.com/OCA/l10n-brazil/pull/2338/files#diff-70e9bee40acbcca3d5d0fcbb461c93d7634d0e2e1f11392545bd839f74253256R155

Bom são ideias, pois se conseguir dormir normal depois de escrever codigo assim isso ainda é outro desafio...

cc @renatonlima @antoniospneto @felipemotter @marcelsavegnago

felipemotter commented 1 year ago

Fala @rvalyi, sim, nosso medo também era este, porém em todos os testes que fizemos não conseguimos chegar ao problema no create, o que acabamos concluindo que não iria acontecer.

Faz uma semana que estamos tentando seguir por um caminho diferente, após testar alguns casos, principalmente no caso de notas de entrada, vimos que a modificação ainda não estava legal. Por exemplo, no caso em que a empresa do regime de lucro real se credita de pis cofins, icms, etc.., o correto é retirar esses impostos da conta de despesa/ativo, ou seja, não trabalhamos com impostos dedutíveis. Neste caso, os impostos por fora também não vão ser bem lançados conforme o exemplo a seguir:

image image O IPI está sendo duplicado no total dos recebíveis. (favor ignorar a conta utilizada, neste caso deveria ser de estoque e não CMV) Outra observação é que nesse exemplo, estou usando a PR #2337. Estou fazendo o fluxo completo vindo do Purchase, porque se não buga o ind_final e ocorre uma inconsistência nos valores do icms. (Vamos abordar em outra PR)

Como alternativa a #2303 estamos trabalhando nesta branch: https://github.com/Engenere/l10n-brazil/tree/14.0-get-balance-values

Aqui passamos a usar os amounts como base para calcular o balance e não o price_subtotal ou price_total, desta forma podemos manter o comportamento destes igual em ambos os casos (com ou sem impostos dedutíveis). Já conseguimos tratar o create, porém falta o write(não começamos ainda)

Motivos para isto:


1) Hoje o subtotal/total são tratados para serem utiilizados a fim de calcular o balance da linha do produto, ou seja, se houver ou não impostos dedutíveis, eles vão ter comportamentos diferentes. Em contraponto a isso, no Brasil vemos o subtotal incluindo o valor dos produtos impostos por dentro(pis, cofins, icms, etc), enquanto o price_total seria o valor dos produtos mais os impostos por fora(IPI). As notas fiscais são assim e a v12 também mantem esse padrão. Código que faz essa alteração: https://github.com/OCA/l10n-brazil/blob/ee356cd03f6ed415db3f5578f2fd63665a39ee92/l10n_br_account/models/account_invoice_line.py#L337-L347

Exemplos da forma que está hoje, considerando um produto para revenda com valor de R$1.000, com 12% de ICMS, 1,65% PIS, 7,6% COFINS e 10% de IPI.

Sem configurar impostos dedutíveis: price_subtotal = valor - icms - pis - cofins = R$787,50 price_total = valor + ipi - icms - pis - cofins = R$887,50 (_Este exemplo mostra porque a forma que propomos utilizar o pricetotal para calculo do balance da linha do produto acaba prejudicando os casos sem impostos dedutíveis)

Usando impostos dedutíveis: price_subtotal = valor = R$1000 price_total = valor + ipi = R$1100

Sendo o balance da linha: R$787,50 sem impostos dedutíveis R$1100 com impostos dedutíveis

Por fim, achamos que o correto era o price_subtotal e o price_total terem comportamentos iguais em ambos casos para manter um padrão que vemos estabelecido no Brasil e que já existia na v12.0.


2) Além da diferenciação acima, existe uma inconsistência envolvendo isso. Sem utilizar impostos dedutíveis, ao calcular o preço a primeira vez ele vai deduzir os impostos do subtotal, porém ao criar a fatura(salvar a primeira vez) o subtotal será corrigido para o valor dos produtos incluindo impostos por dentro. Mas não para por ai, se editar essa mesma fatura e mexer no preço, ele vai deduzir o impostos e dessa vez não vai haver alteração ao salvar, gerando faturas em que o subtotal não tem um padrão, uma hora inclui impostos por dentro, outra hora não. Provavelmente este problema está vindo da PR #2303 justamente no create rsrsrsrs (desculpe) Exemplo do problema: Peek 2023-02-14 21-16

renatonlima commented 1 year ago

Olá pessoal, eu me lembro que eu havia trabalhado nos totais dos impostos e na contabilização, o principal problema que eu vejo é que diferente da 12.0 onde existia o account.invoice.line que poderia ter um subtotal e o account.move.line poderia ter outro subtotal, na 14.0 o valor do subtotal é igual tanto no documento fical quanto na contabilização, então na localização deveriamos ou criar um novo campo para ter o valor para a operação fiscal (se não me engano já existe um campo assim no mixin fiscal da linha) ou alterar o calculo do débito/crédito para corrigir o valor contábil.

Uma coisa importante no caso das vendas ou compras os valores são contabilizados brutos e feito um lançamento em uma conta redutora da receita/compras:

Screenshot from 2023-02-16 12-14-49

No caso das remessas são lançados apenas os valores dos impostos

antoniospneto commented 1 year ago

@renatonlima

uma ressalva quanto a essa parte do seu comentário:

Uma coisa importante no caso das vendas ou compras os valores são contabilizados brutos e feito um lançamento em uma conta redutora da receita/compras:

Posso estar errado, mas no meu entender há casos sim que não se deve contabilizar o valor bruto para serem deduzidos os impostos em seguida. É muito comum no caso de uma operação de compras de matéria prima.

Aqui um exemplo:

D - Estoque (ativo) 6.547,50 D - IPI a recuperar (ativo) 1.000,00 D - ICMS a recuperar (ativo) 1.620,00 D - PIS a recuperar (ativo) 148,50 D - COFINS a recuperar (ativo) 684,00 C - Fornecedores (passivo) 10.000

Veja que apesar do valor bruto ser 10.000 o valor que contabilizamos no estoque já é sem os impostos: R$6.547,50. não precisamos incluir os lançamentos das deduções dos impostos neste caso. Por se uma compra de matéria-prima não há contabilização de despesa.

antoniospneto commented 1 year ago

@renatonlima

Olá pessoal, eu me lembro que eu havia trabalhado nos totais dos impostos e na contabilização, o principal problema que eu vejo é que diferente da 12.0 onde existia o account.invoice.line que poderia ter um subtotal e o account.move.line poderia ter outro subtotal, na 14.0 o valor do subtotal é igual tanto no documento fical quanto na contabilização, então na localização deveriamos ou criar um novo campo para ter o valor para a operação fiscal (se não me engano já existe um campo assim no mixin fiscal da linha) ou alterar o calculo do débito/crédito para corrigir o valor contábil.

Quanto a isso é o que estamos abordando na PR #2347

A gente criou um novo método que vai calcular o debito ou crédito levando em conta a lógica do Brasil: https://github.com/OCA/l10n-brazil/blob/1273c095d289d606de62d3e9de0bae7faca0a931/l10n_br_account/models/account_invoice_line.py#L525-L564

No Odoo nativo esses campos são calculados no método _get_fields_onchange_subtotal_model mas como não podemos mudar a assinatura dele para receber os novos parâmetros a gente simplesmente zera o retorno do método e chamamos o nosso novo método em tudo que é canto onde o método nativo é chamado tbm, mas chamamos no final rss, onchanges, create e write.

rvalyi commented 1 year ago

@antoniospneto é feio mas é possível receber outro parametros: botar eles no contexto e ou numa variável "thread local", como por exemplo atributos de type(self), como eu fiz na remessa. Tipo bota os parâmetros no contexto, possivelmente numa lista para cada account.move.line e depois usa o type(self) para contar para qual linha o método está sendo chamado e ler os parâmetros do contexto. Feio, mas possível...

renatonlima commented 1 year ago

@antoniospneto,

Eu não me recordo no caso de compras, a sequencia dos lançamentos mas existe lançamento das deduções dos impostos sobre compras para apurar o custo de matéria prima, em um exemplo do plano de contas de um cliente:

Screenshot from 2023-02-16 15-27-54

Pois o lançamento contábil do estoque seria feito pela movimentação de estoque, que no caso do brasil ainda precisa ser feito algumas implementações.

Sobre o método _get_fields_onchange_subtotal_model eu acho mais inteligente editar esse método e o _get_fields_onchange_subtotal passar os parametros da localização pelo contexto e não precisar alterar outros métodos como o create e write, onchanges e computes do que criar um novo método e ter que injetalo nos outros métodos (create e write, onchanges e computes)

antoniospneto commented 1 year ago

@renatonlima

No Brasil não se pode contabilizar a compra da matéria-prima como uma Despesa ou Custo, ela deve ser lançada na conta de estoque de matéria-prima (ATIVO). Não consegui compreender bem o plano de contas do seu cliente, eu não vejo como certo a conta "matéria prima" estar no grupo de despesas e nem mesmo no grupo de custos, ela deveria estar no Ativo.

O custo você só vai lançar posterior a venda, não nesse momento da compra.

No caso das empresas do regime normal que se creditam de alguns impostos, você não pode contabilizar esses impostos no valor do estoque (matéria-prima) então não há o que se deduzir.

@rvalyi @renatonlima

Quanto ao utilizar o contexto me parece uma alternativa interessante, apesar da gente ter seguido uma caminho diferente, ainda estamos trabalhando na PR #2347 vamos estudar a possibilidade de fazer dessa forma.

felipemotter commented 1 year ago

No anglossaxon da mesma forma teria uma conta provisória de estoques(no ativo).... que mais tarde seria confirmado no picking.

Mas mesmo com toda essa questão da forma de contabilizar os estoques(com dedutíveis ou não), cada empresa pode ter seu próprio jeito. A questão é que concordamos que nem sempre o valor do subtotal/total fiscal será igual ao credit/debit, então a alternativa seria uma das que o @renatonlima citou e nós seguimos essa lógica na PR #2303 .

Acho válido tentar pelo contexto, logo vamos fazer alguns testes.

rvalyi commented 1 year ago

sim é importante passar a usar o modo anglo-saxon e impacta mesma nas contas da compra. Agora que a gente se livrou do figura que queria ser PSC do projeto sem nem entender nada com nada tá na hora de trocar isso nos planos de demo...

rvalyi commented 1 year ago

proposta de fix aqui https://github.com/OCA/l10n-brazil/pull/2363

felipemotter commented 1 year ago

Como prometido, grande @rvalyi , segue minha análise da proposta #2363 onde eu faço um contraponto referenciando também a minha PR #2347 que tenta resolver o problema dos totais, só que não contemplando as remessas.

É um assunto que desde a migração eu venho estudando e me aprofundando, já que a fusão do account.invoice e do account.move mudou muito as lógicas e deixou ainda mais claro a realidade alternativa que vivemos no Brasil com a forma que gerimos e contabilizamos nossos impostos.

Gostaria de ressaltar minha opinião (e do @antoniospneto) que já deixei no https://github.com/OCA/l10n-brazil/pull/2347#issuecomment-1435730312 , em que não vai existir solução bonita para a 14.0 por causa dos métodos gigantescos da Odoo SA nessa versão e da própria complexidade brasileira. Um caminho muito mais fácil nos espera na 16.0, mas para a versão em questão estamos fu##.

REFERENTE A PR #2363

dedutiveis_price_unit_errado

Não fui mais afundo, mas ele não reconhece uma fiscal_operation_line_id nesse momento, o que faz a mudança do unit_price: dedutiveis_debug_no_op_line

sem_dedutiveis_contabilidade O IPI está sendo calculado 2 vezes na conta fornecedores, o price_unit é alterado, o subtotal fica distorcido e novamente o ipi é dobrado no total.

PR #2347:

nossa-dedutiveis-contabilidade

nossa-sem-dedutiveis-contabilidade

nossa-dedutiveis-frete-contabilidade

Uma observação é que para lançamentos sem dedutíveis, foi necessário um novo campo que adicione as outras despesas ao untaxed para usá-lo no cálculo do balanço. Com o uso dessa variável os lançamentos também permanecem corretos com ou sem outras despesas.

Essa PR não lida com remessa sem financeiro.

Estas mudanças estão rodando a 2 semanas em um cliente junto com a PR #2341.

OUTROS PROBLEMAS NO ACCOUNT QUE NÃO ESTÃO SENDO COBERTOS POR NENHUMA DAS PRs:

  1. O campo amount_untaxed do move(campo nativo do odoo) tem comportamento diferente da linha(adicionado pela localização). No nativo seria o balance de todas as linhas da fatura - balance de todos os impostos (na teoria, sem absolutamente todos os impostos, por dentro ou por fora). Enquanto na localização, o amount_untaxed da linha seria o valor dos produtos sem impostos por fora e sem desconto, em resumo price_unit*qt - discount.

Exemplo:

  1. As outras despesas não estão sendo somadas na base dos impostos, com exceção do icms que está sendo calculado certo.

  2. Os totais na visão da fatura, em ambas as PRs, deixam a desejar. Nossa ideia é depois deixar igual a visão do sale e purchase

Considerações finais:

Não estou falando que a pr #2347 está 100% correta e nem que seja melhor que trabalhar com os contextos. Para ser realista, eu não cheguei a entender como a lógica do contexto funciona. Minha preocupação é atender todas as situações necessárias e se for possível adaptar a #2363 aos casos que ainda não engloba, seria totalmente a favor.

mbcosta commented 1 year ago

Pessoal procurei resolver o problema no PR https://github.com/OCA/l10n-brazil/pull/2412 acredito que foi possível resolver tanto o calculo dos Valores Totais na Fatura, a divergência que existe entre esses valores com o Pedido de Venda ou Compra que gerou a Fatura( adicionei testes para validar os totais ) e os valores dos Lançamentos Contábeis quando tem ou não Dedutíveis, nesse caso o que fiz foi alterar o valor do price_total no método _get_fields_onchange_subtotal_model , acredito que está de acordo com o que o @renatonlima comentou:

"Sobre o método _get_fields_onchange_subtotal_model eu acho mais inteligente editar esse método e o _get_fields_onchange_subtotal passar os parametros da localização pelo contexto e não precisar alterar outros métodos como o create e write, onchanges e computes do que criar um novo método e ter que injetalo nos outros métodos (create e write, onchanges e computes)"

rvalyi commented 1 year ago

valeu pelo trabalho pesado @mbcosta eu vou olhar um pouco a parte técnica, mas eu acho que vamos precisar do @renatonlima para verificar melhor a parte funcional mesmo.

rvalyi commented 1 year ago

o problema foi solucionado aqui https://github.com/OCA/l10n-brazil/pull/2347