181 lines
5.8 KiB
PHP
181 lines
5.8 KiB
PHP
<?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]);
|
||
}
|
||
|
||
}
|
||
|
||
}
|