feat(offers): 補齊 provider-verification 可見性缺口——子端點過濾與預約入口檢查
Run Tests / test (pull_request) Successful in 1m56s
Run Tests / test (pull_request) Successful in 1m56s
實作 openspec change provider-verification-gaps(8/8 tasks): - schedules/reviews publicList 套用 visibleToPublic,隱藏課程回 404 - MemberBookingController::store Layer 1 擋未驗證教練課程的新預約(422) - 政策:教練被取消驗證只擋新預約,既有 pending/confirmed/completed 照常 - 主規格 Notes 已知限制轉為正式 Requirements - 測試 +5(可見性子端點 3、預約入口 2),既有 booking/review 測試 helper 補 verified ProviderProfile - 容器內全套件 151 passed / 388 assertions;另以 demo 資料端到端驗證 (已驗證教練 200/200/200、未驗證 404/404/404) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -45,9 +45,14 @@ class MemberBookingController extends Controller
|
||||
'notes' => 'nullable|string|max:500',
|
||||
]);
|
||||
|
||||
$schedule = CourseSchedule::with('divingOffer')->findOrFail($data['schedule_id']);
|
||||
$schedule = CourseSchedule::with('divingOffer.provider.providerProfile')->findOrFail($data['schedule_id']);
|
||||
|
||||
// Layer 1:快速失敗
|
||||
// 可見性繞過防護:課程屬未驗證教練時不可建立新預約(既有預約不受影響,見 provider-verification 規格)
|
||||
$offer = $schedule->divingOffer;
|
||||
if ($offer->provider_id !== null && !($offer->provider?->providerProfile?->is_verified)) {
|
||||
return response()->json(['status' => false, 'message' => '此課程目前不開放預約'], 422);
|
||||
}
|
||||
if ($schedule->status !== ScheduleStatus::Open) {
|
||||
return response()->json(['status' => false, 'message' => '此時段不開放預約'], 422);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class ReviewController extends Controller
|
||||
|
||||
public function publicList(Request $request, int $offerId)
|
||||
{
|
||||
$offer = DivingOffer::findOrFail($offerId);
|
||||
$offer = DivingOffer::visibleToPublic()->findOrFail($offerId);
|
||||
$user = $request->user();
|
||||
$perPage = min((int) $request->query('per_page', 20), 50);
|
||||
$sort = $request->query('sort', 'helpful');
|
||||
|
||||
@@ -95,7 +95,7 @@ class ScheduleController extends Controller
|
||||
|
||||
public function publicList(int $offerId)
|
||||
{
|
||||
$offer = DivingOffer::findOrFail($offerId);
|
||||
$offer = DivingOffer::visibleToPublic()->findOrFail($offerId);
|
||||
$schedules = CourseSchedule::where('diving_offer_id', $offer->id)
|
||||
->where('status', ScheduleStatus::Open->value)
|
||||
->whereDate('scheduled_date', '>=', now()->toDateString())
|
||||
|
||||
Reference in New Issue
Block a user