query('_export')) {
case 'product':
if (! Admin::user()->can('dcat.admin.orders.export_order_products')) {
throw new AuthorizationException('没有操作权限');
}
$query = Order::with(['user.userInfo', 'products']);
$grid = $this->grid();
$grid->processFilter();
foreach ($grid->model()->getQueries() as $condition) {
if (in_array($condition['method'], ['paginate', 'get', 'orderBy', 'orderByDesc'], true)) {
continue;
}
call_user_func_array([$query, $condition['method']], $condition['arguments'] ?? []);
}
return response()->streamDownload(function () use ($query) {
$writer = WriterEntityFactory::createXLSXWriter();
$writer->openToBrowser('订单商品'.time().'.xlsx');
$writer->addRow(WriterEntityFactory::createRowFromArray([
'商品ID',
'商品名称',
'数量',
'价格',
'金额',
'待发货数量',
'所属订单',
'下单手机',
'支付方式',
'付款时间',
'订单状态',
'下单时间',
'是否换货',
]));
$query->lazyById()->each(function ($order) use ($writer) {
foreach ($order->products as $product) {
$writer->addRow(
WriterEntityFactory::createRowFromArray([
$product->sku_id,
$product->name,
$product->quantity,
bcdiv($product->sell_price, '100', 2),
bcdiv($product->total_amount, '100', 2),
$product->remain_quantity,
$order->sn,
$order->user->phone,
$order->pay_way?->text(),
$order->pay_at?->toDateTimeString(),
$order->order_status_text,
$order->created_at?->toDateTimeString(),
$order->is_change ? '是' : '否',
])
);
}
});
$writer->close();
});
break;
}
return parent::index($content);
}
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
$grid = new Grid(Order::with(['user', 'userInfo', 'tags']));
$grid->setResource('orders');
$grid->model()->orderBy('id', 'desc');
$grid->column('id')->sortable()->if(function () {
return Admin::user()->can('dcat.admin.orders.show');
})->then(function (Column $column) {
$column->link(function ($value) {
return admin_route('orders.show', ['order' => $value]);
});
});
$grid->column('sn')->copyable();
$grid->column('tags', '标签')->display(function ($tags) {
return $tags->implode('name');
})->label();
$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 <<
{$nickname}
{$phone}
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('order_status')->display(function ($value) {
return $this->order_status;
})->using([
0=>'待付款',
1=>'待发货',
2=>'发货中',
3=>'已发货',
9=>'已完成',
10=>'已取消',
])->dot([
0=>'primary',
1=>'warning',
2=>'danger',
3=>'success',
9=>'success',
10=>'#b3b9bf',
])->filter(
OrderStatusIn::make([
0=>'待付款',
1=>'待发货',
2=>'发货中',
3=>'已发货',
9=>'已完成',
10=>'已取消',
])
);
$grid->column('pay_way')->display(function ($v) {
return $v?->mallText();
})->circleDot(PayWay::colors());
$grid->column('pay_at');
$grid->column('created_at')->sortable();
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$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('tags', function ($query) {
$query->whereHas('tags', function ($q) {
$q->whereIn('tags.id', $this->input);
});
}, '标签')->multipleSelect(Tag::orderTag()->pluck('name', 'id'))->width(3);
$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->like('pay_sn')->width(3);
});
$grid->tools(function (Grid\Tools $tools) {
if (Admin::user()->can('dcat.admin.orders.export_shipping_orders')) {
$tools->append(new ExportShippingOrder());
}
if (Admin::user()->can('dcat.admin.orders.export_order_products')) {
$tools->append(new ExportProduct());
}
});
$grid->actions(function (Grid\Displayers\Actions $actions) {
if (Admin::user()->can('dcat.admin.orders.show')) {
$actions->disableView(false);
}
if (Admin::user()->can('dcat.admin.orders.tags')) {
$actions->append(new OrderSetTag());
}
});
$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 = number_format($query->sum('total_amount') / 100, 2);
$market_price = number_format($query->sum('market_price') / 100, 2);
$cost_price = number_format($query->sum('cost_price') / 100, 2);
$sales_value = number_format($query->sum('sales_value'));
return <<
| 统计 |
订单数: $count |
订单总额: $total_amount |
市场价: $market_price |
成本价: $cost_price |
成长值: $sales_value |
HTML;
});
return $grid;
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return function (Row $row) use ($id) {
$row->column(5, function ($column) use ($id) {
$builder = Order::with(['user', 'userCoupon', 'tags', 'store'])->withCount('afterSales');
$column->row(Show::make($id, $builder, function (Show $show) {
// $show->field('id');
$show->row(function (Show\Row $show) {
$show->width(6)->field('user.phone');
$show->field('store.title', '店铺');
$show->width(6)->field('sn');
$show->field('order_status')->as(function ($v) {
return $this->order_status;
})->using([
0=>'待付款',
1=>'待发货',
2=>'发货中',
3=>'已发货',
9=>'已完成',
10=>'已取消',
])->dot([
0=>'primary',
1=>'warning',
2=>'danger',
3=>'success',
9=>'success',
10=>'#b3b9bf',
]);
$show->field('created_at');
$show->width(6)->field('tags')->as(function () {
return $this->tags->pluck('name');
})->label();
$show->field('pay_at');
$show->field('pay_way', '支付方式')->as(function () {
return $this->pay_way?->text();
})->circleDot(PayWay::colors());
$show->field('pay_sn');
$show->field('out_trade_no');
});
$show->row(function (Show\Row $show) {
$show->width(6)->field('consignee_name');
$show->field('consignee_telephone');
$show->width(12)->field('consignee')->width(10, 1)->as(function () {
return $this->consignee_zone . ' '. $this->consignee_address;
});
});
$userCouponId = $show->model()->user_coupon_id;
$show->row(function (Show\Row $show) use ($userCouponId) {
$show->width(6)->field('products_total_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$show->field('vip_discount_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('- ¥');
if ($userCouponId) {
$show->field('user_coupon.coupon_name', '优惠券')->label();
$show->field('coupon_discount_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('- ¥');
}
$show->field('shipping_fee')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('+ ¥');
$show->field('reduced_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('- ¥');
$show->field('profit');
$show->field('total_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
});
$show->row(function (Show\Row $show) use ($userCouponId) {
$show->width(6)->field('sales_value');
$show->field('completed_at', '完成时间');
$show->field('note');
$show->field('remark');
});
$show->panel()
->tools(function (Show\Tools $tools) use ($show) {
$tools->disableEdit();
$tools->disableDelete();
if ($show->model()->status == Order::STATUS_PENDING) {
if (Admin::user()->can('dcat.admin.orders.reduce')) {
$tools->append(new OrderReduce());
}
if (Admin::user()->can('dcat.admin.orders.pay')) {
$tools->append(new OrderPay());
}
}
$tools->append(new OrderRemark());
if ($show->model()->isPending() || $show->model()->isWaitShipping() || $show->model()->isShipping()) {
$tools->append(new OrderConsigneeInfo());
}
});
}));
});
$row->column(7, function ($column) use ($id) {
$builder = OrderProduct::withCount('afterSales')->where('order_id', $id);
$productGrid = Grid::make($builder, function (Grid $grid) {
$grid->column('name')->display(function ($value) {
if ($this->isGift()) {
$value = '【赠品】'.$value;
}
return $value;
});
// $grid->column('cover')->image(50, 50);
$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('vip_discount_amount', '会员折扣')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('coupon_discount_amount', '优惠券折扣')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('reduced_amount', '减免金额')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('bargain_amount', '砍价优惠')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('sales_value', '销售值');
$grid->column('remain_quantity');
$grid->column('product_total_amount')->display(function () {
return bcdiv($this->total_amount, 100, 2);
})->prepend('¥');
$grid->column('afterSalesCount', '售后情况')->display(function ($value) {
return $value > 0 ? 1 : 0;
})->using([
0=>'正常', 1=>'有售后',
])->dot([
0=>'success',
1=>'danger',
])->if(function () {
return $this->afterSalesCount > 0 && Admin::user()->can('dcat.admin.after_sales.index');
})
->then(function (Column $column) {
$column->link(function ($value) {
return admin_url('after-sales?order_product_id='.$this->id);
});
});
$grid->disableActions();
$grid->disablePagination();
$grid->disableRefreshButton();
});
$packageBuilder = OrderPackage::where('order_id', $id);
$packageGrid = Grid::make($packageBuilder, function (Grid $grid) {
$grid->column('shipping_company', '物流公司');
$grid->column('shipping_number', '物流单号');
$grid->column('packageProducts', '包裹商品')->display('包裹商品')->modal(function ($modal) {
$modal->title('商品');
return PackageProductSimpleTable::make(['id'=>$this->id]);
})->setHeaderAttributes(['style' => 'color:#5b69bc']);
$grid->column('created_at', '发货时间');
$grid->column('status', '包裹状态')->using([
OrderPackage::STATUS_WAIT => '揽收',
OrderPackage::STATUS_ONTHEWAY =>'途中',
OrderPackage::STATUS_DISTRIBUTE=>'派送',
OrderPackage::STATUS_CHECK=>'签收',
OrderPackage::STATUS_QUESTION => '疑难',
OrderPackage::STATUS_REFUND => '退签',
OrderPackage::STATUS_REFUSE => '拒签',
OrderPackage::STATUS_OTHER => '其他',
OrderPackage::STATUS_AUTOCHECK => '自动签收',
])->dot([
OrderPackage::STATUS_REFUND =>'danger',
OrderPackage::STATUS_REFUSE =>'danger',
OrderPackage::STATUS_AUTOCHECK =>'success',
OrderPackage::STATUS_CHECK =>'success',
OrderPackage::STATUS_WAIT =>'primary',
OrderPackage::STATUS_ONTHEWAY =>'primary',
OrderPackage::STATUS_DISTRIBUTE=>'primary',
OrderPackage::STATUS_QUESTION =>'warning',
]);
$grid->column('kuaidi_info', '物流详情')->display('详情')->modal(function ($modal) {
$modal->title('物流详情');
return KuaidiInfo::make();
});
$grid->column('is_failed', '正常')->bool([
0=>true,
1=>false,
]);
$grid->model()->orderBy('created_at', 'desc');
$grid->disableActions();
$grid->disablePagination();
$grid->disableRefreshButton();
});
$logBuilder = OrderLog::with('administrator')->where('order_id', $id);
$orderLogoGrid = Grid::make($logBuilder, function (Grid $grid) {
$grid->column('administrator.name', '操作人');
$grid->column('content', '操作明细')->display(function ($content) {
return $content;
});
$grid->column('created_at', '操作时间');
$grid->model()->orderBy('created_at', 'desc');
$grid->disableActions();
$grid->disablePagination();
$grid->disableRefreshButton();
});
$column->row(Box::make('订单商品', $productGrid));
$packagesBox = Box::make('发货包裹', $packageGrid);
//显示发货动作
$order = Order::findOrFail($id);
if ($order->isWaitShipping() || $order->isShipping()) {
$packagesBox->tool(new OrderCreatePackage($id));
}
$column->row($packagesBox->collapsable());
$logsBox = Box::make('操作记录', $orderLogoGrid);
$column->row($logsBox->collapsable());
// 参与活动
// $activityBuilder = OrderActivity::with('activity')->where('order_id', $id);
// $activityBox = Box::make('参与活动', Grid::make($activityBuilder, function (Grid $grid) {
// $grid->column('activity.title', '活动名称');
// $grid->column('show', '活动详情')->display(function () {
// return '查看';
// })->link(function () {
// return admin_route('activities.show', ['activity' =>$this->activity_id]);
// })->setHeaderAttributes(['style' => 'color:#5b69bc']);
// $grid->disableActions();
// $grid->disablePagination();
// $grid->disableRefreshButton();
// }));
// $column->row($activityBox->collapsable());
// 返利记录
$profitBuilder = OrderProfit::with(['user'])->where('order_id', $id);
$profitBox = Box::make('返利记录', Grid::make($profitBuilder, function (Grid $grid) {
$grid->column('user.phone', '受益人');
$grid->column('role_name', '代理等级');
$grid->column('ratio', '比例')->display(function ($v) {
return $v . '%';
});
$grid->column('money', '金额');
$grid->column('status', '状态')->using(OrderProfit::$statusMap)->dot(OrderProfit::$statusColor);
$grid->disableActions();
$grid->disablePagination();
$grid->disableRefreshButton();
}));
$column->row($profitBox->collapsable());
});
};
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Form::make(new Order(), function (Form $form) {
$form->display('id');
$form->text('user_id');
$form->text('sn');
$form->text('user_coupon_id');
$form->text('coupon_discount_amount');
$form->text('vip_discount_amount');
$form->text('reduced_amount');
$form->text('shipping_fee');
$form->text('products_total_amount');
$form->text('total_amount');
$form->text('weight');
$form->text('note');
$form->text('remark');
$form->text('pay_sn');
$form->text('pay_way');
$form->text('pay_at');
$form->text('consignee_name');
$form->text('consignee_telephone');
$form->text('consignee_zone');
$form->text('consignee_address');
$form->text('status');
$form->text('completed_at');
$form->display('created_at');
$form->display('updated_at');
});
}
public function orders(Request $request)
{
$sn = $request->input('q');
$query = Order::select('id', 'sn as text');
if ($sn) {
$query->where('sn', 'like', "%$sn%");
return $query->paginate(null);
}
return response()->json($query->get());
}
public function orderProducts(Request $request)
{
$orderId = $request->input('q');
$query = OrderProduct::select('id', 'name as text');
if ($orderId) {
$query->where('order_id', $orderId);
}
return response()->json($query->get());
}
public function exportShippingOrder(Request $request)
{
return response()->streamDownload(function () {
$writer = WriterEntityFactory::createXLSXWriter();
$writer->openToBrowser('发货单'.date('Ymd').'.xlsx');
$writer->addRow(WriterEntityFactory::createRowFromArray([
'订单编号', '下单手机号', '商品编号', '商品名称', '数量', '姓名', '电话', '地址', '下单时间', '快递公司', '发货单号', '发货数量',
]));
foreach (Order::with('products', 'user')->needShipping()->cursor() as $order) {
foreach ($order->products as $product) {
if ($product->remain_quantity > 0) {
$writer->addRow(WriterEntityFactory::createRowFromArray([
$order->sn,
$order->user->phone,
$product->sku_id,
$product->name.'数量:'.$product->remain_quantity,
$product->remain_quantity,
$order->consignee_name,
$order->consignee_telephone,
$order->consignee_zone.$order->consignee_address,
$order->created_at->toDateTimeString(),
]));
}
}
};
$writer->close();
});
}
}