style(booking): 以 pint 格式化預約 Controller
Run Tests / test (pull_request) Successful in 34s

純格式化,不含邏輯變更。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-18 01:35:38 +08:00
parent ddbf956144
commit 8042f0bafb
2 changed files with 48 additions and 47 deletions
@@ -8,8 +8,8 @@ use App\Exceptions\BookingRuleViolationException;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Booking; use App\Models\Booking;
use App\Models\CourseSchedule; use App\Models\CourseSchedule;
use App\Notifications\BookingCreatedNotification;
use App\Notifications\BookingCancelledNotification; use App\Notifications\BookingCancelledNotification;
use App\Notifications\BookingCreatedNotification;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@@ -23,7 +23,7 @@ class MemberBookingController extends Controller
->where('member_id', $request->user()->id) ->where('member_id', $request->user()->id)
->orderByDesc('created_at') ->orderByDesc('created_at')
->get() ->get()
->map(fn($b) => $this->formatBooking($b)); ->map(fn ($b) => $this->formatBooking($b));
return response()->json(['status' => true, 'data' => $bookings]); return response()->json(['status' => true, 'data' => $bookings]);
} }
@@ -41,9 +41,9 @@ class MemberBookingController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$data = $request->validate([ $data = $request->validate([
'schedule_id' => 'required|integer|exists:course_schedules,id', 'schedule_id' => 'required|integer|exists:course_schedules,id',
'participants' => 'required|integer|min:1', 'participants' => 'required|integer|min:1',
'notes' => 'nullable|string|max:500', 'notes' => 'nullable|string|max:500',
]); ]);
$schedule = CourseSchedule::with('divingOffer.provider.providerProfile')->findOrFail($data['schedule_id']); $schedule = CourseSchedule::with('divingOffer.provider.providerProfile')->findOrFail($data['schedule_id']);
@@ -51,7 +51,7 @@ class MemberBookingController extends Controller
// Layer 1:快速失敗 // Layer 1:快速失敗
// 可見性繞過防護:課程教練未通過審核時不可建立新預約(既有預約不受影響,見 provider-verification 規格) // 可見性繞過防護:課程教練未通過審核時不可建立新預約(既有預約不受影響,見 provider-verification 規格)
$offer = $schedule->divingOffer; $offer = $schedule->divingOffer;
if ($offer->provider_id !== null && !($offer->provider?->providerProfile?->is_verified)) { if ($offer->provider_id !== null && ! ($offer->provider?->providerProfile?->is_verified)) {
// is_verified 為 accessor(= verification_status === approved) // is_verified 為 accessor(= verification_status === approved)
return response()->json(['status' => false, 'message' => '此課程目前不開放預約'], 422); return response()->json(['status' => false, 'message' => '此課程目前不開放預約'], 422);
} }
@@ -82,12 +82,12 @@ class MemberBookingController extends Controller
} }
return Booking::create([ return Booking::create([
'schedule_id' => $schedule->id, 'schedule_id' => $schedule->id,
'member_id' => $memberId, 'member_id' => $memberId,
'participants' => $data['participants'], 'participants' => $data['participants'],
'total_price' => $schedule->divingOffer->price * $data['participants'], 'total_price' => $schedule->divingOffer->price * $data['participants'],
'status' => BookingStatus::Pending, 'status' => BookingStatus::Pending,
'notes' => $data['notes'] ?? null, 'notes' => $data['notes'] ?? null,
]); ]);
}); });
} catch (BookingRuleViolationException $e) { } catch (BookingRuleViolationException $e) {
@@ -99,13 +99,13 @@ class MemberBookingController extends Controller
$provider = $booking->schedule->divingOffer->provider; $provider = $booking->schedule->divingOffer->provider;
$provider->notify(new BookingCreatedNotification($booking)); $provider->notify(new BookingCreatedNotification($booking));
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error('BookingCreatedNotification failed: ' . $e->getMessage()); Log::error('BookingCreatedNotification failed: '.$e->getMessage());
} }
return response()->json([ return response()->json([
'status' => true, 'status' => true,
'message' => '預約已送出,等待教練確認', 'message' => '預約已送出,等待教練確認',
'data' => $this->formatBooking($booking->fresh(['schedule.divingOffer'])), 'data' => $this->formatBooking($booking->fresh(['schedule.divingOffer'])),
], 201); ], 201);
} }
@@ -117,13 +117,13 @@ class MemberBookingController extends Controller
} }
$canCancelFrom = [BookingStatus::Pending, BookingStatus::Confirmed]; $canCancelFrom = [BookingStatus::Pending, BookingStatus::Confirmed];
if (!in_array($booking->status, $canCancelFrom)) { if (! in_array($booking->status, $canCancelFrom)) {
return response()->json(['status' => false, 'message' => '此預約狀態無法取消'], 422); return response()->json(['status' => false, 'message' => '此預約狀態無法取消'], 422);
} }
// 24h 截止驗證 // 24h 截止驗證
$schedule = $booking->schedule; $schedule = $booking->schedule;
$courseStart = Carbon::parse($schedule->scheduled_date->toDateString() . ' ' . $schedule->start_time); $courseStart = Carbon::parse($schedule->scheduled_date->toDateString().' '.$schedule->start_time);
if (now()->diffInHours($courseStart, false) < 24) { if (now()->diffInHours($courseStart, false) < 24) {
return response()->json(['status' => false, 'message' => '距課程開始不足 24 小時,無法取消,請聯繫教練'], 422); return response()->json(['status' => false, 'message' => '距課程開始不足 24 小時,無法取消,請聯繫教練'], 422);
} }
@@ -149,7 +149,7 @@ class MemberBookingController extends Controller
$provider = $booking->schedule->divingOffer->provider; $provider = $booking->schedule->divingOffer->provider;
$provider->notify(new BookingCancelledNotification($booking, cancelledBy: 'member')); $provider->notify(new BookingCancelledNotification($booking, cancelledBy: 'member'));
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error('BookingCancelledNotification(member) failed: ' . $e->getMessage()); Log::error('BookingCancelledNotification(member) failed: '.$e->getMessage());
} }
return response()->json(['status' => true, 'message' => '預約已取消']); return response()->json(['status' => true, 'message' => '預約已取消']);
@@ -158,20 +158,21 @@ class MemberBookingController extends Controller
private function formatBooking(Booking $b): array private function formatBooking(Booking $b): array
{ {
$offer = $b->schedule?->divingOffer; $offer = $b->schedule?->divingOffer;
return [ return [
'id' => $b->id, 'id' => $b->id,
'offer_id' => $offer?->id, 'offer_id' => $offer?->id,
'offer_title' => $offer?->title, 'offer_title' => $offer?->title,
'offer_location' => $offer?->location, 'offer_location' => $offer?->location,
'offer_region' => $offer?->region, 'offer_region' => $offer?->region,
'offer_price' => $offer?->price, 'offer_price' => $offer?->price,
'scheduled_date' => $b->schedule?->scheduled_date?->toDateString(), 'scheduled_date' => $b->schedule?->scheduled_date?->toDateString(),
'start_time' => $b->schedule?->start_time, 'start_time' => $b->schedule?->start_time,
'participants' => $b->participants, 'participants' => $b->participants,
'total_price' => $b->total_price, 'total_price' => $b->total_price,
'status' => $b->status->value, 'status' => $b->status->value,
'notes' => $b->notes, 'notes' => $b->notes,
'created_at' => $b->created_at?->toISOString(), 'created_at' => $b->created_at?->toISOString(),
]; ];
} }
} }
@@ -21,10 +21,10 @@ class ProviderBookingController extends Controller
{ {
$provider = $request->user(); $provider = $request->user();
$bookings = Booking::with(['member', 'schedule.divingOffer']) $bookings = Booking::with(['member', 'schedule.divingOffer'])
->whereHas('schedule', fn($q) => $q->where('provider_id', $provider->id)) ->whereHas('schedule', fn ($q) => $q->where('provider_id', $provider->id))
->orderByDesc('created_at') ->orderByDesc('created_at')
->get() ->get()
->map(fn($b) => $this->formatBooking($b)); ->map(fn ($b) => $this->formatBooking($b));
return response()->json(['status' => true, 'data' => $bookings]); return response()->json(['status' => true, 'data' => $bookings]);
} }
@@ -34,7 +34,7 @@ class ProviderBookingController extends Controller
$booking = Booking::with('schedule')->findOrFail($id); $booking = Booking::with('schedule')->findOrFail($id);
$this->authorizeProvider($request, $booking); $this->authorizeProvider($request, $booking);
if (!$booking->canTransitionTo(BookingStatus::Confirmed)) { if (! $booking->canTransitionTo(BookingStatus::Confirmed)) {
return response()->json(['status' => false, 'message' => '當前狀態無法確認'], 422); return response()->json(['status' => false, 'message' => '當前狀態無法確認'], 422);
} }
@@ -63,7 +63,7 @@ class ProviderBookingController extends Controller
$booking->load('member'); $booking->load('member');
$booking->member->notify(new BookingConfirmedNotification($booking)); $booking->member->notify(new BookingConfirmedNotification($booking));
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error('BookingConfirmedNotification failed: ' . $e->getMessage()); Log::error('BookingConfirmedNotification failed: '.$e->getMessage());
} }
return response()->json(['status' => true, 'message' => '預約已確認', 'data' => $this->formatBooking($booking->fresh(['member', 'schedule.divingOffer']))]); return response()->json(['status' => true, 'message' => '預約已確認', 'data' => $this->formatBooking($booking->fresh(['member', 'schedule.divingOffer']))]);
@@ -74,7 +74,7 @@ class ProviderBookingController extends Controller
$booking = Booking::with('schedule')->findOrFail($id); $booking = Booking::with('schedule')->findOrFail($id);
$this->authorizeProvider($request, $booking); $this->authorizeProvider($request, $booking);
if (!$booking->canTransitionTo(BookingStatus::Rejected)) { if (! $booking->canTransitionTo(BookingStatus::Rejected)) {
return response()->json(['status' => false, 'message' => '當前狀態無法拒絕'], 422); return response()->json(['status' => false, 'message' => '當前狀態無法拒絕'], 422);
} }
@@ -84,7 +84,7 @@ class ProviderBookingController extends Controller
$booking->load('member'); $booking->load('member');
$booking->member->notify(new BookingRejectedNotification($booking)); $booking->member->notify(new BookingRejectedNotification($booking));
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error('BookingRejectedNotification failed: ' . $e->getMessage()); Log::error('BookingRejectedNotification failed: '.$e->getMessage());
} }
return response()->json(['status' => true, 'message' => '預約已拒絕']); return response()->json(['status' => true, 'message' => '預約已拒絕']);
@@ -95,7 +95,7 @@ class ProviderBookingController extends Controller
$booking = Booking::with('schedule')->findOrFail($id); $booking = Booking::with('schedule')->findOrFail($id);
$this->authorizeProvider($request, $booking); $this->authorizeProvider($request, $booking);
if (!$booking->canTransitionTo(BookingStatus::ProviderCancelled)) { if (! $booking->canTransitionTo(BookingStatus::ProviderCancelled)) {
return response()->json(['status' => false, 'message' => '當前狀態無法取消'], 422); return response()->json(['status' => false, 'message' => '當前狀態無法取消'], 422);
} }
@@ -115,7 +115,7 @@ class ProviderBookingController extends Controller
$booking->load('member'); $booking->load('member');
$booking->member->notify(new BookingCancelledNotification($booking, cancelledBy: 'provider')); $booking->member->notify(new BookingCancelledNotification($booking, cancelledBy: 'provider'));
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error('BookingCancelledNotification(provider) failed: ' . $e->getMessage()); Log::error('BookingCancelledNotification(provider) failed: '.$e->getMessage());
} }
return response()->json(['status' => true, 'message' => '預約已取消']); return response()->json(['status' => true, 'message' => '預約已取消']);
@@ -126,7 +126,7 @@ class ProviderBookingController extends Controller
$booking = Booking::with('schedule')->findOrFail($id); $booking = Booking::with('schedule')->findOrFail($id);
$this->authorizeProvider($request, $booking); $this->authorizeProvider($request, $booking);
if (!$booking->canTransitionTo(BookingStatus::Completed)) { if (! $booking->canTransitionTo(BookingStatus::Completed)) {
return response()->json(['status' => false, 'message' => '只有已確認的預約才能標記完成'], 422); return response()->json(['status' => false, 'message' => '只有已確認的預約才能標記完成'], 422);
} }
@@ -136,7 +136,7 @@ class ProviderBookingController extends Controller
$booking->load('member'); $booking->load('member');
$booking->member->notify(new BookingCompletedNotification($booking)); $booking->member->notify(new BookingCompletedNotification($booking));
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error('BookingCompletedNotification failed: ' . $e->getMessage()); Log::error('BookingCompletedNotification failed: '.$e->getMessage());
} }
return response()->json(['status' => true, 'message' => '預約已標記為完成']); return response()->json(['status' => true, 'message' => '預約已標記為完成']);
@@ -152,17 +152,17 @@ class ProviderBookingController extends Controller
private function formatBooking(Booking $b): array private function formatBooking(Booking $b): array
{ {
return [ return [
'id' => $b->id, 'id' => $b->id,
'member_name' => $b->member?->name, 'member_name' => $b->member?->name,
'member_email' => $b->member?->email, 'member_email' => $b->member?->email,
'offer_title' => $b->schedule?->divingOffer?->title, 'offer_title' => $b->schedule?->divingOffer?->title,
'scheduled_date' => $b->schedule?->scheduled_date?->toDateString(), 'scheduled_date' => $b->schedule?->scheduled_date?->toDateString(),
'start_time' => $b->schedule?->start_time, 'start_time' => $b->schedule?->start_time,
'participants' => $b->participants, 'participants' => $b->participants,
'total_price' => $b->total_price, 'total_price' => $b->total_price,
'status' => $b->status->value, 'status' => $b->status->value,
'notes' => $b->notes, 'notes' => $b->notes,
'created_at' => $b->created_at?->toISOString(), 'created_at' => $b->created_at?->toISOString(),
]; ];
} }
} }