Skip to content

[18.0] l10n_br_fiscal_certificate: refactor l10n_br_fiscal_certificate to reuse new certificate core module - #5107

Open
rvalyi wants to merge 3 commits into
OCA:18.0from
akretion:18.0-certificate-refactor
Open

rvalyi wants to merge 3 commits into
OCA:18.0from
akretion:18.0-certificate-refactor

Conversation

@rvalyi

@rvalyi rvalyi commented Sep 3, 2026

Copy link
Copy Markdown
Member

Resumo

Este PR refatora o módulo l10n_br_fiscal_certificate para estender o módulo core certificate (certificate.certificate) do Odoo, em vez de manter um modelo próprio (l10n_br_fiscal.certificate). Toda a lógica genérica de certificado — parsing de PFX/PKCS12, extração de datas, número de série, validade, chave privada e cadeia de certificados — passa a ser responsabilidade do core. O módulo brasileiro mantém apenas o que é genuinamente específico do Brasil.

Motivação

O módulo duplicava lógica que já existe (e continua evoluindo) no core certificate:

  • parsing do PFX/PKCS12 e extração de metadados (emissor, titular, CNPJ/CPF, datas);
  • cálculo de validade (is_valid);
  • extração da chave privada;
  • extração da cadeia de certificados (CAs);
  • validação de senha/arquivo.

O core faz tudo isso de forma mais robusta e completa: suporta DER, PEM e PKCS12; is_valid é pesquisável; a chave privada fica separada em certificate.key; os certificados da cadeia são criados automaticamente; e há escopo por empresa.

O que muda

  • O modelo l10n_br_fiscal.certificate deixa de existir e vira _inherit de
    certificate.certificate, adicionando apenas:
    • scope (seleção estendida com o valor l10n_br);
    • type (nf-e / e-cpf / e-cnpj);
    • subtype (a1 / a3);
    • owner_cnpj_cpf (computado a partir de subject_common_name);
    • issuer_name (computado a partir de pem_certificate).
  • res.company mantém certificate_nfe_id / certificate_ecnpj_id (agora apontando para certificate.certificate) e o método _get_br_ecertificate(), que continua devolvendo o objeto Certificado do erpbrasil.assinatura. Ou seja, a assinatura XML-DSig dos documentos fiscais (NF-e, CT-e, MDF-e, NFS-e) não muda.
  • Os campos file / password foram mapeados para content / pkcs12_password.

Menos código para manter

Apesar de o script de migração adicionar linhas, a lógica de negócio que passamos a manter é bem menor:

  • models/certificate.py: de 146 linhas → 66 linhas (−80 linhas de parsing,
    validação, cálculo de datas/nome/validade, constraints, onchange e overrides de
    create/write, tudo agora delegado ao core);
  • os scripts de migração (migrations/18.0.2.0.0/pre-migration.py + post-migration.py,
    ~138 linhas) são código executado uma única vez durante a migração da base — não é lógica de negócio a ser mantida no dia a dia.

Ou seja, trocamos ~80 linhas de lógica recorrente (e vários conceitos: modelo próprio, parsing, validade, nome, chave privada, cadeia) por código de migração que roda uma única vez. O módulo fica restrito ao que é brasileiro: tipo/subtipo do certificado, CNPJ/CPF do titular e a integração com o erpbrasil.assinatura.

À prova de futuro (Odoo 20)

  • O core certificate é mantido ativamente pela Odoo S.A. e, no Odoo 20, já traz a
    nova API BinaryBytes, _verify, suporte a Ed25519, chave criptografada e
    scope='ca'. Como a extensão brasileira não toca mais em codificação binária (content/pem_certificate), a migração para o Odoo 20 fica absorvida pelo core — o port do módulo BR tende a zero.
  • owner_cnpj_cpf e issuer_name são campos computados (derivados de
    subject_common_name/pem_certificate), portanto não há dado armazenado que precise de nova migração.
  • _get_br_ecertificate() mantém o contrato com os módulos fiscais, que continuam assinando via erpbrasil.assinatura (XML-DSig rsa-sha1, que o core certificate não
    substitui).

Migração de dados

Como o modelo mudou de nome e passou a ser escopado por empresa, foi incluído um script de migração no padrão OpenUpgrade (migrations/18.0.2.0.0/):

  • pre-migration.py copia os certificados legados para uma tabela temporária (o campo binário file vive em ir.attachment);
  • post-migration.py recria cada certificado como certificate.certificate (mapeando file→content, password→pkcs12_password, type, subtype e derivando company_id dos vínculos em res.company), re-aponta as FKs certificate_nfe_id / certificate_ecnpj_id e remove a tabela legada.

Observação: o core certificate.certificate exige company_id, então os certificados passam a ser escopados por empresa (antes eram globais).

Assisted by GLM 5.3

antes:

2026-09-03_10-59

depois:

2026-09-03_12-38 2026-09-03_12-38_1

@rvalyi
rvalyi marked this pull request as draft September 3, 2026 13:35
@OCA-git-bot OCA-git-bot added series:18.0 mod:l10n_br_nfe Module l10n_br_nfe mod:l10n_br_fiscal_certificate Module l10n_br_fiscal_certificate mod:l10n_br_ie_search Module l10n_br_ie_search labels Sep 3, 2026
@OCA-git-bot

Copy link
Copy Markdown
Contributor

Hi @renatonlima,
some modules you are maintaining are being modified, check this out!

@rvalyi rvalyi changed the title [18.0] l10n_br_fiscal_certificate: Refatorar o l10n_br_fiscal_certificate para reutilizar o módulo core certificate [18.0] l10n_br_fiscal_certificate: refactor l10n_br_fiscal_certificate to reuse new certificate core module Sep 3, 2026
The fiscal certificate was refactored to extend the Odoo core certificate.certificate model, which stores the uploaded pfx in 'content' and its password in 'pkcs12_password'. Adapt the NFe signing path and the tests that create fake certificates to the new fields and model.
The fiscal certificate was refactored to extend the Odoo core certificate.certificate model. Adapt the SEFAZ test to create the fake certificate with the core model and its 'content'/'pkcs12_password' fields.
@CristianoMafraJunior

Copy link
Copy Markdown
Member

Muito bom parabéns, uma duvida besta por que não olhei o código, dessa forma a senha do certificado fica criptografado no bando de dados?

@rvalyi
rvalyi force-pushed the 18.0-certificate-refactor branch from bce855f to fa9b52f Compare September 3, 2026 14:28
@rvalyi

rvalyi commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Muito bom parabéns, uma duvida besta por que não olhei o código, dessa forma a senha do certificado fica criptografado no bando de dados?

A senha do certificado continua sem criptografia, assim como ta no core e ate na branch master. Mas eu acabei de criar (com meu amigue GLM) um pequeno glue module que resolve isso usando o modulo data_encryption da OCA. Seria bom se vc puder dar um feedback OCA/server-env#294

@rvalyi
rvalyi marked this pull request as ready for review September 3, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:l10n_br_fiscal_certificate Module l10n_br_fiscal_certificate mod:l10n_br_ie_search Module l10n_br_ie_search mod:l10n_br_nfe Module l10n_br_nfe series:18.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants