Created
April 30, 2020 08:35
-
-
Save worstn8mare/b2c531c529f223e33d0a529c5bab3acb 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; | |
private $qualifiedUsers6; | |
private $qualifiedUsers10; | |
/** | |
* @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' => $userTiers[$uplineUserId]['tier'], | |
'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(); | |
} | |
} | |
/* | |
* wdd666 ID:3459908 - 77 | |
* wdd777 ID:3459952, - 90 | |
* wdd888 ID:3459956, - 92 | |
* wdd999 ID:3459959, - 93 | |
*/ | |
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; | |
$transferSummaryFile = $this->directory . 'transfer_summary_lifetime' . $this->fileDate . '.csv'; | |
$fp = fopen($transferSummaryFile, 'w'); | |
fputcsv($fp, ['total_deposit', 'total_withdrawal', 'total_amount', 'user_id']); | |
foreach ($this->transferLifetimeSummary as $fields) { | |
fputcsv($fp, $fields); | |
} | |
fclose($fp); | |
} | |
/* | |
* $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) | |
{ | |
// use goldmine2settings here | |
// get trade->level, and get values of goldmine2settings[trade->level] | |
// this should have tier_no_share, normal, contract amounts. only tier_no_share property to use here | |
$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 = isset($userTiers[$uplineUserId]) ? $userTiers[$uplineUserId]['tier'] : 0; | |
$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])) { | |
if ($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; | |
// use goldmine2settings here | |
// get trade->level, and get values of goldmine2settings[trade->level] | |
// this should have tier_no_share, normal, contract amounts. only tier_no_share property to use here | |
} | |
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($userTiers[$uplineUserId])) { | |
$userTiers[$uplineUserId]['balance'] = $this->getInvestedAmount($uplineUserId); | |
} | |
if ($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