SGEProduto · Domínio · Desenvolvimento
Repositório

migration-reference · implemented

Migration 01 — addresses

Base backend de endereços próprios de cada cadastro e cópia histórica na própria tabela.

Contrato implementado

ColunaTipo PostgreSQLNuloChaves/índicesRegra
idbigintnãoPKIdentificador interno.
city_idbigintnãoFK, índiceReferencia cities.id; exclusão RESTRICT. A UF é obtida da cidade.
streetvarchar(255)não—Rua ou logradouro obrigatório.
numbervarchar(255)não—Número textual obrigatório; aceita 123 A, 0 e s/n.
neighborhoodvarchar(255)não—Bairro obrigatório.
zip_codevarchar(255)sim—Valor opcional; sem validação de formato ou limpeza de dígitos nesta etapa.
created_attimestamp(0)sim—Timestamp nativo do Laravel; preenchido pelo Eloquent no timezone institucional.
updated_attimestamp(0)sim—Timestamp nativo do Laravel; atualizado pelo Eloquent.

A migration usa $table->timestamps(), com a nulabilidade padrão do Laravel. O Eloquent converte esses campos automaticamente em datas, sem casts explícitos no model. Inserções diretas que não passem pelo Eloquent podem deixar os timestamps nulos. O down() remove a tabela.

A cidade é obrigatória e selecionada no catálogo local, criado antes desta tabela. Não há complement, UF duplicada, tabela de snapshots, copied_from_address_id ou campos de autoria. A tabela não usa SoftDeletes nem Scout/Searchable.

Propriedade dos endereços

addresses centraliza as colunas de endereço, mas suas linhas não são compartilhadas. Cada linha pode pertencer a no máximo um registro proprietário, seja em user_personal_data, campuses, granting_parties ou nos futuros endereços históricos de internships. Isso vale também para dois registros da mesma tabela: conteúdo idêntico recebe IDs diferentes. Um novo proprietário recebe uma nova linha, nunca o address_id já vinculado a outro registro. A cópia histórica cria outra linha na mesma tabela.

O schema atual contém FKs nos cadastros proprietários, mas ainda não impõe essa exclusividade entre todas as tabelas. Os futuros fluxos de integração devem respeitar a regra ao criar e trocar endereços; uma garantia no banco exige desenho próprio antes de ser declarada implementada.

Na gestão de campi, a edição atualiza a mesma linha de endereço e preserva seu ID. Antes da mudança, o controller verifica referências em campi, dados pessoais, concedentes e estágios; se encontrar outro proprietário ou uso histórico, rejeita a operação. A verificação é de aplicação, pois o schema não impõe exclusividade entre as FKs.

Model, validação e auditoria

Address declara os campos cadastrais com #[Fillable], usa HasFactory e possui casts de city_id para inteiro e dos campos textuais para string. Address::city() é BelongsTo; City::addresses() é HasMany. As relações com modelos ainda inexistentes não foram adicionadas.

AddressValidationRules centraliza as regras aplicadas no evento saving do model: cidade existente, logradouro, número e bairro obrigatórios, todos com os limites do schema. O número é textual, sem restringir os valores ao formato numérico. A rota de campus valida o endereço aninhado em um Form Request e cria ou atualiza Address via Eloquent. Ainda não há endpoint genérico para gerenciar endereços.

O CEP omitido, nulo ou vazio é persistido como null. Valores informados não passam por validação de CEP, normalização por helper ou remoção de máscara; varchar(255) preserva o valor sem preenchimento de espaços. A validação de oito dígitos e o tratamento de máscaras serão definidos em uma etapa futura.

O Activity Log registra os campos cadastrais, somente quando há mudanças, sem registros vazios. A autoria vem do próprio mecanismo de auditoria. AddressFactory usa CityFactory para criar fixtures independentes de rede e da carga completa do catálogo.

Cópia histórica implementada

