diff --git a/app/Admin/Actions/Grid/DealerManagerSubsidyBatchPay.php b/app/Admin/Actions/Grid/DealerManagerSubsidyBatchPay.php
new file mode 100644
index 00000000..39365184
--- /dev/null
+++ b/app/Admin/Actions/Grid/DealerManagerSubsidyBatchPay.php
@@ -0,0 +1,51 @@
+ 付款';
+
+ /**
+ * @param Model|Authenticatable|HasPermissions|null $user
+ *
+ * @return bool
+ */
+ protected function authorize($user): bool
+ {
+ return $user->can('dcat.admin.dealer_manager_subsidies.batch_pay');
+ }
+
+ // 确认弹窗信息
+ public function confirm()
+ {
+ return '您确定要支付选中的管理者津贴吗?';
+ }
+
+ // 处理请求
+ public function handle(Request $request)
+ {
+ try {
+ DB::transaction(function () {
+ foreach ($this->getKey() as $id) {
+ $dealerManagerSubsidy = DealerManagerSubsidy::lockForUpdate()->settled()->find($id);
+
+ if ($dealerManagerSubsidy?->isPending()) {
+ (new ManagerSubsidyService())->pay($dealerManagerSubsidy);
+ }
+ }
+ });
+ } catch (Throwable $e) {
+ return $this->response()->error('操作失败:'.$e->getMessage())->refresh();
+ }
+
+ return $this->response()->success('操作成功')->refresh();
+ }
+}
diff --git a/app/Admin/Actions/Grid/DealerManagerSubsidyPay.php b/app/Admin/Actions/Grid/DealerManagerSubsidyPay.php
new file mode 100644
index 00000000..0c706e8c
--- /dev/null
+++ b/app/Admin/Actions/Grid/DealerManagerSubsidyPay.php
@@ -0,0 +1,44 @@
+ 付款';
+
+ /**
+ * @param Model|Authenticatable|HasPermissions|null $user
+ *
+ * @return bool
+ */
+ protected function authorize($user): bool
+ {
+ return $user->can('dcat.admin.dealer_manager_subsidies.pay');
+ }
+
+ // 确认弹窗信息
+ public function confirm()
+ {
+ return '您确定要支付选中的管理者津贴吗?';
+ }
+
+ // 处理请求
+ public function handle(Request $request)
+ {
+ DB::transaction(function () {
+ $id = $this->getKey();
+
+ (new ManagerSubsidyService())->pay(
+ DealerManagerSubsidy::lockForUpdate()->settled()->findOrFail($id)
+ );
+ });
+
+ return $this->response()->success('操作成功')->refresh();
+ }
+}
diff --git a/app/Admin/Controllers/DealerManageSubsidyLogController.php b/app/Admin/Controllers/DealerManageSubsidyLogController.php
index c08155fc..cf7fc89e 100644
--- a/app/Admin/Controllers/DealerManageSubsidyLogController.php
+++ b/app/Admin/Controllers/DealerManageSubsidyLogController.php
@@ -19,6 +19,7 @@ class DealerManageSubsidyLogController extends AdminController
protected function grid()
{
$builder = DealerManageSubsidyLog::with(['user', 'order', 'product']);
+
return Grid::make($builder, function (Grid $grid) {
$grid->model()->orderBy('id', 'desc');//默认ID倒叙
$grid->column('id')->sortable();
diff --git a/app/Admin/Controllers/DealerManagerSubsidyController.php b/app/Admin/Controllers/DealerManagerSubsidyController.php
new file mode 100644
index 00000000..5875b766
--- /dev/null
+++ b/app/Admin/Controllers/DealerManagerSubsidyController.php
@@ -0,0 +1,127 @@
+settled();
+
+ return Grid::make($builder, function (Grid $grid) {
+ $grid->model()->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_manager_sales_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('is_manager', '管理者')->bool();
+ $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_manager_subsidies.batch_pay')) {
+ $batch->add(new DealerManagerSubsidyBatchPay());
+ }
+ });
+ });
+
+ $grid->actions(function (Grid\Displayers\Actions $actions) {
+ if ($actions->row->isPending() && Admin::user()->can('dcat.admin.dealer_manager_subsidies.pay')) {
+ $actions->append(new DealerManagerSubsidyPay());
+ }
+ });
+
+ $grid->filter(function (Grid\Filter $filter) {
+ $filter->panel();
+
+ $filter->equal('user.phone', '手机号')->width(3);
+ $filter->equal('status', '状态')->select(DealerManagerSubsidyStatus::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 = DealerManagerSubsidy::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'));
+ });
+ });
+ });
+ }
+}
diff --git a/app/Admin/routes.php b/app/Admin/routes.php
index 804eac4d..04304fc5 100644
--- a/app/Admin/routes.php
+++ b/app/Admin/routes.php
@@ -186,8 +186,11 @@ Route::group([
$router->get('dealer-earnings-manager', 'DealerEarningController@index')->name('dealer_earnings.manager');
$router->get('dealer-earnings-purchase', 'DealerEarningController@index')->name('dealer_earnings.purchase');
- //批零明细
+ // 管理者津贴
+ $router->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-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/DealerManagerSubsidyStatus.php b/app/Enums/DealerManagerSubsidyStatus.php
index 8400c0a1..e18c013c 100644
--- a/app/Enums/DealerManagerSubsidyStatus.php
+++ b/app/Enums/DealerManagerSubsidyStatus.php
@@ -5,4 +5,25 @@ namespace App\Enums;
enum DealerManagerSubsidyStatus: 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/DealerManagerSubsidy.php b/app/Models/DealerManagerSubsidy.php
index caea0024..42d1e89e 100644
--- a/app/Models/DealerManagerSubsidy.php
+++ b/app/Models/DealerManagerSubsidy.php
@@ -38,6 +38,27 @@ class DealerManagerSubsidy 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);
+ }
+
+ public function user()
+ {
+ return $this->belongsTo(User::class, 'user_id');
+ }
+
+ public function userinfo()
+ {
+ return $this->belongsTo(UserInfo::class, 'user_id', 'user_id');
+ }
+
/**
* 此管理津贴所属的经销商
*/
@@ -51,6 +72,16 @@ class DealerManagerSubsidy extends Model
return $this->morphOne(DealerEarning::class, 'earningable');
}
+ /**
+ * 仅查询待付款的管理津贴
+ *
+ * @return bool
+ */
+ public function isPending(): bool
+ {
+ return $this->is_settle && $this->status === DealerManagerSubsidyStatus::Pending;
+ }
+
public function isCompleted()
{
return $this->status === DealerManagerSubsidyStatus::Completed;
diff --git a/app/Services/Dealer/ManagerSubsidyService.php b/app/Services/Dealer/ManagerSubsidyService.php
new file mode 100644
index 00000000..ab766710
--- /dev/null
+++ b/app/Services/Dealer/ManagerSubsidyService.php
@@ -0,0 +1,43 @@
+isPending()) {
+ throw new BizException('管理者津贴 不是待付款状态');
+ }
+
+ $dealerManagerSubsidy->update([
+ 'status' => DealerManagerSubsidyStatus::Completed,
+ ]);
+
+ $dealerManagerSubsidy->earning->update([
+ 'pay_way' => DealerEarning::PAY_WAY_WALLET,
+ 'pay_at' => now(),
+ 'pay_info' => null,
+ 'status' => DealerEarningStatus::Completed,
+ ]);
+
+ (new WalletService())->changeBalance(
+ $dealerManagerSubsidy->user,
+ $dealerManagerSubsidy->real_amount,
+ DealerWalletAction::ManagerSubsidyIn,
+ '收入-管理者津贴',
+ $dealerManagerSubsidy
+ );
+ }
+}
diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php
index 6f0a37bd..f87da2cc 100644
--- a/database/seeders/AdminMenuSeeder.php
+++ b/database/seeders/AdminMenuSeeder.php
@@ -342,7 +342,7 @@ class AdminMenuSeeder extends Seeder
[
'title'=>'管理者津贴',
'icon' => '',
- 'uri' => 'dealer-earnings-manager?filter-earningable_type[]=dealer_manager_subsidy',
+ 'uri' => 'dealer-manager-subsidies',
],
[
'title'=>'管理者津贴明细',
diff --git a/database/seeders/AdminPermissionSeeder.php b/database/seeders/AdminPermissionSeeder.php
index 389bd35b..eaec93ee 100644
--- a/database/seeders/AdminPermissionSeeder.php
+++ b/database/seeders/AdminPermissionSeeder.php
@@ -352,6 +352,14 @@ class AdminPermissionSeeder extends Seeder
'pay'=>['name' =>'确认打款'],
],
],
+ 'dealer_manager_subsidies' => [
+ 'name' =>'管理者津贴',
+ 'curd' => ['index'],
+ 'children' => [
+ 'pay' => ['name' => '付款'],
+ 'batch_pay' => ['name' => '批量付款'],
+ ],
+ ],
'dealer_manager_sales_logs'=>[
'name' =>'管理者津贴明细',
'curd' => ['index'],