From 4c46ab7277d5db066aa5683ddbc0e72c7e983209 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 12:27:07 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E9=97=A8=E5=BA=97=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Finance/StoreStatisticController.php | 41 ++++------------- app/Admin/Filters/LedgerFilter.php | 10 +++++ .../Controllers/Api/StatisticsController.php | 27 ++++-------- app/Services/StatisticService.php | 44 +++++++++++++++++++ 4 files changed, 71 insertions(+), 51 deletions(-) create mode 100644 app/Services/StatisticService.php diff --git a/app/Admin/Controllers/Finance/StoreStatisticController.php b/app/Admin/Controllers/Finance/StoreStatisticController.php index d6ed2ad..94b46a0 100644 --- a/app/Admin/Controllers/Finance/StoreStatisticController.php +++ b/app/Admin/Controllers/Finance/StoreStatisticController.php @@ -3,20 +3,22 @@ namespace App\Admin\Controllers\Finance; use App\Admin\Controllers\AdminController; -use App\Admin\Filters\LedgerFilter; -use App\Admin\Filters\StoreFilter; -use App\Models\Ledger; -use App\Models\Store; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; +use App\Services\StatisticService; class StoreStatisticController extends AdminController { public function index() { if ($this->actionOfGetData()) { + $input = request()->input(); + + $sorts = [ + [request()->input('orderBy') ?: 'sales', request()->input('orderDir') ?: 'desc'], + ['id', 'asc'], + ]; + return $this->response()->success([ - 'items' => $this->getStoreStatistics(request()), + 'items' => (new StatisticService())->stores($input, $sorts), ]); } @@ -47,29 +49,4 @@ class StoreStatisticController extends AdminController ) ); } - - protected function getStoreStatistics(Request $request): array - { - /** @var \Illuminate\Database\Eloquent\Collection */ - $stats = Ledger::with(['store']) - ->select(['store_id', DB::raw('SUM(sales) as sales'), DB::raw('SUM(expenditure) as expenditure')]) - ->filter($request->input(), LedgerFilter::class) - ->groupBy('store_id') - ->get(); - - // 排序规则 - $sortBy = [ - [$request->input('orderBy') ?: 'sales', $request->input('orderDir') ?: 'desc'], - ]; - - return $stats->map(fn ($item) => [ - 'title' => $item->store->title, - 'sales' => trim_zeros($item->sales ?? '0'), - 'expenditure' => trim_zeros($item->expenditure ?? '0'), - ]) - ->sortBy($sortBy) - ->values() - ->map(fn ($item, $key) => array_merge($item, ['ranking' => $key + 1])) - ->all(); - } } diff --git a/app/Admin/Filters/LedgerFilter.php b/app/Admin/Filters/LedgerFilter.php index 4b51b74..8f34a74 100644 --- a/app/Admin/Filters/LedgerFilter.php +++ b/app/Admin/Filters/LedgerFilter.php @@ -44,4 +44,14 @@ class LedgerFilter extends ModelFilter $query->whereIn('check_status', explode(',', $checkStatus)); }); } + + public function startAt($startAt) + { + $this->where('date', '>=', $startAt); + } + + public function endAt($endAt) + { + $this->where('date', '<=', $endAt); + } } diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index f68da6e..2ab7562 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -3,13 +3,10 @@ namespace App\Http\Controllers\Api; use App\Admin\Filters\LedgerFilter; -use App\Admin\Filters\StoreFilter; -use App\Http\Resources\StoreResource; use App\Models\Ledger; -use App\Models\Store; +use App\Services\StatisticService; use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; -use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; @@ -73,7 +70,7 @@ class StatisticsController extends Controller /** * 门店统计 */ - public function stores(Request $request) + public function stores(Request $request, StatisticService $statisticService) { $request->validate( rules: [ @@ -86,22 +83,14 @@ class StatisticsController extends Controller ], ); - $storeLedgerStats = Ledger::select(['store_id', DB::raw('SUM(sales) as sales')]) - ->whereBetween('date', [$request->input('start_at'), $request->input('end_at')]) - ->groupBy('store_id'); + $input = array_merge( + $this->defaultFilterInput($request), + $request->only(['start_at', 'end_at']), + ); - $stores = Store::filter($this->defaultFilterInput($request), StoreFilter::class) - ->leftJoinSub($storeLedgerStats, 'store_ledger_stats', fn ($join) => $join->on('stores.id', '=', 'store_ledger_stats.store_id')) - ->orderBy('sales', 'desc') - ->orderBy('id', 'asc') - ->get(); + $sorts = [['sales', 'desc'], ['id', 'asc']]; - return $stores->map(function (Store $store) { - return [ - 'store' => StoreResource::make($store), - 'sales' => trim_zeros($store->sales ?: 0), - ]; - }); + return $statisticService->stores($input, $sorts); } /** diff --git a/app/Services/StatisticService.php b/app/Services/StatisticService.php new file mode 100644 index 0000000..734c7c3 --- /dev/null +++ b/app/Services/StatisticService.php @@ -0,0 +1,44 @@ +filter(Arr::only($input, ['date_range', 'start_at', 'end_at']), LedgerFilter::class) + ->groupBy('store_id'); + + $stores = Store::filter(Arr::only($input, ['store_id', 'region']), StoreFilter::class) + ->leftJoinSub($storeLedgerStats, 'store_ledger_stats', fn ($join) => $join->on('stores.id', '=', 'store_ledger_stats.store_id')) + ->when($sorts, function ($query, $sorts) { + foreach ($sorts as $sort) { + $query->orderBy($sort[0], $sort[1]); + } + }) + ->get(); + + return $stores->map(function (Store $store, $key) { + return [ + 'ranking' => $key + 1, + 'store' => [ + 'id' => $store->id, + 'title' => $store->title, + ], + 'sales' => trim_zeros($store->sales ?: 0), + 'expenditure' => trim_zeros($store->expenditure ?: 0), + ]; + })->all(); + } +} From 8d4e1e6d2c77bbf8416b01403f18bf3e0d1356e1 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 12:28:36 +0800 Subject: [PATCH 2/9] Fix --- app/Admin/Controllers/Finance/StoreStatisticController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Admin/Controllers/Finance/StoreStatisticController.php b/app/Admin/Controllers/Finance/StoreStatisticController.php index 94b46a0..306245d 100644 --- a/app/Admin/Controllers/Finance/StoreStatisticController.php +++ b/app/Admin/Controllers/Finance/StoreStatisticController.php @@ -42,7 +42,7 @@ class StoreStatisticController extends AdminController ])) ->columns([ amis()->TableColumn('ranking', '排序'), - amis()->TableColumn('title', '门店'), + amis()->TableColumn('store.title', '门店'), amis()->TableColumn('sales', '收入')->sortable(), amis()->TableColumn('expenditure', '支出')->sortable(), ]) From 170267740ac3cff5bf6d87779d247c67bfddcfd4 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 13:28:29 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E9=94=80=E5=94=AE=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Admin/Filters/LedgerItemFilter.php | 9 +- .../Controllers/Api/StatisticsController.php | 97 +++++++++++++++++++ app/Models/LedgerItem.php | 1 - routes/api.php | 4 +- 4 files changed, 106 insertions(+), 5 deletions(-) diff --git a/app/Admin/Filters/LedgerItemFilter.php b/app/Admin/Filters/LedgerItemFilter.php index 1afb388..2825a3b 100644 --- a/app/Admin/Filters/LedgerItemFilter.php +++ b/app/Admin/Filters/LedgerItemFilter.php @@ -18,9 +18,12 @@ class LedgerItemFilter extends ModelFilter return; } - $provinceCode = Arr::get($region, 'provinceCode'); - $cityCode = Arr::get($region, 'cityCode'); - if (empty($provinceCode) && empty($cityCode)) { + // 区划代码 - 省份 + $provinceCode = (string) Arr::get($region, 'provinceCode'); + // 区划代码 - 城市 + $cityCode = (string) Arr::get($region, 'cityCode'); + + if ($provinceCode === '' && $cityCode === '') { return; } diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index 2ab7562..b7853b1 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -3,7 +3,10 @@ namespace App\Http\Controllers\Api; use App\Admin\Filters\LedgerFilter; +use App\Admin\Filters\LedgerItemFilter; +use App\Models\Keyword; use App\Models\Ledger; +use App\Models\LedgerItem; use App\Services\StatisticService; use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; @@ -93,6 +96,100 @@ class StatisticsController extends Controller return $statisticService->stores($input, $sorts); } + /** + * 销售统计 + */ + public function sales(Request $request): array + { + $request->validate( + rules: [ + 'start_at' => ['bail', 'required', 'date_format:Y-m-d'], + 'end_at' => ['bail', 'required', 'date_format:Y-m-d'], + ], + attributes: [ + 'start_at' => '开始日期', + 'end_at' => '结束日期', + ], + ); + + // 开始日期 + $startAt = Carbon::parse($request->input('start_at')); + // 结束日期 + $endAt = Carbon::parse($request->input('end_at')); + + $input = $this->defaultFilterInput($request); + + /** @var \Illuminate\Database\Eloquent\Collection */ + $lotteryTypes = Keyword::where('parent_key', 'lottery_type')->get(); + + /** @var \Illuminate\Support\Collection */ + $ledgerStatistics = Ledger::select([ + 'date', + DB::raw('SUM(new_customers) as new_customers'), + DB::raw('SUM(sales) as sales'), + DB::raw('SUM(expenditure) as expenditure') + ]) + ->filter($input, LedgerFilter::class) + ->whereBetween('date', [$startAt->format('Y-m-d'), $endAt->format('Y-m-d')]) + ->groupBy(['date']) + ->get() + ->keyBy('date'); + + /** @var \Illuminate\Support\Collection */ + $ledgerItemStatistics = LedgerItem::select([ + 'date', + 'ledger_item_type_id', + DB::raw('SUM(sales) as sales'), + DB::raw('SUM(expenditure) as expenditure'), + ]) + ->filter($input, LedgerItemFilter::class) + ->whereIn('ledger_item_type_id', $lotteryTypes->pluck('key')) + ->whereBetween('date', [$startAt->format('Y-m-d'), $endAt->format('Y-m-d')]) + ->groupBy(['date', 'ledger_item_type_id']) + ->get() + ->groupBy('date'); + + $data = collect(); + $date = $endAt->copy(); + + while ($date->gte($startAt)) { + $_date = $date->format('Y-m-d'); + $ledgerStatistic = $ledgerStatistics->get($_date); + /** @var \Illuminate\Support\Collection */ + $lotteryTypeStatistics = $ledgerItemStatistics->get($_date, collect())->keyBy('ledger_item_type_id'); + + $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeStatistics) { + $lotteryTypeStatistic = $lotteryTypeStatistics->get($lotteryType->key); + return [ + 'name' => $lotteryType->name, + 'sales' => trim_zeros($lotteryTypeStatistic->sales ?? 0), + 'expenditure' => trim_zeros($lotteryTypeStatistic->expenditure ?? 0), + ]; + }); + + $data->push([ + 'date' => $_date, + 'ledger' => [ + 'new_customers' => $ledgerStatistic->new_customers ?? 0, + 'sales' => trim_zeros($ledgerStatistic->sales ?? 0), + 'expenditure' => trim_zeros($ledgerStatistic->expenditure ?? 0), + ], + 'lottery_types' => $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeStatistics) { + $lotteryTypeStatistic = $lotteryTypeStatistics->get($lotteryType->key); + return [ + 'name' => $lotteryType->name, + 'sales' => trim_zeros($lotteryTypeStatistic->sales ?? 0), + 'expenditure' => trim_zeros($lotteryTypeStatistic->expenditure ?? 0), + ]; + }), + ]); + + $date->subDay(); + } + + return $data->all(); + } + /** * 准备趋势数据 */ diff --git a/app/Models/LedgerItem.php b/app/Models/LedgerItem.php index d00de50..fdb5dfd 100644 --- a/app/Models/LedgerItem.php +++ b/app/Models/LedgerItem.php @@ -13,7 +13,6 @@ class LedgerItem extends Model use Filterable, HasDateTimeFormatter, HasFactory; protected $casts = [ - 'date' => 'date', 'approved' => 'bool', ]; diff --git a/routes/api.php b/routes/api.php index 31b262d..62764cf 100644 --- a/routes/api.php +++ b/routes/api.php @@ -39,6 +39,8 @@ Route::group([ Route::get('/statistics/dashboard', [StatisticsController::class, 'dashboard']); // 统计数据 - 门店统计 Route::get('/statistics/stores', [StatisticsController::class, 'stores']); + // 统计数据 - 销售统计 + Route::get('/statistics/sales', [StatisticsController::class, 'sales']); // 数据上报 Route::apiResource('/ledgers', LedgerController::class)->only(['store', 'show']); @@ -67,7 +69,7 @@ Route::group([ // 报销管理 Route::apiResource('reimbursements', \App\Http\Controllers\Api\ReimbursementController::class); - + // 审核流程 Route::get('workflow', [\App\Http\Controllers\Api\WorkflowController::class, 'index']); Route::get('workflow/{id}', [\App\Http\Controllers\Api\WorkflowController::class, 'show']); From e94c349a3e67bf309d31259cf038ccb7b9325904 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 14:43:06 +0800 Subject: [PATCH 4/9] Update --- .../Controllers/Api/StatisticsController.php | 49 ++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index b7853b1..8cb454c 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -43,14 +43,31 @@ class StatisticsController extends Controller //-------------------------------------------------------------------------- // 近 30 天趋势数据 //-------------------------------------------------------------------------- - $start = $yesterday->copy()->subDays(29); - $end = $yesterday->copy(); + $startAt = $yesterday->copy()->subDays(29); + $endAt = $yesterday->copy(); + /** @var \Illuminate\Database\Eloquent\Collection */ $ledgers30days = (clone $query) - ->whereBetween('date', [$start, $end]) + ->whereBetween('date', [$startAt, $endAt]) ->get(['date', 'sales', 'expenditure']) ->keyBy('date'); + $trend = collect(); + + while ($startAt->lte($endAt)) { + $ledger = $ledgers30days->get( + $date = $startAt->format('Y-m-d') + ); + + $trend->push([ + 'date' => $date, + 'sales' => trim_zeros($ledger->sales ?? 0), + 'expenditure' => trim_zeros($ledger->expenditure ?? 0), + ]); + + $startAt->addDay(); + } + return [ // 本月总账录入 'current_month_ledger' => [ @@ -66,7 +83,7 @@ class StatisticsController extends Controller 'expenditure' => trim_zeros($yesterdayLedger->expenditure ?? 0), ], // 近30天趋势数据 - 'trend_data_of_30days' => $this->prepareTrendData($start->copy(), $end->copy(), $ledgers30days), + 'trend_data_of_30days' => $trend, ]; } @@ -190,30 +207,6 @@ class StatisticsController extends Controller return $data->all(); } - /** - * 准备趋势数据 - */ - protected function prepareTrendData(Carbon $start, Carbon $end, Collection $ledgers): array - { - $data = collect(); - - do { - $ledger = $ledgers->get( - $date = $start->format('Y-m-d') - ); - - $data->push([ - 'date' => $date, - 'sales' => trim_zeros($ledger->sales ?? 0), - 'expenditure' => trim_zeros($ledger->expenditure ?? 0), - ]); - - $start->addDay(); - } while ($start->lte($end)); - - return $data->all(); - } - /** * 处理区域和门店过滤条件 */ From 9878a1fc5c25bf6c69ee292b83137b1de1e95b5a Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 15:05:32 +0800 Subject: [PATCH 5/9] Update --- .../Controllers/Api/StatisticsController.php | 121 ++---------------- app/Services/StatisticService.php | 109 ++++++++++++++++ 2 files changed, 119 insertions(+), 111 deletions(-) diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index 8cb454c..844176c 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -3,12 +3,8 @@ namespace App\Http\Controllers\Api; use App\Admin\Filters\LedgerFilter; -use App\Admin\Filters\LedgerItemFilter; -use App\Models\Keyword; use App\Models\Ledger; -use App\Models\LedgerItem; use App\Services\StatisticService; -use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; @@ -18,7 +14,7 @@ class StatisticsController extends Controller /** * 首页统计 */ - public function dashboard(Request $request): array + public function dashboard(Request $request, StatisticService $statisticService): array { $query = Ledger::filter( $this->defaultFilterInput($request), LedgerFilter::class @@ -40,34 +36,6 @@ class StatisticsController extends Controller //-------------------------------------------------------------------------- $yesterdayLedger = (clone $query)->where('date', $yesterday->format('Y-m-d'))->first(); - //-------------------------------------------------------------------------- - // 近 30 天趋势数据 - //-------------------------------------------------------------------------- - $startAt = $yesterday->copy()->subDays(29); - $endAt = $yesterday->copy(); - - /** @var \Illuminate\Database\Eloquent\Collection */ - $ledgers30days = (clone $query) - ->whereBetween('date', [$startAt, $endAt]) - ->get(['date', 'sales', 'expenditure']) - ->keyBy('date'); - - $trend = collect(); - - while ($startAt->lte($endAt)) { - $ledger = $ledgers30days->get( - $date = $startAt->format('Y-m-d') - ); - - $trend->push([ - 'date' => $date, - 'sales' => trim_zeros($ledger->sales ?? 0), - 'expenditure' => trim_zeros($ledger->expenditure ?? 0), - ]); - - $startAt->addDay(); - } - return [ // 本月总账录入 'current_month_ledger' => [ @@ -83,7 +51,9 @@ class StatisticsController extends Controller 'expenditure' => trim_zeros($yesterdayLedger->expenditure ?? 0), ], // 近30天趋势数据 - 'trend_data_of_30days' => $trend, + 'trend_data_of_30days' => $statisticService->ledgerTrends( + $yesterday->copy()->subDays(29), $yesterday->copy() + ), ]; } @@ -116,7 +86,7 @@ class StatisticsController extends Controller /** * 销售统计 */ - public function sales(Request $request): array + public function sales(Request $request, StatisticService $statisticService): array { $request->validate( rules: [ @@ -129,82 +99,11 @@ class StatisticsController extends Controller ], ); - // 开始日期 - $startAt = Carbon::parse($request->input('start_at')); - // 结束日期 - $endAt = Carbon::parse($request->input('end_at')); - - $input = $this->defaultFilterInput($request); - - /** @var \Illuminate\Database\Eloquent\Collection */ - $lotteryTypes = Keyword::where('parent_key', 'lottery_type')->get(); - - /** @var \Illuminate\Support\Collection */ - $ledgerStatistics = Ledger::select([ - 'date', - DB::raw('SUM(new_customers) as new_customers'), - DB::raw('SUM(sales) as sales'), - DB::raw('SUM(expenditure) as expenditure') - ]) - ->filter($input, LedgerFilter::class) - ->whereBetween('date', [$startAt->format('Y-m-d'), $endAt->format('Y-m-d')]) - ->groupBy(['date']) - ->get() - ->keyBy('date'); - - /** @var \Illuminate\Support\Collection */ - $ledgerItemStatistics = LedgerItem::select([ - 'date', - 'ledger_item_type_id', - DB::raw('SUM(sales) as sales'), - DB::raw('SUM(expenditure) as expenditure'), - ]) - ->filter($input, LedgerItemFilter::class) - ->whereIn('ledger_item_type_id', $lotteryTypes->pluck('key')) - ->whereBetween('date', [$startAt->format('Y-m-d'), $endAt->format('Y-m-d')]) - ->groupBy(['date', 'ledger_item_type_id']) - ->get() - ->groupBy('date'); - - $data = collect(); - $date = $endAt->copy(); - - while ($date->gte($startAt)) { - $_date = $date->format('Y-m-d'); - $ledgerStatistic = $ledgerStatistics->get($_date); - /** @var \Illuminate\Support\Collection */ - $lotteryTypeStatistics = $ledgerItemStatistics->get($_date, collect())->keyBy('ledger_item_type_id'); - - $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeStatistics) { - $lotteryTypeStatistic = $lotteryTypeStatistics->get($lotteryType->key); - return [ - 'name' => $lotteryType->name, - 'sales' => trim_zeros($lotteryTypeStatistic->sales ?? 0), - 'expenditure' => trim_zeros($lotteryTypeStatistic->expenditure ?? 0), - ]; - }); - - $data->push([ - 'date' => $_date, - 'ledger' => [ - 'new_customers' => $ledgerStatistic->new_customers ?? 0, - 'sales' => trim_zeros($ledgerStatistic->sales ?? 0), - 'expenditure' => trim_zeros($ledgerStatistic->expenditure ?? 0), - ], - 'lottery_types' => $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeStatistics) { - $lotteryTypeStatistic = $lotteryTypeStatistics->get($lotteryType->key); - return [ - 'name' => $lotteryType->name, - 'sales' => trim_zeros($lotteryTypeStatistic->sales ?? 0), - 'expenditure' => trim_zeros($lotteryTypeStatistic->expenditure ?? 0), - ]; - }), - ]); - - $date->subDay(); - } - - return $data->all(); + return $statisticService->sales( + Carbon::parse($request->input('start_at')), + Carbon::parse($request->input('end_at')), + $this->defaultFilterInput($request), + ); } /** diff --git a/app/Services/StatisticService.php b/app/Services/StatisticService.php index 734c7c3..54e6424 100644 --- a/app/Services/StatisticService.php +++ b/app/Services/StatisticService.php @@ -3,14 +3,47 @@ namespace App\Services; use App\Admin\Filters\LedgerFilter; +use App\Admin\Filters\LedgerItemFilter; use App\Admin\Filters\StoreFilter; +use App\Models\Keyword; use App\Models\Ledger; +use App\Models\LedgerItem; use App\Models\Store; use Illuminate\Support\Arr; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; class StatisticService { + /** + * 总账趋势 + */ + public function ledgerTrends(Carbon $start, Carbon $end, array $input = []): array + { + $ledgers = Ledger::filter($input, LedgerFilter::class) + ->whereBetween('date', [$start->format('Y-m-d'), $end->format('Y-m-d')]) + ->get(['date', 'sales', 'expenditure']) + ->keyBy('date'); + + $data = collect(); + + while ($start->lte($end)) { + $ledger = $ledgers->get( + $date = $start->format('Y-m-d') + ); + + $data->push([ + 'date' => $date, + 'sales' => trim_zeros($ledger->sales ?? 0), + 'expenditure' => trim_zeros($ledger->expenditure ?? 0), + ]); + + $start->addDay(); + } + + return $data->all(); + } + /** * 门店统计 */ @@ -41,4 +74,80 @@ class StatisticService ]; })->all(); } + + /** + * 销售统计 + */ + public function sales(Carbon $start, Carbon $end, array $input = []): array + { + /** @var \Illuminate\Database\Eloquent\Collection */ + $lotteryTypes = Keyword::where('parent_key', 'lottery_type')->get(); + + /** @var \Illuminate\Support\Collection */ + $ledgerStatistics = Ledger::select([ + 'date', + DB::raw('SUM(new_customers) as new_customers'), + DB::raw('SUM(sales) as sales'), + DB::raw('SUM(expenditure) as expenditure') + ]) + ->filter($input, LedgerFilter::class) + ->whereBetween('date', [$start->format('Y-m-d'), $end->format('Y-m-d')]) + ->groupBy(['date']) + ->get() + ->keyBy('date'); + + /** @var \Illuminate\Support\Collection */ + $ledgerItemStatistics = LedgerItem::select([ + 'date', + 'ledger_item_type_id', + DB::raw('SUM(sales) as sales'), + DB::raw('SUM(expenditure) as expenditure'), + ]) + ->filter($input, LedgerItemFilter::class) + ->whereIn('ledger_item_type_id', $lotteryTypes->pluck('key')) + ->whereBetween('date', [$start->format('Y-m-d'), $end->format('Y-m-d')]) + ->groupBy(['date', 'ledger_item_type_id']) + ->get() + ->groupBy('date'); + + $data = collect(); + + while ($end->gte($start)) { + $date = $end->format('Y-m-d'); + + $ledgerStatistic = $ledgerStatistics->get($date); + /** @var \Illuminate\Support\Collection */ + $lotteryTypeStatistics = $ledgerItemStatistics->get($date, collect())->keyBy('ledger_item_type_id'); + + $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeStatistics) { + $lotteryTypeStatistic = $lotteryTypeStatistics->get($lotteryType->key); + return [ + 'name' => $lotteryType->name, + 'sales' => trim_zeros($lotteryTypeStatistic->sales ?? 0), + 'expenditure' => trim_zeros($lotteryTypeStatistic->expenditure ?? 0), + ]; + }); + + $data->push([ + 'date' => $date, + 'ledger' => [ + 'new_customers' => $ledgerStatistic->new_customers ?? 0, + 'sales' => trim_zeros($ledgerStatistic->sales ?? 0), + 'expenditure' => trim_zeros($ledgerStatistic->expenditure ?? 0), + ], + 'lottery_types' => $lotteryTypes->map(function ($lotteryType) use ($lotteryTypeStatistics) { + $lotteryTypeStatistic = $lotteryTypeStatistics->get($lotteryType->key); + return [ + 'name' => $lotteryType->name, + 'sales' => trim_zeros($lotteryTypeStatistic->sales ?? 0), + 'expenditure' => trim_zeros($lotteryTypeStatistic->expenditure ?? 0), + ]; + }), + ]); + + $end->subDay(); + } + + return $data->all(); + } } From 4dc454bd8aeb798491b70522374a4c953399a7e9 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 15:06:54 +0800 Subject: [PATCH 6/9] Update --- app/Http/Controllers/Api/StatisticsController.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index 844176c..161c242 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -16,9 +16,9 @@ class StatisticsController extends Controller */ public function dashboard(Request $request, StatisticService $statisticService): array { - $query = Ledger::filter( - $this->defaultFilterInput($request), LedgerFilter::class - ); + $input = $this->defaultFilterInput($request); + + $query = Ledger::filter($input, LedgerFilter::class); // 昨天 $yesterday = Carbon::yesterday(); @@ -52,7 +52,9 @@ class StatisticsController extends Controller ], // 近30天趋势数据 'trend_data_of_30days' => $statisticService->ledgerTrends( - $yesterday->copy()->subDays(29), $yesterday->copy() + $yesterday->copy()->subDays(29), + $yesterday->copy(), + $input, ), ]; } From 18349a9ca51daf3593d73154e83e8e941b7f1cac Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 15:31:40 +0800 Subject: [PATCH 7/9] Update --- .../Controllers/Api/StatisticsController.php | 87 +++++++++++-------- app/Services/StatisticService.php | 18 +++- 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index 161c242..4b07090 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -2,12 +2,9 @@ namespace App\Http\Controllers\Api; -use App\Admin\Filters\LedgerFilter; -use App\Models\Ledger; use App\Services\StatisticService; use Illuminate\Http\Request; use Illuminate\Support\Carbon; -use Illuminate\Support\Facades\DB; class StatisticsController extends Controller { @@ -18,44 +15,43 @@ class StatisticsController extends Controller { $input = $this->defaultFilterInput($request); - $query = Ledger::filter($input, LedgerFilter::class); - // 昨天 $yesterday = Carbon::yesterday(); - //-------------------------------------------------------------------------- - // 本月总账录入 - //-------------------------------------------------------------------------- - $currentMonthLedger = (clone $query) - ->select([DB::raw('SUM(sales) as sales'), DB::raw('SUM(expenditure) as expenditure')]) - ->whereBetween('date', [$yesterday->copy()->startOfMonth()->format('Y-m-d'), $yesterday->format('Y-m-d')]) - ->first(); - - //-------------------------------------------------------------------------- - // 昨日总账录入 - //-------------------------------------------------------------------------- - $yesterdayLedger = (clone $query)->where('date', $yesterday->format('Y-m-d'))->first(); - - return [ - // 本月总账录入 - 'current_month_ledger' => [ - // 截止日期 - 'deadline' => $yesterday->format('Y-m-d'), - 'sales' => trim_zeros($currentMonthLedger->sales ?? 0), - 'expenditure' => trim_zeros($currentMonthLedger->expenditure ?? 0), - ], - // 昨日累计金额 - 'yesterday_ledger' => [ - 'date' => $yesterday->format('Y-m-d'), - 'sales' => trim_zeros($yesterdayLedger->sales ?? 0), - 'expenditure' => trim_zeros($yesterdayLedger->expenditure ?? 0), - ], - // 近30天趋势数据 - 'trend_data_of_30days' => $statisticService->ledgerTrends( - $yesterday->copy()->subDays(29), + // 本月上报数据统计 + $currentMonthLedger = array_merge( + ['deadline' => $yesterday->format('Y-m-d')], + $statisticService->ledger( + $yesterday->copy()->startOfMonth(), $yesterday->copy(), $input, ), + ); + + // 昨日总账录入 + $yesterdayLedger = array_merge( + ['date' => $yesterday->format('Y-m-d')], + $statisticService->ledger( + $yesterday->copy(), + $yesterday->copy(), + $input, + ), + ); + + // 近30天趋势数据 + $trendsOf30days = $statisticService->ledgerTrends( + $yesterday->copy()->subDays(29), + $yesterday->copy(), + $input, + ); + + return [ + // 本月总账录入 + 'current_month_ledger' => $currentMonthLedger, + // 昨日累计金额 + 'yesterday_ledger' => $yesterdayLedger, + // 近30天趋势数据 + 'trends_of_30days' => $trendsOf30days, ]; } @@ -108,6 +104,27 @@ class StatisticsController extends Controller ); } + public function sales2(Request $request, StatisticService $statisticService): array + { + $request->validate( + rules: [ + 'start_at' => ['bail', 'required', 'date_format:Y-m-d'], + ], + attributes: [ + 'start_at' => '开始日期', + ], + ); + + // yesterday + // + + return $statisticService->sales( + Carbon::parse($request->input('start_at')), + Carbon::parse($request->input('end_at')), + $this->defaultFilterInput($request), + ); + } + /** * 处理区域和门店过滤条件 */ diff --git a/app/Services/StatisticService.php b/app/Services/StatisticService.php index 54e6424..16f04bb 100644 --- a/app/Services/StatisticService.php +++ b/app/Services/StatisticService.php @@ -16,7 +16,23 @@ use Illuminate\Support\Facades\DB; class StatisticService { /** - * 总账趋势 + * 上报数据统计 + */ + public function ledger(Carbon $start, Carbon $end, array $input = []): array + { + $ledger = Ledger::filter($input, LedgerFilter::class) + ->select([DB::raw('SUM(sales) as sales'), DB::raw('SUM(expenditure) as expenditure')]) + ->whereBetween('date', [$start->format('Y-m-d'), $end->format('Y-m-d')]) + ->first(); + + return [ + 'sales' => trim_zeros($ledger->sales ?? 0), + 'expenditure' => trim_zeros($ledger->expenditure ?? 0), + ]; + } + + /** + * 上报数据趋势 */ public function ledgerTrends(Carbon $start, Carbon $end, array $input = []): array { From 12bc95b45a1e5755b02e060167fde68ca805b952 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 16:46:51 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=80=BB=E8=B4=A6=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/StatisticsController.php | 70 +++++++++++++------ app/Services/StatisticService.php | 4 +- routes/api.php | 2 + 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index 4b07090..5df0369 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -55,6 +55,55 @@ class StatisticsController extends Controller ]; } + /** + * 总账统计 + */ + public function ledger(Request $request, StatisticService $statisticService) + { + $request->validate( + rules: [ + 'start_at' => ['bail', 'required', 'date_format:Y-m-d'], + 'end_at' => ['bail', 'required', 'date_format:Y-m-d'], + 'before_start_at' => ['bail', 'required', 'date_format:Y-m-d'], + 'before_end_at' => ['bail', 'required', 'date_format:Y-m-d'], + ], + attributes: [ + 'start_at' => '开始日期', + 'end_at' => '结束日期', + 'before_start_at' => '对比开始日期', + 'before_end_at' => '对比结束日期', + ], + ); + + $input = $this->defaultFilterInput($request); + + $ledger = $statisticService->ledger( + Carbon::parse($request->input('start_at')), + Carbon::parse($request->input('end_at')), + $input, + ); + + $beforeLedger = $statisticService->ledger( + Carbon::parse($request->input('before_start_at')), + Carbon::parse($request->input('before_end_at')), + $input, + ); + + // 销售涨幅 + $salesGrowthRate = 0; + + if (bccomp($beforeLedger['sales'], '0', 2) === 0) { + $salesGrowthRate = '-'; + } else { + $diff = bcsub($ledger['sales'], $beforeLedger['sales'], 2); + $salesGrowthRate = bcdiv(bcmul($diff, '100'), $beforeLedger['sales'], 2); + } + + return array_merge($ledger, [ + 'sales_growth_rate' => $salesGrowthRate, + ]); + } + /** * 门店统计 */ @@ -104,27 +153,6 @@ class StatisticsController extends Controller ); } - public function sales2(Request $request, StatisticService $statisticService): array - { - $request->validate( - rules: [ - 'start_at' => ['bail', 'required', 'date_format:Y-m-d'], - ], - attributes: [ - 'start_at' => '开始日期', - ], - ); - - // yesterday - // - - return $statisticService->sales( - Carbon::parse($request->input('start_at')), - Carbon::parse($request->input('end_at')), - $this->defaultFilterInput($request), - ); - } - /** * 处理区域和门店过滤条件 */ diff --git a/app/Services/StatisticService.php b/app/Services/StatisticService.php index 16f04bb..abb310c 100644 --- a/app/Services/StatisticService.php +++ b/app/Services/StatisticService.php @@ -16,7 +16,7 @@ use Illuminate\Support\Facades\DB; class StatisticService { /** - * 上报数据统计 + * 总账统计 */ public function ledger(Carbon $start, Carbon $end, array $input = []): array { @@ -32,7 +32,7 @@ class StatisticService } /** - * 上报数据趋势 + * 总账数据趋势 */ public function ledgerTrends(Carbon $start, Carbon $end, array $input = []): array { diff --git a/routes/api.php b/routes/api.php index 62764cf..5718540 100644 --- a/routes/api.php +++ b/routes/api.php @@ -41,6 +41,8 @@ Route::group([ Route::get('/statistics/stores', [StatisticsController::class, 'stores']); // 统计数据 - 销售统计 Route::get('/statistics/sales', [StatisticsController::class, 'sales']); + // 统计数据 - 总账统计 + Route::get('/statistics/ledger', [StatisticsController::class, 'ledger']); // 数据上报 Route::apiResource('/ledgers', LedgerController::class)->only(['store', 'show']); From 74bb543e7eadca9da8c643faf705c055021e86bd Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Apr 2024 16:57:52 +0800 Subject: [PATCH 9/9] Update --- .../Controllers/Api/StatisticsController.php | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Api/StatisticsController.php b/app/Http/Controllers/Api/StatisticsController.php index 5df0369..4539bbe 100644 --- a/app/Http/Controllers/Api/StatisticsController.php +++ b/app/Http/Controllers/Api/StatisticsController.php @@ -13,43 +13,50 @@ class StatisticsController extends Controller */ public function dashboard(Request $request, StatisticService $statisticService): array { + $request->validate( + rules: ['date' => ['filled', 'date_format:Y-m-d']], + attributes: ['date' => '日期'], + ); + $input = $this->defaultFilterInput($request); - // 昨天 - $yesterday = Carbon::yesterday(); + $date = Carbon::yesterday(); + if ($request->filled('date')) { + $date = Carbon::parse($request->input('date')); + } // 本月上报数据统计 - $currentMonthLedger = array_merge( - ['deadline' => $yesterday->format('Y-m-d')], + $monthLedger = array_merge( + ['deadline' => $date->format('Y-m-d')], $statisticService->ledger( - $yesterday->copy()->startOfMonth(), - $yesterday->copy(), + $date->copy()->startOfMonth(), + $date->copy(), $input, ), ); // 昨日总账录入 - $yesterdayLedger = array_merge( - ['date' => $yesterday->format('Y-m-d')], + $yesdayLedger = array_merge( + ['date' => $date->format('Y-m-d')], $statisticService->ledger( - $yesterday->copy(), - $yesterday->copy(), + $date->copy(), + $date->copy(), $input, ), ); // 近30天趋势数据 $trendsOf30days = $statisticService->ledgerTrends( - $yesterday->copy()->subDays(29), - $yesterday->copy(), + $date->copy()->subDays(29), + $date->copy(), $input, ); return [ // 本月总账录入 - 'current_month_ledger' => $currentMonthLedger, + 'current_month_ledger' => $monthLedger, // 昨日累计金额 - 'yesterday_ledger' => $yesterdayLedger, + 'yesday_ledger' => $yesdayLedger, // 近30天趋势数据 'trends_of_30days' => $trendsOf30days, ];