feat: enhance admin role management and reconciliation features

- Updated AGENTS.md to clarify site admin roles and their associated permissions.
- Refactored reconciliation controllers to include admin user validation and improved access control based on admin roles.
- Enhanced AdminReconcileJobService to support player-specific reconciliation and site-based job creation.
- Removed deprecated rebate commission report functionality from the API and related services.
- Improved dashboard overview builders to accommodate new site operator roles and their specific functionalities.
This commit is contained in:
2026-06-16 16:04:01 +08:00
parent 3a59cc3f42
commit 4e370a79dc
35 changed files with 1230 additions and 180 deletions

View File

@@ -2,12 +2,15 @@
namespace App\Http\Controllers\Api\V1\Admin\Reconcile;
use App\Models\AdminSite;
use App\Models\AdminUser;
use App\Models\TransferOrder;
use App\Models\ReconcileJob;
use Illuminate\Http\Request;
use App\Models\ReconcileItem;
use App\Support\AdminAgentScope;
use App\Support\AdminApiList;
use App\Support\AdminReconcileScope;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
use App\Support\AdminTransferOrderCapabilities;
@@ -28,11 +31,27 @@ final class ReconcileItemIndexController extends Controller
$admin = $request->lotteryAdmin();
abort_if($admin === null, 401);
if ($denied = AdminReconcileScope::denyUnlessJobAccessible($admin, $reconcile_job)) {
return $denied;
}
$p = AdminApiList::readPaging($request, 50, 200);
$paginator = $reconcile_job->items()
->orderBy('id')
->paginate($p['perPage'], ['*'], 'page', $p['page']);
$itemsQuery = $reconcile_job->items()->orderBy('id');
if (! $admin->isSuperAdmin()) {
$siteIds = $admin->accessibleAdminSiteIds() ?? [];
$siteCodes = $siteIds === []
? []
: AdminSite::query()
->whereIn('id', $siteIds)
->pluck('code')
->map(static fn ($code): string => (string) $code)
->all();
$agent = AdminAgentScope::primaryAgentNode($admin);
AdminReconcileScope::applyItemsTransferPlayerScope($itemsQuery, $siteCodes, $agent);
}
$paginator = $itemsQuery->paginate($p['perPage'], ['*'], 'page', $p['page']);
$transferNos = collect($paginator->items())
->map(fn (ReconcileItem $item) => $item->side_a_ref)

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api\V1\Admin\Reconcile;
use App\Models\ReconcileJob;
use App\Support\AdminReconcileScope;
use Illuminate\Http\Request;
use App\Support\AdminApiList;
use Illuminate\Http\JsonResponse;
@@ -13,6 +14,9 @@ final class ReconcileJobIndexController extends Controller
{
public function __invoke(Request $request): JsonResponse
{
$admin = $request->lotteryAdmin();
abort_if($admin === null, 401);
$p = AdminApiList::readPaging($request);
$type = trim((string) $request->query('reconcile_type', ''));
@@ -21,6 +25,8 @@ final class ReconcileJobIndexController extends Controller
$q->where('reconcile_type', $type);
}
AdminReconcileScope::applyToJobsQuery($q, $admin);
$paginator = $q->paginate($p['perPage'], ['*'], 'page', $p['page']);
return AdminApiList::json($paginator, fn (ReconcileJob $j) => $this->row($j));

View File

@@ -3,15 +3,24 @@
namespace App\Http\Controllers\Api\V1\Admin\Reconcile;
use App\Models\ReconcileJob;
use App\Support\AdminReconcileScope;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
/** GET /api/v1/admin/reconcile-jobs/{reconcile_job} */
final class ReconcileJobShowController extends Controller
{
public function __invoke(ReconcileJob $reconcile_job): JsonResponse
public function __invoke(Request $request, ReconcileJob $reconcile_job): JsonResponse
{
$admin = $request->lotteryAdmin();
abort_if($admin === null, 401);
if ($denied = AdminReconcileScope::denyUnlessJobAccessible($admin, $reconcile_job)) {
return $denied;
}
return ApiResponse::success([
'id' => (int) $reconcile_job->id,
'job_no' => $reconcile_job->job_no,