134 行
4.9 KiB
PHP
134 行
4.9 KiB
PHP
<?php
|
||
|
||
namespace addons\shopro\service\partner;
|
||
|
||
/**
|
||
* 创客协同(逐代 10% 递减级联,最低发放不能少于 0.10 元截断)/ 创客卓越 5%(只一层)
|
||
*/
|
||
class MakerPeerReward
|
||
{
|
||
public function run($order, $buyerId, $chain, $diffResult, ActiveService $active)
|
||
{
|
||
$bonus = PartnerConfig::makerBonus();
|
||
$peerRate = (float) PartnerConfig::get('partner_maker_peer_rate', 0.10);
|
||
$overRate = (float) PartnerConfig::get('partner_maker_overtaken_rate', 0.05);
|
||
$minAmount = (float) PartnerConfig::get('partner_peer_min_amount', 0.10);
|
||
if ($minAmount <= 0) {
|
||
$minAmount = 0.10;
|
||
}
|
||
$maxPeerGenerations = (int) PartnerConfig::get('partner_maker_peer_max_generations', 50);
|
||
if ($maxPeerGenerations <= 0) {
|
||
$maxPeerGenerations = 50;
|
||
}
|
||
$paid = $diffResult['paid'] ?? [];
|
||
$indexByUser = [];
|
||
foreach ($chain as $i => $node) {
|
||
$indexByUser[$node['user_id']] = $i;
|
||
}
|
||
|
||
foreach ($paid as $item) {
|
||
$from = $indexByUser[$item['user_id']] ?? -1;
|
||
if ($from < 0) {
|
||
continue;
|
||
}
|
||
|
||
$levelBonus = (float) ($bonus[$item['level']] ?? 0);
|
||
$currentFrom = $from;
|
||
$currentBase = $levelBonus;
|
||
$sourceUserId = $item['user_id'];
|
||
|
||
for ($gen = 1; $gen <= $maxPeerGenerations; $gen++) {
|
||
$peerIdx = $this->findUpIndex($chain, $currentFrom + 1, function ($node) use ($item) {
|
||
return intval($node['level']) === intval($item['level']);
|
||
});
|
||
if ($peerIdx < 0) {
|
||
break;
|
||
}
|
||
|
||
$peer = $chain[$peerIdx];
|
||
$amount = round($currentBase * $peerRate, 2);
|
||
if ($amount < $minAmount) {
|
||
break; // 收益少于 0.10 元,上级平级不再拿,严格截断
|
||
}
|
||
|
||
if (!$active->isActive($peer['agent'] ?? $peer)) {
|
||
PartnerRewardService::writeSkip(
|
||
$order,
|
||
$buyerId,
|
||
$peer['user_id'],
|
||
'maker_peer',
|
||
'maker',
|
||
'inactive_30d',
|
||
"协同创客(第{$gen}代) 30 日无自购"
|
||
);
|
||
} else {
|
||
PartnerRewardService::account(
|
||
$order,
|
||
$buyerId,
|
||
$peer['user_id'],
|
||
'maker_peer',
|
||
'maker',
|
||
$amount,
|
||
$currentBase,
|
||
[
|
||
'generation' => $gen,
|
||
'formula' => "创客协同(第{$gen}代) {$currentBase} × " . ($peerRate * 100) . "% = {$amount}",
|
||
'from_user_id' => $sourceUserId,
|
||
'level' => $item['level'],
|
||
]
|
||
);
|
||
}
|
||
|
||
// 下一代平级的寻源起点与计算基数:以当前平级创客为基础,基数变为当前平级奖金
|
||
$currentFrom = $peerIdx;
|
||
$currentBase = $amount;
|
||
$sourceUserId = $peer['user_id'];
|
||
|
||
if ($currentBase < $minAmount) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (empty($paid)) {
|
||
return;
|
||
}
|
||
$highest = $paid[count($paid) - 1];
|
||
$from = $indexByUser[$highest['user_id']] ?? -1;
|
||
$lower = $this->findUp($chain, $from + 1, function ($node) use ($highest) {
|
||
return intval($node['level']) >= 2 && intval($node['level']) < intval($highest['level']);
|
||
});
|
||
if (!$lower) {
|
||
return;
|
||
}
|
||
$amount = round((float) $highest['cap'] * $overRate, 2);
|
||
if (!$active->isActive($lower['agent'] ?? $lower)) {
|
||
PartnerRewardService::writeSkip($order, $buyerId, $lower['user_id'], 'maker_overtaken', 'maker', 'inactive_30d', '卓越创客 30 日无自购');
|
||
return;
|
||
}
|
||
if ($amount < $minAmount) {
|
||
return;
|
||
}
|
||
PartnerRewardService::account($order, $buyerId, $lower['user_id'], 'maker_overtaken', 'maker', $amount, $highest['cap'], [
|
||
'formula' => "创客卓越 最高基数 {$highest['cap']} × " . ($overRate * 100) . "% = {$amount}",
|
||
'from_user_id' => $highest['user_id'],
|
||
]);
|
||
}
|
||
|
||
protected function findUpIndex($chain, $start, $matcher)
|
||
{
|
||
for ($i = $start; $i < count($chain); $i++) {
|
||
if ($matcher($chain[$i])) {
|
||
return $i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
protected function findUp($chain, $start, $matcher)
|
||
{
|
||
$idx = $this->findUpIndex($chain, $start, $matcher);
|
||
return $idx >= 0 ? $chain[$idx] : null;
|
||
}
|
||
}
|