Files
Verde-Web/app/Http/Controllers/Api/V1/Qr/MyQrCodeController.php
2026-07-02 13:55:34 +08:00

120 lines
4.1 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\Qr;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Resources\QrCodeResource;
use App\Models\Household;
use App\Models\QrCode;
use App\Services\Qr\QrAllocator;
use App\States\QrCode\Active;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class MyQrCodeController extends ApiController
{
public function index(Request $request): JsonResponse
{
$request->validate([
'status' => ['nullable', 'in:unassigned,allocated,active,used,expired,voided'],
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
]);
$household = Household::where('head_user_id', $request->user()->id)->first();
if (! $household) {
return $this->ok([], 'No household yet');
}
$perPage = (int) $request->input('per_page', 50);
$codes = QrCode::query()
->where('assigned_to_household_id', $household->id)
->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')))
->orderByDesc('id')
->paginate($perPage);
return $this->ok(
QrCodeResource::collection($codes),
null,
[
'page' => $codes->currentPage(),
'per_page' => $codes->perPage(),
'total' => $codes->total(),
],
);
}
public function balance(Request $request): JsonResponse
{
$household = Household::where('head_user_id', $request->user()->id)->first();
if (! $household) {
return $this->ok([
'active' => 0, 'allocated' => 0, 'used' => 0, 'expired' => 0,
'low_balance' => false,
]);
}
$counts = QrCode::query()
->where('assigned_to_household_id', $household->id)
->selectRaw('status, COUNT(*) as count')
->groupBy('status')
->pluck('count', 'status')
->all();
$active = (int) ($counts['active'] ?? 0);
$threshold = (int) config('qr.low_balance_threshold', 5);
return $this->ok([
'active' => $active,
'allocated' => (int) ($counts['allocated'] ?? 0),
'used' => (int) ($counts['used'] ?? 0),
'expired' => (int) ($counts['expired'] ?? 0),
'low_balance' => $active <= $threshold,
'low_balance_threshold' => $threshold,
]);
}
public function activate(Request $request, QrCode $qrCode, QrAllocator $allocator): JsonResponse
{
$request->validate([
'activate_batch' => ['nullable', 'boolean'],
]);
$household = Household::where('head_user_id', $request->user()->id)->first();
if (! $household) {
return $this->forbidden('You must have an active household');
}
$activateBatch = $request->boolean('activate_batch');
if ($activateBatch) {
// Activate the whole batch
if (! $qrCode->batch_id) {
return $this->fail('This QR code does not belong to a batch', null, 422);
}
$activatedCount = $allocator->activateBatch($qrCode, $household);
if ($activatedCount === 0) {
return $this->fail('No unactivated codes found in this batch, or you do not have permission to activate this batch', null, 422);
}
return $this->ok(['activated_count' => $activatedCount], "Successfully activated $activatedCount QR codes in the batch");
}
// Single code activation
if ($qrCode->assigned_to_household_id !== $household->id) {
return $this->forbidden('This code is not assigned to your household');
}
if ($qrCode->status instanceof Active) {
return $this->ok(new QrCodeResource($qrCode), 'Code already active');
}
if (! $allocator->activate($qrCode)) {
return $this->fail('Code cannot be activated from its current state', null, 422);
}
return $this->ok(new QrCodeResource($qrCode->fresh()), 'Code activated');
}
}