6
0
Fork 0
jiqu-library-server/app/Admin/Controllers/Store/StaffPerformanceController.php

219 lines
10 KiB
PHP

<?php
namespace App\Admin\Controllers\Store;
use App\Enums\OfflineOrderStatus;
use App\Models\OfflineOrder;
use App\Models\Order;
use App\Models\UserInfo;
use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
use Illuminate\Support\Facades\DB;
class StaffPerformanceController extends AdminController
{
protected $translation = 'store-staff-performance';
protected function grid()
{
$datetime = request('datetime');
// 开始时间
$start = $datetime['start'] ?? '';
// 结束时间
$end = $datetime['end'] ?? '';
$infoTable = (new UserInfo())->getTable();
$inviteUsersCounts = UserInfo::select([
'inviter_id',
DB::raw('count(1) as invite_users_count')
])
->when($start || $end, function ($builder) use ($start, $end) {
if ($start && $end) {
return $builder->whereBetween('created_at', [$start, $end]);
}
return $builder->when($start, fn ($builder) => $builder->where('created_at', '>=', $start))
->when($end, fn ($builder) => $builder->where('created_at', '<=', $end));
})
->groupBy('inviter_id');
// 线上订单业绩
$onlineOrderPerformances = Order::select([
'inviter_id',
DB::raw('COUNT(1) AS orders_count'),
DB::raw('SUM(point_discount_amount) AS points_deduction_amount'),
DB::raw('SUM(total_amount) AS payment_amount'),
DB::raw('SUM(profit) AS profit'),
])
->whereIn('status', [
Order::STATUS_PAID,
Order::STATUS_COMPLETED,
])
->when($start || $end, function ($builder) use ($start, $end) {
if ($start && $end) {
return $builder->whereBetween('pay_at', [$start, $end]);
}
return $builder->when($start, fn ($builder) => $builder->where('pay_at', '>=', $start))
->when($end, fn ($builder) => $builder->where('pay_at', '<=', $end));
})
->groupBy('inviter_id');
// 线下订单业绩
$offlineOrderPerformances = OfflineOrder::select([
'staff_id',
DB::raw('COUNT(1) AS orders_count'),
DB::raw('SUM(points_deduction_amount) AS points_deduction_amount'),
DB::raw('SUM(payment_amount) AS payment_amount'),
])
->where('status', OfflineOrderStatus::Paid)
->when($start || $end, function ($builder) use ($start, $end) {
if ($start && $end) {
return $builder->whereBetween('payment_time', [$start, $end]);
}
return $builder->when($start, fn ($builder) => $builder->where('payment_time', '>=', $start))
->when($end, fn ($builder) => $builder->where('payment_time', '<=', $end));
})
->groupBy('staff_id');
$builder = UserInfo::with(['user'])
->leftJoinSub($inviteUsersCounts, 'invite_users_counts', fn ($join) => $join->on("{$infoTable}.user_id", '=', 'invite_users_counts.inviter_id'))
->leftJoinSub($onlineOrderPerformances, 'online_performances', fn ($join) => $join->on("{$infoTable}.user_id", '=', 'online_performances.inviter_id'))
->leftJoinSub($offlineOrderPerformances, 'offline_performances', fn ($join) => $join->on("{$infoTable}.user_id", '=', 'offline_performances.staff_id'))
->select([
'user_id',
'nickname',
'avatar',
'invite_users_count',
// 线上订单
DB::raw('online_performances.orders_count AS online_orders_count'),
DB::raw('online_performances.points_deduction_amount AS online_points_deduction_amount'),
DB::raw('online_performances.payment_amount AS online_payment_amount'),
DB::raw('online_performances.profit AS online_profit'),
// 线下订单
DB::raw('offline_performances.orders_count AS offline_orders_count'),
DB::raw('offline_performances.points_deduction_amount AS offline_points_deduction_amount'),
DB::raw('offline_performances.payment_amount AS offline_payment_amount'),
])
->where('is_company', true);
$grid = new Grid($builder);
$grid->model()->orderBy('user_id', 'desc');
$grid->combine('online_order', [
'online_orders_count',
'online_total_amount',
'online_points_deduction_amount',
'online_payment_amount',
'online_profit',
]);
$grid->combine('offline_order', [
'offline_orders_count',
'offline_total_amount',
'offline_points_deduction_amount',
'offline_payment_amount',
]);
$grid->column('user_id', 'ID');
$grid->column('phone')->display(fn () => $this->user?->phone)->copyable();
$grid->column('nickname');
$grid->column('invite_users_count')->display(fn ($v) => (int) $v);
// 线上订单业绩
$grid->column('online_orders_count')->display(fn ($v) => (int) $v);
$grid->column('online_total_amount')->display(fn () => bcdiv($this->online_points_deduction_amount + $this->online_payment_amount, 100, 2));
$grid->column('online_points_deduction_amount')->display(fn ($v) => bcdiv($v, 100, 2));
$grid->column('online_payment_amount')->display(fn ($v) => bcdiv($v, 100, 2));
$grid->column('online_profit')->display(fn ($v) => $v ?? '0.00');
// 线下订单业绩
$grid->column('offline_orders_count')->display(fn ($v) => (int) $v);
$grid->column('offline_total_amount')->display(fn () => bcdiv($this->offline_points_deduction_amount + $this->offline_payment_amount, 100, 2));
$grid->column('offline_points_deduction_amount')->display(fn ($v) => bcdiv($v, 100, 2));
$grid->column('offline_payment_amount')->display(fn ($v) => bcdiv($v, 100, 2));
$grid->disableRefreshButton();
$grid->disableFilterButton();
$grid->disableActions();
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->like('user.phone', '手机号')->width(3);
$filter->between('datetime')->datetime()->ignore()->width(4);
});
$grid->footer(function ($collection) use ($grid, $infoTable, $onlineOrderPerformances, $offlineOrderPerformances) {
// 线上订单
$onlineQuery = UserInfo::query()
->leftJoinSub($onlineOrderPerformances, 'online_performances', fn ($join) => $join->on("{$infoTable}.user_id", '=', 'online_performances.inviter_id'))
->select([
DB::raw('SUM(online_performances.orders_count) AS orders_count'),
DB::raw('SUM(online_performances.points_deduction_amount) AS points_deduction_amount'),
DB::raw('SUM(online_performances.payment_amount) AS payment_amount'),
DB::raw('SUM(online_performances.profit) AS profit'),
])
->where('is_company', true);
// 线下订单
$offlineQuery = UserInfo::query()
->leftJoinSub($offlineOrderPerformances, 'offline_performances', fn ($join) => $join->on("{$infoTable}.user_id", '=', 'offline_performances.staff_id'))
->select([
// 线下订单
DB::raw('SUM(offline_performances.orders_count) AS orders_count'),
DB::raw('SUM(offline_performances.points_deduction_amount) AS points_deduction_amount'),
DB::raw('SUM(offline_performances.payment_amount) AS payment_amount'),
])
->where('is_company', true);
$grid->model()->getQueries()->unique()->each(function ($value) use (&$onlineQuery, &$offlineQuery) {
if (in_array($value['method'], ['paginate', 'get', 'orderBy', 'orderByDesc'], true)) {
return;
}
$onlineQuery = call_user_func_array([$onlineQuery, $value['method']], $value['arguments'] ?? []);
$offlineQuery = call_user_func_array([$offlineQuery, $value['method']], $value['arguments'] ?? []);
});
$onlineResults = $onlineQuery->first();
$onlineOrdersCount = $onlineResults['orders_count'] ?? 0;
$onlinePointsDeductionAmount = bcdiv($onlineResults['points_deduction_amount'] ?? 0, 100, 2);
$onlinePaymentAmount = bcdiv($onlineResults['payment_amount'] ?? 0, 100, 2);
$onlineTotalAmount = bcadd($onlinePointsDeductionAmount, $onlinePaymentAmount, 2);
$onlineProfit = $onlineResults['profit'] ?? 0;
$offlineResults = $offlineQuery->first();
$offlineOrdersCount = $offlineResults['orders_count'] ?? 0;
$offlinePointsDeductionAmount = bcdiv($offlineResults['points_deduction_amount'] ?? 0, 100, 2);
$offlinePaymentAmount = bcdiv($offlineResults['payment_amount'] ?? 0, 100, 2);
$offlineTotalAmount = bcadd($offlinePointsDeductionAmount, $offlinePaymentAmount, 2);
return <<<HTML
<table class="table table-bordered">
<tbody>
<tr>
<td>线上订单统计</td>
<td>订单数: $onlineOrdersCount</td>
<td>订单总额: $onlineTotalAmount</td>
<td>积分抵扣: $onlinePointsDeductionAmount</td>
<td>实付总额: $onlinePaymentAmount</td>
<td>累计返利: $onlineProfit</td>
<tr>
<tr>
<td>线下订单统计</td>
<td>订单数: $offlineOrdersCount</td>
<td>订单总额: $offlineTotalAmount</td>
<td>积分抵扣: $offlinePointsDeductionAmount</td>
<td colspan="2">实付总额: $offlinePaymentAmount</td>
<tr>
</tbody>
</table>
HTML;
});
return $grid;
}
}