6
0
Fork 0

order:profit

base
panliang 2022-08-04 13:52:55 +08:00
parent 4499c057f6
commit 9843991b94
7 changed files with 110 additions and 153 deletions

View File

@ -1,29 +0,0 @@
<?php
namespace App\Admin\Actions\Show;
use Dcat\Admin\Show\AbstractTool;
use Dcat\Admin\Widgets\Modal;
use App\Admin\Forms\ProfitSuccessForm;
use App\Models\OrderProfit;
class ProfitSuccess extends AbstractTool
{
protected $title = '支付';
public function allowed()
{
$info = OrderProfit::find($this->getKey());
return $info->status != 2;
}
public function html()
{
$form = ProfitSuccessForm::make()->payload(['id' => $this->getKey()]);;
return Modal::make()
->lg()
->title($this->title)
->body($form)
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm btn-success\"><i class=\"feather icon-check\"></i>&nbsp;{$this->title}</a>&nbsp;&nbsp;");
}
}

View File

@ -8,8 +8,8 @@ use Dcat\Admin\Grid;
use Dcat\Admin\Show; use Dcat\Admin\Show;
use Dcat\Admin\Http\Controllers\AdminController; use Dcat\Admin\Http\Controllers\AdminController;
use App\Admin\Extensions\Grid\Tools\ProfitBatchSuccess; use App\Admin\Extensions\Grid\Tools\ProfitBatchSuccess;
use App\Admin\Actions\Show\ProfitSuccess;
use App\Enums\PayWay; use App\Enums\PayWay;
use Dcat\Admin\Admin;
class OrderProfitController extends AdminController class OrderProfitController extends AdminController
{ {
@ -43,13 +43,16 @@ class OrderProfitController extends AdminController
$filter->like('order.sn')->width(3); $filter->like('order.sn')->width(3);
$filter->like('fromUser.phone')->width(3); $filter->like('fromUser.phone')->width(3);
$filter->like('user.phone')->width(3); $filter->like('user.phone')->width(3);
$filter->equal('status')->select(OrderProfit::$statusMap)->width(3);
}); });
// $grid->showRowSelector(); $grid->showRowSelector();
// $grid->batchActions(function (Grid\Tools\BatchActions $batch) { $grid->batchActions(function (Grid\Tools\BatchActions $batch) {
// $batch->disableDelete(); $batch->disableDelete();
// $batch->add(new ProfitBatchSuccess()); if (Admin::user()->can('dcat.admin.profit.pay')) {
// }); $batch->add(new ProfitBatchSuccess());
}
});
}); });
} }
@ -88,10 +91,6 @@ class OrderProfitController extends AdminController
$tools->disableEdit(); $tools->disableEdit();
$tools->disableDelete(); $tools->disableDelete();
}); });
$show->tools(function (Show\Tools $tools) {
$tools->append(new ProfitSuccess());
});
}); });
} }

View File

@ -2,41 +2,33 @@
namespace App\Admin\Extensions\Grid\Tools; namespace App\Admin\Extensions\Grid\Tools;
use App\Models\Profit; use App\Admin\Forms\ProfitSuccessForm;
use Dcat\Admin\Grid\BatchAction; use Dcat\Admin\Grid\BatchAction;
use Illuminate\Http\Request; use Dcat\Admin\Widgets\Modal;
use Illuminate\Support\Facades\DB;
use Throwable;
class ProfitBatchSuccess extends BatchAction class ProfitBatchSuccess extends BatchAction
{ {
protected $title = '支付成功'; protected $title = '支付';
protected function authorize($user): bool protected function html()
{ {
return $user->can('dcat.admin.profit.pay'); $form = ProfitSuccessForm::make();
return Modal::make()
->lg()
->title($this->title)
->body($form)
->onLoad($this->getModalScript())
->button($this->title);
} }
public function confirm() protected function getModalScript()
{
return '是否确认?';
}
// 处理请求
public function handle(Request $request)
{ {
// 弹窗显示后往隐藏的id表单中写入批量选中的行ID
return <<<JS
// 获取选中的ID数组 // 获取选中的ID数组
$keys = $this->getKey(); var key = {$this->getSelectedKeysScript()}
try {
DB::beginTransaction();
DB::commit(); $('#order-profit-ids').val(key);
} catch (Throwable $th) { JS;
DB::rollBack();
report($th);
return $this->response()->error('操作失败,'.$th->getMessage())->refresh();
}
return $this->response()->success('操作成功')->refresh();
} }
} }

View File

