added countries support expanded for ISO 3166 standard
This commit is contained in:
+85
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Add ISO 3166 governance metadata and ISO 3166-2 subdivision support.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('countries', function (Blueprint $table): void {
|
||||
if (! Schema::hasColumn('countries', 'iso_status')) {
|
||||
$table->string('iso_status', 32)->default('official')->index()->after('is_active')->comment('ISO 3166-1 lifecycle status: official, reserved, transitional, deleted, user_assigned, exceptionally_reserved.');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('countries', 'independent')) {
|
||||
$table->boolean('independent')->nullable()->after('iso_status')->comment('Whether the ISO 3166-1 entry represents an independent state where known.');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('countries', 'region')) {
|
||||
$table->string('region')->nullable()->index()->after('independent')->comment('UN M49-style broad region for filtering and reporting.');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('countries', 'subregion')) {
|
||||
$table->string('subregion')->nullable()->index()->after('region')->comment('UN M49-style subregion for filtering and reporting.');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('countries', 'source')) {
|
||||
$table->string('source')->nullable()->after('last_synced_at')->comment('Reference data source used for the last sync.');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('countries', 'source_version')) {
|
||||
$table->string('source_version')->nullable()->after('source')->comment('Reference data version/release identifier.');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('countries', 'metadata')) {
|
||||
$table->json('metadata')->nullable()->after('source_version')->comment('Additional non-authoritative metadata, never used as the primary ISO identity.');
|
||||
}
|
||||
});
|
||||
|
||||
if (! Schema::hasTable('country_subdivisions')) {
|
||||
Schema::create('country_subdivisions', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->foreignId('country_id')->constrained('countries')->cascadeOnDelete();
|
||||
$table->char('country_alpha2', 2)->index()->comment('Parent ISO 3166-1 alpha-2 code, duplicated for fast lookup and imports.');
|
||||
$table->string('code', 16)->unique()->comment('Full ISO 3166-2 subdivision code, for example GB-ENG or US-CA.');
|
||||
$table->string('subdivision_code', 12)->comment('Subdivision part after the country prefix, for example ENG or CA.');
|
||||
$table->string('name')->comment('ISO 3166-2 subdivision name.');
|
||||
$table->string('local_name')->nullable()->comment('Optional local-language display name.');
|
||||
$table->string('type')->nullable()->index()->comment('Subdivision type, for example country, province, state, territory, council area.');
|
||||
$table->boolean('is_active')->default(true)->index()->comment('Whether this subdivision is currently available in business workflows.');
|
||||
$table->string('iso_status', 32)->default('official')->index()->comment('ISO 3166-2 lifecycle status.');
|
||||
$table->unsignedInteger('sort_order')->default(0)->index();
|
||||
$table->timestamp('last_synced_at')->nullable();
|
||||
$table->string('source')->nullable();
|
||||
$table->string('source_version')->nullable();
|
||||
$table->json('metadata')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['country_id', 'subdivision_code']);
|
||||
$table->index(['country_alpha2', 'is_active', 'sort_order', 'name']);
|
||||
$table->index(['type', 'is_active']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the ISO 3166 support additions.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('country_subdivisions');
|
||||
|
||||
Schema::table('countries', function (Blueprint $table): void {
|
||||
foreach (['metadata', 'source_version', 'source', 'subregion', 'region', 'independent', 'iso_status'] as $column) {
|
||||
if (Schema::hasColumn('countries', $column)) {
|
||||
$table->dropColumn($column);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -6,8 +6,14 @@ use Illuminate\Database\Seeder;
|
||||
|
||||
class CountriesDatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed ISO 3166 country reference data.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$this->call(IsoCountriesSeeder::class);
|
||||
$this->call([
|
||||
IsoCountriesSeeder::class,
|
||||
IsoCountrySubdivisionsSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +270,9 @@ class IsoCountriesSeeder extends Seeder
|
||||
'is_active' => true,
|
||||
'sort_order' => $index + 1,
|
||||
'last_synced_at' => $now,
|
||||
'iso_status' => 'official',
|
||||
'source' => 'bundled-iso-3166-1',
|
||||
'source_version' => '2026-06-15',
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Countries\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Modules\Countries\Models\Country;
|
||||
use Modules\Countries\Models\CountrySubdivision;
|
||||
|
||||
class IsoCountrySubdivisionsSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed high-value ISO 3166-2 subdivisions used by UK/US business workflows.
|
||||
*
|
||||
* This module is structured to import the full ISO 3166-2 data set from an approved licensed source.
|
||||
* The bundled seed keeps the module useful out of the box without pretending to be the complete ISO 3166-2 catalogue.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$rows = [
|
||||
['country' => 'GB', 'code' => 'GB-ENG', 'name' => 'England', 'type' => 'country'],
|
||||
['country' => 'GB', 'code' => 'GB-SCT', 'name' => 'Scotland', 'type' => 'country'],
|
||||
['country' => 'GB', 'code' => 'GB-WLS', 'name' => 'Wales', 'type' => 'country'],
|
||||
['country' => 'GB', 'code' => 'GB-NIR', 'name' => 'Northern Ireland', 'type' => 'province'],
|
||||
['country' => 'US', 'code' => 'US-AL', 'name' => 'Alabama', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-AK', 'name' => 'Alaska', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-AZ', 'name' => 'Arizona', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-AR', 'name' => 'Arkansas', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-CA', 'name' => 'California', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-CO', 'name' => 'Colorado', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-CT', 'name' => 'Connecticut', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-DE', 'name' => 'Delaware', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-FL', 'name' => 'Florida', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-NY', 'name' => 'New York', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-TX', 'name' => 'Texas', 'type' => 'state'],
|
||||
['country' => 'US', 'code' => 'US-WA', 'name' => 'Washington', 'type' => 'state'],
|
||||
['country' => 'CA', 'code' => 'CA-AB', 'name' => 'Alberta', 'type' => 'province'],
|
||||
['country' => 'CA', 'code' => 'CA-BC', 'name' => 'British Columbia', 'type' => 'province'],
|
||||
['country' => 'CA', 'code' => 'CA-ON', 'name' => 'Ontario', 'type' => 'province'],
|
||||
['country' => 'CA', 'code' => 'CA-QC', 'name' => 'Quebec', 'type' => 'province'],
|
||||
];
|
||||
|
||||
foreach ($rows as $index => $row) {
|
||||
$country = Country::query()->where('alpha2', $row['country'])->first();
|
||||
|
||||
if (! $country) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CountrySubdivision::query()->updateOrCreate(
|
||||
['code' => $row['code']],
|
||||
[
|
||||
'country_id' => $country->id,
|
||||
'country_alpha2' => $country->alpha2,
|
||||
'subdivision_code' => substr($row['code'], 3),
|
||||
'name' => $row['name'],
|
||||
'local_name' => null,
|
||||
'type' => $row['type'],
|
||||
'is_active' => true,
|
||||
'iso_status' => 'official',
|
||||
'sort_order' => $index + 1,
|
||||
'last_synced_at' => $now,
|
||||
'source' => 'bundled-bootstrap',
|
||||
'source_version' => '2026-06-15',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user