Module 2 — Geographic Data: PSGC tables (regions/provinces/cities/ barangays) with native geometry(polygon|point, 4326) columns; cascading dropdown endpoints; ST_Contains-based GPS resolution; service-area CRUD with barangay attach/detach; SamplePsgcSeeder + psgc:import command. Module 3 — User Management: 5 role-specific profile tables (driver/ helper/scanner/store_partner with verification_status + rejection reason); profile auto-created on register; admin user CRUD with filters/pagination, suspend/activate, profile approve/reject; self-service /me + /me/profile with role-aware validation that blocks self-approval and resets rejected profiles to pending on resubmit. 69 feature tests passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
126 lines
4.6 KiB
PHP
126 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Barangay;
|
|
use App\Models\CityMunicipality;
|
|
use App\Models\Province;
|
|
use App\Models\Region;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use MatanYadaev\EloquentSpatial\Objects\Point;
|
|
use MatanYadaev\EloquentSpatial\Objects\Polygon;
|
|
use Throwable;
|
|
|
|
class PsgcImport extends Command
|
|
{
|
|
protected $signature = 'psgc:import {file : Path to PSGC JSON file}';
|
|
|
|
protected $description = 'Import PSGC hierarchy (regions/provinces/cities/barangays) from JSON';
|
|
|
|
public function handle(): int
|
|
{
|
|
$path = $this->argument('file');
|
|
|
|
if (! is_file($path)) {
|
|
$this->error("File not found: {$path}");
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$payload = json_decode((string) file_get_contents($path), true);
|
|
|
|
if (! is_array($payload)) {
|
|
$this->error('Invalid JSON');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$counts = ['regions' => 0, 'provinces' => 0, 'cities' => 0, 'barangays' => 0];
|
|
|
|
try {
|
|
DB::transaction(function () use ($payload, &$counts) {
|
|
foreach ($payload['regions'] ?? [] as $r) {
|
|
Region::updateOrCreate(
|
|
['psgc_code' => $r['psgc_code']],
|
|
[
|
|
'code' => $r['code'],
|
|
'name' => $r['name'],
|
|
'island_group' => $r['island_group'] ?? null,
|
|
],
|
|
);
|
|
$counts['regions']++;
|
|
}
|
|
|
|
foreach ($payload['provinces'] ?? [] as $p) {
|
|
$region = Region::where('psgc_code', $p['region_psgc'])->firstOrFail();
|
|
Province::updateOrCreate(
|
|
['psgc_code' => $p['psgc_code']],
|
|
[
|
|
'code' => $p['code'],
|
|
'name' => $p['name'],
|
|
'region_id' => $region->id,
|
|
'income_classification' => $p['income_classification'] ?? null,
|
|
],
|
|
);
|
|
$counts['provinces']++;
|
|
}
|
|
|
|
foreach ($payload['cities_municipalities'] ?? [] as $c) {
|
|
$province = Province::where('psgc_code', $c['province_psgc'])->firstOrFail();
|
|
CityMunicipality::updateOrCreate(
|
|
['psgc_code' => $c['psgc_code']],
|
|
[
|
|
'code' => $c['code'],
|
|
'name' => $c['name'],
|
|
'province_id' => $province->id,
|
|
'type' => $c['type'] ?? 'municipality',
|
|
'is_capital' => (bool) ($c['is_capital'] ?? false),
|
|
'classification' => $c['classification'] ?? null,
|
|
],
|
|
);
|
|
$counts['cities']++;
|
|
}
|
|
|
|
foreach ($payload['barangays'] ?? [] as $b) {
|
|
$city = CityMunicipality::where('psgc_code', $b['city_psgc'])->firstOrFail();
|
|
$boundary = isset($b['boundary_geojson'])
|
|
? Polygon::fromJson(json_encode($b['boundary_geojson']))
|
|
: null;
|
|
$centroid = isset($b['centroid'])
|
|
? new Point((float) $b['centroid']['lat'], (float) $b['centroid']['lng'], 4326)
|
|
: null;
|
|
|
|
Barangay::updateOrCreate(
|
|
['psgc_code' => $b['psgc_code']],
|
|
[
|
|
'code' => $b['code'],
|
|
'name' => $b['name'],
|
|
'city_municipality_id' => $city->id,
|
|
'urban_rural' => $b['urban_rural'] ?? Barangay::URBAN_RURAL_UNKNOWN,
|
|
'population' => $b['population'] ?? null,
|
|
'boundary' => $boundary,
|
|
'centroid' => $centroid,
|
|
],
|
|
);
|
|
$counts['barangays']++;
|
|
}
|
|
});
|
|
} catch (Throwable $e) {
|
|
$this->error('Import failed: '.$e->getMessage());
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$this->info(sprintf(
|
|
'Imported %d regions, %d provinces, %d cities, %d barangays',
|
|
$counts['regions'],
|
|
$counts['provinces'],
|
|
$counts['cities'],
|
|
$counts['barangays'],
|
|
));
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
}
|