nfe / whmcs-addon

Módulo Nota Fiscal para WHMCS via NFE.io. Automatiza a emissão de notas fiscais.
10 stars 8 forks source link

[BUG] Correção nos Campos 'created_at' e 'updated_at' #156

Closed andrekutianski closed 2 months ago

andrekutianski commented 4 months ago

Descreva o erro

Foi identificado um comportamento no banco de dados do módulo que pode ser aprimorado. O problema está relacionado aos campos created_at e updated_at na tabela mod_nfeio_si_serviceinvoices.

Atualmente, o campo created_at está sendo atualizado para o timestamp atual (current_timestamp()) toda vez que uma atualização ocorre em um registro. Isso resulta em um alteração indevida do campo created_at sempre que um registro é modificado.

`created_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),

Para corrigir tal comportamento, sugere-se uma alteração na definição do campo created_at para eliminar a atualização automática a cada modificação do registro.

Aqui está o comando SQL que se propõe para essa alteração:

ALTER TABLE mod_nfeio_si_serviceinvoices 
CHANGE created_at created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

Com essa correção, o campo created_at se manterá constante após a criação de um registro, independentemente de quaisquer alterações subsequentes.

Além disso, sugere-se uma melhoria para a coluna updated_at. Recomenda-se que essa coluna seja alterada para receber um timestamp atual a cada atualização que ocorrer em um registro. Isso proporciona uma maneira precisa de acompanhar quando a última alteração em um registro foi feita.

Para fazer esta alteração, pode-se usar a seguinte declaração:

ALTER TABLE mod_nfeio_si_serviceinvoices 
CHANGE updated_at updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

Uma vez estas alterações sendo implementadas, aumentarão a precisão das informações de timestamp e simplificarão a rastreabilidade dos registros.

Como reproduzir

Qualquer atualização de registro realizada pelo módulo reproduz este comportamento.

Comportamento esperado

Informação da coluna created_at não deve ser alterada quando atualizado registro no banco.

Ambiente e versões:

andrekutianski commented 4 months ago

Realizando uma análise mais detalhada, verifiquei que nas versões mais recentes do MySQL, se você definir o primeiro campo TIMESTAMP na tabela sem outro valor default, ele será automaticamente alterado para CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. Isso acontece devido à diretiva explicit_defaults_for_timestamp do MySQL ser desativada por padrão.

No módulo, na criação da tabela, os campos created_at e updated_at estão especificados como TIMESTAMP (o que está correto) como mostrado abaixo:

https://github.com/nfe/whmcs-addon/blob/ad98fc2ebbb1ee9f6fc52db4fe787ce31d49713b/modules/addons/NFEioServiceInvoices/lib/Models/ServiceInvoices/Repository.php#L118-L119

Como created_at é o primeiro campo TIMESTAMP na tabela, o MySQL automaticamente impõe uma regra ON UPDATE CURRENT_TIMESTAMP se a diretiva explicit_defaults_for_timestamp estiver desativada.

Você pode verificar isso executando o seguinte comando SQL no seu banco de dados MySQL:

SHOW VARIABLES LIKE 'explicit_defaults_for_timestamp';

image

A imagem abaixo exemplifica os valores dos campos logo após o registro da NF na fila de emissão:

image

Após o retorno da emissao na API, o valor de created_at é substituido quando realizado atualizacao do status conforme exemplificado na imagem a seguir:

image

NOTA: Esta condicao não ocorre na atualizacao do registro quando o retorno é proveniente do webhook pois o callback está preservando manualmente o valor atual de created_at:

https://github.com/nfe/whmcs-addon/blob/ad98fc2ebbb1ee9f6fc52db4fe787ce31d49713b/modules/addons/NFEioServiceInvoices/callback.php#L94

Causa

A possível causa deste comportamento nas colunas created_at e updated_at pode ser pelo fato de inexistir uma definicao do padrao para o tipo timestamp na aplicacao, levando a imposicao automatica da regra explicit_defaults_for_timestamp de acordo com o definido pelo servico.

Esta condicao ocorre em todos os campos do tipo TIMESTAMP da aplicacao onde não exista uma definicao de valor padrao quando da sua criacao no banco de dados.

Conclusão

Em conclusão, este não é um problema do MySQL/MariaDB, já que se trata de uma parametrizacão de ambiente e poderá variar conforme configuracão do servico e que deve ser tratado pela aplicacao (módulo).

Solucão

Uma possível solucão para este comportamento seria atribuir a todos os campos created_at e updated_at um valor padrão em sua criacão no banco (e também a qualquer outra coluna do tipo TIMESTAMP).

Sugestão 1

Atribuir as colunas como nulas, evitando a imposicão da diretriz pelo banco de dados:


$table->timestamp('created_at')->nullable();
$table->timestamp('updated_at')->nullable();

Sugestão 2

Definir as colunas com condicoes especificas de atribuicao de valores para insercao e atualizacao:


$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrentOnUpdate();

As tabelas existentes deverão receber alteracão dos atributos.

Referências

  1. https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html
  2. https://mariadb.com/kb/en/server-system-variables/#explicit_defaults_for_timestamp
  3. https://stackoverflow.com/a/57832212/15132546
  4. https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/prerequisites/database-server/mysql#configuring-the-database-instance