migration-reference · implemented
Migration 01A — cities
Catálogo local das cidades brasileiras identificadas pelo código IBGE.
Contrato
| Coluna | Tipo PostgreSQL | Nulo | Chaves/índices | Regra |
|---|---|---|---|---|
id | bigint | não | PK | Identificador interno usado pelas FKs. |
ibge_code | char(7) | não | UQ | Código oficial do município. |
name | varchar(120) | não | índice (state, name) | Nome oficial usado nos selects e relatórios. |
state | char(2) | não | índice | Sigla da UF validada por BrazilianState. |
created_at | timestamp(0) | não | — | Inclusão no catálogo. |
updated_at | timestamp(0) | não | — | Última sincronização. |
O catálogo nacional tem 5.571 municípios e é importado localmente. O catálogo conferido está salvo em database/data/cities.json e versionado junto com o projeto. A migration create_cities_table, o model City e o CitySeeder estão implementados: o seeder lê esse arquivo e insere/atualiza as cidades de forma idempotente pelo ibge_code, sem apagar registros existentes. CityValidationRules centraliza código IBGE, nome e UF e é aplicado ao salvar o model, ao validar o catálogo no seeder e ao aceitar respostas do comando de coleta.
Não há chamada à BrasilAPI para consultas de cidades nem para o cálculo de feriados. A API/IBGE pode ser usada para obter ou revisar o arquivo versionado antes de uma nova implantação. A busca opcional por CEP, documentada em addresses, fica para uma etapa futura; quando existir, a cidade continuará sendo resolvida no catálogo local, sem criação de municípios pela resposta externa.
City usa Scout/Meilisearch para a busca textual no select de cidade da gestão de campi. O índice contém ID, nome, UF e código IBGE, com state filtrável; o filtro de UF é aplicado no mecanismo de busca. Não há consulta inicial para carregar opções. A busca começa com 2 caracteres, após debounce de 500 ms, e retorna até 20 cidades. O nome da cidade já selecionada é preservado na edição. O catálogo no banco continua sendo a fonte da seleção e das FKs; a cidade nunca é um enum nem texto livre. A indexação Eloquent usa fila após commit. Após importar o catálogo existente, execute scout:import 'App\Models\City' e processe a fila, além de sincronizar as configurações dos índices.
O código IBGE é a identidade da cidade. O CitySeeder pode atualizar o nome oficial associado ao mesmo código em uma carga controlada; documentos gerados preservam os valores formatados no snapshot da geração, e endereços históricos continuam apontando para a mesma identidade municipal. Não há enum de cidades nem exclusão lógica como operação normal.
Geração do catálogo e carga local
O comando Artisan cities:fetch consulta a lista de UFs, busca os municípios de cada uma, valida os códigos IBGE e gera o arquivo local. A configuração da URL fica em services.brasil_api.base_url; não há URL duplicada dentro do comando.
php artisan cities:fetch
php artisan cities:fetch --forceO comando não substitui um catálogo existente sem --force. A opção --output permite gerar um arquivo temporário ou alternativo para revisão. A gravação do catálogo é atômica: falhas durante a coleta não deixam um JSON parcial no caminho final.
O arquivo database/data/cities.json contém somente dados de referência, em formato estável e revisável:
[
{
"ibge_code": "4300109",
"name": "Agudo",
"state": "RS"
}
]O CitySeeder implementado:
- lê o arquivo local sem fazer requisições de rede;
- valida o código IBGE com sete dígitos, a UF contra
BrazilianState, o nome não vazio e o limite da coluna usandoCityValidationRules; - insere ou atualiza pelo
ibge_code, em lotes de 500 registros e dentro de uma transação; - rejeita códigos IBGE duplicados no catálogo;
- nunca apaga cidades automaticamente, porque endereços e feriados podem referenciá-las;
- é chamado explicitamente pelo seeder principal.
Para carregar ou recarregar o catálogo, use:
php artisan db:seed --class=Database\\Seeders\\CitySeederA obtenção do arquivo ocorre fora do fluxo de seed, durante o desenvolvimento ou em uma sincronização administrativa explícita. Depois de revisado e commitado, qualquer ambiente consegue popular o banco de forma determinística e reproduzível.
Integridade
PRIMARY KEY (id);UNIQUE (ibge_code);INDEX (state)eINDEX (state, name)para filtros por UF e consultas locais por nome;- a validação de
stateusa os 27 valores deBrazilianState; - a UF do endereço é obtida por
city_id, sem campo estadual duplicado; feriados municipais devem pertencer à UF da cidade selecionada.
O model City declara holidays() para os feriados municipais e addresses() para os endereços. CityFactory cria fixtures independentes de rede e do catálogo nacional nos testes de backend.
Checklist
- Criar
create_cities_tableantes decreate_addresses_table. - Criar Model
Citycom cast destate. - Adicionar
City::addresses()eCityFactorypara fixtures de backend. - Gerar e revisar
database/data/cities.jsoncom o catálogo nacional pelo comando Artisan. - Criar
CitySeederidempotente, executável sem rede e seguro para reexecução. - Testar migration, carga local, unicidade do código IBGE e filtro por UF/nome.
- Testar campos inválidos do catálogo e preservar dados existentes quando a validação falha.