198 lines
7.5 KiB
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);
|
|
}
|
|
}
|