diff --git a/app/Admin/Actions/Show/OrderCreatePackage.php b/app/Admin/Actions/Show/OrderCreatePackage.php index 77f51d59..93342547 100644 --- a/app/Admin/Actions/Show/OrderCreatePackage.php +++ b/app/Admin/Actions/Show/OrderCreatePackage.php @@ -8,11 +8,9 @@ use Dcat\Admin\Widgets\Modal; class OrderCreatePackage extends AbstractTool { - public function __construct($title = null, $id) + public function __construct($id, $title = null) { - if ($title) { - $this->title = $title; - } + parent::__construct($title); $this->setKey($id); } /** diff --git a/app/Admin/Controllers/OrderController.php b/app/Admin/Controllers/OrderController.php index af02d3f4..67eaa8a7 100644 --- a/app/Admin/Controllers/OrderController.php +++ b/app/Admin/Controllers/OrderController.php @@ -304,7 +304,7 @@ class OrderController extends AdminController //显示发货动作 $order = OrderModel::findOrFail($id); if ($order->isWaitShipping() || $order->isShipping()) { - $packagesBox->tool(new OrderCreatePackage(null, $id)); + $packagesBox->tool(new OrderCreatePackage($id)); } $column->row($packagesBox->collapsable()); diff --git a/app/Admin/Controllers/SettingController.php b/app/Admin/Controllers/SettingController.php index b162c00b..37e074da 100644 --- a/app/Admin/Controllers/SettingController.php +++ b/app/Admin/Controllers/SettingController.php @@ -8,6 +8,7 @@ use App\Admin\Forms\Settings\Distribution; use App\Admin\Forms\Settings\Ios; use App\Admin\Forms\Settings\Kuaidi100; use App\Admin\Forms\Settings\Unipush; +use App\Admin\Forms\Settings\Withdraw; use App\Admin\Repositories\Setting; use Dcat\Admin\Admin; use Dcat\Admin\Form; @@ -110,14 +111,34 @@ class SettingController extends AdminController case 'app': $tab->add('系统配置', new App(), true); $tab->addLink('会员奖励配置', admin_route('settings.index', ['type'=>'distribution'])); + $tab->addLink('提现配置', admin_route('settings.index', ['type'=>'withdraw'])); $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'ios'])); $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); $tab->addLink('Uni-push配置', admin_route('settings.index', ['type'=>'unipush'])); break; + case 'distribution': + $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); + $tab->add('会员奖励配置', new Distribution(), true); + $tab->addLink('提现配置', admin_route('settings.index', ['type'=>'withdraw'])); + $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); + $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'android'])); + $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); + $tab->addLink('Uni-push配置', admin_route('settings.index', ['type'=>'unipush'])); + break; + case 'withdraw': + $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); + $tab->addLink('会员奖励配置', admin_route('settings.index', ['type'=>'distribution'])); + $tab->add('提现配置', new Withdraw(), true); + $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); + $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'android'])); + $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); + $tab->addLink('Uni-push配置', admin_route('settings.index', ['type'=>'unipush'])); + break; case 'ios': $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); $tab->addLink('会员奖励配置', admin_route('settings.index', ['type'=>'distribution'])); + $tab->addLink('提现配置', admin_route('settings.index', ['type'=>'withdraw'])); $tab->add('Ios配置', new Ios(), true); $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'android'])); $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); @@ -126,6 +147,7 @@ class SettingController extends AdminController case 'android': $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); $tab->addLink('会员奖励配置', admin_route('settings.index', ['type'=>'distribution'])); + $tab->addLink('提现配置', admin_route('settings.index', ['type'=>'withdraw'])); $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); $tab->add('Android配置', new Android(), true); $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); @@ -134,6 +156,7 @@ class SettingController extends AdminController case 'kuaidi100': $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); $tab->addLink('会员奖励配置', admin_route('settings.index', ['type'=>'distribution'])); + $tab->addLink('提现配置', admin_route('settings.index', ['type'=>'withdraw'])); $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'android'])); $tab->add('快递100配置', new Kuaidi100(), true); @@ -142,19 +165,12 @@ class SettingController extends AdminController case 'unipush': $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); $tab->addLink('会员奖励配置', admin_route('settings.index', ['type'=>'distribution'])); + $tab->addLink('提现配置', admin_route('settings.index', ['type'=>'withdraw'])); $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'android'])); $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); $tab->add('Uni-push配置', new Unipush(), true); break; - case 'distribution': - $tab->addLink('系统配置', admin_route('settings.index', ['type'=>'app'])); - $tab->add('会员奖励配置', new Distribution(), true); - $tab->addLink('Ios配置', admin_route('settings.index', ['type'=>'ios'])); - $tab->addLink('Android配置', admin_route('settings.index', ['type'=>'android'])); - $tab->addLink('快递100配置', admin_route('settings.index', ['type'=>'kuaidi100'])); - $tab->addLink('Uni-push配置', admin_route('settings.index', ['type'=>'unipush'])); - break; default: break; } diff --git a/app/Admin/Controllers/UserController.php b/app/Admin/Controllers/UserController.php index a5d82d86..b7feaa35 100644 --- a/app/Admin/Controllers/UserController.php +++ b/app/Admin/Controllers/UserController.php @@ -61,6 +61,8 @@ class UserController extends AdminController $actions->append(new EnableUser()); } } + + // todo-禁用可提,禁用余额 }); $grid->filter(function (Grid\Filter $filter) { diff --git a/app/Admin/Controllers/WalletToBankLogController.php b/app/Admin/Controllers/WalletToBankLogController.php index 9dff45f2..317aede6 100644 --- a/app/Admin/Controllers/WalletToBankLogController.php +++ b/app/Admin/Controllers/WalletToBankLogController.php @@ -31,6 +31,12 @@ class WalletToBankLogController extends AdminController $grid->column('amount')->display(function ($v) { return bcdiv($v, 100, 2); })->prepend('¥'); + $grid->column('service_amount')->display(function ($v) { + return bcdiv($v, 100, 2); + })->prepend('¥'); + $grid->column('account_amount')->display(function ($v) { + return bcdiv($v, 100, 2); + })->prepend('¥'); $grid->column('status')->using([ WalletToBankLogModel::STATUS_PENDING=>'待处理', WalletToBankLogModel::STATUS_AGREE=>'同意', @@ -43,6 +49,10 @@ class WalletToBankLogController extends AdminController $grid->column('remarks'); $grid->column('created_at')->sortable(); + + $grid->model()->orderBy('status', 'asc'); + $grid->model()->orderBy('created_at', 'desc'); + $grid->actions(function (Grid\Displayers\Actions $actions) { if ($actions->row->status == 0 && Admin::user()->can('dcat.admin.wallet_to_bank_logs.verify')) { $actions->append(new WalletToBankLogVerify()); diff --git a/app/Admin/Forms/Settings/Withdraw.php b/app/Admin/Forms/Settings/Withdraw.php new file mode 100644 index 00000000..1d870a73 --- /dev/null +++ b/app/Admin/Forms/Settings/Withdraw.php @@ -0,0 +1,45 @@ +updateOrCreate([ + 'key' => 'withdraw', + ], ['value' => $input]); + + //清配置缓存 + app(SettingService::class)->cleanCache('withdraw'); + + return $this + ->response() + ->success('配置更新成功!') + ->refresh(); + } + + /** + * Build a form here. + */ + public function form() + { + $appSettings = Setting::where('key', 'withdraw')->value('value'); + + // $this->switch('is_use', '提现开关')->value($appSettings['is_use'] ?? 0); + + $this->number('threshold_amount', '起提金额(元)')->value($appSettings['threshold_amount'] ?? 0); + $this->currency('rate', '提现费率')->value($appSettings['rate'] ?? 0)->symbol('%'); + } +} diff --git a/app/Endpoint/Api/Http/Controllers/Account/WalletController.php b/app/Endpoint/Api/Http/Controllers/Account/WalletController.php index 9d7b3451..aa0b5507 100644 --- a/app/Endpoint/Api/Http/Controllers/Account/WalletController.php +++ b/app/Endpoint/Api/Http/Controllers/Account/WalletController.php @@ -7,9 +7,11 @@ use App\Endpoint\Api\Http\Resources\BalanceLogResource; use App\Endpoint\Api\Http\Resources\DistributionPreIncomeResource; use App\Endpoint\Api\Http\Resources\WalletLogResource; use App\Endpoint\Api\Http\Resources\WalletToBankLogResource; +use App\Exceptions\BalanceFrozenException; use App\Exceptions\BizException; use App\Exceptions\InvalidPaySerialNumberException; use App\Exceptions\PayPasswordIncorrectException; +use App\Exceptions\WalletFrozenException; use App\Exceptions\WalletNotEnoughException; use App\Helpers\Paginator as PaginatorHelper; use App\Models\BalanceLog; @@ -170,17 +172,37 @@ class WalletController extends Controller ]); $user = $request->user(); + $amount = Arr::get($input, 'amount', 0); + + if (is_null($user->bank)) { + throw new BizException('请先绑定设置银行卡'); + } + //校验是否冻结 + if ($user->wallet->is_frozen) { + throw new WalletFrozenException(); + } + //校验是否关闭提现 + if (!$user->wallet->withdrawable) { + throw new BizException('可提账户已被限制提现'); + } + + // todo-校验提现门槛 + if (bcdiv($amount, 100, 2) < app_settings('withdraw.threshold_amount', 0)) { + throw new BizException('提现金额需大于'.app_settings('withdraw.threshold_amount', 0).'元'); + } + //校验安全密码 if (! $user->wallet?->verifyPassword($input['wallet_password'])) { throw new PayPasswordIncorrectException(); } - if (is_null($user->bank)) { - throw new BizException('请先绑定设置银行卡'); - } try { DB::beginTransaction(); + $rate = app_settings('withdraw.rate', '0.00');//手续费率 + + //计算手续费(四舍五入) + $serviceAmount = round($rate*$amount); //生成提现记录 $log = WalletToBankLog::create([ 'user_id' =>$user->id, @@ -188,11 +210,14 @@ class WalletController extends Controller 'bank_number' => $user->bank->bank_number, 'bank_description' => $user->bank->bank_description, 'username' => $user->bank->real_name, - 'amount'=> Arr::get($input, 'amount', 0), + 'amount'=> $amount, + 'rate' => $rate, + 'service_amount' => $serviceAmount, + 'account_amount' => $amount-$serviceAmount, ]); //减去用户可提金额 - $walletService->changeBalance($user, -Arr::get($input, 'amount', 0), WalletLog::ACTION_WITHDRAW_BANK, '提现-银行卡', $log); + $walletService->changeBalance($user, -$amount, WalletLog::ACTION_WITHDRAW_BANK, '提现-银行卡', $log); DB::commit(); } catch (WalletNotEnoughException $th) { DB::rollBack(); @@ -235,6 +260,14 @@ class WalletController extends Controller ]); $user = $request->user(); + //校验是否冻结 + if ($user->wallet->is_frozen) { + throw new WalletFrozenException(); + } + //校验是否关闭提现 + if (!$user->wallet->withdrawable) { + throw new BizException('可提账户已被限制提现'); + } //校验安全密码 if (! $user->wallet?->verifyPassword($input['wallet_password'])) { throw new PayPasswordIncorrectException(); @@ -273,12 +306,26 @@ class WalletController extends Controller 'wallet_password' => ['bail', 'required', 'filled', 'string', 'size:6'], ]); + $user = $request->user(); + //校验是否冻结 + if ($user->balance->is_frozen) { + throw new BalanceFrozenException(); + } + //校验是否关闭转账 + if (!$user->balance->transferable) { + throw new BizException('余额账户已被限制转账'); + } + //判断转账对象是否存在 $toUser = User::where('phone', '=', $input['phone'])->first(); if (is_null($toUser)) { throw new BizException('转账对象不存在'); } - $user = $request->user(); + //校验安全密码 + if (! $user->wallet?->verifyPassword($input['wallet_password'])) { + throw new PayPasswordIncorrectException(); + } + try { DB::beginTransaction(); //转出对象 diff --git a/app/Endpoint/Api/Http/Resources/UserBalanceResource.php b/app/Endpoint/Api/Http/Resources/UserBalanceResource.php index 8d40ff93..db64af12 100644 --- a/app/Endpoint/Api/Http/Resources/UserBalanceResource.php +++ b/app/Endpoint/Api/Http/Resources/UserBalanceResource.php @@ -19,14 +19,16 @@ class UserBalanceResource extends JsonResource 'balance'=> '0.00', // 'total_expenses'=> $this->total_expenses, // 'total_revenue' => $this->total_revenue, - // 'withdrawable' => $this->withdrawable, + 'withdrawable' => true, + 'is_frozen' => false, ]; } return [ 'balance'=>$this->balance_format, // 'total_expenses'=> $this->total_expenses, // 'total_revenue' => $this->total_revenue, - // 'withdrawable' => $this->withdrawable, + 'withdrawable' => (bool) $this->withdrawable, + 'is_frozen' => (bool) $this->is_frozen, ]; } } diff --git a/app/Endpoint/Api/Http/Resources/UserWalletResource.php b/app/Endpoint/Api/Http/Resources/UserWalletResource.php index 97964c0e..ff9ab026 100644 --- a/app/Endpoint/Api/Http/Resources/UserWalletResource.php +++ b/app/Endpoint/Api/Http/Resources/UserWalletResource.php @@ -19,16 +19,18 @@ class UserWalletResource extends JsonResource 'balance'=> '0.00', // 'total_expenses'=> $this->total_expenses, // 'total_revenue' => $this->total_revenue, - // 'withdrawable' => $this->withdrawable, + 'withdrawable' => true, 'has_password' => false, + 'is_frozen' => false, ]; } return [ - 'balance'=>$this->balance_format, + 'balance'=> $this->balance_format, // 'total_expenses'=> $this->total_expenses, // 'total_revenue' => $this->total_revenue, - // 'withdrawable' => $this->withdrawable, - 'has_password' => (bool) is_null($this?->password) ? false : true, + 'withdrawable' => (bool) $this->withdrawable, + 'is_frozen' => (bool) $this->is_frozen, + 'has_password' => (bool) $this->password??false, ]; } } diff --git a/app/Endpoint/Api/Http/Resources/WalletToBankLogResource.php b/app/Endpoint/Api/Http/Resources/WalletToBankLogResource.php index f5805bce..34f15dae 100644 --- a/app/Endpoint/Api/Http/Resources/WalletToBankLogResource.php +++ b/app/Endpoint/Api/Http/Resources/WalletToBankLogResource.php @@ -24,6 +24,7 @@ class WalletToBankLogResource extends JsonResource 'created_at' => $this->created_at->toDateTimeString(), 'status' => $this->status, 'remarks' => $this->remarks, + 'service_amount' => $this->service_amount_format, ]; } } diff --git a/app/Exceptions/BalanceFrozenException.php b/app/Exceptions/BalanceFrozenException.php new file mode 100644 index 00000000..fd81f3e4 --- /dev/null +++ b/app/Exceptions/BalanceFrozenException.php @@ -0,0 +1,11 @@ + 0, 'total_expenses' => 0, 'transferable' => true, + 'is_frozen' => false, ]; /** @@ -25,6 +26,7 @@ class Balance extends Model 'total_expenses', 'total_revenue', 'transferable', + 'is_frozen', ]; /** @@ -32,6 +34,7 @@ class Balance extends Model */ protected $casts = [ 'transferable' => 'bool', + 'is_frozen'=>'bool', ]; public function getBalanceFormatAttribute() diff --git a/app/Models/Wallet.php b/app/Models/Wallet.php index 16d00bcd..deddd986 100644 --- a/app/Models/Wallet.php +++ b/app/Models/Wallet.php @@ -24,6 +24,7 @@ class Wallet extends Model 'total_revenue' => 0, 'total_expenses' => 0, 'withdrawable' => true, + 'is_frozen' => false, ]; /** @@ -36,6 +37,7 @@ class Wallet extends Model 'total_revenue', 'withdrawable', 'password', //安全密码 + 'is_frozen', ]; /** @@ -43,6 +45,7 @@ class Wallet extends Model */ protected $casts = [ 'withdrawable' => 'bool', + 'is_frozen'=>'bool', ]; public function getBalanceFormatAttribute() diff --git a/app/Models/WalletToBankLog.php b/app/Models/WalletToBankLog.php index 22aa6b48..99cd4208 100644 --- a/app/Models/WalletToBankLog.php +++ b/app/Models/WalletToBankLog.php @@ -27,6 +27,9 @@ class WalletToBankLog extends Model 'amount', 'status', 'remarks', + 'rate', + 'service_amount', + 'account_amount', ]; /** @@ -42,4 +45,9 @@ class WalletToBankLog extends Model { return trim_trailing_zeros(bcdiv($this->attributes['amount'], 100, 2)); } + + public function getServiceAmountFormatAttribute() + { + return trim_trailing_zeros(bcdiv($this->attributes['service_amount'], 100, 2)); + } } diff --git a/database/migrations/2021_12_29_114710_add_is_frozen_to_wallets_table.php b/database/migrations/2021_12_29_114710_add_is_frozen_to_wallets_table.php new file mode 100644 index 00000000..59653709 --- /dev/null +++ b/database/migrations/2021_12_29_114710_add_is_frozen_to_wallets_table.php @@ -0,0 +1,34 @@ +boolean('is_frozen')->default(false)->comment('是否冻结'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('wallets', function (Blueprint $table) { + // + $table->dropColumn(['is_frozen']); + }); + } +} diff --git a/database/migrations/2021_12_29_114737_add_is_frozen_to_balances_table.php b/database/migrations/2021_12_29_114737_add_is_frozen_to_balances_table.php new file mode 100644 index 00000000..c87300bb --- /dev/null +++ b/database/migrations/2021_12_29_114737_add_is_frozen_to_balances_table.php @@ -0,0 +1,34 @@ +boolean('is_frozen')->default(false)->comment('是否冻结'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('balances', function (Blueprint $table) { + // + $table->dropColumn(['is_frozen']); + }); + } +} diff --git a/database/migrations/2021_12_29_133010_add_service_to_wallet_to_bank_logs_table.php b/database/migrations/2021_12_29_133010_add_service_to_wallet_to_bank_logs_table.php new file mode 100644 index 00000000..e21e6ff3 --- /dev/null +++ b/database/migrations/2021_12_29_133010_add_service_to_wallet_to_bank_logs_table.php @@ -0,0 +1,36 @@ +unsignedDecimal('rate', 18, 2)->default(0)->comment('费率'); + $table->unsignedBigInteger('service_amount')->comment('手续费:分'); + $table->unsignedBigInteger('account_amount')->comment('到账金额:分'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('wallet_to_bank_logs', function (Blueprint $table) { + // + $table->dropColumn(['rate', 'service_amount', 'account_amount']); + }); + } +} diff --git a/database/seeders/AppSettingSeeder.php b/database/seeders/AppSettingSeeder.php index d023d635..230b9d44 100644 --- a/database/seeders/AppSettingSeeder.php +++ b/database/seeders/AppSettingSeeder.php @@ -36,6 +36,12 @@ class AppSettingSeeder extends Seeder ], 'remarks' => '系统配置', ], + 'withdraw' => [ + 'value'=>[ + 'threshold_amount'=>0, + 'rate'=>'0.00', + ], + ], 'ios' => [ 'value'=> [ 'v'=>0, diff --git a/resources/lang/zh_CN/wallet-to-bank-log.php b/resources/lang/zh_CN/wallet-to-bank-log.php index df230627..8be77bee 100644 --- a/resources/lang/zh_CN/wallet-to-bank-log.php +++ b/resources/lang/zh_CN/wallet-to-bank-log.php @@ -11,6 +11,8 @@ return [ 'bank_description' => '收款银行开户行', 'username' => '持卡人', 'amount' => '提现金额', + 'service_amount' => '手续费', + 'account_amount' => '到账金额', 'status' => '状态', 'remarks' => '备注', 'created_at'=> '申请时间',