You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.6 KiB
132 lines
4.6 KiB
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\AudienceSmsLog;
|
|
use App\Models\Competition;
|
|
use App\Services\Sms\AudienceSmsLogService;
|
|
use App\Support\BizDateTime;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class AudienceSmsLogController extends Controller
|
|
{
|
|
public function index(Request $request, Competition $competition, AudienceSmsLogService $service): JsonResponse
|
|
{
|
|
$filters = $request->validate([
|
|
'page' => ['sometimes', 'integer', 'min:1'],
|
|
'per_page' => ['sometimes', 'integer', 'min:1', 'max:100'],
|
|
'mobile' => ['sometimes', 'nullable', 'string', 'max:20'],
|
|
'status' => ['sometimes', 'nullable', 'string', Rule::in([
|
|
'',
|
|
AudienceSmsLog::STATUS_PENDING,
|
|
AudienceSmsLog::STATUS_SENDING,
|
|
AudienceSmsLog::STATUS_DELIVERED,
|
|
AudienceSmsLog::STATUS_DROPPED,
|
|
AudienceSmsLog::STATUS_FAILED,
|
|
])],
|
|
'scene' => ['sometimes', 'nullable', 'string', Rule::in([
|
|
'',
|
|
AudienceSmsLog::SCENE_PRE_REGISTER,
|
|
AudienceSmsLog::SCENE_APPROVED,
|
|
AudienceSmsLog::SCENE_AUDIENCE_LOGIN,
|
|
AudienceSmsLog::SCENE_PARTICIPANT_LOGIN,
|
|
])],
|
|
]);
|
|
|
|
$service->syncFromLogApi($competition);
|
|
|
|
$query = $this->buildQuery($competition, $filters);
|
|
$perPage = min((int) ($filters['per_page'] ?? 15), 100);
|
|
$paginator = $query->paginate($perPage);
|
|
$paginator->getCollection()->transform(fn (AudienceSmsLog $row) => $this->toArray($row));
|
|
|
|
return response()->json($paginator);
|
|
}
|
|
|
|
public function sync(Competition $competition, AudienceSmsLogService $service): JsonResponse
|
|
{
|
|
return response()->json($service->syncFromLogApi($competition, true));
|
|
}
|
|
|
|
public function resend(
|
|
Competition $competition,
|
|
AudienceSmsLog $audience_sms_log,
|
|
AudienceSmsLogService $service,
|
|
): JsonResponse {
|
|
$created = $service->resend($competition, $audience_sms_log);
|
|
|
|
return response()->json($this->toArray($created));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $filters
|
|
* @return Builder<AudienceSmsLog>
|
|
*/
|
|
private function buildQuery(Competition $competition, array $filters): Builder
|
|
{
|
|
$query = AudienceSmsLog::query()
|
|
->where('competition_id', $competition->id)
|
|
->orderByDesc('sent_at')
|
|
->orderByDesc('id');
|
|
|
|
$mobile = trim((string) ($filters['mobile'] ?? ''));
|
|
if ($mobile !== '') {
|
|
$query->where('mobile', 'like', '%'.$mobile.'%');
|
|
}
|
|
|
|
$status = trim((string) ($filters['status'] ?? ''));
|
|
if ($status === AudienceSmsLog::STATUS_FAILED) {
|
|
$query->whereIn('status', [AudienceSmsLog::STATUS_FAILED, AudienceSmsLog::STATUS_DROPPED]);
|
|
} elseif ($status !== '') {
|
|
$query->where('status', $status);
|
|
}
|
|
|
|
$scene = trim((string) ($filters['scene'] ?? ''));
|
|
if ($scene !== '') {
|
|
$query->where('scene', $scene);
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function toArray(AudienceSmsLog $row): array
|
|
{
|
|
return [
|
|
'id' => $row->id,
|
|
'competition_id' => $row->competition_id,
|
|
'audience_registration_id' => $row->audience_registration_id,
|
|
'scene' => $row->scene,
|
|
'scene_label' => AudienceSmsLog::sceneLabel((string) $row->scene),
|
|
'mobile' => $row->mobile,
|
|
'template_id' => $row->template_id,
|
|
'content' => $row->content,
|
|
'send_id' => $row->send_id,
|
|
'status' => $row->status,
|
|
'status_label' => $this->statusLabel($row->status),
|
|
'fee' => $row->fee,
|
|
'report_state' => $row->report_state,
|
|
'dropped_reason' => $row->dropped_reason,
|
|
'can_resend' => $row->canResend(),
|
|
'sent_at' => BizDateTime::toIso8601($row->sent_at),
|
|
'delivered_at' => BizDateTime::toIso8601($row->delivered_at),
|
|
];
|
|
}
|
|
|
|
private function statusLabel(string $status): string
|
|
{
|
|
return match ($status) {
|
|
AudienceSmsLog::STATUS_DELIVERED => '发送成功',
|
|
AudienceSmsLog::STATUS_DROPPED, AudienceSmsLog::STATUS_FAILED => '发送失败',
|
|
AudienceSmsLog::STATUS_SENDING => '发送中',
|
|
default => '待回执',
|
|
};
|
|
}
|
|
}
|