validate([ 'household_ids' => ['required', 'array', 'min:1', 'max:200'], 'household_ids.*' => ['string', 'exists:households,uuid'], ]); $admin = $request->user(); $results = []; foreach ($data['household_ids'] as $uuid) { $h = Household::where('uuid', $uuid)->first(); if (! $h) { $results[] = ['id' => $uuid, 'ok' => false, 'reason' => 'not_found']; continue; } if ($h->verification_status === Household::VERIFICATION_APPROVED) { $results[] = ['id' => $uuid, 'ok' => false, 'reason' => 'already_approved']; continue; } if (! $h->proof_of_residency_path) { $results[] = ['id' => $uuid, 'ok' => false, 'reason' => 'no_proof']; continue; } DB::transaction(function () use ($h, $admin) { $h->markVerified($admin); }); HouseholdVerified::dispatch($h->fresh(), $admin); $results[] = ['id' => $uuid, 'ok' => true]; } $okCount = collect($results)->where('ok', true)->count(); return $this->ok([ 'approved' => $okCount, 'rejected' => count($results) - $okCount, 'results' => $results, ], "Approved {$okCount} of ".count($results).' households'); } public function suspendUsers(Request $request): JsonResponse { $data = $request->validate([ 'user_ids' => ['required', 'array', 'min:1', 'max:200'], 'user_ids.*' => ['string', 'exists:users,uuid'], ]); $results = []; foreach ($data['user_ids'] as $uuid) { $u = User::where('uuid', $uuid)->first(); if (! $u) { $results[] = ['id' => $uuid, 'ok' => false, 'reason' => 'not_found']; continue; } if ($u->role === User::ROLE_ADMIN) { $results[] = ['id' => $uuid, 'ok' => false, 'reason' => 'admin_protected']; continue; } $u->forceFill(['status' => User::STATUS_SUSPENDED])->save(); $results[] = ['id' => $uuid, 'ok' => true]; } $okCount = collect($results)->where('ok', true)->count(); return $this->ok(['suspended' => $okCount, 'results' => $results], "Suspended {$okCount} users"); } public function activateUsers(Request $request): JsonResponse { $data = $request->validate([ 'user_ids' => ['required', 'array', 'min:1', 'max:200'], 'user_ids.*' => ['string', 'exists:users,uuid'], ]); $results = []; foreach ($data['user_ids'] as $uuid) { $u = User::where('uuid', $uuid)->first(); if (! $u) { $results[] = ['id' => $uuid, 'ok' => false, 'reason' => 'not_found']; continue; } $u->forceFill(['status' => User::STATUS_ACTIVE])->save(); $results[] = ['id' => $uuid, 'ok' => true]; } $okCount = collect($results)->where('ok', true)->count(); return $this->ok(['activated' => $okCount, 'results' => $results], "Activated {$okCount} users"); } public function voidQrCodes(Request $request): JsonResponse { $data = $request->validate([ 'serials' => ['required', 'array', 'min:1', 'max:500'], 'serials.*' => ['string'], 'reason' => ['required', 'string', 'min:3', 'max:500'], ]); $admin = $request->user(); $results = []; foreach ($data['serials'] as $serial) { $code = QrCode::where('serial', $serial)->first(); if (! $code) { $results[] = ['serial' => $serial, 'ok' => false, 'reason' => 'not_found']; continue; } if (! $code->status->canTransitionTo(Voided::class)) { $results[] = ['serial' => $serial, 'ok' => false, 'reason' => 'cannot_void_from_'.(string) $code->status]; continue; } $code->status->transitionTo(Voided::class); $code->forceFill([ 'metadata' => array_merge($code->metadata ?? [], [ 'voided_at' => now()->toIso8601String(), 'voided_by_admin_id' => $admin->id, 'void_reason' => $data['reason'], ]), ])->save(); $results[] = ['serial' => $serial, 'ok' => true]; } $okCount = collect($results)->where('ok', true)->count(); return $this->ok(['voided' => $okCount, 'results' => $results], "Voided {$okCount} codes"); } }