271 lines
11 KiB
PHP
271 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Admin\Controllers\Store;
|
|
|
|
use Dcat\Admin\{Form, Grid, Admin, Show};
|
|
use Dcat\Admin\Http\Controllers\AdminController;
|
|
use App\Models\{Order, OrderProduct, OrderPackage};
|
|
use App\Enums\PayWay;
|
|
use Dcat\Admin\Layout\Row;
|
|
use Dcat\Admin\Widgets\{Box, Tab, Card};
|
|
use App\Constants\OrderStatus;
|
|
|
|
class OrderController extends AdminController
|
|
{
|
|
public $statusMap = [
|
|
0 => '待付款',
|
|
1 => '待发货',
|
|
2 => '发货中',
|
|
3 => '已发货',
|
|
9 => '已完成',
|
|
10 => '已取消',
|
|
];
|
|
public $statusColor = [
|
|
0 => 'primary',
|
|
1 => 'warning',
|
|
2 => 'danger',
|
|
3 => 'success',
|
|
9 => 'success',
|
|
10 => '#b3b9bf',
|
|
];
|
|
protected $translation = 'store-order';
|
|
|
|
protected function grid()
|
|
{
|
|
$grid = new Grid(Order::with(['user', 'userInfo', 'inviter', 'inviterInfo', 'store']));
|
|
|
|
$user = Admin::user();
|
|
$canAdmin = $this->canAdmin();
|
|
if (!$canAdmin) {
|
|
$stores = $user->stores->pluck('id');
|
|
$grid->model()->whereIn('store_id', $stores);
|
|
}
|
|
|
|
$grid->model()->whereNotNull('store_id')->orderBy('created_at', 'desc');
|
|
|
|
$grid->column('store.title', '门店');
|
|
$grid->column('sn')->copyable();
|
|
$grid->column('user_id')->display(function () {
|
|
$nickname = $this->userInfo?->nickname ?? '---';
|
|
$avatar = $this->userInfo?->avatar ?? 'https://via.placeholder.com/45x45.png';
|
|
$phone = $this->user?->phone;
|
|
return <<<HTML
|
|
<img src="{$avatar}" width="45" />
|
|
<span class="label bg-danger">{$nickname}</span>
|
|
<span class="label bg-success">{$phone}</span>
|
|
HTML;
|
|
});
|
|
$grid->column('inviter_id')->display(function () {
|
|
$nickname = $this->inviterInfo?->nickname ?? '---';
|
|
$avatar = $this->inviterInfo?->avatar ?? 'https://via.placeholder.com/45x45.png';
|
|
$phone = $this->inviter?->phone;
|
|
return <<<HTML
|
|
<img src="{$avatar}" width="45" />
|
|
<span class="label bg-danger">{$nickname}</span>
|
|
<span class="label bg-success">{$phone}</span>
|
|
HTML;
|
|
});
|
|
$grid->column('total_amount')->display(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
})->prepend('¥');
|
|
$grid->column('market_price')->display(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
})->prepend('¥');
|
|
$grid->column('cost_price')->display(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
})->prepend('¥');
|
|
$grid->column('sales_value');
|
|
$grid->column('order_status')->using($this->statusMap)->dot($this->statusColor);
|
|
$grid->column('created_at');
|
|
$grid->column('pay_at');
|
|
$grid->column('completed_at');
|
|
|
|
$grid->showViewButton($user->can('dcat.admin.store.order.show'));
|
|
|
|
$grid->filter(function (Grid\Filter $filter) {
|
|
$filter->panel();
|
|
$filter->equal('store_id', '门店')->select('api/store')->width(3);
|
|
$filter->like('sn')->width(3);
|
|
$filter->where('user_id', function ($q) {
|
|
$q->where(function ($q) {
|
|
$q->whereHas('user', fn($q) => $q->where('phone', 'like', '%'.$this->input.'%'))
|
|
->orWhereHas('userInfo', fn($q) => $q->where('nickname', 'like', '%'.$this->input.'%'));
|
|
});
|
|
})->width(3)->placeholder('昵称/手机号');
|
|
$filter->where('inviter_id', function ($q) {
|
|
$q->where(function ($q) {
|
|
$q->whereHas('inviter', fn($q) => $q->where('phone', 'like', '%'.$this->input.'%'))
|
|
->orWhereHas('inviterInfo', fn($q) => $q->where('nickname', 'like', '%'.$this->input.'%'));
|
|
});
|
|
})->width(3)->placeholder('昵称/手机号');
|
|
// $filter->equal('pay_way')->select([
|
|
// PayWay::WxpayMiniProgram->value => PayWay::WxpayMiniProgram->text(),
|
|
// PayWay::Offline->value => PayWay::Offline->text(),
|
|
// ])->width(3);
|
|
$filter->where('order_status', function ($q) {
|
|
switch ($this->input) {
|
|
case OrderStatus::PENDING:
|
|
$q->where('status', Order::STATUS_PENDING);
|
|
break;
|
|
case OrderStatus::WAIT_SHIPPING:
|
|
$q->where('status', Order::STATUS_PAID)->where('shipping_state', Order::SHIPPING_STATE_PENDING);
|
|
break;
|
|
case OrderStatus::SHIPPING:
|
|
$q->where('status', Order::STATUS_PAID)->where('shipping_state', Order::SHIPPING_STATE_PROCESSING);
|
|
break;
|
|
case OrderStatus::SHIPPED:
|
|
$q->where('status', Order::STATUS_PAID)->where('shipping_state', Order::SHIPPING_STATE_PROCESSED);
|
|
break;
|
|
case OrderStatus::COMPLETED:
|
|
$q->where('status', Order::STATUS_COMPLETED);
|
|
break;
|
|
case OrderStatus::CANCELLED:
|
|
$q->where('status', Order::STATUS_CANCELLED);
|
|
break;
|
|
}
|
|
})->select([
|
|
OrderStatus::PENDING => '待付款',
|
|
OrderStatus::WAIT_SHIPPING => '待发货',
|
|
OrderStatus::SHIPPING => '发货中',
|
|
OrderStatus::SHIPPED => '已发货',
|
|
OrderStatus::COMPLETED => '已完成',
|
|
OrderStatus::CANCELLED => '已取消'
|
|
])->width(3);
|
|
$filter->between('created_at')->dateTime()->width(6);
|
|
$filter->between('completed_at')->dateTime()->width(6);
|
|
});
|
|
|
|
$grid->footer(function ($collection) use ($grid) {
|
|
$query = Order::query();
|
|
$grid->model()->getQueries()->unique()->each(function ($value) use (&$query) {
|
|
if (in_array($value['method'], ['paginate', 'get', 'orderBy', 'orderByDesc'], true)) {
|
|
return;
|
|
}
|
|
|
|
$query = call_user_func_array([$query, $value['method']], $value['arguments'] ?? []);
|
|
});
|
|
$count = $query->count();
|
|
$total_amount = round($query->sum('total_amount') / 100, 2, PHP_ROUND_HALF_DOWN);
|
|
$market_price = round($query->sum('market_price') / 100, 2, PHP_ROUND_HALF_DOWN);
|
|
$cost_price = round($query->sum('cost_price') / 100, 2, PHP_ROUND_HALF_DOWN);
|
|
$sales_value = round($query->sum('sales_value'), 2, PHP_ROUND_HALF_DOWN);
|
|
$profit = round($total_amount - $cost_price, 2, PHP_ROUND_HALF_DOWN);
|
|
return <<<HTML
|
|
<table class="table table-bordered">
|
|
<tbody>
|
|
<tr>
|
|
<td>统计</td>
|
|
<td>订单数: $count</td>
|
|
<td>订单总额: $total_amount</td>
|
|
<td>总毛利: $profit</td>
|
|
<td>成长值: $sales_value</td>
|
|
<tr>
|
|
</tbody>
|
|
</table>
|
|
HTML;
|
|
});
|
|
return $grid;
|
|
}
|
|
|
|
protected function detail($id)
|
|
{
|
|
$show = Show::make($id, Order::with(['user', 'inviter']));
|
|
$show->field('id');
|
|
$show->field('sn');
|
|
$show->field('user.phone');
|
|
$show->field('inviter.phone');
|
|
$show->field('total_amount')->as(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
});
|
|
$show->field('market_price')->as(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
});
|
|
$show->field('cost_price')->as(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
});
|
|
$show->field('products_total_amount')->as(fn($value) => bcdiv($value, 100, 2));
|
|
$show->field('coupon_discount_amount')->as(fn($value) => bcdiv($value, 100, 2));
|
|
// $show->field('vip_discount_amount')->as(fn($value) => bcdiv($value, 100, 2));
|
|
$show->field('total_amount', '支付金额')->as(fn($value) => bcdiv($value, 100, 2));
|
|
$show->field('sales_value');
|
|
$show->field('order_status')->as(function ($v) {
|
|
return $this->order_status;
|
|
})->using($this->statusMap)->dot($this->statusColor);
|
|
$show->field('pay_way')->as(function ($v) {
|
|
return $this->pay_way?->mallText();
|
|
})->circleDot(PayWay::colors());
|
|
$show->field('created_at');
|
|
$show->field('pay_at');
|
|
$show->field('completed_at');
|
|
|
|
$show->panel()->tools(function ($tools) {
|
|
$tools->disableEdit();
|
|
$tools->disableDelete();
|
|
});
|
|
|
|
$row = new Row();
|
|
$row->column(5, $show);
|
|
$tab = Tab::make()->withCard();
|
|
$tab->add('商品', Card::make($this->gridProduct($id)));
|
|
$tab->add('提货记录', Card::make($this->gridPackage($id)));
|
|
|
|
$row->column(7, $tab);
|
|
return $row;
|
|
}
|
|
|
|
protected function gridProduct($id)
|
|
{
|
|
$grid = Grid::make(OrderProduct::with([]));
|
|
$grid->model()->where('order_id', $id);
|
|
|
|
$grid->column('name');
|
|
$grid->column('specs', '规格')->label();
|
|
$grid->column('sell_price', '销售价格')->display(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
})->prepend('¥');
|
|
$grid->column('vip_price', '会员价格')->display(function ($value) {
|
|
return bcdiv($value, 100, 2);
|
|
})->prepend('¥');
|
|
$grid->column('quantity');
|
|
$grid->column('sales_value');
|
|
$grid->column('remain_quantity');
|
|
$grid->column('product_total_amount')->display(function () {
|
|
return bcdiv($this->total_amount, 100, 2);
|
|
})->prepend('¥');
|
|
|
|
$grid->disableActions();
|
|
$grid->disablePagination();
|
|
$grid->disableRefreshButton();
|
|
|
|
return $grid;
|
|
}
|
|
|
|
protected function gridPackage($id)
|
|
{
|
|
$grid = Grid::make(OrderPackage::with(['inviter', 'orderProducts']));
|
|
|
|
$grid->model()->where('order_id', $id)->orderBy('created_at', 'desc');
|
|
|
|
$grid->column('products', '商品')->display(function () {
|
|
$html = '';
|
|
foreach($this->orderProducts as $item) {
|
|
$html .= '<div><span class="label bg-primary">'.$item->name.'</span><span class="label bg-danger">'.$item->pivot->quantity.'</span></div>';
|
|
}
|
|
return $html;
|
|
});
|
|
$grid->column('created_at', '提货时间');
|
|
$grid->column('inviter.phone', '员工');
|
|
|
|
$grid->disableActions();
|
|
$grid->disablePagination();
|
|
$grid->disableRefreshButton();
|
|
|
|
return $grid;
|
|
}
|
|
|
|
protected function canAdmin()
|
|
{
|
|
return Admin::user()->isRole('administrator');
|
|
}
|
|
}
|