'datetime', 'end_at' => 'datetime', 'lat' => 'float', 'lng' => 'float', 'gallery_media' => 'array', 'tags' => 'array', 'sort' => 'integer', 'is_active' => 'boolean', 'total_quota' => 'integer', 'min_people_per_order' => 'integer', 'max_people_per_order' => 'integer', ]; public function venue(): BelongsTo { return $this->belongsTo(Venue::class); } public function reservations(): HasMany { return $this->hasMany(Reservation::class); } public function activityDays(): HasMany { return $this->hasMany(ActivityDay::class)->orderBy('activity_date'); } /** * H5 活动列表/热门:未结束优先(按开始日期升序,空开始日置后);已结束置底(按结束日期降序)。 */ public function scopeOrderForH5Listing(Builder $query): Builder { $today = now()->startOfDay(); return $query ->orderByRaw('CASE WHEN end_at IS NOT NULL AND end_at < ? THEN 1 ELSE 0 END ASC', [$today]) ->orderByRaw('CASE WHEN end_at IS NOT NULL AND end_at < ? THEN end_at END DESC', [$today]) ->orderByRaw('CASE WHEN (end_at IS NULL OR end_at >= ?) AND start_at IS NULL THEN 1 ELSE 0 END ASC', [$today]) ->orderByRaw('CASE WHEN end_at IS NULL OR end_at >= ? THEN start_at END ASC', [$today]) ->orderByDesc('id'); } /** * 按未取消预约的票数合计,回写 activities.registered_count(展示用「已预约总人数」)。 */ public static function refreshRegisteredCountFromReservations(int $activityId): void { $total = (int) Reservation::query() ->where('activity_id', $activityId) ->where('status', '!=', 'cancelled') ->get() ->sum(fn (Reservation $r) => max(1, (int) ($r->ticket_count ?? 1))); static::query()->where('id', $activityId)->update(['registered_count' => $total]); } }