Files
site/app/Domain/Votes/Services/VoteService.php
2025-04-21 16:03:20 +02:00

181 lines
5.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Domain\Votes\Services;
use DB;
use Carbon\Carbon;
use App\Models\User;
use App\Domain\Points\Models\Point;
use App\Domain\Points\Enums\DirectionEnum;
use App\Domain\Subscriptions\Models\Subscription;
use App\Domain\Subscriptions\Service\SubscriptionService;
class VoteService
{
public $vote;
public $leaders;
public function __construct($vote)
{
$leader_count = nova_get_setting('vote_leader_count');
$leaders = SubscriptionService::leaders();
$leaders = array_column(array_slice($leaders, 0, $leader_count), 'user_id');
$this->leaders = $leaders;
$this->vote = $vote;
}
public function accrualPoints()
{
DB::beginTransaction();
$procent_site = (int)nova_get_setting('vote_procent_site');
$procent_site = $procent_site / 100;
$procent_top = (int)nova_get_setting('vote_procent_leader');
$procent_top = $procent_top / 100;
$procent_local = (int)nova_get_setting('vote_procent_local_leader');
$procent_local = $procent_local / 100;
$subscriptions = Subscription::with('user.subscribers.subscription')->where('ends_at', '>', Carbon::now())
->where('status', 'complete')->get();
$sum_site = 0;
$sdr_leader_pay = 0;
$sdr_leader_for_all_pay = [];
foreach ($subscriptions as $subscription) {
$user = $subscription->user;
$subscribers = $this->activeSubs($user->subscribers);
// Фильтр лидеров
$subscribersLeader = $subscribers->filter(function ($subscriber) {
return $subscriber->pivot->leader === 1;
});
// Фильтр простых пользователей
$subscribersSimple = $subscribers->filter(function ($subscriber) {
return $subscriber->pivot->leader === 0;
});
$price = $subscription->price;
$to_site = round($price * $procent_site);
$sum_site += $to_site;
$sdr = round($price - $to_site); // сумма для распределения
$sdr_leader_global = round($sdr * $procent_top);
$sdr_leader_local = round($sdr * $procent_local);
$sdr_simple = $sdr - $sdr_leader_global - $sdr_leader_local;
// добавляем лидерам
$sdr_leader_pay += $sdr_leader_global;
//если 0 подписок, но куплена подписка на сайт
// отдаем лидеру 40%, а 60% сайту
if($subscribers->isEmpty()){
$sum_site += ($sdr - $sdr_leader_global); // 20%сайту(вместо локальных) и 40%сайту (вместо простых)
}else {
if ($subscribersLeader->isNotEmpty()) {
//Выплачиваем каждому локальному лидеру
$sdr_parts_local = round($sdr_leader_local / $subscribersLeader->count());
//сохраняем транзакции локальных лидеров
foreach ($subscribersLeader as $subs) {
$sdr_leader_for_all_pay[$subs->id][] = $sdr_parts_local;
}
}else{
$sum_site += $sdr_leader_local; //если у пользователя есть подписки, но он не выбрал лидеров
}
if ($subscribersSimple->isNotEmpty()) {
//Выплачиваем каждому юзеру
$sdr_parts = round($sdr_simple / $subscribersSimple->count());
//сохраняем транзакции простых пользователей
foreach ($subscribersSimple as $subs) {
$sdr_leader_for_all_pay[$subs->id][] = $sdr_parts;
}
}else{
$sum_site += $sdr_simple;
}
}
$this->updateSubs($subscription);
}
$part_for_leader = round($sdr_leader_pay/count($this->leaders));
foreach ($this->leaders as $leader) {
$sdr_leader_for_all_pay[$leader][] = $part_for_leader;
}
$this->payUsers($sdr_leader_for_all_pay);
$this->payForSystemUser($sum_site);
DB::commit();
}
private function payUsers($sdr)
{
$sdr_users_pay = array_map(function ($lines) {
return array_sum($lines);
}, $sdr);
foreach ($sdr_users_pay as $user_pay_id => $sdr_user) {
$this->addPoint($user_pay_id, $sdr_user);
}
}
private function payForSystemUser($sum_site)
{
$system_user_id = User::system()->id;
$this->addPoint($system_user_id, $sum_site);
}
private function addPoint($user_id, $amount)
{
$point = new Point;
$point->user_id = $user_id;
$point->point = $amount;
$point->type = 'votes'; //YSV ENUM!
$point->direction = DirectionEnum::COMING();
$point->save();
$this->vote->users()->attach($user_id, ['payment' => $amount]);
}
private function updateSubs($sub)
{
$sub->status = 'end'; //YSV ENUM!
$sub->save();
}
//проверка на акт. подписки
private function activeSubs($subscribers)
{
return $subscribers->filter(function ($subscriber) {
return optional($subscriber->subscription->first())->ends_at > Carbon::now();
});
}
public function freeMode()
{
$users = SubscriptionService::freeLeaders();
foreach ($users as $leader) {
$this->vote->users()->attach($leader->id, ['payment' => $leader->countVote]);
}
}
}