count(); // 员工总数 $employeesCount = Employee::onlyOnline()->count(); return [ 'stores_count' => $storesCount, 'employees_count' => $employeesCount, ]; } /** * 销售趋势 */ public function salesTrend(Request $request): array { $request->validate( rules: [ 'last' => ['bail', 'required', Rule::in(['7days', '30days', '180days', '365days'])], ], ); $last = $request->input('last'); $data = collect(); if (in_array($last, ['7days', '30days'])) { // 按天 $days = match ($last) { '7days' => 7, '30days' => 30, }; // 今天 $today = Carbon::today(); // 开始时间 $startAt = $today->copy()->subDays($days); // 结束时间 $endAt = $today->copy()->subDay(); $ledgers = Ledger::select(['date', DB::raw('SUM(sales) as sales')]) ->whereBetween('date', [$startAt->toDateString(), $endAt->toDateString()]) ->groupBy('date') ->get() ->keyBy('date'); while ($startAt->lte($endAt)) { $date = $startAt->toDateString(); $ledger = $ledgers->get($date); $data->push([ 'date' => $date, 'sales' => trim_zeros($ledger->sales ?? 0), ]); $startAt->addDay(); } } elseif (in_array($last, ['180days', '365days'])) { // 按月 $months = match ($last) { '180days' => 6, // 6个月 '365days' => 12, // 12个月 }; // 今天 $today = Carbon::today(); // 开始时间 $startAt = $today->copy()->startOfMonth()->subMonths($months); // 结束时间 $endAt = $today->copy()->startOfMonth()->subMonth()->endOfMonth(); $ledgers = Ledger::select([DB::raw("DATE_FORMAT(`date`, '%Y-%m') as month"), DB::raw('SUM(sales) as sales')]) ->whereBetween('date', [$startAt->toDateString(), $endAt->toDateString()]) ->groupBy('month') ->get() ->keyBy('month'); for ($i=0; $i < $months; $i++) { $month = $startAt->format('Y-m'); $ledger = $ledgers->get($month); $data->push([ 'month' => $month, 'sales' => trim_zeros($ledger->sales ?? 0), ]); $startAt->addMonth(); } } return $data->all(); } /** * 彩种销售趋势 */ public function lotterySalesTrend(Request $request): array { $request->validate( rules: [ 'last' => ['bail', 'required', Rule::in(['7days', '30days', '180days', '365days'])], ], ); $last = $request->input('last'); $data = collect(); /** @var \Illuminate\Database\Eloquent\Collection */ $lotteryTypes = Keyword::where('parent_key', 'lottery_type')->get(); if (in_array($last, ['7days', '30days'])) { // 按天 $days = match ($last) { '7days' => 7, '30days' => 30, }; // 今天 $today = Carbon::today(); // 开始时间 $startAt = $today->copy()->subDays($days); // 结束时间 $endAt = $today->copy()->subDay(); /** @var \Illuminate\Support\Collection */ $lotteryTypeLedgers = LedgerItem::select([ 'date', 'ledger_item_type_id', DB::raw('SUM(sales) as sales'), ]) ->whereBetween('date', [$startAt->toDateString(), $endAt->toDateString()]) ->groupBy(['date', 'ledger_item_type_id']) ->get() ->groupBy('date'); while ($startAt->lte($endAt)) { $date = $startAt->toDateString(); $lotteryTypeLedgerItems = $lotteryTypeLedgers->get($date, collect())->keyBy('ledger_item_type_id'); $data->push([ 'date' => $date, 'data' => $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeLedgerItems) { $lotteryTypeLedgerItem = $lotteryTypeLedgerItems->get($lotteryType->key); return [ 'id' => $lotteryType->key, 'name' => $lotteryType->name, 'sales' => trim_zeros($lotteryTypeLedgerItem->sales ?? 0), ]; }), ]); $startAt->addDay(); } } elseif (in_array($last, ['180days', '365days'])) { // 按月 $months = match ($last) { '180days' => 6, // 6个月 '365days' => 12, // 12个月 }; // 今天 $today = Carbon::today(); // 开始时间 $startAt = $today->copy()->startOfMonth()->subMonths($months); // 结束时间 $endAt = $today->copy()->startOfMonth()->subMonth()->endOfMonth(); /** @var \Illuminate\Support\Collection */ $lotteryTypeLedgers = LedgerItem::select([ DB::raw("DATE_FORMAT(`date`, '%Y-%m') as month"), 'ledger_item_type_id', DB::raw('SUM(sales) as sales'), ]) ->whereBetween('date', [$startAt->toDateString(), $endAt->toDateString()]) ->groupBy(['month', 'ledger_item_type_id']) ->get() ->keyBy('month'); for ($i=0; $i < $months; $i++) { $month = $startAt->format('Y-m'); $lotteryTypeLedgerItems = $lotteryTypeLedgers->get($month, collect())->keyBy('ledger_item_type_id'); $data->push([ 'month' => $month, 'data' => $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeLedgerItems) { $lotteryTypeLedgerItem = $lotteryTypeLedgerItems->get($lotteryType->key); return [ 'id' => $lotteryType->key, 'name' => $lotteryType->name, 'sales' => trim_zeros($lotteryTypeLedgerItem->sales ?? 0), ]; }), ]); $startAt->addMonth(); } } return [ 'lottery_types' => $lotteryTypes->map(function ($lotteryType) { return [ 'id' => $lotteryType->id, 'name' => $lotteryType->name, ]; }), 'data' => $data->all(), ]; } /** * 门店销量排名 */ public function storeSalesRanking(Request $request): array { $request->validate( rules: [ 'last' => ['bail', 'required', Rule::in(['7days', '30days', '180days', '365days'])], ], ); $last = $request->input('last'); $storeSales = Ledger::select(['store_id', DB::raw('SUM(sales) as sales')]) ->when($last, function ($query, $last) { $today = Carbon::today(); if (in_array($last, ['7days', '30days'])) { $days = match ($last) { '7days' => 7, '30days' => 30, }; $query->whereBetween('date', [ $today->copy()->subDays($days)->toDateString(), $today->copy()->subDay()->toDateString(), ]); } elseif (in_array($last, ['180days', '365days'])) { $months = match ($last) { '180days' => 6, // 6个月 '365days' => 12, // 12个月 }; $query->whereBetween('date', [ $today->copy()->startOfMonth()->subMonths($months)->toDateString(), $today->copy()->startOfMonth()->subMonth()->endOfMonth()->toDateString(), ]); } }) ->groupBy('store_id'); $stores = Store::leftJoinSub($storeSales, 'store_sales', fn ($join) => $join->on('stores.id', '=', 'store_sales.store_id')) ->orderBy('store_sales.sales', 'DESC') ->limit(30) ->get(); return $stores->map(function (Store $store) { return [ 'store' => [ 'id' => $store->id, 'title' => $store->title, ], 'sales' => trim_zeros($store->sales ?: 0), ]; })->all(); } /** * 年度目标 */ public function yearlyGoals(Request $request): array { $request->validate( rules: [ 'year' => ['bail', 'required', 'int'], ], ); $aggregates = TaskPerformance::select([ DB::raw('SUM(`expected_performance`) as expected_performance'), DB::raw('SUM(`actual_performance`) as actual_performance'), ])->whereYear(DB::raw("STR_TO_DATE(CONCAT(`month`, '-01'), '%Y-%m-%d')"), $request->input('year'))->first(); return [ // 目标业绩 'expected_performance' => trim_zeros($aggregates['expected_performance'] ?? 0), // 实际业绩 'actual_performance' => trim_zeros($aggregates['actual_performance'] ?? 0), ]; } }