文件
Henglianshutong/addons/shopro/service/partner/WalletMigrationService.php

142 行
4.8 KiB
PHP

<?php
namespace addons\shopro\service\partner;
use think\Db;
use app\admin\model\shopro\user\User as UserModel;
use addons\shopro\service\Wallet;
/**
* 历史收益全量结转至商城余额服务
*/
class WalletMigrationService
{
/**
* 结转前数据预览(只读试算)
*
* @return array
*/
public function preview()
{
$query = UserModel::where('commission', '>', 0);
$totalCount = (int) $query->count();
$totalCommission = (float) $query->sum('commission');
$sampleList = UserModel::where('commission', '>', 0)
->field('id,nickname,mobile,money,commission')
->order('commission', 'desc')
->limit(20)
->select();
$samples = [];
foreach ($sampleList as $u) {
$samples[] = [
'id' => (int) $u->id,
'nickname' => (string) ($u->nickname ?: '用户' . $u->id),
'mobile' => (string) ($u->mobile ?: ''),
'current_money' => number_format((float) $u->money, 2, '.', ''),
'current_commission' => number_format((float) $u->commission, 2, '.', ''),
'target_money' => number_format((float) bcadd((string) $u->money, (string) $u->commission, 2), 2, '.', ''),
];
}
return [
'total_users' => $totalCount,
'total_commission' => number_format($totalCommission, 2, '.', ''),
'samples' => $samples,
];
}
/**
* 执行全量结转:将所有会员的 commission 余额转入 money 钱包
*
* @param bool $isDryRun 是否只读模拟
* @param callable|null $progressCallback 进度回调
* @param array $operator 操作人上下文
* @return array
*/
public function transferAll($isDryRun = false, $progressCallback = null, $operator = [])
{
if ($isDryRun) {
$preview = $this->preview();
return [
'status' => 'dry_run',
'dry_run' => true,
'total_users' => $preview['total_users'],
'transferred_amount' => $preview['total_commission'],
'success_count' => 0,
'fail_count' => 0,
'errors' => [],
'preview' => $preview,
];
}
$userIds = UserModel::where('commission', '>', 0)->order('id', 'asc')->column('id');
$totalUsers = count($userIds);
$successCount = 0;
$failCount = 0;
$transferredAmount = '0.00';
$errors = [];
foreach ($userIds as $idx => $userId) {
try {
$transferResult = Db::transaction(function () use ($userId) {
$user = UserModel::where('id', $userId)->lock(true)->find();
if (!$user) {
return 0.0;
}
$amount = floatval($user->commission);
if ($amount <= 0) {
return 0.0;
}
// 1. 扣减佣金钱包
Wallet::change($user, 'commission', -$amount, 'transfer_to_money', [
'batch_migration' => 1,
'reason' => '全量历史收益结转至商城余额',
], '收益结转至商城余额');
// 2. 增加商城余额
Wallet::change($user, 'money', $amount, 'transfer_by_commission', [
'batch_migration' => 1,
'reason' => '全量历史收益结转至商城余额',
], '收益结转至商城余额');
return $amount;
});
if ($transferResult > 0) {
$successCount++;
$transferredAmount = bcadd($transferredAmount, (string) $transferResult, 2);
}
if (is_callable($progressCallback)) {
$progressCallback($idx + 1, $totalUsers, $userId, $transferResult, null);
}
} catch (\Throwable $e) {
$failCount++;
$errItem = [
'user_id' => $userId,
'error' => $e->getMessage(),
];
$errors[] = $errItem;
if (is_callable($progressCallback)) {
$progressCallback($idx + 1, $totalUsers, $userId, 0.0, $e->getMessage());
}
}
}
return [
'status' => 'completed',
'dry_run' => false,
'total_users' => $totalUsers,
'success_count' => $successCount,
'fail_count' => $failCount,
'transferred_amount' => number_format((float) $transferredAmount, 2, '.', ''),
'errors' => $errors,
];
}
}