T
T
targeting242021-01-31 21:56:46
Yii
targeting24, 2021-01-31 21:56:46

Please do a code review, ok, not ok?

The task is to build a partner grid referral tree according to the following criteria:
calculate the total volume volume * coeff_h * coeff_cr for all levels of the referral system for a period of time
calculate profitability (amount profit) for a certain period of time
calculate the number of direct referrals and the number of all client referrals

<?php


namespace app\commands;


use app\models\Users;
use yii\console\Controller;
use \yii\helpers\BaseConsole;
use yii\helpers\Console;

/**
 * Class ReferralController
 * @package app\commands
 */
class ReferralController extends Controller
{
    /**
     * Метод для построения дерева и вывода общего количества рефералов
     */
    public function actionTree(){
        //Вводим uid полльзователя
        $client_uid = BaseConsole::input("Введите uid пользователя: ");
        $this->checkValidUid($client_uid);

        //Получаем всех пользователей
        $users = Users::find()
            ->select(['client_uid', 'partner_id'])
            ->asArray()
            ->all();

        /**
         * Функция прохода по всем пользователя и поиск рефералов (используется рекурсивный метод)
         *
         * @param $users //массив пользователей
         * @param $client_uid //uid клиента
         * @param int $level // уровень, то есть вложенность рефералов меняется если находим у реферала реферала
         */
        function printBuildTree($users, $client_uid, $level = 0) {
            foreach ($users as $arr) {
                if ($arr['partner_id'] == $client_uid) {
                    if ($level == 0){
                        //Печать дерева
                        echo "|" . "    |-- " . $arr['client_uid']  ."\n";
                    }
                    else{
                        //Печать дерева
                        echo "|" . str_repeat("    |-- ", $level + 1) . $arr['client_uid'] . "\n";
                    }
                    //Сама рекурсия, то есть находим реферала и для него ищем реферала
                    printBuildTree($users, $arr['client_uid'], $level + 1);
                }
            }
        }

        /**
         * Функция подсчета прямых рефералов
         *
         * @param $users
         * @param $client_uid
         * @param int $level
         * @param int $i
         * @return int
         */
        function getDirectReferral($users, $client_uid, $level = 0, $i = 0) {
            foreach ($users as $arr) {
                if ($arr['partner_id'] == $client_uid) {
                    if ($level == 0){
                        $i++;
                        $i += getDirectReferral($users, $arr['client_uid'], $level + 1);
                    }
                }
            }
            return $i;
        }

        /**
         * Функция подсчета всех рефералов
         *
         * @param $users
         * @param $client_uid
         * @param int $level
         * @param int $i
         * @return int
         */
        function getAllReferral($users, $client_uid, $level = 0, $i = 0) {
            foreach ($users as $arr) {
                if ($arr['partner_id'] == $client_uid) {
                    $i++;
                    $i += getAllReferral($users, $arr['client_uid'], $level + 1);
                }
            }
            return $i;
        }
        echo "|-- " . $client_uid . "\n";

        $result = printBuildTree($users, $client_uid);
        echo $result;
        echo "Всего прямых рефералов: " . getDirectReferral($users, $client_uid) . "\n";
        echo "Всего всех рефералов: " . getAllReferral($users, $client_uid) . "\n";
        //82824897
    }

    /**
     * Метод получения Прибыльности и Суммарного объема
     */
    public function actionTotalVolume(){
        //Вводим uid полльзователя
        $client_uid = BaseConsole::input("Введите uid пользователя: ");
        //Вводим дату ОТ
        $date_from = BaseConsole::input("Введите дату ОТ в формате ГОД-Месяц-День ЧАСЫ:МИНУТЫ:СЕКУНДЫ ");
        //Вводим дату ДО
        $date_to = BaseConsole::input("Введите дату ДО в формате ГОД-Месяц-День ЧАСЫ:МИНУТЫ:СЕКУНДЫ ");
        $this->checkValidUid($client_uid);

        //Проверяем если ввели дату то делаем условие
        if (!empty($date_from)){
            $date_from_condition = ['>=', 't.close_time',
                $date_from];
        }
        else{
            $date_from_condition = [];
        }

        //Проверяем если ввели дату то делаем условие
        if (!empty($date_to)){
            $date_to_condition = ['<=', 't.close_time',
                $date_to];
        }
        else{
            $date_to_condition = [];
        }

        //Получаем всех пользователей
        $users = (new \yii\db\Query())
            ->select(['volume', 'coeff_h', 'coeff_cr', 'a.client_uid', 'profit', 'partner_id'])
            ->from(['u' => 'users'])
            ->leftJoin(['a' => 'accounts'], 'a.client_uid = u.client_uid')
            ->leftJoin(['t' => 'trades'], 't.login = a.login')
            ->where(['u.client_uid' => $client_uid])
            ->andWhere($date_from_condition)
            ->andWhere($date_to_condition)
            ->all();
        $total_volume = 0;
        $sum_profit = 0;
        foreach ($users as $arr) {
            $total_volume += $arr['volume'] * $arr['coeff_h'] * $arr['coeff_cr'];
            $sum_profit += $arr['profit'];
        }

        echo "Прибыльность: " . $sum_profit . "\n";
        echo "Суммарный объем: " . $total_volume . "\n";
    }

    /**
     * Функция проверки на пустоту и валидность uid
     *
     * @param $client_uid
     */
    protected function checkValidUid($client_uid){
        if (empty($client_uid) || !is_numeric($client_uid)){
            $this->stdout("uid не может быть пустым и должен содержать число \n", Console::FG_RED);
            exit();
        }
    }
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Maxim, 2021-01-31
@targeting24

In short, the main thing is that it works, in your case.
If a little expanded:

  1. Function within a function is bad. You wear.
  2. All the code in the controller is bad too. Take it out to calculators, services, repositories.
  3. Use camelCase in variables.
  4. Look in the documentation for how to correctly receive user data (input) through the console
  5. Some comments are redundant and some titles are not logical. Remove unnecessary comments and work on naming.

These are the highlights. Here it is worth relying not on the code, but on your knowledge. You lack knowledge and should dive into the topic of refactoring, OOP, clean code, etc.
Your code is the result of your knowledge.

A
Andrey Slashchinin, 2021-01-31
@slashinin

I agree with Maxim and add on my own that with complex selections using aggregating functions such as summation, etc. it is worth considering the option of denormalizing data to speed up and simplify calculations. Those. create a copy of the data with a structure that makes counting easier and faster.
Description of the data denormalization method

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question