feat: 重构注单控制器以复用共享筛选逻辑

新增 TicketItemListFilters trait,用于封装注单列表的通用筛选逻辑。
更新 AdminPlayerTicketItemsIndexController、AdminTicketItemIndexController 与 TicketItemsIndexController,统一使用新的注单编号搜索与订单日期范围筛选方法,提升代码复用性与可读性。
增强 AdminRiskPoolManualStatusController:支持发布手动停售状态变更通知。
优化 RiskPoolService 与 TicketWalletService:钱包资金变动后实时通知余额更新。
更新测试用例,确保重构后功能行为保持一致。
This commit is contained in:
2026-05-26 17:14:19 +08:00
parent 36e50383ba
commit 618201f980
12 changed files with 408 additions and 84 deletions

View File

@@ -5,8 +5,9 @@ namespace App\Http\Controllers\Api\V1\Admin\Player;
use App\Models\Player;
use App\Models\TicketItem;
use App\Support\ApiResponse;
use App\Support\PaginationTrait;
use App\Support\CurrencyFormatter;
use App\Support\PaginationTrait;
use App\Support\TicketItemListFilters;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\AdminPlayerTicketItemsRequest;
@@ -19,6 +20,7 @@ use App\Http\Requests\Admin\AdminPlayerTicketItemsRequest;
final class AdminPlayerTicketItemsIndexController extends Controller
{
use PaginationTrait;
use TicketItemListFilters;
public function __invoke(AdminPlayerTicketItemsRequest $request, Player $player): JsonResponse
{
@@ -56,22 +58,8 @@ final class AdminPlayerTicketItemsIndexController extends Controller
$query->whereIn('ticket_items.status', $statusValues);
}
if ($number !== '') {
$query->where(function ($q) use ($number): void {
$q->where('ticket_items.original_number', 'like', '%'.$number.'%')
->orWhere('ticket_items.normalized_number', 'like', '%'.$number.'%')
->orWhere('ticket_items.ticket_no', 'like', '%'.$number.'%')
->orWhereHas('order', fn ($order) => $order->where('order_no', 'like', '%'.$number.'%'));
});
}
if (is_string($startDate) && $startDate !== '') {
$query->whereHas('order', fn ($q) => $q->whereDate('created_at', '>=', $startDate));
}
if (is_string($endDate) && $endDate !== '') {
$query->whereHas('order', fn ($q) => $q->whereDate('created_at', '<=', $endDate));
}
$this->applyTicketItemNumberSearch($query, $number);
$this->applyOrderPlacedDateRange($query, $startDate, $endDate);
$paginator = $query->paginate(perPage: $perPage, page: $page, columns: ['*']);

View File

@@ -66,12 +66,17 @@ final class AdminRiskPoolManualStatusController extends Controller
}
$targetStatus = $soldOut ? 1 : 0;
if ((int) $pool->sold_out_status !== $targetStatus) {
$soldOutBefore = (int) $pool->sold_out_status;
if ($soldOutBefore !== $targetStatus) {
$pool->forceFill([
'sold_out_status' => $targetStatus,
'version' => (int) $pool->version + 1,
])->save();
if ($targetStatus === 1) {
$this->riskPoolService->publishManualSoldOut($draw, $number4d);
}
RiskPoolLockLog::query()->create([
'draw_id' => $draw->id,
'normalized_number' => $number4d,

View File

@@ -8,6 +8,7 @@ use App\Models\TicketItem;
use App\Support\ApiResponse;
use App\Support\CurrencyFormatter;
use App\Support\PaginationTrait;
use App\Support\TicketItemListFilters;
use Illuminate\Http\JsonResponse;
/**
@@ -25,6 +26,7 @@ use Illuminate\Http\JsonResponse;
final class AdminTicketItemIndexController extends Controller
{
use PaginationTrait;
use TicketItemListFilters;
public function __invoke(TicketItemListRequest $request): JsonResponse
{
@@ -72,24 +74,12 @@ final class AdminTicketItemIndexController extends Controller
}
$number = trim((string) ($validated['number'] ?? ''));
if ($number !== '') {
$query->where(function ($q) use ($number): void {
$q->where('ticket_items.original_number', 'like', '%'.$number.'%')
->orWhere('ticket_items.normalized_number', 'like', '%'.$number.'%')
->orWhere('ticket_items.ticket_no', 'like', '%'.$number.'%')
->orWhereHas('order', fn ($order) => $order->where('order_no', 'like', '%'.$number.'%'));
});
}
$startDate = $validated['start_date'] ?? null;
if (is_string($startDate) && $startDate !== '') {
$query->whereHas('order', fn ($q) => $q->whereDate('created_at', '>=', $startDate));
}
$endDate = $validated['end_date'] ?? null;
if (is_string($endDate) && $endDate !== '') {
$query->whereHas('order', fn ($q) => $q->whereDate('created_at', '<=', $endDate));
}
$this->applyTicketItemNumberSearch($query, $number);
$this->applyOrderPlacedDateRange(
$query,
is_string($validated['start_date'] ?? null) ? $validated['start_date'] : null,
is_string($validated['end_date'] ?? null) ? $validated['end_date'] : null,
);
$paginator = $query->paginate(perPage: $perPage, page: $page, columns: ['*']);

View File

@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api\V1\Ticket;
use Carbon\Carbon;
use App\Models\Player;
use App\Models\TicketItem;
use App\Support\ApiResponse;
use App\Support\TicketItemListFilters;
use Illuminate\Http\Request;
use App\Support\PaginationTrait;
use Illuminate\Http\JsonResponse;
@@ -18,6 +18,7 @@ use App\Http\Controllers\Controller;
final class TicketItemsIndexController extends Controller
{
use PaginationTrait;
use TicketItemListFilters;
public function __invoke(Request $request): JsonResponse
{
@@ -56,23 +57,8 @@ final class TicketItemsIndexController extends Controller
$query->whereIn('ticket_items.status', $statusValues);
}
if ($number !== '') {
$query->where(function ($q) use ($number): void {
$q->where('ticket_items.original_number', 'like', '%'.$number.'%')
->orWhere('ticket_items.normalized_number', 'like', '%'.$number.'%')
->orWhere('ticket_items.ticket_no', 'like', '%'.$number.'%');
});
}
if ($startDate !== null) {
$fromUtc = $this->scheduleDateStartUtc($startDate);
$query->whereHas('order', fn ($q) => $q->where('created_at', '>=', $fromUtc));
}
if ($endDate !== null) {
$toUtc = $this->scheduleDateEndUtc($endDate);
$query->whereHas('order', fn ($q) => $q->where('created_at', '<=', $toUtc));
}
$this->applyTicketItemNumberSearch($query, $number);
$this->applyOrderPlacedDateRange($query, $startDate, $endDate);
$paginator = $query->paginate(perPage: $perPage, page: $page);
@@ -122,23 +108,4 @@ final class TicketItemsIndexController extends Controller
return $value;
}
private function scheduleTimezone(): string
{
return (string) config('lottery.draw.timezone', 'UTC');
}
private function scheduleDateStartUtc(string $ymd): Carbon
{
return Carbon::createFromFormat('Y-m-d', $ymd, $this->scheduleTimezone())
->startOfDay()
->utc();
}
private function scheduleDateEndUtc(string $ymd): Carbon
{
return Carbon::createFromFormat('Y-m-d', $ymd, $this->scheduleTimezone())
->endOfDay()
->utc();
}
}