@ -3,31 +3,16 @@
namespace App\Admin\Forms; namespace App\Admin\Forms;
use App\Services\DistributeService; use App\Services\DistributeService;
use App\Exceptions\BizException;
use App\Models\OrderProfit; use App\Models\OrderProfit;
use Dcat\Admin\Contracts\LazyRenderable; use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget; use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form; use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Throwable;
use App\Enums\PayWay; use App\Enums\PayWay;
class ProfitSuccessForm extends Form implements LazyRenderable class ProfitSuccessForm extends Form implements LazyRenderable
{ {
use LazyWidget; use LazyWidget;
/**
* 权限判断,如不需要可以删除此方法
*
* @param Model|Authenticatable|HasPermissions|null $user
*
* @return bool
*/
protected function authorize($user): bool
{
return $user->can('dcat.admin.profit.pay');
}
/** /**
* Handle the form request. * Handle the form request.
* *
@ -37,26 +22,23 @@ class ProfitSuccessForm extends Form implements LazyRenderable
*/ */
public function handle(array $input) public function handle(array $input)
{ {
$order = OrderProfit::findOrFail($this->payload['id']); $ids = explode(',', $input['ids']);
$list = OrderProfit::whereIn('id', $ids)->whereNotIn('status', [1, 2])->get()->groupBy('user_id');
$way = $input['pay_way'];
$service = new DistributeService(); $service = new DistributeService();
if ($input['pay_way'] === PayWay::WxpayTransfer->value && !$order->pay_no) { foreach($list as $id => $items) {
$order->update([ try {
'pay_no' => serial_number(), DB::beginTransaction();
'pay_way' => PayWay::WxpayTransfer->value if ($way === PayWay::WxpayTransfer->value) {
]); $service->wechatTransfers($items);
} } else if ($way === PayWay::Offline->value) {
try { $service->success($items, $input);
DB::beginTransaction(); }
if ($input['pay_way'] === PayWay::WxpayTransfer->value) { DB::commit();
$service->wechatTransfer($order); } catch (\Exception $e) {
} else { DB::rollBack();
$service->success($order, $input); return $this->response()->error($e->getMessage());
} }
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
throw new BizException('操作失败:'.$th->getMessage());
} }
return $this->response()->success('操作成功')->refresh(); return $this->response()->success('操作成功')->refresh();
} }
@ -66,15 +48,13 @@ class ProfitSuccessForm extends Form implements LazyRenderable
*/ */
public function form() public function form()
{ {
$order = OrderProfit::findOrFail($this->payload['id']); $this->hidden('ids')->attribute('id', 'order-profit-ids');
$this->datetime('paid_at')->value(now()); $this->datetime('paid_at')->value(now());
$this->radio('pay_way')->options([ $this->radio('pay_way')->options([
PayWay::Offline->value => PayWay::Offline->text(), PayWay::Offline->value => PayWay::Offline->text(),
PayWay::WxpayTransfer->value => PayWay::WxpayTransfer->text() PayWay::WxpayTransfer->value => PayWay::WxpayTransfer->text()
])->default(PayWay::Offline->value); ])->default(PayWay::Offline->value);
$this->text('pay_no'); $this->text('pay_no');
$this->text('remarks')->value($order->remark);
$this->disableResetButton(); $this->disableResetButton();
} }

View File

@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Enums\PayWay; use App\Enums\PayWay;
use App\Models\Order; use App\Models\Order;
use App\Models\OrderProfit;
use App\Services\DistributeService; use App\Services\DistributeService;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -45,14 +46,10 @@ class OrderProfitCommand extends Command
// 售后过期天数 7 // 售后过期天数 7
$saleDays = app_settings('app.sale_after_expire_days'); $saleDays = app_settings('app.sale_after_expire_days');
// 支付方式
$payWay = PayWay::WxpayTransfer->value;
while (true) { while (true) {
$page = 0; $page = 0;
$orders = Order::with([ $orders = Order::query()
'profits' => fn($q) => $q->where('status', 0)
])
// 订单已完成 // 订单已完成
->where('status', Order::STATUS_COMPLETED) ->where('status', Order::STATUS_COMPLETED)
// 没有售后订单 // 没有售后订单
@ -61,35 +58,30 @@ class OrderProfitCommand extends Command
->where('completed_at', '<', now()->subDays($saleDays)) ->where('completed_at', '<', now()->subDays($saleDays))
// 未支付提成 // 未支付提成
->whereNull('profit_paid') ->whereNull('profit_paid')
->limit(200) ->limit(10)
->get(); ->get();
foreach ($orders as $order) { // 修改提成记录的状态为 等待结算
foreach($order->profits as $profit) { OrderProfit::whereIn('order_id', $orders->pluck('id'))->where('status', 0)->update(['status' => 4]);
try {
DB::beginTransaction(); // 获取 等待结算 的提成记录, 按照 user_id 分组
if ($payWay === PayWay::WxpayTransfer->value) { $list = OrderProfit::where('status', 4)->get()->groupBy('user_id');
if (!$profit->pay_no) { foreach($list as $id => $items) {
$profit->update([ try {
'pay_no' => serial_number(), DB::beginTransaction();
'pay_way' => $payWay $service->wechatTransfers($items);
]); DB::commit();
} } catch (\Exception $e) {
$service->wechatTransfer($profit); DB::rollBack();
} $this->error($e->getMessage());
DB::commit();
} catch (\Throwable $e) {
DB::rollBack();
$this->error($e->getMessage());
}
}
// 没有待付款的提成记录
if (!$order->profits()->where('status', 0)->exists()) {
// 更新订单
$order->update(['profit_paid' => now()]);
} }
} }
// 没有待付款的提成记录
// if (!$order->profits()->where('status', 0)->exists()) {
// $order->update(['profit_paid' => now()]);
// }
$page++; $page++;
if ($page === 0) { if ($page === 0) {

View File

@ -11,17 +11,19 @@ class OrderProfit extends Model
use HasFactory, HasDateTimeFormatter; use HasFactory, HasDateTimeFormatter;
public static $statusMap = [ public static $statusMap = [
0 => '待付款', 0 => '订单未结算',
4 => '待付款',
1 => '付款中', 1 => '付款中',
2 => '已付款', 2 => '已付款',
3 => '付款失败' 3 => '付款失败',
]; ];
public static $statusColor = [ public static $statusColor = [
0 => 'primary', 0 => 'primary',
1 => 'warning', 1 => 'warning',
2 => 'success', 2 => 'success',
3 => 'danger' 3 => 'danger',
4 => 'gray'
]; ];
protected $fillable = ['id', 'order_id', 'from_user_id', 'user_id', 'role', 'role_name', 'growth_value', 'ratio', 'money', 'sub_money', 'status', 'paid_at', 'pay_no', 'pay_way', 'pay_data', 'remarks']; protected $fillable = ['id', 'order_id', 'from_user_id', 'user_id', 'role', 'role_name', 'growth_value', 'ratio', 'money', 'sub_money', 'status', 'paid_at', 'pay_no', 'pay_way', 'pay_data', 'remarks'];

View File

@ -2,11 +2,13 @@
namespace App\Services; namespace App\Services;
use App\Models\{User, Order, SalesValueLog, Agent, OrderProfit}; use App\Models\{User, Order, SalesValueLog, Agent, OrderProfit, SocialiteUser};
use App\Services\Payment\WxpayService; use App\Services\Payment\WxpayService;
use App\Enums\SocialiteType; use App\Enums\SocialiteType;
use App\Exceptions\BizException; use App\Exceptions\BizException;
use App\Exceptions\WeChatPayException; use App\Exceptions\WeChatPayException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
/** /**
* 分销模块 * 分销模块
@ -159,45 +161,64 @@ class DistributeService
} }
/** /**
* 批量支付
* 使用微信企业付款, 支付返利金额 * 使用微信企业付款, 支付返利金额
* 调用之前, 需要提前生成商户订单号 * 支付的金额必须大于 1, 并且是同一个人的
*
* @throws WeChatPayException
*/ */
public function wechatTransfer(OrderProfit $profit) public function wechatTransfers(Collection $list)
{ {
$user = $profit->user; if ($list->count() === 0) {
$openid = $user->socialites()->where('socialite_type', SocialiteType::WechatMiniProgram->value)->value('socialite_id'); throw new BizException('记录数必须大于 0');
if ($profit->money <= 0) {
throw new WeChatPayException('返利金额必须大于0');
} }
$filtered = collect();
$money = 0;
$userId = $list->first()->user_id;
// 商户订单号
$sn = serial_number();
foreach($list as $item) {
// 待付款, 同一收款用户
if ($item->status === 4 && $item->user_id === $userId) {
$item->update([
'status' => 1,
'pay_no' => $sn
]);
$money += $item->money;
$filtered->push($item);
}
}
if ($money < 1) {
throw new BizException('金额小于 1, 无法打款');
}
$openid = SocialiteUser::where('socialite_type', SocialiteType::WechatMiniProgram->value)->where('user_id', $userId)->value('socialite_id');
if (!$openid) { if (!$openid) {
throw new WeChatPayException('没有 openid'); throw new BizException('用户 '.$userId.' 没有 openid');
} }
$result = (new WxpayService())->transfer([ $result = (new WxpayService())->transfer([
'partner_trade_no' => $profit->pay_no, 'partner_trade_no' => $sn,
'openid' => $openid, 'openid' => $openid,
'check_name' => 'NO_CHECK', 'check_name' => 'NO_CHECK',
'amount' => $profit->money * 100, 'amount' => $money * 100,
'desc' => '推荐返利', 'desc' => '推荐返利',
]); ]);
$this->success($profit, $result); $this->success($filtered, $result);
} }
/** /**
* 返现记录支付成功 * 支付成功
* *
* @param \App\Models\OrderProfit $profit * @param Collection $list 提成记录
* @param mixed $data [paid_at, remarks, pay_way] * @param array $result [paid_at, remarks]
*/ */
public function success(OrderProfit $profit, $data = null) public function success(Collection $list, $result = [])
{ {
$profit->update([ OrderProfit::whereIn('id', $list->pluck('id'))->update([
'status' => 2, 'status' => 2,
'paid_at' => data_get($data, 'paid_at', now()), 'paid_at' => data_get($result, 'paid_at', now()),
'pay_data' => $data, 'pay_data' => $result,
'remarks' => data_get($data, 'remarks'), 'remarks' => data_get($result, 'remarks'),
]); ]);
} }
} }