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

134 行
4.9 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?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;
}
}