门店统计

main
Jing Li 2024-04-16 12:27:07 +08:00
parent 60e7ce8301
commit 4c46ab7277
4 changed files with 71 additions and 51 deletions

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
/**

View File

@ -0,0 +1,44 @@
<?php
namespace App\Services;
use App\Admin\Filters\LedgerFilter;
use App\Admin\Filters\StoreFilter;
use App\Models\Ledger;
use App\Models\Store;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
class StatisticService
{
/**
* 门店统计
*/
public function stores(array $input = [], array $sorts = []): array
{
$storeLedgerStats = Ledger::select(['store_id', DB::raw('SUM(sales) as sales'), DB::raw('SUM(expenditure) as expenditure')])
->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();
}
}