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.

61 lines
2.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Services;
use App\Models\Reservation;
use Carbon\Carbon;
use Illuminate\Support\Collection;
class ReservationExpiryService
{
/**
* 将「活动日/入馆日历日已过当日 23:59:59、仍为待核销、未核销」的预约标记为 expired。
* 均以应用时区的**日历日**为准:活动日当天(含整日至 23:59:59仍可待核销自**次日 0:00** 起视为已过活动日。
* - 普通活动:以 activity_days.activity_date 对应日历日为准(不再按场次 session_end_at 提前过期)。
* - 抢票:以 entry_date 对应日历日为准。
*/
public function expireStalePendingReservations(): int
{
$tz = (string) config('app.timezone');
$today = Carbon::now($tz)->toDateString();
$ids = $this->stalePendingReservationIds($today);
if ($ids->isEmpty()) {
return 0;
}
return Reservation::query()->whereIn('id', $ids)->update([
'status' => 'expired',
'updated_at' => now(),
]);
}
/**
* @return Collection<int, int>
*/
private function stalePendingReservationIds(string $today): Collection
{
$idsActivity = Reservation::query()
->join('activity_days', 'activity_days.id', '=', 'reservations.activity_day_id')
->where('reservations.status', 'pending')
->whereNull('reservations.verified_at')
->whereNotNull('reservations.activity_day_id')
->whereDate('activity_days.activity_date', '<', $today)
->where(function ($q) {
$q->whereNull('reservations.reservation_kind')
->orWhere('reservations.reservation_kind', Reservation::KIND_ACTIVITY);
})
->pluck('reservations.id');
$idsTicketGrab = Reservation::query()
->where('reservation_kind', Reservation::KIND_TICKET_GRAB)
->where('status', 'pending')
->whereNull('verified_at')
->whereNotNull('entry_date')
->whereDate('entry_date', '<', $today)
->pluck('id');
return $idsActivity->merge($idsTicketGrab)->unique()->values();
}
}