Created
May 5, 2020 11:06
-
-
Save worstn8mare/1b89e13c99f9f0d7fb9bbc6591fa0470 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Modules\Commission\Services; | |
use Carbon\Carbon; | |
use Illuminate\Support\Facades\DB; | |
use Illuminate\Support\Facades\File; | |
use Modules\Commission\Models\Goldmine2CommissionBypass; | |
use Modules\Commission\Models\Goldmine2CommissionBypassLevels; | |
use Modules\Credit\Models\BankAccount; | |
use Modules\Mt4\Models\Mt4Trade; | |
use Modules\Mt4\Models\Mt4User; | |
use Modules\Mt4Transfer\Models\Mt4TradeType; | |
use Modules\Mt4Transfer\Models\Trader; | |
use Modules\User\Models\User; | |
class Goldmine2CommissionService extends CommissionAbstract | |
{ | |
public $goldmine2Settings; | |
protected $maxDepth = 12; | |
protected $goldmineType = 'goldmine 2 commission'; | |
protected $goldmineTypeId; | |
private $masterTraderLots; | |
private $lotPerVolume; | |
/** | |
* @var string | |
*/ | |
private $mt4TradesTable; | |
/** | |
* @var string | |
*/ | |
private $mt4UsersTable; | |
/** | |
* @var bool|string | |
*/ | |
private $enabledPromo; | |
/** | |
* @var bool|string | |
*/ | |
private $enabledPromoValues; | |
private $usersPromoClassification; | |
private $qualifiedUsers; | |
/** | |
* @var bool|string | |
*/ | |
private $bypassMinimumAmount; | |
private $transferSummary; | |
/** | |
* @var string | |
*/ | |
private $directory; | |
/** | |
* @var string | |
*/ | |
private $fileDate; | |
private $userTiersCurrent; | |
private $transferLifetimeSummary; | |
/** | |
* @var Goldmine2CommissionBypass | |
*/ | |
private $gm2BypassModel; | |
public function __construct(Goldmine2CommissionBypass $gm2BypassModel) | |
{ | |
$this->logText = ''; | |
$this->directory = storage_path('logs') . '/goldmine2/'; | |
if (!File::exists($this->directory)) { | |
File::makeDirectory($this->directory); | |
} | |
$this->fileDate = Carbon::now()->format('Y-m-d-h-i-s'); | |
$this->path = $this->directory . "goldmine2-" . $this->fileDate; | |
$this->gm2BypassModel = $gm2BypassModel; | |
} | |
public function payout($tradeCommissions, $userTiers) | |
{ | |
// commissions here is already the total of profit and volume from mt4_trades | |
$goldmineCommissionToInsert = []; | |
$goldminePayoutToInsert = []; | |
$goldmineCommissionUsers = $tradeCommissions->pluck('user_id', 'user_id')->toArray(); | |
$bank_accounts = BankAccount::get()->pluck('id', 'reference_id')->toArray(); | |
$this->userTiers = $userTiers; | |
if (count($goldmineCommissionUsers) > 0) { | |
$sponsorTreeNodes = $this->sponsorTreeData->filter(function ($sponsorNode) use ($goldmineCommissionUsers) { | |
return in_array($sponsorNode['user_id'], $goldmineCommissionUsers); | |
}); | |
foreach ($sponsorTreeNodes as $node) { | |
$uplines = $this->sponsorTreeData->filter(function ($sponsorNode) use ($node) { | |
return $sponsorNode['lft'] < $node['lft'] && $sponsorNode['rgt'] > $node['rgt']; | |
}); | |
$uplines_sorted = $uplines->sortByDesc('level'); | |
$trade = $tradeCommissions[$node['user_id']]; | |
$trade['level'] = 1; | |
$invested_amount = $this->getInvestedAmount($trade->user_id); | |
$this->logText .= "[Contributor]: " . $node['user_id'] . " [total trades] " . $trade->total_trades . " [invested_amount]: $invested_amount \n"; | |
foreach ($uplines_sorted as $upline) { | |
if ($trade->level > $this->maxDepth) { | |
break; | |
} | |
$uplineUserId = $upline['user_id']; | |
if (!$this->isEligible($trade, $userTiers, $uplineUserId)) { | |
$trade->level++; | |
continue; | |
} | |
if (!$this->toCompressUser($uplineUserId, $userTiers, $trade->level)) { | |
$calculated_amount = $this->calculateAmount($trade, $userTiers, $uplineUserId); | |
if ($calculated_amount > 0) { | |
$goldmineCommissionToInsert[] = [ | |
'user_id' => $uplineUserId, | |
'contributor_user_id' => $node['user_id'], | |
'amount' => $invested_amount, // amount field in goldmine 2 is the invested amount | |
'calculated_amount' => $calculated_amount, | |
'level_percentage' => 0, | |
'commission_percentage' => 0, | |
'level' => $trade->level, | |
'payout_date' => $trade->open_time, | |
'created_at' => Carbon::now(), | |
'updated_at' => Carbon::now(), | |
'goldmine_commission_type' => $this->goldmineTypeId, | |
]; | |
$transactionCode = $this->generateTransactionCode($uplineUserId, $node['user_id'], $this->bankTransactionType); | |
$this->appendGoldmineCommissionLogs( | |
[ | |
'user_id' => $uplineUserId, | |
'user_tier' => $this->getTier($userTiers, $uplineUserId), | |
'user_isContract' => $userTiers[$uplineUserId]['contract_type_id'], //---> add contract for snapshot user_tier | |
'contributor_id' => $node['user_id'], | |
'amount' => $invested_amount, // amount field in goldmine 2 is the invested amount | |
'calculated_amount' => $calculated_amount, | |
'trade_volume' => $trade->total_trades, | |
'transaction_code' => $transactionCode, | |
'user_level' => $trade->level | |
] | |
); | |
$goldminePayoutToInsert[] = [ | |
'credit' => $calculated_amount, | |
'transaction_code' => $transactionCode, | |
'transaction_date' => Carbon::now(), | |
'bank_transaction_type_id' => $this->bankTransactionType, | |
'bank_credit_type_id' => $this->bankCreditTypeId, | |
'transfer_account_id' => null, | |
'bank_account_id' => isset($bank_accounts[$uplineUserId]) ? $bank_accounts[$uplineUserId] : null, | |
'done_by' => 1, // assume admin | |
'remarks' => 'Goldmine 2 Commission', | |
'created_at' => Carbon::now(), | |
'updated_at' => Carbon::now() | |
]; | |
} | |
$trade->level++; | |
} | |
} | |
} | |
} | |
$this->persistCommissionTrades($goldmineCommissionToInsert); | |
$this->persistGoldmineCommissionLogs(); | |
$this->persistBankAccountStatement($goldminePayoutToInsert); | |
return true; | |
} | |
public function setValues() | |
{ | |
parent::setValues(); // TODO: Change the autogenerated stub | |
$this->goldmine2Settings = json_decode(setting('goldmine_payout_amount_per_lot'), true); | |
$this->mt4TradesTable = (new Mt4Trade())->getTable(); | |
$this->mt4UsersTable = (new Mt4User())->getTable(); | |
$this->lotPerVolume = setting('lot_per_volume'); | |
$this->getEnabledPromo(); | |
$this->setBypassMinimumAmount(); | |
$this->fetchQualifiedUsers(); | |
} | |
public function getTradeLots($tradeStartDate, $tradeEndDate) | |
{ | |
return User::join('user_mt4_ids', function ($join) { | |
$join->on('user_mt4_ids.user_id', '=', 'users.id') | |
->whereNotNull('trader_id') | |
->where('mt4_trade_type_id', Mt4TradeType::COPY_TRADE); // do checking here | |
}) | |
->join('traders', 'traders.id', '=', 'user_mt4_ids.trader_id') | |
->join($this->mt4TradesTable, function ($join) use ($tradeStartDate, $tradeEndDate) { | |
$join->on('user_mt4_ids.member_id', '=', $this->mt4TradesTable . '.login') | |
->whereBetween($this->mt4TradesTable . '.open_time', [$tradeStartDate, $tradeEndDate]) | |
->whereIn($this->mt4TradesTable . '.cmd', $this->cmd); | |
}) | |
->join($this->mt4UsersTable, $this->mt4UsersTable . '.login', '=', $this->mt4TradesTable . '.login') | |
->join('bank_accounts', 'bank_accounts.reference_id', '=', 'users.id'); | |
} | |
public function getEnabledPromo() | |
{ | |
$this->enabledPromo = json_decode(setting('goldmine_2_promotion_release_criteria')); | |
$this->enabledPromoValues = json_decode(setting('goldmine_2_promotion_registration_payout'), true); | |
$this->usersPromoClassification = []; | |
if ($this->enabledPromo->enabled) { | |
$this->usersPromoClassification = User::select( | |
[ | |
'id', | |
'member_id', | |
'contract_type_id', | |
DB::raw(" | |
CASE | |
WHEN created_at <= '" . Carbon::parse($this->enabledPromo->end)->endOfDay()->format('y-m-d H:i:s') . "' THEN true | |
ELSE false | |
END AS is_promotion | |
") | |
] | |
)->get() | |
->keyBy('id') | |
->toArray(); | |
} | |
} | |
public function bypassCommQualificationCheck($uplineId, $userTiers, $level) | |
{ | |
$returnValue = false; | |
if (isset($this->qualifiedUsers[$uplineId])) { | |
$qualifiedUser = $this->qualifiedUsers[$uplineId]; | |
$balance = $this->getUserBalance($uplineId); // use current user tier for balance | |
if ($level <= $qualifiedUser['level'] && $this->checkMinimumAmountForBypass($balance)) { | |
$this->logText .= "ByPass qualified! "; | |
$returnValue = true; | |
} else { | |
$this->logText .= "ByPass not qualified! Only upto {$qualifiedUser['level']} "; | |
} | |
} | |
return $returnValue; | |
} | |
public function setTotalTransfer($transferSummary) | |
{ | |
$this->transferSummary = $transferSummary; | |
$transferSummaryFile = $this->directory . 'transfer_summary_' . $this->fileDate . '.csv'; | |
$fp = fopen($transferSummaryFile, 'w'); | |
fputcsv($fp, ['total_deposit', 'total_withdrawal', 'total_amount', 'user_id']); | |
foreach ($this->transferSummary as $fields) { | |
fputcsv($fp, $fields); | |
} | |
fclose($fp); | |
} | |
public function setTotalTransferLifetime($transferSummary) | |
{ | |
$this->transferLifetimeSummary = $transferSummary; | |
} | |
/* | |
* $userTiersCurrent is the current day user tier snapshot runs (Saturday for weekly, current day for daily) | |
* while $userTiers is the previous user tier snapshot (Thursday for weekly, previous day for daily) | |
*/ | |
public function setUserTierSnapshotCurrent($snapshot) | |
{ | |
$this->userTiersCurrent = $snapshot; | |
} | |
public function fetchQualifiedUsers() | |
{ | |
$noLevel = Goldmine2CommissionBypassLevels::where('level', 0)->firstOrFail(); | |
$this->qualifiedUsers = Goldmine2CommissionBypass::join('goldmine2_commission_bypass_levels', 'goldmine2_commission_bypass_levels.id', '=', 'goldmine2_commission_bypass.level_id') | |
->where('level_id', '!=', $noLevel->id)->select([ | |
'goldmine2_commission_bypass.user_id', | |
'goldmine2_commission_bypass_levels.level', | |
'goldmine2_commission_bypass_levels.amount', | |
])->get()->keyBy('user_id')->toArray(); | |
} | |
/** | |
* @param $trade | |
* @param $userTiers | |
* @param $uplineUserId | |
* @return string | |
*/ | |
protected function calculateAmount($trade, $userTiers, $uplineUserId) | |
{ | |
$goldmineLevel = $this->goldmine2Settings[$trade->level]; | |
$payoutAmount = $this->userHasContract($userTiers[$uplineUserId]['contract_type_id']) ? $goldmineLevel['contract'] : $goldmineLevel['normal']; // z | |
$amountFollowingTrader = $this->getInvestedAmount($trade->user_id); // x | |
$masterTraderTrades = $trade->total_trades; // L | |
$toDivide = 10000; // y | |
$calculated_amount = bcmul(bcmul(bcdiv($amountFollowingTrader, $toDivide, 8), $masterTraderTrades, 8), $payoutAmount, 2); | |
$this->logText .= "\t\t\t [calculated_amount]: $calculated_amount \n"; | |
// x - amount following a trader --> (volume / 100) | |
// y - fixed amount 10,000 | |
// L - master trader trades per week | |
// z - goldmine level amount (contract / normal) | |
// (x / y) (L) (z) | |
return $calculated_amount; | |
} | |
protected function isEligible($trade, $userTiers, $uplineUserId) | |
{ | |
$goldmineLevel = $this->promotionQualified($uplineUserId, $trade->level); | |
$tierLog = $this->getTier($userTiers, $uplineUserId); | |
$result = false; | |
$this->logText .= "\t[upline_id]: " . $uplineUserId . " [upline_tier]: " . $tierLog . " [tier no share]: " . implode(",", $goldmineLevel['tier_no_share']) . " [current_level]: " . $trade->level; | |
$this->logText .= "\n\t\t\t [isEligible]: "; | |
if (isset($this->qualifiedUsers[$uplineUserId]) && $this->bypassCommQualificationCheck($uplineUserId, $userTiers, $trade->level)) { | |
return true; | |
} | |
$result = $tierLog == 0 ? false : !in_array($tierLog, $goldmineLevel['tier_no_share']); | |
$this->logText .= ($result ? "yes!" : "no \n"); | |
return $result; | |
} | |
protected function promotionQualified($uplineUserId, $level) | |
{ | |
if ($this->enabledPromo->enabled) { | |
$isPromoQualified = $this->usersPromoClassification[$uplineUserId]['is_promotion']; | |
$this->logText .= "\t\t --- Promo Enabled, " . ($isPromoQualified ? "User qualified" : "Not Qualified") . "\n"; | |
return $isPromoQualified ? $this->enabledPromoValues[$level] : $this->goldmine2Settings[$level]; | |
} | |
// $this->logText .= "\t Promo Disabled\n"; | |
return $this->goldmine2Settings[$level]; | |
} | |
/** | |
* @param $uplineUserId | |
* @param $userTiers | |
* @param $level | |
* @return bool | |
*/ | |
protected function toCompressUser($uplineUserId, $userTiers, $level = null) | |
{ | |
if (isset($this->qualifiedUsers[$uplineUserId]) && $this->bypassCommQualificationCheck($uplineUserId, $userTiers, $level)) { | |
$this->logText .= "\n"; | |
return false; | |
} | |
return parent::toCompressUser($uplineUserId, $userTiers); | |
} | |
protected function getInvestedAmount($userId) | |
{ | |
return isset($this->transferSummary[$userId]) ? $this->transferSummary[$userId]['amount'] : 0; | |
} | |
private function setBypassMinimumAmount() | |
{ | |
$this->bypassMinimumAmount = setting('goldmine_2_bypass_minimum_balance'); | |
} | |
private function checkMinimumAmountForBypass($balance) | |
{ | |
return $balance >= $this->bypassMinimumAmount; | |
} | |
// get current balance | |
private function getUserBalance($uplineUserId) | |
{ | |
return isset($this->transferLifetimeSummary[$uplineUserId]) ? $this->transferLifetimeSummary[$uplineUserId]['amount'] : 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment