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

View File

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

View File

@ -3,31 +3,16 @@
namespace App\Admin\Forms;
use App\Services\DistributeService;
use App\Exceptions\BizException;
use App\Models\OrderProfit;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Facades\DB;
use Throwable;
use App\Enums\PayWay;
class ProfitSuccessForm extends Form implements LazyRenderable
{
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.
*
@ -37,26 +22,23 @@ class ProfitSuccessForm extends Form implements LazyRenderable
*/
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();
if ($input['pay_way'] === PayWay::WxpayTransfer->value && !$order->pay_no) {
$order->update([
'pay_no' => serial_number(),
'pay_way' => PayWay::WxpayTransfer->value
]);
}
try {
DB::beginTransaction();
if ($input['pay_way'] === PayWay::WxpayTransfer->value) {
$service->wechatTransfer($order);
} else {
$service->success($order, $input);
foreach($list as $id => $items) {
try {
DB::beginTransaction();
if ($way === PayWay::WxpayTransfer->value) {
$service->wechatTransfers($items);
} else if ($way === PayWay::Offline->value) {
$service->success($items, $input);
}
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
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();
}
@ -66,15 +48,13 @@ class ProfitSuccessForm extends Form implements LazyRenderable
*/
public function form()
{
$order = OrderProfit::findOrFail($this->payload['id']);
$this->hidden('ids')->attribute('id', 'order-profit-ids');
$this->datetime('paid_at')->value(now());
$this->radio('pay_way')->options([
PayWay::Offline->value => PayWay::Offline->text(),
PayWay::WxpayTransfer->value => PayWay::WxpayTransfer->text()
])->default(PayWay::Offline->value);
$this->text('pay_no');
$this->text('remarks')->value($order->remark);
$this->disableResetButton();
}

View File

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

View File

@ -11,17 +11,19 @@ class OrderProfit extends Model
use HasFactory, HasDateTimeFormatter;
public static $statusMap = [
0 => '待付款',
0 => '订单未结算',
4 => '待付款',
1 => '付款中',
2 => '已付款',
3 => '付款失败'
3 => '付款失败',
];
public static $statusColor = [
0 => 'primary',
1 => 'warning',
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'];

View File

@ -2,11 +2,13 @@
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\Enums\SocialiteType;
use App\Exceptions\BizException;
use App\Exceptions\WeChatPayException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
/**
* 分销模块
@ -159,45 +161,64 @@ class DistributeService
}
/**
* 批量支付
* 使用微信企业付款, 支付返利金额
* 调用之前, 需要提前生成商户订单号
*
* @throws WeChatPayException
* 支付的金额必须大于 1, 并且是同一个人的
*/
public function wechatTransfer(OrderProfit $profit)
public function wechatTransfers(Collection $list)
{
$user = $profit->user;
$openid = $user->socialites()->where('socialite_type', SocialiteType::WechatMiniProgram->value)->value('socialite_id');
if ($profit->money <= 0) {
throw new WeChatPayException('返利金额必须大于0');
if ($list->count() === 0) {
throw new BizException('记录数必须大于 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) {
throw new WeChatPayException('没有 openid');
throw new BizException('用户 '.$userId.' 没有 openid');
}
$result = (new WxpayService())->transfer([
'partner_trade_no' => $profit->pay_no,
'partner_trade_no' => $sn,
'openid' => $openid,
'check_name' => 'NO_CHECK',
'amount' => $profit->money * 100,
'amount' => $money * 100,
'desc' => '推荐返利',
]);
$this->success($profit, $result);
$this->success($filtered, $result);
}
/**
* 返现记录支付成功
* 支付成功
*
* @param \App\Models\OrderProfit $profit
* @param mixed $data [paid_at, remarks, pay_way]
* @param Collection $list 提成记录
* @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,
'paid_at' => data_get($data, 'paid_at', now()),
'pay_data' => $data,
'remarks' => data_get($data, 'remarks'),
'paid_at' => data_get($result, 'paid_at', now()),
'pay_data' => $result,
'remarks' => data_get($result, 'remarks'),
]);
}
}