diff --git a/app/Admin/Actions/Grid/DealerManageSubsidyBatchPay.php b/app/Admin/Actions/Grid/DealerManageSubsidyBatchPay.php new file mode 100644 index 00000000..caa4546d --- /dev/null +++ b/app/Admin/Actions/Grid/DealerManageSubsidyBatchPay.php @@ -0,0 +1,51 @@ + 付款'; + + /** + * @param Model|Authenticatable|HasPermissions|null $user + * + * @return bool + */ + protected function authorize($user): bool + { + return $user->can('dcat.admin.dealer_manage_subsidies.batch_pay'); + } + + // 确认弹窗信息 + public function confirm() + { + return '您确定要支付选中的管理津贴吗?'; + } + + // 处理请求 + public function handle(Request $request) + { + try { + DB::transaction(function () { + foreach ($this->getKey() as $id) { + $dealerManageSubsidy = DealerManageSubsidy::lockForUpdate()->settled()->find($id); + + if ($dealerManageSubsidy?->isPending()) { + (new ManageSubsidyService())->pay($dealerManageSubsidy); + } + } + }); + } catch (Throwable $e) { + return $this->response()->error('操作失败:'.$e->getMessage())->refresh(); + } + + return $this->response()->success('操作成功')->refresh(); + } +} diff --git a/app/Admin/Actions/Grid/DealerManageSubsidyPay.php b/app/Admin/Actions/Grid/DealerManageSubsidyPay.php new file mode 100644 index 00000000..6f21ea8d --- /dev/null +++ b/app/Admin/Actions/Grid/DealerManageSubsidyPay.php @@ -0,0 +1,44 @@ + 付款'; + + /** + * @param Model|Authenticatable|HasPermissions|null $user + * + * @return bool + */ + protected function authorize($user): bool + { + return $user->can('dcat.admin.dealer_manage_subsidies.pay'); + } + + // 确认弹窗信息 + public function confirm() + { + return '您确定要支付选中的管理津贴吗?'; + } + + // 处理请求 + public function handle(Request $request) + { + DB::transaction(function () { + $id = $this->getKey(); + + (new ManageSubsidyService())->pay( + DealerManageSubsidy::lockForUpdate()->settled()->findOrFail($id) + ); + }); + + return $this->response()->success('操作成功')->refresh(); + } +} diff --git a/app/Admin/Controllers/DealerManageSubsidyController.php b/app/Admin/Controllers/DealerManageSubsidyController.php new file mode 100644 index 00000000..e643f44e --- /dev/null +++ b/app/Admin/Controllers/DealerManageSubsidyController.php @@ -0,0 +1,167 @@ +model()->settled()->orderBy('id', 'desc'); + + $grid->column('settle_period', '结算周期')->display(function () { + return $this->start_at->rawFormat('Y/m/d') . '-' . $this->end_at->rawFormat('Y/m/d'); + })->link(function () { + return admin_route('dealer_manage_subsidy_logs.index', [ + 'user[phone]' => $this->user?->phone, + 'order_completed_at[start]' => $this->start_at->toDateTimeString(), + 'order_completed_at[end]' => $this->end_at->toDateTimeString(), + ]); + }); + $grid->column('user.phone', '手机号'); + $grid->column('userinfo.nickname', '昵称'); + $grid->column('lvl', '经销商等级')->display(function () { + return $this->lvl->text(); + }); + $grid->column('total_amount', '津贴总额')->prepend('¥'); + $grid->column('fee', '手续费')->prepend('¥')->help('手续费=津贴总额*手续费率'); + $grid->column('real_amount', '总收入')->prepend('¥')->help('总收入=津贴总额-手续费'); + $grid->column('fee_rate', '手续费率')->append('%'); + $grid->column('remark', '备注')->display('查看')->modal(function ($modal) { + $modal->title('备注'); + + return "
".nl2br($this->remark).'
'; + }); + $grid->column('status', '状态')->display(function ($v) { + return '  '.$v->text(); + }); + $grid->column('earning.pay_at', '付款时间'); + + $grid->showRowSelector(); + + $grid->tools(function ($tools) { + $tools->batch(function ($batch) { + $batch->disableDelete(); + + if (Admin::user()->can('dcat.admin.dealer_manage_subsidies.batch_pay')) { + $batch->add(new DealerManageSubsidyBatchPay()); + } + }); + }); + + $grid->actions(function (Grid\Displayers\Actions $actions) { + if ($actions->row->isPending() && Admin::user()->can('dcat.admin.dealer_manage_subsidies.pay')) { + $actions->append(new DealerManageSubsidyPay()); + } + }); + + $grid->filter(function (Grid\Filter $filter) { + $filter->panel(); + + $filter->equal('user.phone', '手机号')->width(3); + $filter->equal('status', '状态')->select(DealerManageSubsidyStatus::texts())->width(3); + $filter->whereBetween('settle_period', function ($query) { + $start = $this->input['start'] ?? null; + $end = $this->input['end'] ?? null; + + $query->when($start, function ($query, $start) { + $query->where('start_at', '>=', "{$start} 00:00:00"); + }); + + $query->when($end, function ($query, $end) { + $query->where('end_at', '<=', "{$end} 23:59:59"); + }); + }, '结算周期')->date()->width(6); + }); + + $grid->header(function ($collection) use ($grid) { + return tap(new Row(), function ($row) use ($grid) { + $query = DealerManageSubsidyModel::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'] ?? []); + }); + + $totalAmount = (clone $query)->sum('total_amount'); + $totalFee = (clone $query)->sum('fee'); + + $row->column(3, new InfoBox('津贴总额', $totalAmount, 'fa fa-cny')); + $row->column(3, new InfoBox('手续费', $totalFee, 'fa fa-cny')); + }); + }); + }); + + return Grid::make($builder, function (Grid $grid) { + $grid->model()->orderBy('id', 'desc');//默认ID倒叙 + $grid->column('id')->sortable(); + $grid->column('user.phone', '手机号')->copyable(); + $grid->column('lvl', '等级')->display(function () { + return $this->lvl->text(); + }); + $grid->column('order.sn', '订单编号'); + $grid->column('product.name', '商品名称'); + $grid->column('sales_volume', '销量'); + $grid->column('total_amount', '金额'); + $grid->column('order_completed_at', '结算时间')->sortable(); + $grid->column('created_at')->sortable(); + + $grid->disableCreateButton(); + $grid->disableActions(); + $grid->header(function ($collection) use ($grid) { + $query = DealerManageSubsidyLogModel::query(); + + // 拿到表格筛选 where 条件数组进行遍历 + $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'] ?? []); + }); + + // 查出统计数据 + $totalAmount = (clone $query)->sum('total_amount'); + // 自定义组件 + return "
金额:".$totalAmount.' 元
'; + }); + $grid->filter(function (Grid\Filter $filter) { + $filter->panel(false); + $filter->equal('user.phone', '手机号')->width(3); + $filter->between('order_completed_at', '结算时间')->dateTime()->width(7); + }); + }); + } +} diff --git a/app/Admin/Controllers/DealerManageSubsidyLogController.php b/app/Admin/Controllers/DealerManageSubsidyLogController.php index cf7fc89e..6057badc 100644 --- a/app/Admin/Controllers/DealerManageSubsidyLogController.php +++ b/app/Admin/Controllers/DealerManageSubsidyLogController.php @@ -3,10 +3,13 @@ namespace App\Admin\Controllers; use App\Admin\Repositories\DealerManageSubsidyLog; +use App\Admin\Widgets\InfoBox; use App\Models\DealerManageSubsidyLog as DealerManageSubsidyLogModel; +use Dcat\Admin\Admin; use Dcat\Admin\Form; use Dcat\Admin\Grid; use Dcat\Admin\Http\Controllers\AdminController; +use Dcat\Admin\Layout\Row; use Dcat\Admin\Show; class DealerManageSubsidyLogController extends AdminController @@ -18,10 +21,20 @@ class DealerManageSubsidyLogController extends AdminController */ protected function grid() { + Admin::style( + <<model()->orderBy('id', 'desc');//默认ID倒叙 + $grid->column('id')->sortable(); $grid->column('user.phone', '手机号')->copyable(); $grid->column('lvl', '等级')->display(function () { @@ -37,6 +50,19 @@ class DealerManageSubsidyLogController extends AdminController $grid->disableCreateButton(); $grid->disableActions(); $grid->header(function ($collection) use ($grid) { + return tap(new Row(), function ($row) use ($grid) { + $query = DealerManageSubsidyLogModel::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'] ?? []); + }); + + $row->column(3, new InfoBox('津贴总额', (clone $query)->sum('total_amount'), 'fa fa-cny')); + }); $query = DealerManageSubsidyLogModel::query(); // 拿到表格筛选 where 条件数组进行遍历 diff --git a/app/Admin/Repositories/DealerManageSubsidy.php b/app/Admin/Repositories/DealerManageSubsidy.php new file mode 100644 index 00000000..32f3343a --- /dev/null +++ b/app/Admin/Repositories/DealerManageSubsidy.php @@ -0,0 +1,16 @@ +get('dealer-manager-subsidies', 'DealerManagerSubsidyController@index')->name('dealer_manager_subsidies.index'); $router->get('dealer-manager-sales-logs', 'DealerManagerSalesLogController@index')->name('dealer_manager_sales_logs.index'); - //批零明细 + // 管理津贴 + $router->get('dealer-manage-subsidies', 'DealerManageSubsidyController@index')->name('dealer_manage_subsidies.index'); $router->get('dealer-manage-subsidy-logs', 'DealerManageSubsidyLogController@index')->name('dealer_manage_subsidy_logs.index'); + $router->get('dealer-purchase-logs', 'DealerPurchaseLogController@index')->name('dealer_purchase_logs.index'); //批零余额提现 diff --git a/app/Enums/DealerManageSubsidyStatus.php b/app/Enums/DealerManageSubsidyStatus.php index 2a6ed321..3dac0ed1 100644 --- a/app/Enums/DealerManageSubsidyStatus.php +++ b/app/Enums/DealerManageSubsidyStatus.php @@ -5,4 +5,25 @@ namespace App\Enums; enum DealerManageSubsidyStatus: int { case Pending = 0; case Completed = 5; + + public function color(): string + { + return match ($this) { + static::Pending => '#5b69bc', + static::Completed => '#21b978', + }; + } + + public function text(): string + { + return static::texts()[$this->value] ?? 'Unknown'; + } + + public static function texts(): array + { + return [ + static::Pending->value => '待付款', + static::Completed->value => '已付款', + ]; + } } diff --git a/app/Models/DealerManageSubsidy.php b/app/Models/DealerManageSubsidy.php index 3c4f3a5c..fd7b74f0 100644 --- a/app/Models/DealerManageSubsidy.php +++ b/app/Models/DealerManageSubsidy.php @@ -38,6 +38,17 @@ class DealerManageSubsidy extends Model 'is_settle', ]; + /** + * 仅查询已结算的管理津贴 + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeSettled($query) + { + return $query->where('is_settle', true); + } + /** * 此管理津贴所属的经销商 */ @@ -46,11 +57,31 @@ class DealerManageSubsidy extends Model return $this->belongsTo(Dealer::class, 'user_id', 'user_id'); } + public function user() + { + return $this->belongsTo(User::class, 'user_id'); + } + + public function userinfo() + { + return $this->belongsTo(UserInfo::class, 'user_id', 'user_id'); + } + public function earning() { return $this->morphOne(DealerEarning::class, 'earningable'); } + /** + * 仅查询待付款的管理津贴 + * + * @return bool + */ + public function isPending(): bool + { + return $this->is_settle && $this->status === DealerManageSubsidyStatus::Pending; + } + public function isCompleted() { return $this->status === DealerManageSubsidyStatus::Completed; diff --git a/app/Services/Dealer/ManageSubsidyService.php b/app/Services/Dealer/ManageSubsidyService.php new file mode 100644 index 00000000..24a50bdd --- /dev/null +++ b/app/Services/Dealer/ManageSubsidyService.php @@ -0,0 +1,43 @@ +isPending()) { + throw new BizException('管理津贴 不是待付款状态'); + } + + $dealerManageSubsidy->update([ + 'status' => DealerManageSubsidyStatus::Completed, + ]); + + $dealerManageSubsidy->earning->update([ + 'pay_way' => DealerEarning::PAY_WAY_WALLET, + 'pay_at' => now(), + 'pay_info' => null, + 'status' => DealerEarningStatus::Completed, + ]); + + (new WalletService())->changeBalance( + $dealerManageSubsidy->user, + $dealerManageSubsidy->real_amount, + DealerWalletAction::ManageSubsidyIn, + '收入-管理津贴', + $dealerManageSubsidy + ); + } +} diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index f87da2cc..3b2a3654 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -342,7 +342,7 @@ class AdminMenuSeeder extends Seeder [ 'title'=>'管理者津贴', 'icon' => '', - 'uri' => 'dealer-manager-subsidies', + 'uri' => 'dealer-earnings-manage?filter-earningable_type[]=dealer_manager_subsidy', ], [ 'title'=>'管理者津贴明细', diff --git a/database/seeders/AdminPermissionSeeder.php b/database/seeders/AdminPermissionSeeder.php index eaec93ee..6589ac4c 100644 --- a/database/seeders/AdminPermissionSeeder.php +++ b/database/seeders/AdminPermissionSeeder.php @@ -364,6 +364,14 @@ class AdminPermissionSeeder extends Seeder 'name' =>'管理者津贴明细', 'curd' => ['index'], ], + 'dealer_manage_subsidies' => [ + 'name' =>'管理津贴', + 'curd' => ['index'], + 'children' => [ + 'pay' => ['name' => '付款'], + 'batch_pay' => ['name' => '批量付款'], + ], + ], 'dealer_manage_subsidy_logs'=>[ 'name' =>'管理津贴明细', 'curd' => ['index'],