Files
Verde-Web/app/Http/Controllers/Api/V1/SuperAdmin/SuperAdminTenantController.php

198 lines
7.5 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\SuperAdmin;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Requests\SuperAdmin\StoreTenantRequest;
use App\Http\Resources\SuperAdmin\SuperAdminTenantResource;
use App\Models\NotificationPreference;
use App\Models\Tenant;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
class SuperAdminTenantController extends ApiController
{
public function index(Request $request): JsonResponse
{
$request->validate([
'status' => ['nullable', 'in:onboarding,active,suspended'],
'q' => ['nullable', 'string', 'max:100'],
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
]);
$perPage = (int) $request->input('per_page', 25);
$tenants = Tenant::query()
->with(['cityMunicipality.province.region'])
->withCount(['users', 'households', 'trucks', 'barangays'])
->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')))
->when($request->filled('q'), function ($q) use ($request) {
$term = '%'.$request->string('q').'%';
$q->where(function ($qq) use ($term) {
$qq->where('name', 'like', $term)
->orWhere('code', 'like', $term)
->orWhere('short_name', 'like', $term);
});
})
->orderBy('name')
->paginate($perPage);
return $this->ok(
SuperAdminTenantResource::collection($tenants),
null,
[
'page' => $tenants->currentPage(),
'per_page' => $tenants->perPage(),
'total' => $tenants->total(),
'last_page' => $tenants->lastPage(),
],
);
}
public function store(StoreTenantRequest $request): JsonResponse
{
$data = $request->validated();
$tenant = DB::transaction(function () use ($data) {
$boundary = $this->buildPolygon($data['boundary_polygon']);
$tenant = Tenant::create([
'name' => $data['name'],
'short_name' => $data['short_name'],
'city_municipality_id' => $data['city_municipality_id'],
'boundary_polygon' => $boundary,
'theme_color' => $data['theme_color'] ?? '#16a34a',
'logo_path' => $data['logo_path'] ?? null,
'contact_email' => $data['contact_email'],
'contact_phone' => $data['contact_phone'],
'status' => $data['status'] ?? Tenant::STATUS_ONBOARDING,
'timezone' => $data['timezone'] ?? 'Asia/Manila',
]);
// Create default LGU admin account
$user = User::create([
'tenant_id' => $tenant->id,
'first_name' => 'LGU',
'last_name' => 'Admin',
'email' => $data['admin_email'],
'phone' => $data['contact_phone'],
'password' => Hash::make($data['admin_password']),
'role' => User::ROLE_ADMIN,
'status' => User::STATUS_ACTIVE,
]);
$user->assignRole(User::ROLE_ADMIN);
NotificationPreference::create([
'user_id' => $user->id,
'language' => 'en',
]);
return $tenant;
});
return $this->created(
new SuperAdminTenantResource(
$tenant->load(['cityMunicipality.province.region', 'users'])
),
'LGU onboarded successfully'
);
}
public function show(Tenant $tenant): JsonResponse
{
$tenant->load(['cityMunicipality.province.region', 'users']);
$tenant->loadCount(['users', 'households', 'trucks', 'barangays']);
return $this->ok(new SuperAdminTenantResource($tenant));
}
public function update(StoreTenantRequest $request, Tenant $tenant): JsonResponse
{
$data = $request->validated();
DB::transaction(function () use ($tenant, $data) {
$boundary = $this->buildPolygon($data['boundary_polygon']);
$tenant->update([
'name' => $data['name'],
'short_name' => $data['short_name'],
'city_municipality_id' => $data['city_municipality_id'],
'boundary_polygon' => $boundary,
'theme_color' => $data['theme_color'] ?? $tenant->theme_color,
'logo_path' => $data['logo_path'] ?? $tenant->logo_path,
'contact_email' => $data['contact_email'],
'contact_phone' => $data['contact_phone'],
'status' => $data['status'] ?? $tenant->status,
'timezone' => $data['timezone'] ?? $tenant->timezone,
]);
$admin = $tenant->users()->where('role', User::ROLE_ADMIN)->first();
if (! $admin && ! empty($data['admin_email']) && ! empty($data['admin_password'])) {
$admin = User::create([
'tenant_id' => $tenant->id,
'first_name' => 'LGU',
'last_name' => 'Admin',
'email' => $data['admin_email'],
'phone' => $data['contact_phone'],
'password' => Hash::make($data['admin_password']),
'role' => User::ROLE_ADMIN,
'status' => User::STATUS_ACTIVE,
]);
$admin->assignRole(User::ROLE_ADMIN);
NotificationPreference::create([
'user_id' => $admin->id,
'language' => 'en',
]);
} elseif ($admin) {
if (! empty($data['admin_email'])) {
// Ignore unique constraint on the same user
$existing = User::where('email', $data['admin_email'])->where('id', '!=', $admin->id)->first();
if (! $existing) {
$admin->email = $data['admin_email'];
}
}
if (! empty($data['admin_password'])) {
$admin->password = Hash::make($data['admin_password']);
}
if ($admin->isDirty('email') || $admin->isDirty('password')) {
$admin->save();
}
}
});
$tenant->load(['cityMunicipality.province.region', 'users']);
$tenant->loadCount(['users', 'households', 'trucks', 'barangays']);
return $this->ok(new SuperAdminTenantResource($tenant), 'LGU updated successfully');
}
public function destroy(Tenant $tenant): JsonResponse
{
$tenant->delete();
return $this->ok(null, 'LGU deleted successfully');
}
private function buildPolygon(array $points): Polygon
{
$ring = array_map(
fn ($p) => new Point((float) $p['lat'], (float) $p['lng'], 4326),
$points,
);
$first = $ring[0];
$last = $ring[count($ring) - 1];
if ($first->latitude !== $last->latitude || $first->longitude !== $last->longitude) {
$ring[] = new Point($first->latitude, $first->longitude, 4326);
}
return new Polygon([new LineString($ring)], 4326);
}
}