option('from'); $end = (string) $this->option('to'); $out = (string) ($this->option('output') ?: storage_path( 'app/export_venues_activities_'.str_replace('-', '', $start).'_'.str_replace('-', '', $end).'.xlsx' )); $regPeople = "SUM(CASE WHEN reservations.status <> 'cancelled' THEN COALESCE(reservations.ticket_count, 1) ELSE 0 END)"; $regOrders = "SUM(CASE WHEN reservations.status <> 'cancelled' THEN 1 ELSE 0 END)"; $cancelOrders = "SUM(CASE WHEN reservations.status = 'cancelled' THEN 1 ELSE 0 END)"; $cancelPeople = "SUM(CASE WHEN reservations.status = 'cancelled' THEN COALESCE(reservations.ticket_count, 1) ELSE 0 END)"; $verifiedPeople = "SUM(CASE WHEN reservations.status = 'verified' THEN COALESCE(reservations.ticket_count, 1) ELSE 0 END)"; $pendingPeople = "SUM(CASE WHEN reservations.status = 'pending' THEN COALESCE(reservations.ticket_count, 1) ELSE 0 END)"; $expiredPeople = "SUM(CASE WHEN reservations.status = 'expired' THEN COALESCE(reservations.ticket_count, 1) ELSE 0 END)"; $baseJoin = function ($q) { $q->join('activities', function ($j) { $j->on('activities.id', '=', 'activity_days.activity_id')->whereNull('activities.deleted_at'); }) ->join('venues', 'venues.id', '=', 'activities.venue_id') ->join('reservations', function ($j) { $j->on('reservations.activity_day_id', '=', 'activity_days.id') ->whereNull('reservations.deleted_at') ->where(function ($qq) { $qq->whereNull('reservations.reservation_kind') ->orWhere('reservations.reservation_kind', 'activity'); }); }); }; $venueRows = ActivityDay::query() ->select([ 'venues.id as venue_id', 'venues.name as venue_name', DB::raw("GROUP_CONCAT(DISTINCT DATE_FORMAT(activity_days.activity_date, '%Y-%m-%d') ORDER BY activity_days.activity_date SEPARATOR ', ') as activity_dates"), DB::raw('COUNT(DISTINCT activities.id) as activity_count'), DB::raw('COUNT(DISTINCT activity_days.id) as session_count'), DB::raw("{$regOrders} as registration_orders"), DB::raw("{$regPeople} as registration_people"), DB::raw("{$cancelOrders} as cancelled_orders"), DB::raw("{$cancelPeople} as cancelled_people"), DB::raw("{$verifiedPeople} as verified_people"), ]) ->tap($baseJoin) ->whereBetween('activity_days.activity_date', [$start, $end]) ->groupBy('venues.id', 'venues.name') ->havingRaw("{$regOrders} > 0 OR {$cancelOrders} > 0") ->orderBy('venues.name') ->get(); $sessionRows = ActivityDay::query() ->select([ 'venues.id as venue_id', 'venues.name as venue_name', 'activities.id as activity_id', 'activities.title as activity_title', 'activity_days.id as activity_day_id', 'activity_days.session_name', 'activity_days.activity_date', 'activity_days.session_start_at', 'activity_days.session_end_at', 'activity_days.day_quota', 'activity_days.booked_count', DB::raw("{$regOrders} as registration_orders"), DB::raw("{$regPeople} as registration_people"), DB::raw("{$cancelOrders} as cancelled_orders"), DB::raw("{$cancelPeople} as cancelled_people"), DB::raw("{$verifiedPeople} as verified_people"), DB::raw("{$pendingPeople} as pending_people"), DB::raw("{$expiredPeople} as expired_people"), ]) ->tap($baseJoin) ->whereBetween('activity_days.activity_date', [$start, $end]) ->groupBy( 'venues.id', 'venues.name', 'activities.id', 'activities.title', 'activity_days.id', 'activity_days.session_name', 'activity_days.activity_date', 'activity_days.session_start_at', 'activity_days.session_end_at', 'activity_days.day_quota', 'activity_days.booked_count' ) ->havingRaw("{$regOrders} > 0 OR {$cancelOrders} > 0") ->orderBy('venues.name') ->orderBy('activity_days.activity_date') ->orderBy('activity_days.session_start_at') ->orderBy('activities.id') ->get(); $spreadsheet = new Spreadsheet; $sheet1 = $spreadsheet->getActiveSheet(); $sheet1->setTitle('场馆汇总'); $sheet1Data = [['场馆ID', '场馆名称', '活动日期', '活动数量', '场次数量', '报名人数', '报名总人数', '已取消数', '已取消人数', '到场人数(已核销)']]; foreach ($venueRows as $r) { $sheet1Data[] = [ $r->venue_id, $r->venue_name, $r->activity_dates, (int) $r->activity_count, (int) $r->session_count, (int) $r->registration_orders, (int) $r->registration_people, (int) $r->cancelled_orders, (int) $r->cancelled_people, (int) $r->verified_people, ]; } $sheet1->fromArray($sheet1Data, null, 'A1'); $sheet2 = $spreadsheet->createSheet(); $sheet2->setTitle('场次信息'); $sheet2Data = [['场馆ID', '场馆名称', '活动ID', '活动名称', '场次ID', '场次名称', '活动日期', '场次开始时间', '场次结束时间', '场次名额', '已占用名额', '报名人数', '报名总人数', '已取消数', '已取消人数', '已核销人数', '待核销人数', '已过期人数']]; foreach ($sessionRows as $r) { $sheet2Data[] = [ $r->venue_id, $r->venue_name, $r->activity_id, $r->activity_title, $r->activity_day_id, $r->session_name, $r->activity_date ? (string) $r->activity_date : '', $r->session_start_at ? (string) $r->session_start_at : '', $r->session_end_at ? (string) $r->session_end_at : '', $r->day_quota, $r->booked_count, (int) $r->registration_orders, (int) $r->registration_people, (int) $r->cancelled_orders, (int) $r->cancelled_people, (int) $r->verified_people, (int) $r->pending_people, (int) $r->expired_people, ]; } $sheet2->fromArray($sheet2Data, null, 'A1'); $dir = dirname($out); if (! is_dir($dir)) { mkdir($dir, 0755, true); } (new Xlsx($spreadsheet))->save($out); $this->info("场馆汇总:{$venueRows->count()} 行"); $this->info("场次信息:{$sessionRows->count()} 行"); $this->info("Excel 已生成:{$out}"); return self::SUCCESS; } }