LGPD em customizacoes Protheus

Como adequar codigo Protheus a LGPD: mascaramento, retencao, direito ao esquecimento, log de acesso, anonimizacao em ambientes de homolog.

LGPD (Lei Geral de Protecao de Dados) entrou em vigor em 2020 com forca. Customizacoes Protheus que tratam dados pessoais (CPF, email, telefone, dados sensiveis) precisam adequacao. Esse e o guia operacional.

Dados pessoais em base Protheus tipica

TabelaCampos sensiveis
SA1 (Clientes PF)A1_NOME, A1_CGC (CPF), A1_END, A1_EMAIL, A1_TEL, A1_DTNASC
SA2 (Fornecedor PF)A2_NOME, A2_CGC, A2_EMAIL
SRA (Funcionarios)RA_NOME, RA_CIC (CPF), RA_RG, RA_NASC, RA_EMAIL — todos!
BA1 (Beneficiario PLS)BA1_NOME, BA1_CPF, BA1_DTNASC, dados saude

Os 6 pilares LGPD

  1. Finalidade: dados coletados pra fim especifico
  2. Necessidade: so o estritamente necessario
  3. Transparencia: titular sabe o que coleta
  4. Direito do titular: acesso, correcao, exclusao, portabilidade
  5. Seguranca: tecnica + organizacional
  6. Prestacao de contas: registro de tratamento

Implementacoes praticas

1. Mascaramento de CPF/CNPJ em tela

Static Function MascaraCPF(cCpf)
    // Mostra "123.***.***-01" em vez de "123.456.789-01"
    cCpf := AllTrim(cCpf)
    If Len(cCpf) >= 11
        Return Left(cCpf, 3) + ".***.***-" + Right(cCpf, 2)
    EndIf
Return cCpf

// Uso em browse:
oReport:Section(1):Cell("A1_CGC"):SetBlock({|| MascaraCPF(SA1->A1_CGC)})

2. Log de acesso a dado sensivel

// PE M030LOK — registrar quem leu o cadastro
User Function M030LOK()
    U_LogAcessoLGPD("SA1", SA1->A1_COD, "LEITURA")
Return .T.

Static Function LogAcessoLGPD(cTabela, cChave, cAcao)
    RecLock("ZLGPD", .T.)
    ZLGPD->ZLG_DATA   := dDataBase
    ZLGPD->ZLG_HORA   := Time()
    ZLGPD->ZLG_USER   := RetCodUsr()
    ZLGPD->ZLG_TABELA := cTabela
    ZLGPD->ZLG_CHAVE  := cChave
    ZLGPD->ZLG_ACAO   := cAcao
    ZLGPD->ZLG_IP     := GetClientIP()
    ZLGPD->(MsUnlock())
Return

3. Direito ao esquecimento (anonimizacao)

// Usuario ativa exclusao apos verificar inexistencia de obrigacao fiscal
User Function AnonimizaCli(cCod, cLoja)
    Local cMotivo := ""

    // 1. Validar se ha pendencias fiscais (5 anos da ultima NF)
    SE1->(DBSetOrder(2))
    SE1->(DBSeek(xFilial("SE1") + cCod + cLoja))
    If !SE1->(Eof())
        Return "Cliente tem titulos vigentes - aguardar retencao fiscal"
    EndIf

    // 2. Anonimizar campos
    SA1->(DBSetOrder(1))
    If SA1->(DBSeek(xFilial("SA1") + cCod + cLoja))
        RecLock("SA1", .F.)
        SA1->A1_NOME   := "ANONIMIZADO " + cCod
        SA1->A1_NREDUZ := "ANON"
        SA1->A1_CGC    := Replicate("0", 14)
        SA1->A1_END    := ""
        SA1->A1_EMAIL  := ""
        SA1->A1_TEL    := ""
        SA1->A1_DTNASC := CtoD("")
        SA1->A1_LGPD   := "S"  // flag anonimizado
        SA1->(MsUnlock())

        U_LogAcessoLGPD("SA1", cCod + cLoja, "ANONIMIZADO")
        Return "OK"
    EndIf
Return "Cliente nao encontrado"

4. Sanitizar dados em homolog

-- Apos copiar producao pra homolog
UPDATE sa1010 SET
    a1_nome   = 'CLIENTE ' || a1_cod,
    a1_cgc    = '00000000000000',
    a1_email  = 'sem-email@homolog.local',
    a1_tel    = '0000000000',
    a1_dtnasc = '19700101';

UPDATE sra010 SET
    ra_nome   = 'FUNCIONARIO ' || ra_mat,
    ra_cic    = '00000000000',
    ra_rg     = '0000000',
    ra_email  = 'rh@homolog.local';

Politica de retencao

Tipo de dadoRetencao minimaLei aplicavel
Fiscal (NF, titulos)5 anos apos baixaCodigo Tributario
Trabalhista30 anos apos saidaCLT
Cadastro cliente PFAte fim da relacao + obrigacoes legaisLGPD
Log de acesso LGPD5 anosLGPD
Marketing/CRMAte revogar consentimentoLGPD Art. 8

Checklist de conformidade

Pegadinhas

Veja também