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->point_discount_amount, '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('order_total_amount')->display(function () { return bcdiv($this->point_discount_amount + $this->total_amount, 100, 2); })->prepend('¥'); $grid->column('point_discount_amount')->display(function ($value) { return bcdiv($value, 100, 2); })->prepend('¥'); $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?->text(); })->circleDot(PayWay::colors()); $grid->column('pay_at'); $grid->column('created_at')->sortable(); $grid->column('wx_share', '是否冻结')->display(fn() => data_get($this->wx_share, 'status') == 'Y' ? '是' : '否'); $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(), PayWay::None->value => PayWay::None->text(), ])->width(3); $filter->where('order_type', function ($builder) { if ($this->input == 1) { $builder->where('point_discount_amount', '>', 0); } else { $builder->where('point_discount_amount', 0); } }, '订单类型')->select([1 => '积分订单', 2 => '其他订单'])->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); $filter->where('wx_share_status', function ($q) { $q->when($this->input == 'Y', fn($q1) => $q1->where('wx_share->status', $this->input)); $q->when($this->input != 'Y', fn($q1) => $q1->where('wx_share->status', $this->input)->orWhereNull('wx_share')); } , '是否冻结')->select(['Y' => '是', 'N' => '否'])->width(3); }); $user = Admin::user(); $grid->tools(function (Grid\Tools $tools) use ($user) { if ($user->can('dcat.admin.orders.export_shipping_orders')) { $tools->append(new ExportShippingOrder()); } if ($user->can('dcat.admin.orders.export_order_products')) { $tools->append(new ExportProduct()); } }); $grid->actions(function (Grid\Displayers\Actions $actions) use ($user) { $row = $actions->row; if ($user->can('dcat.admin.orders.show')) { $actions->disableView(false); } if ($user->can('dcat.admin.orders.tags')) { $actions->append(new OrderSetTag()); } // if ($row->pay_at && data_get($row->wx_share, 'status') != 'N') { // $actions->append(new RowWxShareFinish()); // } }); $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(); $payment_amount = bcdiv($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')); $point_discount_amount = bcdiv($query->sum('point_discount_amount'), 100, 2); $total_amount = bcadd($payment_amount, $point_discount_amount, 2); return << 统计 订单数: $count 订单总额: $total_amount 积分抵扣: $point_discount_amount 实付金额: $payment_amount 市场价: $market_price 成本价: $cost_price 成长值: $sales_value HTML; }); return $grid; } /** * Make a show builder. * * @param mixed $id * * @return \Closure|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('order_total_amount')->as(function ($v) { return bcdiv($this->point_discount_amount + $this->total_amount, 100, 2); })->prepend('- ¥'); $show->field('point_discount_amount')->as(function ($v) { return bcdiv($v, 100, 2); })->prepend('- ¥'); $show->field('total_amount')->as(function ($v) { return bcdiv($v, 100, 2); })->prepend('¥'); $show->field('profit'); }); $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()); } if ($show->model()->pay_at && data_get($show->model()->wx_share, 'status') != 'N') { $tools->append(new ShowWxShareFinish()); } }); })); }); $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('point_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(); }); } }