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>
111 lines
5.3 KiB
PHP
111 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use App\Models\Barangay;
|
|
use App\Models\CityMunicipality;
|
|
use App\Models\Province;
|
|
use App\Models\Region;
|
|
use Illuminate\Database\Seeder;
|
|
use Illuminate\Support\Arr;
|
|
use MatanYadaev\EloquentSpatial\Objects\LineString;
|
|
use MatanYadaev\EloquentSpatial\Objects\Point;
|
|
use MatanYadaev\EloquentSpatial\Objects\Polygon;
|
|
|
|
/**
|
|
* Minimal PSGC sample for development. Includes NCR + a handful of
|
|
* cities/barangays with rough rectangular boundary polygons for
|
|
* point-in-polygon resolution tests.
|
|
*
|
|
* Replace with full dataset via `php artisan psgc:import <file>`.
|
|
*/
|
|
class SamplePsgcSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
$regions = [
|
|
['psgc_code' => '130000000', 'code' => 'NCR', 'name' => 'National Capital Region', 'island_group' => 'Luzon'],
|
|
['psgc_code' => '030000000', 'code' => 'R03', 'name' => 'Central Luzon', 'island_group' => 'Luzon'],
|
|
];
|
|
|
|
foreach ($regions as $r) {
|
|
Region::updateOrCreate(['psgc_code' => $r['psgc_code']], $r);
|
|
}
|
|
|
|
$ncr = Region::where('psgc_code', '130000000')->firstOrFail();
|
|
|
|
$provinces = [
|
|
['psgc_code' => '133900000', 'code' => 'NCR-1', 'name' => 'NCR, City of Manila, First District', 'region_id' => $ncr->id],
|
|
['psgc_code' => '137400000', 'code' => 'NCR-2', 'name' => 'NCR, Second District', 'region_id' => $ncr->id],
|
|
['psgc_code' => '137500000', 'code' => 'NCR-3', 'name' => 'NCR, Third District', 'region_id' => $ncr->id],
|
|
['psgc_code' => '137600000', 'code' => 'NCR-4', 'name' => 'NCR, Fourth District', 'region_id' => $ncr->id],
|
|
];
|
|
|
|
foreach ($provinces as $p) {
|
|
Province::updateOrCreate(['psgc_code' => $p['psgc_code']], $p);
|
|
}
|
|
|
|
$manila = Province::where('psgc_code', '133900000')->firstOrFail();
|
|
$ncr2 = Province::where('psgc_code', '137400000')->firstOrFail();
|
|
$ncr4 = Province::where('psgc_code', '137600000')->firstOrFail();
|
|
|
|
$cities = [
|
|
['psgc_code' => '133900000', 'code' => 'MNL', 'name' => 'City of Manila', 'province_id' => $manila->id, 'type' => 'city', 'is_capital' => true],
|
|
['psgc_code' => '137404000', 'code' => 'QC', 'name' => 'Quezon City', 'province_id' => $ncr2->id, 'type' => 'city'],
|
|
['psgc_code' => '137403000', 'code' => 'PSG', 'name' => 'Pasig City', 'province_id' => $ncr2->id, 'type' => 'city'],
|
|
['psgc_code' => '137602000', 'code' => 'MKT', 'name' => 'Makati City', 'province_id' => $ncr4->id, 'type' => 'city'],
|
|
['psgc_code' => '137607000', 'code' => 'TAG', 'name' => 'Taguig City', 'province_id' => $ncr4->id, 'type' => 'city'],
|
|
];
|
|
|
|
foreach ($cities as $c) {
|
|
CityMunicipality::updateOrCreate(['psgc_code' => $c['psgc_code']], $c);
|
|
}
|
|
|
|
$qc = CityMunicipality::where('code', 'QC')->firstOrFail();
|
|
$manilaCity = CityMunicipality::where('code', 'MNL')->firstOrFail();
|
|
$makati = CityMunicipality::where('code', 'MKT')->firstOrFail();
|
|
|
|
// Each barangay gets a small rectangle (~1km box) around a real centroid.
|
|
$barangays = [
|
|
['city' => $qc, 'psgc_code' => '137404036', 'code' => 'QC-DLM', 'name' => 'Diliman', 'lat' => 14.6539, 'lng' => 121.0685],
|
|
['city' => $qc, 'psgc_code' => '137404029', 'code' => 'QC-CMW', 'name' => 'Commonwealth', 'lat' => 14.6970, 'lng' => 121.0780],
|
|
['city' => $qc, 'psgc_code' => '137404014', 'code' => 'QC-BPA', 'name' => 'Bagong Pag-asa', 'lat' => 14.6493, 'lng' => 121.0386],
|
|
['city' => $manilaCity, 'psgc_code' => '133900100', 'code' => 'MNL-ERM', 'name' => 'Ermita', 'lat' => 14.5824, 'lng' => 120.9831],
|
|
['city' => $manilaCity, 'psgc_code' => '133900200', 'code' => 'MNL-MLT', 'name' => 'Malate', 'lat' => 14.5722, 'lng' => 120.9846],
|
|
['city' => $makati, 'psgc_code' => '137602100', 'code' => 'MKT-PBL', 'name' => 'Poblacion', 'lat' => 14.5648, 'lng' => 121.0306],
|
|
['city' => $makati, 'psgc_code' => '137602200', 'code' => 'MKT-BAR', 'name' => 'Bel-Air', 'lat' => 14.5575, 'lng' => 121.0200],
|
|
];
|
|
|
|
foreach ($barangays as $b) {
|
|
Barangay::updateOrCreate(
|
|
['psgc_code' => $b['psgc_code']],
|
|
[
|
|
'code' => $b['code'],
|
|
'name' => $b['name'],
|
|
'city_municipality_id' => $b['city']->id,
|
|
'urban_rural' => Barangay::URBAN,
|
|
'boundary' => $this->boxAround($b['lat'], $b['lng'], 0.005),
|
|
'centroid' => new Point($b['lat'], $b['lng'], 4326),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build a small square polygon centered on (lat,lng) with the given
|
|
* half-edge in degrees (~0.005° ≈ 555m at the equator, smaller in PH).
|
|
*/
|
|
private function boxAround(float $lat, float $lng, float $half): Polygon
|
|
{
|
|
$points = [
|
|
new Point($lat - $half, $lng - $half, 4326),
|
|
new Point($lat - $half, $lng + $half, 4326),
|
|
new Point($lat + $half, $lng + $half, 4326),
|
|
new Point($lat + $half, $lng - $half, 4326),
|
|
new Point($lat - $half, $lng - $half, 4326),
|
|
];
|
|
|
|
return new Polygon([new LineString($points)], 4326);
|
|
}
|
|
}
|