CopyAddress::handle(Address $address): Address exige uma origem persistida, relê a linha dentro de uma transação com bloqueio compartilhado e cria outra linha em addresses. A cópia recebe novo ID e timestamps, não altera a origem e ignora mudanças ainda não salvas no objeto recebido. Cópias sucessivas são independentes.

Uma origem não persistida gera InvalidArgumentException; se a linha já foi removida, a releitura gera ModelNotFoundException. A criação da cópia também passa pelas regras do model e pelo Activity Log.

O fluxo de campus impede editar seu endereço quando uma referência de outro proprietário ou estágio aponta para a mesma linha. Não há bloqueio genérico de edição/exclusão de endereços históricos para os demais cadastros; essa proteção será implementada junto às futuras FKs e operações de formalização. A cópia existe, mas os outros fluxos ainda precisam integrar seu uso.

Na formalização futura, internships.workplace_address_id deverá apontar para uma cópia do endereço da concedente nesta mesma tabela. internships.student_address_id poderá apontar para a cópia do endereço do discente quando necessário. Essas linhas deverão ser preservadas sem alterações retroativas; a mudança do cadastro atual poderá criar outra linha e trocar sua FK.

Consulta de CEP futura

A consulta à BrasilAPI está fora da base atual. Quando implementada, sua resposta servirá apenas como sugestão de preenchimento e não impedirá a edição manual em caso de CEP geral, ausência ou indisponibilidade.

A cidade deverá continuar sendo resolvida exclusivamente no catálogo local: primeiro pelo código IBGE quando disponível; caso contrário, pelo nome normalizado e pela UF. Ausência ou ambiguidade exigirá seleção manual. A integração não poderá criar cidades a partir da resposta externa.

Testes

tests/Feature/AddressesTest.php cobre tipos e limites PostgreSQL, nulabilidade, índices, FK RESTRICT, migrate e rollback, factories, casts, relacionamentos, campos obrigatórios, número textual, CEP opcional sem validação de formato, cópia histórica e Activity Log. tests/Feature/CampusManagementTest.php verifica edição no mesmo endereço, bloqueio quando ele também estiver ligado a outro cadastro ou estágio e rollback dos registros e atividades. Como user_personal_data referencia addresses, o teste de rollback reverte em conjunto as migrations aplicadas a partir de addresses, testa a remoção da tabela e reaplica o conjunto. Os testes usam Http::fake() e preventStrayRequests() para impedir acesso à rede.

BASH
./vendor/bin/sail artisan test --compact tests/Feature/AddressesTest.php tests/Feature/CitiesTest.php tests/Unit/DatabaseDriverGuardTest.php
./vendor/bin/sail exec laravel.test vendor/bin/pint --dirty --format agent

Os testes cobrem o schema PostgreSQL, endereços, cidades e a guarda global de migrations; o mapa atual está em Testes existentes.

Checklist

  • Definir cidade por FK para catálogo IBGE e CEP opcional.
  • Confirmar campos obrigatórios e usar o limite padrão de 255 caracteres para os campos textuais.
  • Criar migration reversível create_addresses_table com índice em city_id e FK RESTRICT.
  • Criar Address, AddressFactory, CityFactory e relacionamentos existentes.
  • Validar cidade, logradouro, bairro e número textual, incluindo s/n.
  • Usar timestamps nativos, sem casts explícitos de data.
  • Registrar alterações cadastrais no Activity Log, sem campos de autoria.
  • Implementar e testar a cópia histórica na própria tabela.
  • Testar schema, migrate, rollback e persistência em PostgreSQL.
  • Atualizar Domínio e modelo de dados.
  • Definir validação e normalização de CEP no futuro fluxo de cadastro.
  • Implementar a consulta opcional de CEP e resolução da cidade no catálogo local.
  • Criar telas e endpoints de cadastro nas etapas correspondentes.
  • Integrar cópias e impedir alteração/exclusão de linhas históricas ao implementar a formalização.

Próximas dependências