1
0
Fork 0
mirror of https://github.com/janickiy/yii2-nomer synced 2025-03-09 15:39:59 +00:00

add files to project

This commit is contained in:
janickiy 2020-02-05 06:34:26 +03:00
commit 5cac498444
3729 changed files with 836998 additions and 0 deletions

View file

@ -0,0 +1,13 @@
<?php
namespace app\modules\admin;
use yii\base\Module;
class AdminModule extends Module
{
public $controllerNamespace = 'app\modules\admin\controllers';
public $defaultRoute = 'dashboard';
public $layout = 'main';
}

View file

@ -0,0 +1,23 @@
<?php
namespace app\modules\admin\assets;
use yii\web\AssetBundle;
class ChartsAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
];
public $js = [
'js/amcharts/amcharts.js',
'js/amcharts/serial.js',
'js/amcharts/themes/light.js',
];
public $depends = [
'app\modules\admin\assets\GlobalAsset',
];
}

View file

@ -0,0 +1,33 @@
<?php
namespace app\modules\admin\assets;
use yii\web\AssetBundle;
class GlobalAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'//fonts.googleapis.com/css?family=Open+Sans:400,300,600,700&subset=all',
'metronic/global/plugins/font-awesome/css/font-awesome.min.css',
'metronic/global/plugins/simple-line-icons/simple-line-icons.min.css',
'metronic/global/plugins/bootstrap/css/bootstrap.min.css',
'metronic/global/plugins/bootstrap-switch/css/bootstrap-switch.min.css',
];
public $js = [
'metronic/global/plugins/jquery-1.11.0.min.js',
'metronic/global/plugins/jquery-migrate.min.js',
'metronic/global/plugins/jquery-ui/jquery-ui-1.10.3.custom.min.js',
'metronic/global/plugins/bootstrap/js/bootstrap.min.js',
'metronic/global/plugins/bootstrap-hover-dropdown/bootstrap-hover-dropdown.min.js',
'metronic/global/plugins/jquery-slimscroll/jquery.slimscroll.min.js',
'metronic/global/plugins/jquery.blockui.min.js',
'metronic/global/plugins/jquery.cokie.min.js',
'metronic/global/plugins/bootstrap-switch/js/bootstrap-switch.min.js',
];
public $depends = [
'yii\web\YiiAsset',
];
}

View file

@ -0,0 +1,26 @@
<?php
namespace app\modules\admin\assets;
use yii\web\AssetBundle;
class ThemeAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'metronic/global/css/components.css',
'metronic/global/css/plugins.css',
'metronic/layout/css/layout.css',
'metronic/layout/css/themes/default.css',
'metronic/layout/css/custom.css',
];
public $js = [
'metronic/global/scripts/app.js',
'metronic/layout/scripts/layout.js',
];
public $depends = [
'app\modules\admin\assets\GlobalAsset',
];
}

View file

@ -0,0 +1,44 @@
<?php
namespace app\modules\admin\controllers;
use Yii;
use yii\data\ActiveDataProvider;
use app\models\Telegram;
use yii\helpers\Url;
use yii\web\NotFoundHttpException;
class AccountsController extends AdminController
{
public function actionTelegram()
{
$model = new Telegram();
$dataProvider = new ActiveDataProvider([
'query' => Telegram::find(),
'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
]);
if (Yii::$app->getRequest()->getIsPost()) {
$model->load(Yii::$app->getRequest()->post());
if (!$model->validate()) {
return $this->render('telegram', compact('model', 'dataProvider'));
}
$model->save();
$this->refresh();
}
return $this->render('telegram', compact('model', 'dataProvider'));
}
public function actionDeleteTelegram($id)
{
if ($instance = Telegram::findOne($id)) $instance->delete();
if (!$instance) throw new NotFoundHttpException('Инстанс не найден.');
$referrer = Yii::$app->getRequest()->getReferrer();
$url = $referrer ? $referrer : Url::to(['accounts/telegram']);
return $this->redirect($url);
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace app\modules\admin\controllers;
use yii\filters\AccessControl;
use yii\web\Controller;
class AdminController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
/* @var $identity \app\models\User */
$identity = \Yii::$app->getUser()->getIdentity();
return $identity->is_admin;
}
],
],
],
];
}
}

View file

@ -0,0 +1,42 @@
<?php
namespace app\modules\admin\controllers;
use app\models\AppleSubscribeEvent;
use yii\data\ActiveDataProvider;
use yii\helpers\ArrayHelper;
class AppleController extends AdminController {
public function actionIndex() {
$query = AppleSubscribeEvent::find();
$subId = \Yii::$app->request->get("sub_id");
if($subId) {
$query->andWhere(["subscription_id" => $subId]);
}
$tm_start = \Yii::$app->request->get("tm_start");
if($tm_start) {
$query->andWhere([">=", "original_start_date", $tm_start]);
}
$tm_end = \Yii::$app->request->get("tm_end");
if($tm_end) {
$query->andWhere(["<=", "original_start_date", $tm_end]);
}
$dataProvider = new ActiveDataProvider([
"query" => $query
]);
$sData = AppleSubscribeEvent::find()->select(["subscription_id", "subscription_name"])->groupBy(["subscription_id", "subscription_name"])->all();
$subs = ArrayHelper::map($sData, "subscription_id", "subscription_name");
return $this->render("index", [
"dataProvider" => $dataProvider,
"subs" => $subs,
"subId" => $subId,
"tm_start" => $tm_start,
"tm_end" => $tm_end
]);
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Call;
use yii\data\ActiveDataProvider;
class CallsController extends AdminController
{
public function actionIndex()
{
$dataProvider = new ActiveDataProvider([
'query' => Call::find()->with('organization')->where(['status' => 'dtmf-1']),
'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
]);
return $this->render('index', compact('dataProvider'));
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Checkout;
use yii\data\ActiveDataProvider;
use yii\db\Expression;
use yii\web\Controller;
class CheckoutsController extends AdminController {
public function actionIndex() {
$dataProvider = new ActiveDataProvider([
"query" => Checkout::find()->where(["tm_done" => null])
]);
return $this->render("index", ["dataProvider" => $dataProvider]);
}
public function actionDone($id) {
$checkout = Checkout::find()->where(["id" => $id])->one();
$checkout->tm_done = new Expression("NOW()");
$checkout->save();
return $this->redirect(["index"]);
}
}

View file

@ -0,0 +1,319 @@
<?php
namespace app\modules\admin\controllers;
use app\models\ApplePayment;
use app\models\Payment;
use app\models\ResultCache;
use app\models\SearchRequest;
use app\models\User;
use app\models\UserSub;
use app\models\Wallet;
use Yii;
use yii\db\Expression;
use yii\db\Query;
use yii\helpers\ArrayHelper;
class DashboardController extends AdminController
{
public function actionIndex()
{
$start = Yii::$app->request->get('tm_start', date('Y-m-d', strtotime('-7 days')));
$end = Yii::$app->request->get('tm_end', date('Y-m-d'));
$searchRequests = (new Query())
->select([
'to_char(requests.tm, \'YYYY-MM-DD\') as date',
'count(1) as requests',
])
->from('requests')
->where(['>=', 'requests.tm', $start . ' 00:00:00'])
->andWhere(['<=', 'requests.tm', $end . ' 23:59:59'])
->groupBy(['date'])
->orderBy(['date' => SORT_ASC])
->all();
$users = (new Query())
->select(['to_char(tm_create, \'YYYY-MM-DD\') as date', 'count(1) as count'])
->from('users')
->where(['<=', 'tm_create', $end . ' 23:59:59'])
->andWhere(['>=', 'tm_create', $start . ' 00:00:00'])
->groupBy('date')
->orderBy(['date' => SORT_ASC])
->all();
$applePayments = (new Query())
->select(['to_char(tm, \'YYYY-MM-DD\') as date', 'count(1) as count'])
->from('apple_payments')
->where(['<=', 'tm', $end . ' 23:59:59'])
->andWhere(['>=', 'tm', $start . ' 00:00:00'])
->andWhere(["refund" => 0])
->andWhere([">", "sum", 0])
->groupBy('date')
->orderBy(['date' => SORT_ASC])
->all();
$requestsStats = [];
$defaultStats = [
'requests' => 0,
'registrations' => 0,
'applePayments' => 0
];
foreach ($searchRequests as $searchRequest) {
if (!isset($requestsStats[$searchRequest['date']])) $requestsStats[$searchRequest['date']] = $defaultStats;
$requestsStats[$searchRequest['date']]['requests'] = $searchRequest['requests'];
}
foreach ($users as $user) {
if (!isset($requestsStats[$user['date']])) $requestsStats[$user['date']] = $defaultStats;
$requestsStats[$user['date']]['registrations'] = $user['count'];
}
foreach ($applePayments as $applePayment) {
if (!isset($requestsStats[$applePayment['date']])) $requestsStats[$applePayment['date']] = $defaultStats;
$requestsStats[$applePayment['date']]['applePayments'] = $applePayment['count'];
}
ksort($requestsStats);
$payments = Payment::find()
->where(['>=', 'tm', date('Y-m-d 00:00:00', strtotime('-30 days'))])
->andWhere(["NOT IN", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_ANDROID, Payment::TYPE_APPLE]])
->all();
$today = (new yii\db\Query())
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(1) as bills'),
new Expression('COUNT(DISTINCT user_id) as bills_users'),
new Expression('(SELECT COUNT(1) FROM payments p WHERE
extract(month from p.tm) = '.date("m").'
AND extract(year from p.tm) = '.date("Y").'
AND extract(day from p.tm) = '.date("d").'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills'),
new Expression('(SELECT COUNT(DISTINCT user_id) FROM payments p WHERE
extract(month from p.tm) = '.date("m").'
AND extract(year from p.tm) = '.date("Y").'
AND extract(day from p.tm) = '.date("d").'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills_users')
])
->from(Payment::tableName().' p')
->where(["=", new Expression("extract(month from tm)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y")])
->andWhere(["=", new Expression("extract(day from tm)"), date("d")])
->andWhere(["NOT IN", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_APPLE]])
->one();
$todayAndroid = (new yii\db\Query())
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(1) as bills'),
new Expression('COUNT(DISTINCT user_id) as bills_users'),
new Expression('(SELECT COUNT(1) FROM payments p WHERE
extract(month from p.tm) = '.date("m").'
AND extract(year from p.tm) = '.date("Y").'
AND extract(day from p.tm) = '.date("d").'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills'),
new Expression('(SELECT COUNT(DISTINCT user_id) FROM payments p WHERE
p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills_users')
])
->from(Payment::tableName().' p')
->where(["=", new Expression("extract(month from tm)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y")])
->andWhere(["=", new Expression("extract(day from tm)"), date("d")])
->andWhere(["type_id" => Payment::TYPE_ANDROID])
->one();
$todayIos = (new yii\db\Query())
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(1) as bills')
])
->from(ApplePayment::tableName())
->where(["=", "tm", date("Y-m-d")])
->one();
$yesterday = (new yii\db\Query())
//->select([new Expression('SUM(amount) as sum'), new Expression('COUNT(1) as bills'), new Expression('COUNT(1) - (COUNT(DISTINCT user_id) + COUNT(case when user_id is NULL then 1 else null end)) as rebills')])
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(DISTINCT user_id) as bills_users'),
new Expression('COUNT(1) as bills'),
new Expression('(SELECT COUNT(1) FROM payments p WHERE
extract(month from p.tm) = '.date("m", strtotime("-1 day")).'
AND extract(year from p.tm) = '.date("Y", strtotime("-1 day")).'
AND extract(day from p.tm) = '.date("d", strtotime("-1 day")).'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills'),
new Expression('(SELECT COUNT(DISTINCT user_id) FROM payments p WHERE
extract(month from p.tm) = '.date("m", strtotime("-1 day")).'
AND extract(year from p.tm) = '.date("Y", strtotime("-1 day")).'
AND extract(day from p.tm) = '.date("d", strtotime("-1 day")).'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills_users')
])
->from(Payment::tableName().' p')
->where(["=", new Expression("extract(month from tm)"), date("m", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(day from tm)"), date("d", strtotime("-1 day"))])
->andWhere(["NOT IN", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_APPLE]])
->one();
$yesterdayIos = (new yii\db\Query())
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(1) as bills')
])
->from(ApplePayment::tableName())
->where(["=", "tm", date("Y-m-d", strtotime("-1 day"))])
->one();
$last30days = (new yii\db\Query())
//->select([new Expression('SUM(amount) as sum'), new Expression('COUNT(1) as bills'), new Expression('COUNT(1) - (COUNT(DISTINCT user_id) + COUNT(case when user_id is NULL then 1 else null end)) as rebills')])
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(DISTINCT user_id) as bills_users'),
new Expression('COUNT(1) as bills'),
new Expression('(SELECT COUNT(1) FROM payments p WHERE
tm >= \''.date("Y-m-d 00:00:00", strtotime("-30 days")).'\'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills'),
new Expression('(SELECT COUNT(DISTINCT user_id) FROM payments p WHERE
tm >= \''.date("Y-m-d 00:00:00", strtotime("-30 days")).'\'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills_users')
])
->from(Payment::tableName())
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->andWhere(["IS NOT", "site_id", null])
->one();
$last30Android = (new yii\db\Query())
->select([new Expression('SUM(amount) as sum'), new Expression('COUNT(1) as bills'), new Expression('COUNT(1) - (COUNT(DISTINCT user_id) + COUNT(case when user_id is NULL then 1 else null end)) as rebills')])
->from(Payment::tableName())
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["type_id" => Payment::TYPE_ANDROID])
->one();
$last30Ios = (new yii\db\Query())
->select([
new Expression('SUM(amount) as sum'),
new Expression('COUNT(1) as bills')
])
->from(ApplePayment::tableName())
->where([">=", "tm", date("Y-m-d", strtotime("-30 days"))])
->one();
$yandexWalletsSum = Wallet::find()->where(["type_id" => Wallet::TYPE_YANDEX])->sum("balance");
$qiwiWalletsSum = Wallet::find()->where(["type_id" => Wallet::TYPE_QIWI])->sum("balance");
$start = Yii::$app->request->get('tm_start', date('Y-m-d', strtotime('-1 days')));
$end = Yii::$app->request->get('tm_end', date('Y-m-d'));
$results = (new Query())
->select(['to_char(requests.tm, \'YYYY-MM-DD\') as date', 'request_results.type_id', '
CASE
WHEN (request_results.data = \'null\' OR request_results.data = \'[]\')
THEN false
ELSE true
END as success', 'count(1)'])
->from('requests')
->innerJoin('request_results', ['requests.id' => new Expression('request_id')])
->where(['>', 'requests.tm', date('Y-m-d', strtotime('-1 days'))])
->groupBy(['date', 'request_results.type_id', 'success'])
->orderBy(['date' => SORT_ASC, 'request_results.type_id' => SORT_ASC, 'success' => SORT_ASC])
->all();
$sourcesStats = [];
foreach ($results as $result) {
if (!isset($sourcesStats[$result['date']])) $sourcesStats[$result['date']] = [];
if (!isset($sourcesStats[$result['date']][$result['type_id']])) {
$sourcesStats[$result['date']][$result['type_id']] = [
'all' => 0,
'success' => 0
];
}
$sourcesStats[$result['date']][$result['type_id']]['all'] += $result['count'];
if ($result['success']) $sourcesStats[$result['date']][$result['type_id']]['success'] += $result['count'];
}
//print_r($sourcesStats); die();
$sourcesDays = array_keys($sourcesStats);
krsort($sourcesDays);
$types = [];
foreach ($sourcesStats as $key => $value) {
$types = array_merge($types, array_keys($value));
}
$types = array_filter(array_unique($types));
$sourcesToday = $sourcesDays[count($sourcesDays) - 1];
$sourcesYesterday = $sourcesDays[count($sourcesDays) - 2];
$typesError = [];
foreach($types as $type) {
if(in_array($type, [ResultCache::TYPE_GETCONTACT, ResultCache::TYPE_VK_OPEN, ResultCache::TYPE_VK])) continue;
$todayPercent = round(ArrayHelper::getValue($sourcesStats, [$sourcesToday, $type, "success"], 0) / ArrayHelper::getValue($sourcesStats, [$sourcesToday, $type, 'all'], 1) * 100, 2, PHP_ROUND_HALF_DOWN);
$yesterdayPercent = round(
ArrayHelper::getValue($sourcesStats, [$sourcesYesterday, $type, 'success'], 0)
/
ArrayHelper::getValue($sourcesStats, [$sourcesYesterday, $type, 'all'], 1) * 100, 2, PHP_ROUND_HALF_DOWN);
if($yesterdayPercent > 0) {
if($todayPercent < ($yesterdayPercent / 2)) {
$typesError[] = ResultCache::getTypeName($type);
}
}
}
$avitoStats = \Yii::$app->cache->get("avito");
$notifyTokens = User::find()->where(["IS NOT", "token", null])->count(1);
$notifyTokensWithoutSubs = User::find()->joinWith("subs")->where(["IS NOT", "token", null])->andWhere([UserSub::tableName().'.id' => null])->count(1);
$todaySubs = UserSub::find()->where(new Expression(
"extract(month from tm_purchase) = ".date("m")."
AND extract(year from tm_purchase) = ".date("Y")."
AND extract(day from tm_purchase) = ".date("d")
))->count(1);
$yesterdaySubs = UserSub::find()->where(new Expression(
"extract(month from tm_purchase) = ".date("m", strtotime("-1 day"))."
AND extract(year from tm_purchase) = ".date("Y", strtotime("-1 day"))."
AND extract(day from tm_purchase) = ".date("d", strtotime("-1 day"))
))->count(1);
$last30daysSubs = UserSub::find()->where([">=", "tm_purchase", date("Y-m-d 00:00:00", strtotime("-30 days"))])->count(1);
return $this->render('index', [
'start' => $start,
'end' => $end,
'requestsStats' => $requestsStats,
'payments' => $payments,
'today' => $today,
'yesterday' => $yesterday,
'yesterdayIos' => $yesterdayIos,
'last30days' => $last30days,
'yandexWalletsSum' => $yandexWalletsSum,
'qiwiWalletsSum' => $qiwiWalletsSum,
'typesError' => $typesError,
'last30Android' => $last30Android,
'last30Ios' => $last30Ios,
'todayAndroid' => $todayAndroid,
'todayIos' => $todayIos,
'avitoStats' => $avitoStats,
'notifyTokens' => $notifyTokens,
'notifyTokensWithoutSubs' => $notifyTokensWithoutSubs,
'todaySubs' => $todaySubs,
'yesterdaySubs' => $yesterdaySubs,
'last30daysSubs' => $last30daysSubs
]);
}
}

View file

@ -0,0 +1,168 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Payment;
use app\models\Site;
use Yii;
use app\models\SearchRequest;
use app\models\forms\AdminHistoryFilterForm;
use yii\data\ActiveDataProvider;
use yii\db\Expression;
use yii\db\Query;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
use yii\web\Controller;
class HistoryController extends AdminController
{
public function actionIndex()
{
$model = new AdminHistoryFilterForm();
$model->load(Yii::$app->getRequest()->get());
$today = date('Y-m-d');
if (!$model->from) {
$model->from = $today;
}
if (!$model->to) {
$model->to = $today;
}
$queries = (new Query())
->select(['
CASE
WHEN (user_id IS NULL)
THEN false
ELSE true
END as registred', 'count(1)'])
->from(SearchRequest::tableName())
->join('LEFT JOIN', 'users', 'requests.user_id = users.id')
->where(['>=', 'tm', $model->from . ' 00:00:00'])
->andWhere(['<=', 'tm', $model->to . ' 23:59:59'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->groupBy('registred')
->all();
$users = Yii::$app->getDb()->createCommand('
SELECT COUNT(DISTINCT user_id)
FROM (SELECT DISTINCT phone, tm FROM requests WHERE user_id IS NULL) r1
JOIN (SELECT DISTINCT phone, tm, user_id FROM requests WHERE user_id IS NOT NULL) r2
ON r1.phone = r2.phone
WHERE r1.tm >= :tm_start AND r1.tm <= :tm_end AND r1.tm < r2.tm;', [
':tm_start' => $model->from . ' 00:00:00',
':tm_end' => $model->to . ' 23:59:59'
])->queryAll();
$phones = SearchRequest::find()
->select('requests.phone')
->joinWith(['user'])
->where(['>=', 'tm', $model->from . ' 00:00:00'])
->andWhere(['<=', 'tm', $model->to . ' 23:59:59'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->distinct()
->count();
$sources = (new Query())
->select(['source_id', new Expression('COUNT(1)')])
->from('requests')
->join('LEFT JOIN', 'users', 'requests.user_id = users.id')
->where(['>=', 'tm', $model->from . ' 00:00:00'])
->andWhere(['<=', 'tm', $model->to . ' 23:59:59'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->groupBy('source_id')
->orderBy('source_id')
->all();
$sitesRequests = (new Query())
->select(['site_id', 'is_payed', 'source_id', new Expression('COUNT(1) as c')])
->from('requests')
->leftJoin('users', 'requests.user_id = users.id')
->where(['>=', 'tm', $model->from . ' 00:00:00'])
->andWhere(['<=', 'tm', $model->to . ' 23:59:59'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->groupBy(['site_id', 'is_payed', 'source_id'])
->orderBy(['site_id' => SORT_ASC, 'is_payed' => SORT_ASC, 'source_id' => SORT_ASC])
->all();
$sitesData = [];
foreach($sitesRequests as $sr) {
$is_payed = in_array($sr["is_payed"], [1, 2]);
if(!isset($sitesData[$sr["site_id"]][$sr["source_id"]][$is_payed])) {
$sitesData[$sr["site_id"]][$sr["source_id"]][$is_payed] = 0;
}
$sitesData[$sr["site_id"]][$sr["source_id"]][$is_payed] += $sr["c"];
}
$type = \Yii::$app->request->get("type", null);
$query = SearchRequest::find()
->andWhere(['>=', 'tm', $model->from . ' 00:00:00'])
->andWhere(['<=', 'tm', $model->to . ' 23:59:59'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->joinWith(['user']);
switch($type) {
case 1:
$query->andWhere(["is_payed" => 0, "is_has_name" => false, "is_has_photo" => false]);
break;
case 2:
$query->andWhere(["is_payed" => 0, "is_has_name" => true, "is_has_photo" => true]);
break;
case 3:
$query->andWhere(["is_payed" => 0, "is_has_name" => true, "is_has_photo" => false]);
break;
case 4:
$query->andWhere(["is_payed" => [1, 2]]);
break;
case 5:
$query->andWhere(["is_payed" => 2]);
break;
case 6:
$query->andWhere(["is_payed" => 1]);
break;
case 7:
$query->andWhere(["user_id" => null]);
break;
case 8:
$query->andWhere(["is not", "user_id", null])->andWhere(["is_payed" => 0]);
break;
}
$siteID = \Yii::$app->request->get("site_id", null);
if($siteID) {
$query->andWhere(['site_id' => $siteID]);
}
if ($model->user) {
$query->andWhere(['user_id' => $model->user]);
}
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
]);
$sites = Site::find()->orderBy(["id" => SORT_ASC])->asArray()->indexBy("id")->all();
$payments = Payment::find()->select(["site_id", new Expression("SUM(amount) as sum")])->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->groupBy("site_id")->indexBy("site_id")->asArray()->all();
$searches = SearchRequest::find()->select(["site_id", new Expression("count(1) as count")])->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->groupBy("site_id")->indexBy("site_id")->asArray()->all();
return $this->render('index', [
'payments' => $payments,
'searches' => $searches,
'model' => $model,
'dataProvider' => $dataProvider,
'queries' => $queries,
'users' => $users,
'phones' => $phones,
'sources' => $sources,
'sites' => $sites,
'sitesData' => $sitesData
]);
}
}

View file

@ -0,0 +1,133 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Notification;
use app\models\NotificationResult;
use app\models\User;
use yii\data\ActiveDataProvider;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\web\Controller;
class NotifyController extends Controller {
public function actionIndex() {
if(\Yii::$app->request->isPost) {
$post = \Yii::$app->request->post();
$notify = new Notification();
$notify->message = ArrayHelper::getValue($post, "message");
$notify->payload = ArrayHelper::getValue($post, "payload");
$notify->tm_create = new Expression("NOW()");
$notify->tm_send = new Expression("NOW()");
if($notify->save()) {
$whom = ArrayHelper::getValue($post, "whom");
switch ($whom) {
case "all":
$users = \Yii::$app->db->createCommand("SELECT id, token FROM users u WHERE AND u.token is NOT NULL")->queryAll();
break;
default:
$users = \Yii::$app->db->createCommand("SELECT u.id, token FROM users u LEFT JOIN subs s ON s.user_id = u.id WHERE s.id is null AND u.token is NOT NULL")->queryAll();
break;
}
//$users = \Yii::$app->db->createCommand("SELECT u.id, token FROM users u WHERE id = 79630")->queryAll();
foreach($users as $u) {
$notifyResult = new NotificationResult();
$notifyResult->notify_id = $notify->id;
$notifyResult->user_id = ArrayHelper::getValue($u, "id");
$notifyResult->status = 0;
$notifyResult->save();
}
$tokensData = ArrayHelper::getColumn($users, "token");
for($i = 0; $i <= ceil(count($tokensData)/100); $i++) {
$tokens = array_slice($tokensData, $i * 100, 100);
$fields = [
'x' => $i,
'id' => $notify->id,
'message' => $notify->message,
'payload' => $notify->payload,
'tokens' => Json::encode($tokens)
];
$fields_string = http_build_query($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://apinomer.com:9999/send");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
curl_close ($ch);
}
}
return $this->redirect(["notify/index"]);
}
$dataProvider = new ActiveDataProvider([
"query" => Notification::find()->orderBy(["id" => SORT_DESC])
]);
return $this->render("index", [
"dataProvider" => $dataProvider
]);
}
public function actionStatus() {
$id = \Yii::$app->request->get("id");
$token = \Yii::$app->request->get("token");
$status = \Yii::$app->request->get("status");
$user = User::find()->where(["token" => $token])->one();
$result = NotificationResult::find()->where(["user_id" => $user->id, "notify_id" => $id])->one();
$result->status = $status;
$result->save();
return "OK";
}
public function actionSend() {
/*
$tokens = \Yii::$app->db->createCommand("SELECT token FROM users u LEFT JOIN subs s ON s.user_id = u.id WHERE s.id is null AND u.token is NOT NULL")->queryColumn();
$payload = [
"message" => [
"item" => "com.wcaller.Wcaller.sub.month.5",
"title" => "Получите премиум доступ",
"- Полная проверка по всем базам\n- Включено 10 проверок в месяц\n- Скидка 30% на покупку проверок!"
]
];
$fields = [
'message' => "Мы начислили вам 2 бесплатных поиска, попробуйте наше приложение, уверены оно вам понравится!",
'payload' => Json::encode($payload),
'tokens' => Json::encode($tokens)
];
$fields_string = http_build_query($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://nomer.io:9999/send");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);
print_r($tokens);
*/
}
}

View file

@ -0,0 +1,37 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Payment;
use app\models\UserSub;
use yii\data\ActiveDataProvider;
use yii\db\Expression;
use yii\db\Query;
class PaymentsController extends AdminController
{
public function actionIndex()
{
$dataProvider = new ActiveDataProvider([
'query' => Payment::find()
->orderBy(['id' => SORT_DESC])
->where(['>=', 'tm', date('Y-m-d 00:00:00', strtotime('-7 day'))])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->orderBy(['tm' => SORT_DESC])
->with(["site", "user", "user.payments"])
]);
$dataProvider->pagination = false;
$todaySubs = UserSub::find()->where(new Expression(
"extract(month from tm_purchase) = ".date("m")."
AND extract(year from tm_purchase) = ".date("Y")."
AND extract(day from tm_purchase) = ".date("d")
))->count(1);
return $this->render('index', [
'dataProvider' => $dataProvider,
'todaySubs' => $todaySubs
]);
}
}

View file

@ -0,0 +1,46 @@
<?php
namespace app\modules\admin\controllers;
use app\components\coupon;
use app\models\PlatiCode;
use yii\data\ActiveDataProvider;
class PlatiController extends AdminController {
public function actionNew() {
$checks = \Yii::$app->request->get("checks");
$count = \Yii::$app->request->get("count");
$codes = coupon::generate_coupons($count, [
"length" => 12,
"letters" => true,
"numbers" => true,
"symbols" => false,
"mixed_case" => true,
"mask" => "XXX-XXX-XXX-XXX"
]);
$newCodes = [];
foreach($codes as $code) {
$platiCode = PlatiCode::find()->where(["code" => $code])->one();
if($platiCode) continue;
$platiCode = new PlatiCode();
$platiCode->code = $code;
$platiCode->checks = $checks;
$platiCode->save();
$newCodes[] = $code."<br>Для зачисления проверок введите код на сайте https://nomer.io/pay/coupon";
}
$file = \Yii::getAlias('@runtime')."/".uniqid("coupons").".txt";
file_put_contents($file, join("\n", $newCodes));
\Yii::$app->response->sendFile($file);
}
public function actionIndex() {
$dataProvider = new ActiveDataProvider([
'query' => PlatiCode::find()
]);
return $this->render('index', ["dataProvider" => $dataProvider]);
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace app\modules\admin\controllers;
use app\models\User;
use yii\helpers\ArrayHelper;
class ReferralsController extends AdminController {
public function actionIndex() {
$users = User::find()->where([">", "ref_id", 0])->asArray()->all();
$refIds = ArrayHelper::getColumn($users, "ref_id");
$refIds = array_unique($refIds);
$refs = User::find()->where(["id" => $refIds])->all();
return $this->render("index", [
"refs" => $refs
]);
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Repost;
use yii\data\ActiveDataProvider;
class RepostsController extends AdminController {
public function actionIndex() {
$dataProvider = new ActiveDataProvider([
"query" => Repost::find()->orderBy(["tm" => SORT_DESC])
]);
return $this->render("index", [
"dataProvider" => $dataProvider
]);
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Retargeting;
use yii\base\Exception;
use yii\data\ActiveDataProvider;
use yii\db\ActiveQuery;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
class RetargetingController extends AdminController {
public function actionIndex() {
$dataProvider = new ActiveDataProvider([
'query' => Retargeting::find()->orderBy(["id" => SORT_DESC])
]);
$todaySent = Retargeting::find()
->where(['status' => Retargeting::STATUS_SENT])
->andWhere(["=", new Expression("extract(month from tm_send)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm_send)"), date("Y")])
->andWhere(["=", new Expression("extract(day from tm_send)"), date("d")])
->count();
$todayRead = Retargeting::find()
->where(['status' => Retargeting::STATUS_READ])
->andWhere(["=", new Expression("extract(month from tm_read)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm_read)"), date("Y")])
->andWhere(["=", new Expression("extract(day from tm_read)"), date("d")])
->count();
$todayClick = Retargeting::find()
->where(['status' => Retargeting::STATUS_CLICK])
->andWhere(["=", new Expression("extract(month from tm_click)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm_click)"), date("Y")])
->andWhere(["=", new Expression("extract(day from tm_click)"), date("d")])
->count();
$yesterdaySent = Retargeting::find()
->where(['status' => Retargeting::STATUS_SENT])
->andWhere(["=", new Expression("extract(month from tm_send)"), date("m", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(year from tm_send)"), date("Y", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(day from tm_send)"), date("d", strtotime("-1 day") )])
->count();
$yesterdayRead = Retargeting::find()
->where(['status' => Retargeting::STATUS_READ])
->andWhere(["=", new Expression("extract(month from tm_read)"), date("m", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(year from tm_read)"), date("Y", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(day from tm_read)"), date("d", strtotime("-1 day"))])
->count();
$yesterdayClick = Retargeting::find()
->where(['status' => Retargeting::STATUS_CLICK])
->andWhere(["=", new Expression("extract(month from tm_click)"), date("m", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(year from tm_click)"), date("Y", strtotime("-1 day"))])
->andWhere(["=", new Expression("extract(day from tm_click)"), date("d", strtotime("-1 day"))])
->count();
$monthSent = Retargeting::find()
->where(['status' => Retargeting::STATUS_SENT])
->andWhere([">=", "tm_send", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->count();
$monthRead = Retargeting::find()
->where(['status' => Retargeting::STATUS_READ])
->andWhere([">=", "tm_read", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->count();
$monthClick = Retargeting::find()
->where(['status' => Retargeting::STATUS_CLICK])
->andWhere([">=", "tm_click", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->count();
return $this->render("index", compact('todaySent', 'todayRead', 'todayClick','yesterdaySent','yesterdayRead','yesterdayClick', 'monthSent', 'monthRead','monthClick'));
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace app\modules\admin\controllers;
use app\models\UrlFilter;
use Yii;
use yii\data\ActiveDataProvider;
use app\models\Settings;
use app\models\User;
use yii\data\SqlDataProvider;
use yii\db\Query;
use yii\helpers\Url;
use yii\web\NotFoundHttpException;
class SettingsController extends AdminController
{
public function actionIndex($tab = 'index')
{
switch ($tab) {
case 'index': {
if (Yii::$app->getRequest()->getIsPost()) {
foreach (Yii::$app->getRequest()->post() as $key => $value) {
Settings::set($key, $value);
}
return $this->redirect(['settings/index', 'tab' => 'index']);
}
}
case 'bans': {
$dataProvider = new ActiveDataProvider([
'query' => User::find()->where(['status' => 0]),
'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
]);
return $this->render('index', compact('tab', 'dataProvider'));
}
case 'domains': {
$model = new UrlFilter();
$dataProvider = new ActiveDataProvider([
'query' => UrlFilter::find(),
'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
]);
if (Yii::$app->getRequest()->getIsPost()) {
$model->load(Yii::$app->getRequest()->post());
if (!$model->validate()) {
return $this->render('index', compact('model', 'dataProvider'));
}
$model->save();
$this->refresh();
}
return $this->render('index', compact('tab', 'model', 'dataProvider'));
}
case 'fingerprints': {
$dataProvider = new SqlDataProvider([
'sql' => \Yii::$app->db->createCommand("SELECT hash, array_agg(user_id) as user_ids, array_agg(ip) as ips FROM \"user_fingerprints\" GROUP BY \"hash\" HAVING COUNT(1) > 1")->rawSql,
'sort' => false
]);
return $this->render('index', compact('tab', 'dataProvider'));
}
case 'blocked-phones': {
$results = (new Query())
->select(['to_char(tm, \'YYYY-MM-DD\') as date', 'status', 'count(1) as count'])
->from('block')
->groupBy(['date', 'status'])
->orderBy(['date' => SORT_DESC, 'status' => SORT_ASC])
->all();
$phones = [];
foreach ($results as $result) {
if (!isset($phones[$result['date']])) $phones[$result['date']] = [
'all' => 0,
'unconfirmed' => 0,
'confirmed' => 0,
'vip' => 0
];
switch ($result['status']) {
case 0:
$phones[$result['date']]['unconfirmed'] = $result['count'];
break;
case 1:
$phones[$result['date']]['confirmed'] = $result['count'];
break;
case 2:
$phones[$result['date']]['vip'] = $result['count'];
break;
}
$phones[$result['date']]['all'] += $result['count'];
}
return $this->render('index', compact('tab', 'phones'));
}
default: throw new NotFoundHttpException('Страница не найдена.');
}
}
public function actionDeleteDomain($id)
{
if ($domain = UrlFilter::findOne($id)) $domain->delete();
if (!$domain) throw new NotFoundHttpException('Домен не найден.');
$referrer = Yii::$app->getRequest()->getReferrer();
$url = $referrer ? $referrer : Url::to(['settings/index', 'tab' => 'domains']);
return $this->redirect($url);
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Payment;
use app\models\SearchRequest;
use Yii;
use yii\data\ActiveDataProvider;
use app\models\Site;
use yii\db\Expression;
class SitesController extends AdminController
{
public function actionIndex()
{
$dataProvider = new ActiveDataProvider([
'query' => Site::find()->orderBy("id")->where(["not in", "id", [6, 14]])
]);
$dataProvider->pagination = false;
$payments = Payment::find()->select(["site_id", new Expression("SUM(amount) as sum")])->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->groupBy("site_id")->indexBy("site_id")->asArray()->all();
$seaches = SearchRequest::find()->select(["site_id", new Expression("count(1) as count")])->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->groupBy("site_id")->indexBy("site_id")->asArray()->all();
//$applePayments = SearchRequest::find()->select(["site_id", new Expression("count(1) as count")])->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->groupBy("site_id")->indexBy("site_id")->asArray()->all();
return $this->render('index', compact('dataProvider', 'payments', 'seaches'));
}
public function actionCreate()
{
$model = new Site();
if ($model->load(Yii::$app->getRequest()->post()) && $model->save()) {
return $this->redirect(['sites/index']);
}
return $this->render('create', compact('model'));
}
public function actionUpdate($id)
{
$model = Site::find()->where(compact('id'))->one();
if ($model->load(Yii::$app->getRequest()->post()) && $model->save()) {
return $this->redirect(['sites/index']);
}
return $this->render('update', compact('model'));
}
public function actionDelete($id)
{
$model = Site::find()->where(compact('id'))->one();
$model->delete();
return $this->redirect(['sites/index']);
}
public function actionSetDemo($id)
{
$model = Site::find()->where(compact('id'))->one();
$model->is_demo = !$model->is_demo;
$model->save();
return $this->redirect(Yii::$app->getRequest()->getReferrer());
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace app\modules\admin\controllers;
use Yii;
use yii\data\ActiveDataProvider;
use yii\data\ArrayDataProvider;
use yii\db\Expression;
use yii\db\Query;
use app\models\SearchRequest;
class StatsController extends AdminController
{
public function actionIndex()
{
$start = Yii::$app->request->get('tm_start', date('Y-m-d', strtotime('-7 days')));
$end = Yii::$app->request->get('tm_end', date('Y-m-d'));
$results = (new Query())
->select(['to_char(requests.tm, \'YYYY-MM-DD\') as date', 'request_results.type_id', '
CASE
WHEN (request_results.data = \'null\' OR request_results.data = \'[]\')
THEN false
ELSE true
END as success', 'count(1)'])
->from('requests')
->innerJoin('request_results', ['requests.id' => new Expression('request_id')])
->where(['>', 'requests.tm', date('Y-m-d', strtotime('-7 days'))])
->groupBy(['date', 'request_results.type_id', 'success'])
->orderBy(['date' => SORT_ASC, 'request_results.type_id' => SORT_ASC, 'success' => SORT_ASC])
->all();
$sourcesStats = [];
foreach ($results as $result) {
if (!isset($sourcesStats[$result['date']])) $sourcesStats[$result['date']] = [];
if (!isset($sourcesStats[$result['date']][$result['type_id']])) {
$sourcesStats[$result['date']][$result['type_id']] = [
'all' => 0,
'success' => 0
];
}
$sourcesStats[$result['date']][$result['type_id']]['all'] += $result['count'];
if ($result['success']) $sourcesStats[$result['date']][$result['type_id']]['success'] += $result['count'];
}
return $this->render('index', compact('start', 'end', 'sourcesStats'));
}
public function actionDetailed($type, $date, $filter = 'all')
{
$type = (int) $type;
$query = (new Query())
->select(['requests.id', 'requests.phone', '
CASE
WHEN (request_results.data = \'null\' OR request_results.data = \'[]\')
THEN false
ELSE true
END as success', 'requests.tm'])
->from('requests')
->innerJoin('request_results', ['requests.id' => new Expression('request_id')])
->where(['request_results.type_id' => $type])
->andWhere(['>=', 'requests.tm', $date . ' 00:00:00'])
->andWhere(['<=', 'requests.tm', $date . ' 23:59:59']);
switch ($filter) {
case 'found': $query->andWhere(['and', ['<>', 'request_results.data', 'null'], ['<>', 'request_results.data', '[]']]); break;
case 'not_found': $query->andWhere(['or', ['request_results.data' => 'null'], ['request_results.data' => '[]']]); break;
default: $filter = 'all'; break;
}
$requests = $query->all();
$dataProvider = new ArrayDataProvider([
'allModels' => $requests,
'sort' => [
'attributes' => ['id', 'success'],
'defaultOrder' => ['id' => SORT_DESC]
]
]);
return $this->render('detailed', compact('type', 'date', 'filter', 'dataProvider'));
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace app\modules\admin\controllers;
use app\models\UserSub;
use yii\data\ActiveDataProvider;
use yii\db\Expression;
use yii\web\User;
class SubscriptionsController extends AdminController {
public function actionIndex() {
$dataProvider = new ActiveDataProvider([
"query" => UserSub::find()
]);
return $this->render("index", [
"dataProvider" => $dataProvider
]);
}
public function actionTest() {
$dataProvider = new ActiveDataProvider([
"query" => UserSub::find()->from(UserSub::tableName()." s")->innerJoin(UserSub::tableName()." s2", "s.original_transaction_id = s2.original_transaction_id")->where(new Expression("s.tm_expires::date - s.tm_purchase::date = 3"))->andWhere(new Expression("s2.tm_expires::date - s2.tm_purchase::date > 5"))
]);
return $this->render("index", [
"dataProvider" => $dataProvider
]);
}
}

View file

@ -0,0 +1,165 @@
<?php
namespace app\modules\admin\controllers;
use app\models\Site;
use app\models\Ticket;
use app\models\TicketComment;
use app\models\TicketReply;
use app\models\User;
use yii\base\Exception;
use yii\data\ActiveDataProvider;
use yii\db\ActiveQuery;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
class TicketsController extends AdminController {
public function actionIndex() {
$statuses = [0, 1];
if(\Yii::$app->getUser()->getId() == 1) {
$statuses = [0, 1, 7];
}
$query = Ticket::find()->where(["is_deleted" => 0, "status" => $statuses])->with("user")->orderBy(["id" => SORT_DESC]);
$ticketsNotRead = new ActiveDataProvider([
'query' => $query
]);
$tIds = ArrayHelper::getColumn($ticketsNotRead->getModels(), "id");
$tickets = new ActiveDataProvider([
'query' => Ticket::find()->where(["NOT IN", "id", $tIds])->andWhere(["is_deleted" => 0])->with("user")->orderBy(["id" => SORT_DESC])
]);
return $this->render("index", [
"tickets" => $tickets,
"ticketsNotRead" => $ticketsNotRead
]);
}
public function actionIgnore($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
$ticket->status = 6;
$ticket->tm_close = new Expression('NOW()');
$ticket->save(false);
return $this->redirect(["tickets/index"]);
}
public function actionDevelop($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
$ticket->status = 7;
$ticket->tm_close = new Expression('NOW()');
$ticket->save(false);
return $this->redirect(["tickets/index"]);
}
public function actionClose($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
$ticket->status = 4;
$ticket->tm_close = new Expression('NOW()');
$ticket->save(false);
return $this->redirect(["tickets/index"]);
}
public function actionDelete($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
$ticket->is_deleted = true;
$ticket->save(false);
return $this->redirect(["tickets/index"]);
}
public function actionReopen($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
$ticket->status = 1;
$ticket->save(false);
return $this->redirect(["tickets/view", "id" => $id]);
}
public function actionCommentDelete($id) {
$comment = TicketComment::find()->where(["id" => $id])->one();
$comment->is_deleted = true;
$comment->save();
return $this->redirect(["tickets/view", "id" => $comment->ticket_id]);
}
public function actionAddReply($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
$text = \Yii::$app->request->post("text");
if(trim($text) != "") {
$reply = new TicketReply();
$reply->subject_id = $ticket->subject_id;
$reply->text = $text;
$reply->save();
return $this->renderAjax('_reply', ['reply' => $reply]);
}
return '';
}
public function actionView($id) {
$ticket = Ticket::find()->where(["id" => $id])->one();
TicketComment::updateAll(["tm_read" => new Expression('NOW()')], "ticket_id = ".$ticket->id." AND tm_read is null AND user_id <> ".\Yii::$app->getUser()->id);
if($ticket->status == 0) {
$ticket->status = 1;
}
$ticket->tm_read = new Expression('NOW()');
$ticket->save(false);
$comments = new ActiveDataProvider([
"query" => TicketComment::find()->where(["ticket_id" => $ticket->id, "is_deleted" => 0])->orderBy(["id" => SORT_ASC])
]);
$comment = new TicketComment();
$replies = TicketReply::find()->all();
return $this->render("view", [
"ticket" => $ticket,
"comments" => $comments,
"comment" => $comment,
"replies" => $replies
]);
}
public function actionComment($id) {
$comment = new TicketComment();
$comment->load(\Yii::$app->request->post());
$comment->ticket_id = $id;
$comment->save();
$ticket = Ticket::find()->where(["id" => $id])->one();
$user = User::find()->where(["id" => $ticket->user_id])->one();
$site = Site::find()->where(["id" => $ticket->site_id])->one();
$ticket->status = 2;
$ticket->save(false);
try {
if(preg_match('/@/', $user->email)) {
\Yii::$app->mailer->compose()
->setHtmlBody("Администратор оставил новый ответ.<br><a href='https://".$site->name."/feedback'></a>")
->setFrom('noreply@'.$site->name)
->setTo($user->email)
->setSubject($site->name." - новый отет на запрос")
->send();
}
} catch (Exception $e) {}
return $this->redirect(["tickets/view", "id" => $id]);
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace app\modules\admin\controllers;
use Yii;
use yii\data\ActiveDataProvider;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use yii\web\NotFoundHttpException;
use app\models\Token;
class TokensController extends AdminController
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'except' => ['query'],
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
/* @var $identity \app\models\User */
$identity = \Yii::$app->getUser()->getIdentity();
return $identity->is_admin;
}
],
],
],
];
}
public function actionIndex()
{
$model = new Token();
$dataProvider = new ActiveDataProvider([
'query' => Token::find(),
'sort' => ['defaultOrder' => ['id' => SORT_DESC]]
]);
if (Yii::$app->getRequest()->getIsPost()) {
$model->load(Yii::$app->getRequest()->post());
if (!$model->validate()) {
return $this->render('index', compact('model', 'dataProvider'));
}
$model->save();
$this->refresh();
}
return $this->render('index', compact('model', 'dataProvider'));
}
public function actionDelete($id)
{
if ($domain = Token::findOne($id)) $domain->delete();
if (!$domain) throw new NotFoundHttpException('Токен не найден.');
$referrer = Yii::$app->getRequest()->getReferrer();
$url = $referrer ? $referrer : Url::to(['tokens/index']);
return $this->redirect($url);
}
public function actionQuery($server, $type)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ArrayHelper::getColumn(Token::find()
->where(['type' => $type])
->andWhere(['server_id' => $server])
->andWhere(['status' => Token::STATUS_ACTIVE])
->all(), 'token');
}
}

View file

@ -0,0 +1,198 @@
<?php
namespace app\modules\admin\controllers;
use app\models\UserAuthLog;
use Yii;
use app\models\Payment;
use app\models\SearchRequest;
use app\models\User;
use yii\data\ActiveDataProvider;
use yii\data\Sort;
use yii\db\Query;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class UsersController extends AdminController
{
public function actionIndex()
{
$tm_start = Yii::$app->getRequest()->get('tm_start', date('Y-m-d'));
$tm_end = Yii::$app->getRequest()->get('tm_end', date('Y-m-d'));
$email = Yii::$app->getRequest()->get('email');
$isVIP = (bool) Yii::$app->getRequest()->get('is_vip', 0);
$isAdmin = (bool) Yii::$app->getRequest()->get('is_admin', 0);
$withChecks = (bool) Yii::$app->getRequest()->get('with_checks', 0);
$registrationsQuery = (new Query())
->select(['auth.source', 'count(users.id)'])
->from('users')
->join('LEFT JOIN', 'auth', 'auth.user_id = users.id')
->groupBy('auth.source')
->orderBy(['auth.source' => SORT_ASC]);
if ($isVIP) $registrationsQuery->andWhere(['users.is_vip' => true]);
if ($isAdmin) $registrationsQuery->andWhere(['users.is_admin' => true]);
if (!$isVIP && !$isAdmin && !$withChecks) {
$registrationsQuery->andWhere(['>=', 'users.tm_create', $tm_start . ' 00:00:00'])
->andWhere(['<=', 'users.tm_create', $tm_end . ' 23:59:59']);
}
if ($withChecks) $registrationsQuery->andWhere(['>', 'users.checks', 0]);
$registrations = $registrationsQuery->all();
$registrationConfirmsQuery = (new Query())
->select(['auth.source', 'count(users.id)'])
->from('users')
->join('LEFT JOIN', 'auth', 'auth.user_id = users.id')
->andWhere(['is_confirm' => true])
->groupBy('auth.source')
->orderBy(['auth.source' => SORT_ASC])
->indexBy('source');
if ($isVIP) $registrationConfirmsQuery->andWhere(['users.is_vip' => true]);
if ($isAdmin) $registrationConfirmsQuery->andWhere(['users.is_admin' => true]);
if (!$isVIP && !$isAdmin && !$withChecks) {
$registrationConfirmsQuery->andWhere(['>=', 'users.tm_create', $tm_start . ' 00:00:00'])
->andWhere(['<=', 'users.tm_create', $tm_end . ' 23:59:59']);
}
if ($withChecks) $registrationConfirmsQuery->andWhere(['>', 'users.checks', 0]);
$registrationConfirms = $registrationConfirmsQuery->all();
$query = User::find();
if ($email) $query->andWhere(['ilike', 'email', $email]);
if ($isVIP) $query->andWhere(['is_vip' => true]);
if ($isAdmin) $query->andWhere(['is_admin' => true]);
if (!$email && !$isVIP && !$isAdmin && !$withChecks) {
$query
->where(['>=', 'tm_create', $tm_start . ' 00:00:00'])
->andWhere(['<=', 'tm_create', $tm_end . ' 23:59:59']);
}
if ($withChecks) $query->andWhere(['>', 'checks', 0]);
$phones = \Yii::$app->db->createCommand("select count(1) from users where tm_create >='".$tm_start." 00:00:00' AND tm_create <= '".$tm_end." 23:59:59' and exists (select * from regexp_matches(users.email, '^[0-9]{11,12}$'))")->queryScalar();
$registrations[] = ["source" => "phone", "count" => $phones];
$ios = \Yii::$app->db->createCommand("select count(1) from users where tm_create >='".$tm_start." 00:00:00' AND tm_create <= '".$tm_end." 23:59:59' and email is null and exists (select * from regexp_matches(users.uuid, '^[0-9A-Z-]{36}$'))")->queryScalar();
$registrations[] = ["source" => "iOS", "count" => $ios];
$android = \Yii::$app->db->createCommand("select count(1) from users where tm_create >='".$tm_start." 00:00:00' AND tm_create <= '".$tm_end." 23:59:59' and email is not null and exists (select * from regexp_matches(users.uuid, '^[0-9A-Za-z-]{36}$'))")->queryScalar();
$registrations[] = ["source" => "Android", "count" => $android];
$dataProvider = new ActiveDataProvider([
'query' => $query->with(['requests']),
'sort' => new Sort([
'attributes' => [
'id',
'checks' => [
'default' => SORT_DESC
]
],
'defaultOrder' => [
'id' => SORT_DESC
]
])
]);
return $this->render('index', compact(
'dataProvider',
'registrations',
'tm_start', 'tm_end',
'email',
'registrationConfirms',
'isVIP',
'isAdmin',
'withChecks'
));
}
public function actionView($id)
{
$model = User::find()->where(compact('id'))->one();
if (!$model) throw new NotFoundHttpException('Пользователь не найден');
if (\Yii::$app->request->isPost) {
$checks = \Yii::$app->request->post('checks');
if ($checks !== null) {
$model->checks += $checks;
$model->save();
\Yii::$app->session->setFlash('success', 'Проверки успешно начислены');
return $this->refresh();
}
if ($model->load(Yii::$app->request->post())) {
$model->save();
return $this->refresh();
}
}
$history = new ActiveDataProvider([
'query' => SearchRequest::find()->where(['user_id' => $model->id]),
'sort' => [
'defaultOrder' => ['id' => SORT_DESC],
'sortParam' => 'history-sort'
],
'pagination' => [
'pageParam' => 'history-page',
'pageSize' => 25
]
]);
$payments = new ActiveDataProvider([
'query' => Payment::find()->where(['user_id' => $model->id]),
'sort' => [
'defaultOrder' => ['id' => SORT_DESC],
'sortParam' => 'payments-sort'
],
'pagination' => [
'pageParam' => 'payments-page',
'pageSize' => 25
]
]);
$auth = new ActiveDataProvider([
'query' => UserAuthLog::find()->where(['user_id' => $model->id]),
'sort' => [
'defaultOrder' => ['id' => SORT_DESC],
'sortParam' => 'auth-sort'
],
'pagination' => [
'pageParam' => 'auth-page',
'pageSize' => 25
]
]);
return $this->render('view', compact('model', 'history', 'payments', 'auth'));
}
public function actionSetVip($id)
{
$user = User::find()->where(compact('id'))->one();
if (!$user) throw new NotFoundHttpException('Пользователь не найден');
$user->is_vip = !$user->is_vip;
if (!$user->save()) {
print_r($user->getErrors()); die();
}
return $this->redirect(Yii::$app->getRequest()->getReferrer());
}
public function actionSetAdmin($id)
{
$user = User::find()->where(compact('id'))->one();
if (!$user) throw new NotFoundHttpException('Пользователь не найден');
$user->is_admin = !$user->is_admin;
$user->save();
return $this->redirect(Yii::$app->getRequest()->getReferrer());
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace app\modules\admin\controllers;
use Yii;
use yii\data\ActiveDataProvider;
use app\models\Wallet;
use yii\web\NotFoundHttpException;
class WalletsController extends AdminController
{
public function actionIndex()
{
$dataProvider = new ActiveDataProvider([
'query' => Wallet::find()->orderBy(['type_id' => SORT_ASC, 'balance' => SORT_DESC])->where(["status" => 1])
]);
$dataProvider->pagination = false;
return $this->render('index', compact('dataProvider'));
}
public function actionCreate()
{
$model = new Wallet();
if (Yii::$app->getRequest()->getIsPost() && $model->load(Yii::$app->request->post()) && $model->save()) {
$this->redirect(['wallets/index']);
}
return $this->render('create', compact('model'));
}
public function actionView($id)
{
$model = Wallet::find()->where(compact('id'))->one();
if (!$model) throw new NotFoundHttpException('Кошелёк не найден.');
if (Yii::$app->getRequest()->getIsPost() && $model->load(Yii::$app->request->post()) && $model->save()) {
$this->redirect(['wallets/index']);
}
return $this->render('view', compact('model'));
}
}

View file

@ -0,0 +1,47 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Telegram */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
use app\models\Telegram;
$this->title = 'Telegram';
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'host')->textInput() ?>
<?= $form->field($model, 'port')->textInput() ?>
<?= Html::submitButton('Добавить', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
<hr>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
'host',
'port',
[
'attribute' => 'status',
'value' => function (Telegram $model) {
return Telegram::getStatusName($model->status);
}
],
'tm_last',
[
'format' => 'raw',
'header' => 'Действия',
'value' => function(Telegram $model) {
return '<a href="' . Url::to(['accounts/delete-telegram', 'id' => $model->id]) . '" onclick="return confirm(\'Удалить инстанс?\')"><i class="icon-trash"></i></a>';
}
]
]
]) ?>

View file

@ -0,0 +1,34 @@
<?php
/* @var $this \yii\web\View */
/* @var $subs array */
/* @var $subId int */
/* @var $tm_start string */
/* @var $tm_end string */
use yii\helpers\Html;
/* @var $dataProvider \yii\data\ActiveDataProvider */
$this->title = "Отчет apple";
?>
<?=Html::beginForm('', 'get'); ?>
<?=Html::dropDownList("sub_id", $subId, $subs, ["prompt" => "Выберите подписку"]);?>
с <?=\yii\jui\DatePicker::widget(["name" => "tm_start", "class" => "form-control input-small", "value" => $tm_start, "dateFormat" => "y-MM-dd"]); ?>
по <?=\yii\jui\DatePicker::widget(["name" => "tm_end", "class" => "form-control input-small", "value" => $tm_end, "dateFormat" => "y-MM-dd"]); ?>
<?=Html::submitButton("Показать", ["class" => "btn btn-primary"]); ?>
<?=Html::endForm(); ?>
<?=\yii\grid\GridView::widget([
"dataProvider" => $dataProvider,
"columns" => [
"event_date",
"event",
"subscription_name",
"original_start_date",
"cancellation_reason",
"quantity"
]
]);?>

View file

@ -0,0 +1,32 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use app\models\Call;
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'organization.number',
'phone',
// 'id',
// 'tm',
// 'cuid',
'duration',
// 'status',
'organization.number',
'organization.name',
'organization.inn',
'organization.maximum_sum',
'organization.region',
[
'header' => 'Номера телефонов',
'value' => function (Call $model) {
return implode(', ', array_filter(ArrayHelper::getColumn($model->organization->phones, 'phone2')));
}
],
]
]);

View file

@ -0,0 +1,47 @@
<?php
/**
* Created by PhpStorm.
* User: firedemon
* Date: 8/3/17
* Time: 7:00 PM
*/
use app\models\User;
use yii\grid\ActionColumn;
use yii\grid\GridView;
use yii\helpers\Html;
$this->title = 'Запросы на выплаты';
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
'tm_create',
'user_id',
'sum',
[
'header' => 'Сумма',
'content' => function($model) {
return \Yii::$app->formatter->asCurrency($model->sum, "RUB");
}
],
[
'header' => 'Пользователь',
'content' => function($model) {
$user = User::find()->where(["id" => $model->user_id])->one();
return Html::a($user->email, ["users/view", "id" => $user->id]);
}
],
[
'class' => ActionColumn::className(),
'template' => '{done}',
'buttons' => [
'done' => function ($url, $model, $key) {
return Html::a('Выплачено', ['done', 'id' => $model->id], ['class' => 'btn btn-primary']);
}
]
],
]
]);

View file

@ -0,0 +1,430 @@
<?php
/* @var $this \yii\web\View */
/* @var $start string */
/* @var $end string */
/* @var $requestsStats array */
/* @var $today array */
/* @var $todayIos array */
/* @var $yesterday array */
/* @var $last30days array */
/* @var $typesError array */
/* @var $notifyTokens int */
/* @var $notifyTokensWithoutSubs int */
/* @var $avitoStats */
/* @var $todaySubs */
/* @var $yesterdaySubs */
/* @var $last30daysSubs */
/* @var $yesterdayIos */
use app\models\SearchRequest;
use yii\db\Expression;
use yii\db\Query;
use yii\helpers\Url;
use yii\jui\DatePicker;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\helpers\Html;
use yii\web\View;
use app\models\Payment;
\app\modules\admin\assets\ChartsAsset::register($this);
$this->title = 'Dashboard';
$requestsDays = array_keys($requestsStats);
krsort($requestsDays);
$searchRequestsChart = [];
foreach ($requestsDays as $day):
$count = 0;
if (isset($requestsStats[$day])):
$count = $requestsStats[$day]['requests'];
endif;
$searchRequestsChart[] = [
"date" => $day,
"value" => $count
];
endforeach;
krsort($searchRequestsChart);
$searchRequestsChart = array_values($searchRequestsChart);
$regsChart = [];
foreach ($requestsDays as $day):
$count = 0;
if (isset($requestsStats[$day])):
$count = $requestsStats[$day]['registrations'];
endif;
$regsChart[] = [
"date" => $day,
"value" => $count
];
endforeach;
krsort($regsChart);
$regsChart = array_values($regsChart);
$appleChart = [];
foreach ($requestsDays as $day):
$count = 0;
if (isset($requestsStats[$day])):
$count = $requestsStats[$day]['applePayments'];
endif;
$appleChart[] = [
"date" => $day,
"value" => $count
];
endforeach;
krsort($appleChart);
$appleChart = array_values($appleChart);
$siteTodayPayments = Payment::find()
->select(["site_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00")])
->andWhere(["<>", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_ANDROID, Payment::TYPE_APPLE]])
->andWhere(["IS NOT", "site_id", null])
->groupBy(["site_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$sitePayments = Payment::find()
->select(["site_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["<>", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_ANDROID, Payment::TYPE_APPLE]])
->andWhere(["IS NOT", "site_id", null])
->groupBy(["site_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$sources = (new Query())
->select(['source_id', new Expression('COUNT(1)')])
->from('requests')
->join('LEFT JOIN', 'users', 'requests.user_id = users.id')
->where(['>=', 'tm', date("Y-m-d") . ' 00:00:00'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->groupBy('source_id')
->orderBy('source_id')
->all();
$sources = ArrayHelper::map($sources, "source_id", "count");
$sitesRequests = (new Query())
->select(['site_id', 'is_payed', 'source_id', new Expression('COUNT(1) as c')])
->from('requests')
->leftJoin('users', 'requests.user_id = users.id')
->where(['>=', 'tm', date("Y-m-d") . ' 00:00:00'])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->groupBy(['site_id', 'is_payed', 'source_id'])
->orderBy(['site_id' => SORT_ASC, 'is_payed' => SORT_ASC, 'source_id' => SORT_ASC])
->all();
$sitesData = [];
foreach($sitesRequests as $sr) {
$is_payed = in_array($sr["is_payed"], [1, 2]);
if(!isset($sitesData[$sr["site_id"]][$sr["source_id"]][$is_payed])) {
$sitesData[$sr["site_id"]][$sr["source_id"]][$is_payed] = 0;
}
$sitesData[$sr["site_id"]][$sr["source_id"]][$is_payed] += $sr["c"];
}
$sites = \app\models\Site::find()->indexBy("id")->asArray()->all();
$last30daysSum = ArrayHelper::getValue($last30days, "sum") + ArrayHelper::getValue($last30Android, "sum") + ArrayHelper::getValue($last30Ios, "sum");
$antiparkonStats = \Yii::$app->cache->get("antiparkon");
?>
<?php if(!count($typesError)): ?>
<div class="alert alert-success">Все поиски работают отлично</div>
<?php else: ?>
<div class="alert alert-danger">У нас проблемы с: <?=join(", ", $typesError);?></div>
<?php endif; ?>
<?php if($avitoStats): ?>
<div class="alert alert-<?=($avitoStats["api_limit"]["of"]-$avitoStats["api_limit"]["used"])>5000?"success":"danger";?>">Остаток поисков по Авито: <?=$avitoStats["api_limit"]["used"];?>/<?=$avitoStats["api_limit"]["of"];?>, оплачено до <?=\Yii::$app->formatter->asDatetime($avitoStats["api_time_limit"]);?></div>
<?php endif; ?>
<?php if($antiparkonStats): ?>
<div class="alert alert-danger">Антипаркон: <?=$antiparkonStats;?></div>
<?php endif; ?>
<h3>Финансы</h3>
<table class="table table-striped table-bordered">
<tr>
<th>Сегодня</th>
<td>Вчера</td>
<td>За последние 30 дней</td>
</tr>
<tr>
<th><?= Yii::$app->formatter->asCurrency(ArrayHelper::getValue($today, "sum") + ArrayHelper::getValue($todayIos, "sum"), 'RUB') ?>
(Было
<?=ArrayHelper::getValue($today, "bills")+ArrayHelper::getValue($todayIos, "bills");?>
платежей от
<?=ArrayHelper::getValue($today, "bills_users")+ArrayHelper::getValue($todayIos, "bills_users");?>
пользователей, ребильных
<?=ArrayHelper::getValue($today, "rebills")+ArrayHelper::getValue($todayIos, "rebills");?>
платежей от
<?=ArrayHelper::getValue($today, "rebills_users")+ArrayHelper::getValue($todayIos, "rebills_users");?> юзеров)</th>
<th><?= Yii::$app->formatter->asCurrency(ArrayHelper::getValue($yesterday, "sum")+ArrayHelper::getValue($yesterdayIos, "sum"), 'RUB') ?>
(Было
<?=ArrayHelper::getValue($yesterday, "bills")+ArrayHelper::getValue($yesterdayIos, "bills");?>
платежей от
<?=ArrayHelper::getValue($yesterday, "bills_users")+ArrayHelper::getValue($yesterdayIos, "bills_users");?>
пользователей, ребильных
<?=ArrayHelper::getValue($yesterday, "rebills")+ArrayHelper::getValue($yesterdayIos, "rebills");?>
платежей от
<?=ArrayHelper::getValue($yesterday, "rebills_users")+ArrayHelper::getValue($yesterdayIos, "rebills_users");?>
юзеров)</th>
<th><?= Yii::$app->formatter->asCurrency($last30daysSum, 'RUB') ?>
(Было
<?=ArrayHelper::getValue($last30days, "bills");?>
платежей от
<?=ArrayHelper::getValue($last30days, "bills_users");?> пользователей, ребильных <?=ArrayHelper::getValue($last30days, "rebills");?> платежей от <?=ArrayHelper::getValue($last30days, "rebills_users");?> юзеров)</th>
</tr>
<tr>
<th><?=\Yii::t('app', '{n,plural,=0{Подписок нет} =1{Одна подписка} one{# подписка} few{# подписки} many{# подписок} other{# подписки}}', ['n' => $todaySubs]);?></th>
<th><?=\Yii::t('app', '{n,plural,=0{Подписок нет} =1{Одна подписка} one{# подписка} few{# подписки} many{# подписок} other{# подписки}}', ['n' => $yesterdaySubs]);?></th>
<th><?=\Yii::t('app', '{n,plural,=0{Подписок нет} =1{Одна подписка} one{# подписка} few{# подписки} many{# подписок} other{# подписки}}', ['n' => $last30daysSubs]);?></th>
</tr>
</table>
<table class="table table-striped table-bordered">
<tr>
<td>Общая сумма в кошельках - <b><?=Yii::$app->formatter->asCurrency($yandexWalletsSum + $qiwiWalletsSum, "RUB");?></b> из них в Яндекс - <b><?=Yii::$app->formatter->asCurrency($yandexWalletsSum, "RUB");?></b> и в киви - <b><?=Yii::$app->formatter->asCurrency($qiwiWalletsSum, "RUB");?></b></td>
</tr>
</table>
<div class="row">
<div class="col-md-6">
<table class="table table-striped table-bordered">
<tr>
<th colspan="3">Кол-во поисков</th>
</tr>
<tr>
<th>Сайт</th>
<th>Web (платные)</th>
<th>Mobile (платные)</th>
</tr>
<?php foreach ($sitesData as $siteID => $data): if(!$siteID) continue; ?>
<tr>
<?php $name = ArrayHelper::getValue(ArrayHelper::getValue($sites, $siteID), 'name'); ?>
<?php $comment = ArrayHelper::getValue(ArrayHelper::getValue($sites, $siteID), 'comment'); ?>
<td><?= $name ? $name : 'Не указано' ?> <?= $comment ? '(' . $comment . ')' : '' ?></td>
<td><?= (ArrayHelper::getValue($data, [SearchRequest::SOURCE_WEB, 0], 0) + ArrayHelper::getValue($data, [SearchRequest::SOURCE_WEB, 1], 0)) ?> (<?= ArrayHelper::getValue($data, [SearchRequest::SOURCE_WEB, 1], 0) ?>)</td>
<td><?= (ArrayHelper::getValue($data, [SearchRequest::SOURCE_MOBILE, 0], 0) + ArrayHelper::getValue($data, [SearchRequest::SOURCE_MOBILE, 1], 0)) ?> (<?= ArrayHelper::getValue($data, [SearchRequest::SOURCE_MOBILE, 1], 0) ?>)</td>
</tr>
<?php endforeach; ?>
<tr>
<th>Всего: </th>
<td><?= ArrayHelper::getValue($sources, SearchRequest::SOURCE_WEB);?></td>
<td><?= ArrayHelper::getValue($sources, SearchRequest::SOURCE_MOBILE);?></td>
</tr>
</table>
</div>
<div class="col-md-3">
<table class="table table-bordered">
<tr><th colspan="2">За сегодня</th></tr>
<?php foreach ($siteTodayPayments as $item): ?>
<tr>
<?php $name = ArrayHelper::getValue(ArrayHelper::getValue($sites, $item['site_id']), 'name'); ?>
<?php $comment = ArrayHelper::getValue(ArrayHelper::getValue($sites, $item['site_id']), 'comment'); ?>
<td><?= $name ? $name : 'Не указано' ?> <?= $comment ? '(' . $comment . ')' : '' ?></td>
<td><?= Yii::$app->formatter->asCurrency($item['amount'], 'RUB') ?></td>
</tr>
<?php endforeach; ?>
<tr><td>Android</td><td><?=Yii::$app->formatter->asCurrency(ArrayHelper::getValue($todayAndroid, "sum", 0), 'RUB');?></td></tr>
<tr><td>Apple</td><td><?=Yii::$app->formatter->asCurrency(ArrayHelper::getValue($todayIos, "sum", 0), 'RUB');?></td></tr>
</table>
</div>
<div class="col-md-3">
<table class="table table-bordered">
<tr><th colspan="2">За 30 дней</th></tr>
<?php foreach ($sitePayments as $item): ?>
<tr>
<?php $name = ArrayHelper::getValue(ArrayHelper::getValue($sites, $item['site_id']), 'name'); ?>
<?php $comment = ArrayHelper::getValue(ArrayHelper::getValue($sites, $item['site_id']), 'comment'); ?>
<td><?= $name ? $name : 'Не указано' ?> <?= $comment ? '(' . $comment . ')' : '' ?></td>
<td><?= Yii::$app->formatter->asCurrency($item['amount'], 'RUB') ?></td>
</tr>
<?php endforeach; ?>
<tr>
<td>Android</td>
<td><?=Yii::$app->formatter->asCurrency($last30Android['sum'], 'RUB');?></td>
</tr>
<tr>
<td>Apple</td>
<td><?=Yii::$app->formatter->asCurrency($last30Ios['sum'], 'RUB');?></td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-md-6">
<table class="table table-striped table-bordered">
<tr>
<td>Пользователей для уведомлений</td>
<td><?=$notifyTokens;?></td>
</tr>
<tr>
<td>Пользователей для уведомлений без подписки</td>
<td><?=$notifyTokensWithoutSubs;?></td>
</tr>
</table>
</div>
</div>
<div class="portlet light bordered">
<div class="portlet-title">
<div class="caption">Фильтры</div>
</div>
<div class="portlet-body form">
<?= Html::beginForm(['stats/index'], 'GET') ?>
<div class="input-group input-medium">
<span class="input-group-addon">С</span>
<?= DatePicker::widget([
'name' => 'tm_start',
'value' => $start,
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control input-small']
]) ?>
<span class="input-group-addon">по</span>
<?= DatePicker::widget([
'name' => 'tm_end',
'value' => $end,
'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control input-small']
]) ?>
<span class="input-group-addon"></span>
<button type="submit" class="form-control btn btn-primary input-small">Показать</button>
</div>
<?= Html::endForm() ?>
</div>
</div>
<table class="table table-striped table-bordered">
<tr>
<th>Дата</th>
<?php foreach ($requestsDays as $day): ?>
<td><?= $day ?></td>
<?php endforeach; ?>
</tr>
<tr style="cursor: pointer;" onclick="renderSearchRequestsChart(); $(this).addClass('warning');">
<th>Количество поисковых запросов</th>
<?php foreach ($requestsDays as $day): ?>
<td>
<?php if (isset($requestsStats[$day])): ?>
<?= $requestsStats[$day]['requests'] ?>
<?php else: ?>
-
<?php endif; ?>
</td>
<?php endforeach; ?>
</tr>
<tr style="cursor: pointer;" onclick="renderRegsChart(); $(this).addClass('warning');">
<th>Коичество регистраций</th>
<?php foreach ($requestsDays as $day): ?>
<td>
<?php if (isset($requestsStats[$day])): ?>
<?= $requestsStats[$day]['registrations'] ?>
<?php else: ?>
-
<?php endif; ?>
</td>
<?php endforeach; ?>
</tr>
<tr style="cursor: pointer;" onclick="renderAppleChart(); $(this).addClass('warning');">
<th>Кол-во покупок в Apple Store</th>
<?php foreach ($requestsDays as $day): ?>
<td>
<?php if (isset($requestsStats[$day])): ?>
<?= $requestsStats[$day]['applePayments'] ?>
<?php else: ?>
-
<?php endif; ?>
</td>
<?php endforeach; ?>
</tr>
</table>
<div id="chartdiv" style="height: 400px;"></div>
<?php if(false): ?><script language="JavaScript"><?php endif; ?>
<?php ob_start();?>
function renderChart(data) {
$('.warning').removeClass('warning');
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"marginRight": 40,
"marginLeft": 40,
"autoMarginOffset": 20,
"mouseWheelZoomEnabled": false,
"dataDateFormat": "YYYY-MM-DD",
"valueAxes": [{
"id": "v1",
"axisAlpha": 0,
"position": "left",
"ignoreAxisWidth":true
}],
"balloon": {
"borderThickness": 1,
"shadowAlpha": 0
},
"graphs": [{
"id": "g1",
"balloon":{
"drop":true,
"adjustBorderColor":false,
"color":"#ffffff"
},
"bullet": "round",
"bulletBorderAlpha": 1,
"bulletColor": "#FFFFFF",
"bulletSize": 2,
"hideBulletsCount": 50,
"lineThickness": 1,
"title": "red line",
"useLineColorForBulletBorder": true,
"valueField": "value",
"balloonText": "<span style='font-size:14px;'>[[value]]</span>"
}],
"chartCursor": {
"pan": true,
"valueLineEnabled": true,
"valueLineBalloonEnabled": true,
"cursorAlpha":1,
"cursorColor":"#258cbb",
"limitToGraph":"g1",
"valueLineAlpha":0.2,
"valueZoomable":true
},
"categoryField": "date",
"categoryAxis": {
"parseDates": true,
"dashLength": 1,
"minorGridEnabled": true
},
"dataProvider": data
} );
}
function renderSearchRequestsChart() {
renderChart(<?=Json::encode($searchRequestsChart);?>);
}
function renderRegsChart() {
renderChart(<?=Json::encode($regsChart);?>);
}
function renderAppleChart() {
renderChart(<?=Json::encode($appleChart);?>);
}
<?php $js = ob_get_contents(); ob_end_clean(); $this->registerJs($js, View::POS_END); ?>

View file

@ -0,0 +1,319 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\forms\AdminHistoryFilterForm */
/* @var $dataProvider \yii\data\ActiveDataProvider */
/* @var $queries array */
/* @var $users array */
/* @var $phones integer */
/* @var $sources array */
/* @var $sites array */
/* @var $requests array */
/* @var $sitesData array */
/* @var $searches array */
/* @var $payments array */
use app\models\Payment;
use yii\grid\GridView;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\jui\DatePicker;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use app\components\SearchHelper;
use app\models\SearchRequest;
use app\models\RequestResult;
use app\models\ResultCache;
$this->title = 'История поиска';
$sources = ArrayHelper::map($sources, "source_id", "count");
$freeNothing = SearchRequest::find()
->where(["is_payed" => 0, "is_has_name" => false, "is_has_photo" => false])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->joinWith(['user'])
->count(1);
$freeAll = SearchRequest::find()
->where(["is_payed" => 0, "is_has_name" => true, "is_has_photo" => true])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->joinWith(['user'])
->count(1);
$freeOnlyName = SearchRequest::find()
->where(["is_payed" => 0, "is_has_name" => true, "is_has_photo" => false])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->joinWith(['user'])
->count(1);
$payed = SearchRequest::find()
->where(["is_payed" => 1])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->joinWith(['user'])
->count(1);
$payedNothing = SearchRequest::find()
->where(["is_payed" => 2])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->andWhere(['or', ['users.is_admin' => false], ['users.is_admin' => null]])
->joinWith(['user'])
->count(1);
$anonymous = SearchRequest::find()
->where(["user_id" => null])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->count(1);
$regged = SearchRequest::find()
->where(["is_payed" => 0])
->andWhere(["is not", "user_id", null])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->count(1);
$androidSearches = SearchRequest::find()
->where(["source_id" => SearchRequest::SOURCE_ANDROID])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->count(1);
$androidSearchesPayed = SearchRequest::find()
->where(["source_id" => SearchRequest::SOURCE_ANDROID])
->andWhere(["is_payed" => 1])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->count(1);
$androidPayments = Payment::find()->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->andWhere(["type_id" => Payment::TYPE_ANDROID])->sum('amount');
$androidSearches30days = SearchRequest::find()->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->andWhere(["source_id" => SearchRequest::SOURCE_ANDROID])->count(1);
$appleSearches = SearchRequest::find()
->where(["source_id" => SearchRequest::SOURCE_IOS])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->count(1);
$appleSearchesPayed = SearchRequest::find()
->where(["source_id" => SearchRequest::SOURCE_IOS])
->andWhere(["is_payed" => 1])
->andWhere([">=", "tm", $model->from." 00:00:00"])
->andWhere(["<=", "tm", $model->to." 23:59:59"])
->count(1);
$applePayments = Payment::find()->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->andWhere(["type_id" => Payment::TYPE_APPLE])->sum('amount');
$appleSearches30days = SearchRequest::find()->where([">=", "tm", date("Y-m-d H:i:s", strtotime("-30 days"))])->andWhere(["source_id" => SearchRequest::SOURCE_IOS])->count(1);
?>
<div class="portlet light bordered">
<div class="portlet-title">
<div class="caption">Фильтры</div>
</div>
<div class="portlet-body form">
<?php $form = ActiveForm::begin(['method' => 'GET', 'action' => '/admin/history']); ?>
<div class="input-group input-medium">
<span class="input-group-addon">С</span>
<?= $form->field($model, 'from', ['template' => '{input}', 'options' => ['class' => '']])->textInput()->widget(DatePicker::className(), [
'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control input-small']
]) ?>
<span class="input-group-addon">по</span>
<?= $form->field($model, 'to', ['template' => '{input}', 'options' => ['class' => '']])->widget(DatePicker::className(), [
'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control input-small']
]) ?>
<?= $form->field($model, 'user', ['template' => '{input}', 'options' => ['class' => '']])->hiddenInput()->label(false) ?>
<span class="input-group-addon"></span>
<?= Html::submitButton('Показать', ['class' => 'form-control btn btn-primary input-small']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
<hr>
<div class="row">
<?php /*
<div class="col-md-4">
<table class="table table-striped table-bordered">
<?php foreach ($queries as $query): ?>
<tr>
<th><?= $query['registred'] ? 'Зарегистрированные' : 'Анонимные' ?></th>
<td><?= $query['count'] ?></td>
</tr>
<?php endforeach; ?>
<?php if (count($users) > 0): ?>
<tr>
<th>Сконвертировавшиеся пользователи</th>
<td><?= $users[0]['count'] ?></td>
</tr>
<?php endif; ?>
<tr>
<th>Количество уникальных номеров</th>
<td><?= $phones ?></td>
</tr>
</table>
</div>
<div class="col-md-4">
<table class="table table-striped table-bordered">
<tr>
<th><?=Html::a("бесплатные - анонимные", Url::current(["type" => 7]));?></th>
<td><?=$anonymous;?></td>
</tr>
<tr>
<th><?=Html::a("бесплатные - зареганные", Url::current(["type" => 8]));?></th>
<td><?=$regged;?></td>
</tr>
<tr>
<th><?=Html::a("бесплатные - ничего не найдено", Url::current(["type" => 1]));?></th>
<td><?=$freeNothing;?></td>
</tr>
<tr>
<th><?=Html::a("бесплатные - имя и фото", Url::current(["type" => 2]));?></th>
<td><?=$freeAll;?></td>
</tr>
<tr>
<th><?=Html::a("бесплатные - только имя", Url::current(["type" => 3]));?></th>
<td><?=$freeOnlyName;?></td>
</tr>
<tr>
<th><?=Html::a("платных запросов", Url::current(["type" => 4]));?></th>
<td><?=($payedNothing + $payed);?></td>
</tr>
<tr>
<th><?=Html::a("платные - ничего не найдено", Url::current(["type" => 5]));?></th>
<td><?=$payedNothing;?></td>
</tr>
<tr>
<th><?=Html::a("платные - найдено", Url::current(["type" => 6]));?></th>
<td><?=$payed;?></td>
</tr>
</table>
</div>
*/ ?>
<div class="col-md-12">
<table class="table table-striped table-bordered">
<tr>
<th colspan="3">Кол-во поисков</th>
</tr>
<tr>
<th>Сайт</th>
<th>Web (платные)</th>
<th>Mobile (платные)</th>
<th>Поиски (за 30 дн)</th>
<th>Платежи (за 30 дн)</th>
</tr>
<?php foreach ($sitesData as $siteID => $data): if(!$siteID) continue; ?>
<tr>
<th><?= Html::a($sites[$siteID]["name"], Url::current(["site_id" => $siteID])) ?> <?=$sites[$siteID]["comment"]?"(".$sites[$siteID]["comment"].")":"";?></th>
<td><?= (ArrayHelper::getValue($data, [SearchRequest::SOURCE_WEB, 0], 0) + ArrayHelper::getValue($data, [SearchRequest::SOURCE_WEB, 1], 0)) ?> (<?= ArrayHelper::getValue($data, [SearchRequest::SOURCE_WEB, 1], 0) ?>)</td>
<td><?= (ArrayHelper::getValue($data, [SearchRequest::SOURCE_MOBILE, 0], 0) + ArrayHelper::getValue($data, [SearchRequest::SOURCE_MOBILE, 1], 0)) ?> (<?= ArrayHelper::getValue($data, [SearchRequest::SOURCE_MOBILE, 1], 0) ?>)</td>
<td><?=ArrayHelper::getValue($searches, [$siteID, "count"]);?></td>
<td><?=\Yii::$app->formatter->asCurrency(ArrayHelper::getValue($payments, [$siteID, "sum"]), "RUB");?></td>
</tr>
<?php endforeach; ?>
<tr>
<th>Android</th>
<td colspan="2"><?=$androidSearches;?> (<?=$androidSearchesPayed;?>)</td>
<td><?=$androidSearches30days;?></td>
<td><?=\Yii::$app->formatter->asCurrency($androidPayments, 'RUB');?></td>
</tr>
<tr>
<th>Apple</th>
<td colspan="2"><?=$appleSearches;?> (<?=$appleSearchesPayed;?>)</td>
<td><?=$appleSearches30days;?></td>
<td><?=\Yii::$app->formatter->asCurrency($applePayments, 'RUB');?></td>
</tr>
<tr>
<th>Всего: </th>
<td><?= $sources[SearchRequest::SOURCE_WEB];?></td>
<td><?= $sources[SearchRequest::SOURCE_MOBILE];?></td>
</tr>
</table>
</div>
</div>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'tm',
[
'format' => 'raw',
'attribute' => 'phone',
'value' => function(SearchRequest $model) {
$phone = preg_replace('/^7/', '8', $model->phone);
return '<a href="/' . $phone . '">' . $phone . '</a>';
}
],
[
'attribute' => 'user_id',
'format' => 'raw',
'value' => function(SearchRequest $model) {
if (!$model->user) return 'Аноним';
return Html::a(trim($model->user->email)?$model->user->email:$model->user->uuid, ['users/view', 'id' => $model->user_id]);
}
],
[
'attribute' => 'ip',
'value' => function(SearchRequest $model) {
return join(', ', [$model->ip, SearchHelper::City($model->ip)]);
}
],
[
'header' => 'Индекс поиска',
'value' => function(SearchRequest $model) {
if ($model->is_payed) {
return array_sum(array_map(function(RequestResult $result) {
return $result->index;
}, $model->results));
}
$finds = [];
if ($model->is_has_name) $finds[] = 'Имя';
if ($model->is_has_photo) $finds[] = 'Фото';
return $finds ? join(', ', $finds) : 'Ничего не найдено';
}
],
[
'header' => 'Стоимость',
'value' => function(SearchRequest $model) {
$type = '';
switch ($model->is_payed) {
case 0: $type = 'Бесплатный (нет проверок)'; break;
case 1: $type = 'Платный'; break;
case 2: $type = 'Бесплатный (не нашли)'; break;
}
if (!$model->user_id) $type .= ', Аноним';
return $type;
}
],
[
'attribute' => 'source_id',
'value' => function(SearchRequest $model) {
return SearchRequest::getSourceText($model->source_id);
}
],
[
'attribute' => 'site_id',
'value' => function(SearchRequest $model) {
if (!$model->site) return null;
return $model->site->name;
}
]
]
]) ?>

View file

@ -0,0 +1,257 @@
<?php
/* @var $this \yii\web\View */
/* @var $content string */
use yii\helpers\Html;
use yii\helpers\Url;
use app\models\Telegram;
use app\models\Token;
use app\modules\admin\assets\ThemeAsset;
ThemeAsset::register($this);
$this->registerCss('.badge-menu { margin-left: 10px; }');
?>
<?php $this->beginPage(); ?>
<!DOCTYPE html>
<!--[if IE 8]>
<html lang="<?= Yii::$app->language ?>" class="ie8"> <![endif]-->
<!--[if IE 9]>
<html lang="<?= Yii::$app->language ?>" class="ie9"> <![endif]-->
<!--[if !IE]><!-->
<html lang="<?= Yii::$app->language ?>"> <!--<![endif]-->
<head>
<meta charset="<?= Yii::$app->charset ?>"/>
<?= Html::csrfMetaTags() ?>
<title><?= Yii::$app->name ?> admin - <?= Html::encode($this->title) ?></title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<meta content="nomer.io Admin" name="description"/>
<meta content="nomer.io" name="author"/>
<link rel="shortcut icon" href="/favicon.ico"/>
<?php $this->head(); ?>
</head>
<body class="page-header-fixed page-sidebar-closed-hide-logo page-content-white">
<?php $this->beginBody(); ?>
<div class="page-wrapper">
<!-- BEGIN HEADER -->
<div class="page-header navbar navbar-fixed-top">
<!-- BEGIN HEADER INNER -->
<div class="page-header-inner ">
<!-- BEGIN LOGO -->
<div class="page-logo">
<div class="menu-toggler sidebar-toggler">
<span></span>
</div>
</div>
<!-- END LOGO -->
<!-- BEGIN RESPONSIVE MENU TOGGLER -->
<a href="javascript:;" class="menu-toggler responsive-toggler" data-toggle="collapse"
data-target=".navbar-collapse">
<span></span>
</a>
</div>
</div>
<div class="clearfix"></div>
<div class="page-container">
<!-- BEGIN SIDEBAR -->
<div class="page-sidebar-wrapper">
<!-- DOC: Set data-auto-scroll="false" to disable the sidebar from auto scrolling/focusing -->
<!-- DOC: Change data-auto-speed="200" to adjust the sub menu slide up/down speed -->
<div class="page-sidebar navbar-collapse collapse">
<!-- BEGIN SIDEBAR MENU -->
<ul class="page-sidebar-menu">
<?php if (\Yii::$app->user->id != 247): ?>
<li class="start <?= Yii::$app->controller->id == 'dashboard' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['dashboard/index']) ?>">
<i class="icon-home"></i>
<span class="title">Dashboard</span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'users' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['users/index']) ?>">
<i class="icon-users"></i>
<span class="title">Пользователи</span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'referrals' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['referrals/index']) ?>">
<i class="icon-user-follow"></i>
<span class="title">Реферальная система</span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'history' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['history/index']) ?>">
<i class="icon-list"></i>
<span class="title">История поиска</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'tickets' ? 'active' : '' ?>">
<?php
$tickets = \app\models\Ticket::find()->where(["status" => [0, 1], "is_deleted" => 0])->count();
?>
<a href="<?= Url::toRoute(['tickets/index']) ?>">
<i class="icon-speech "></i>
<span class="title">Система тикетов</span>
<?php if ($tickets): ?>
<span class="badge badge-danger"><?= $tickets; ?></span>
<?php endif; ?>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'stats' && Yii::$app->controller->action->id == 'index' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['stats/index']) ?>">
<i class="icon-bar-chart"></i>
<span class="title">Статистика</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'payments' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['payments/index']) ?>">
<i class="icon-credit-card"></i>
<span class="title">Платежи</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'subscriptions' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['subscriptions/index']) ?>">
<i class="icon-credit-card"></i>
<span class="title">Подписки</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'checkouts' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['checkouts/index']) ?>">
<i class="icon-credit-card"></i>
<span class="title">Выплаты</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'sites' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['sites/index']) ?>">
<i class="icon-globe"></i>
<span class="title">Сайты</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'notify' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['notify/index']) ?>">
<i class="icon-energy"></i>
<span class="title">Уведомления</span>
<span class="selected"></span>
</a>
</li>
<?php endif; ?>
<li class="<?= Yii::$app->controller->id == 'wallets' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['wallets/index']) ?>">
<i class="icon-wallet"></i>
<span class="title">Кошельки</span>
<span class="selected"></span>
</a>
</li>
<?php if (\Yii::$app->getUser()->id == 1): ?>
<li class="<?= Yii::$app->controller->id == 'tokens' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['tokens/index']) ?>">
<i class="icon-key"></i>
<span class="title">Токены<?php if ($count = Token::find()->where(['status' => Token::STATUS_INACTIVE])->count()) echo '<span class="badge badge-menu badge-danger">' . $count . '</span>' ?></span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'accounts' && Yii::$app->controller->action->id == 'telegram' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['accounts/telegram']) ?>">
<i class="icon-paper-plane"></i>
<span class="title">Telegram<?php if ($count = Telegram::find()->where(['status' => [Telegram::STATUS_INACTIVE, Telegram::STATUS_UNAVAILABLE]])->count()) echo '<span class="badge badge-menu badge-danger">' . $count . '</span>' ?></span>
<span class="selected"></span>
</a>
</li>
<?php endif; ?>
<?php if (\Yii::$app->user->id != 247): ?>
<li class="<?= Yii::$app->controller->id == 'reposts' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['reposts/index']) ?>">
<i class="icon-share"></i>
<span class="title">Репосты</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'retargeting' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['retargeting/index']) ?>">
<i class="icon-bar-chart"></i>
<span class="title">Ретаргетинг</span>
<span class="selected"></span>
</a>
</li>
<li class="<?= Yii::$app->controller->id == 'settings' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['settings/index']) ?>">
<i class="icon-settings"></i>
<span class="title">Настройки</span>
</a>
</li>
<?php endif; ?>
<li class="<?= Yii::$app->controller->id == 'apple' ? 'active' : '' ?>">
<a href="<?= Url::toRoute(['apple/index']) ?>">
<i class="icon-reports"></i>
<span class="title">Отчеты apple</span>
</a>
</li>
</ul>
<!-- END SIDEBAR MENU -->
</div>
</div>
<!-- END SIDEBAR -->
<!-- BEGIN CONTENT -->
<div class="page-content-wrapper">
<div class="page-content">
<!-- BEGIN PAGE HEADER-->
<h3 class="page-title">
<?= $this->title ?>
</h3>
<div class="page-bar">
<ul class="page-breadcrumb">
<li>
<i class="fa fa-home"></i>
<?= Html::a('Главная', '/admin/') ?>
<i class="fa fa-angle-right"></i>
</li>
<li><?= $this->title ?></li>
</ul>
</div>
<!-- END PAGE HEADER-->
<br>
<!-- BEGIN PAGE CONTENT-->
<div class="row">
<div class="col-md-12">
<?= $content ?>
</div>
</div>
<!-- END PAGE CONTENT-->
</div>
</div>
<!-- END CONTENT -->
<!-- BEGIN FOOTER -->
<div class="page-footer">
<div class="page-footer-inner">
<?= date('Y') ?> &copy; <?= Yii::$app->name ?>.
</div>
<div class="page-footer-tools">
<span class="go-top"><i class="fa fa-angle-up"></i></span>
</div>
</div>
</div>
</div>
<!-- END FOOTER -->
<?php $this->endBody(); ?>
<?php $this->registerJs("App.init(); Layout.init();"); ?>
</body>
</html>
<?php $this->endPage(); ?>

View file

@ -0,0 +1,58 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\helpers\Html;
$this->title = "Уведомления в iOS";
?>
<?=Html::beginForm(["notify/index"]); ?>
<div class="form-group">
<label for="whom">Кому отправлять уведомления</label>
<?=Html::dropDownList("whom", "nosub", [
"all" => "Всем",
"nosub" => "Без активных подписок"
], ["class" => "form-control"]);?>
</div>
<div class="form-group">
<label for="message">Текст уведомления</label>
<?=Html::textInput("message", "", ["class" => "form-control"]); ?>
</div>
<div class="form-group">
<label for="payload">Payload</label>
<?=Html::textarea("payload", "", ["class" => "form-control"]); ?>
</div>
<button type="submit" class="btn btn-default">Отправить</button>
<?=Html::endForm();?>
<br><br>
<?=\yii\grid\GridView::widget([
"dataProvider" => $dataProvider,
"columns" => [
"id",
"tm_create",
"message",
[
"header" => "Данные",
"content" => function(\app\models\Notification $model) {
return Html::tag("pre", print_r(\yii\helpers\Json::decode($model->payload), true));
}
],
[
"header" => "Отправлено",
"content" => function(\app\models\Notification $model) {
return $model->getResults()->count(1);
}
],
[
"header" => "Доставлено",
"content" => function(\app\models\Notification $model) {
return $model->getGoodResults()->count(1);
}
]
]
]); ?>

View file

@ -0,0 +1,380 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
/* @var $regions array */
/* @var $todaySubs int */
use app\models\ApplePayment;
use yii\db\Expression;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use app\components\SearchHelper;
use app\models\Payment;
use app\models\User;
$this->title = "Платежи";
$day = date("Y-m-d");
$days = [];
$today = (new yii\db\Query())
// ->select([new Expression('SUM(amount) as sum'), new Expression('COUNT(1) as bills'), new Expression('COUNT(1) - (COUNT(DISTINCT user_id) + COUNT(case when user_id is NULL then 1 else null end)) as rebills')])
->select([new Expression('SUM(amount) as sum'), new Expression('COUNT(1) as bills'), new Expression('(SELECT COUNT(1) FROM payments p WHERE
extract(month from p.tm) = '.date("m").'
AND extract(year from p.tm) = '.date("Y").'
AND extract(day from p.tm) = '.date("d").'
AND p.user_id IN (SELECT user_id FROM payments GROUP BY user_id HAVING COUNT(1) > 1)) as rebills')])
->from(Payment::tableName().' p')
->where(["=", new Expression("extract(month from tm)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y")])
->andWhere(["=", new Expression("extract(day from tm)"), date("d")])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->one();
$last30days = Payment::find()
->select(new Expression('SUM(amount)'))
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["NOT IN", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_APPLE]])
->scalar();
$last30daysDetails = Payment::find()
->select(["type_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["NOT IN", "type_id", [Payment::TYPE_TESTAPPLE, Payment::TYPE_APPLE]])
->groupBy(["type_id"])
->asArray()
->all();
$currentMonth = Payment::find()
->select(new Expression('SUM(amount)'))
->where(["=", new Expression("extract(month from tm)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y")])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->scalar();
/*
$currentMonthDetails = Payment::find()
->select(["type_id", new Expression('SUM(amount) as amount')])
->where(["=", new Expression("extract(month from tm)"), date("m")])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y")])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->groupBy(["type_id"])
->asArray()
->all();
*/
$preventMonth = Payment::find()
->select(new Expression('SUM(amount)'))
->where(["=", new Expression("extract(month from tm)"), date("m", strtotime("-1 month"))])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y", strtotime("-1 month"))])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->scalar();
/*
$preventMonthDetails = Payment::find()
->select(["type_id", new Expression('SUM(amount) as amount')])
->where(["=", new Expression("extract(month from tm)"), date("m", strtotime("-1 month"))])
->andWhere(["=", new Expression("extract(year from tm)"), date("Y", strtotime("-1 month"))])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->groupBy(["type_id"])
->asArray()
->all();
*/
$paymentsData = [
//"all" => [0 => 0, 1 => 0, 2 => 0],
Payment::TYPE_YANDEX => [0 => 0],
Payment::TYPE_YANDEX_WALLET => [0 => 0],
Payment::TYPE_QIWI => [0 => 0],
Payment::TYPE_QIWI_TERMINAL => [0 => 0],
Payment::TYPE_WEBMONEY => [0 => 0]
];
foreach($last30daysDetails as $r) {
$paymentsData[$r["type_id"]][0] = $r["amount"];
}
$iosPayments = (new yii\db\Query())
->select([
new Expression('SUM(amount) as amount'),
])
->from(ApplePayment::tableName())
->where([">=", "tm", date("Y-m-d", strtotime("-30 days"))])
->scalar();
$paymentsData[9][0] = $iosPayments;
/*
foreach($currentMonthDetails as $r) {
$paymentsData[$r["type_id"]][1] = $r["amount"];
}
foreach($preventMonthDetails as $r) {
$paymentsData[$r["type_id"]][2] = $r["amount"];
}
*/
$siteTodayPayments = Payment::find()
->select(["site_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00")])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->andWhere(["IS NOT", "site_id", null])
->groupBy(["site_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$siteTodayMobilePayments = Payment::find()
->select(["type_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00")])
->andWhere(["type_id" => [Payment::TYPE_ANDROID]])
->andWhere(["site_id" => null])
->groupBy(["type_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$sitePayments = Payment::find()
->select(["site_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->andWhere(["IS NOT", "site_id", null])
->groupBy(["site_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$mobilePayments = Payment::find()
->select(["type_id", new Expression('SUM(amount) as amount')])
->where([">=", "tm", date("Y-m-d 00:00:00", strtotime("-30 days"))])
->andWhere(["type_id" => [Payment::TYPE_ANDROID]])
->andWhere(["site_id" => null])
->groupBy(["type_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$siteAllPayments = Payment::find()
->select(["site_id", new Expression('SUM(amount) as amount')])
->andWhere(["<>", "type_id", Payment::TYPE_TESTAPPLE])
->andWhere(["IS NOT", "site_id", null])
->groupBy(["site_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$mobileAllPayments = Payment::find()
->select(["type_id", new Expression('SUM(amount) as amount')])
->andWhere(["type_id" => [Payment::TYPE_ANDROID]])
->andWhere(["site_id" => null])
->groupBy(["type_id"])
->orderBy(["amount" => SORT_DESC])
->asArray()
->all();
$iosAllPayment = (new yii\db\Query())
->select([
new Expression('SUM(amount) as amount'),
])
->from(ApplePayment::tableName())
->scalar();
$sites = \app\models\Site::find()->indexBy("id")->asArray()->all();
$siteTodayData = $site30daysData = $siteAllData = [];
foreach ($siteTodayPayments as $s) {
//$sTitle =
$name = ArrayHelper::getValue(ArrayHelper::getValue($sites, $s['site_id']), 'name');
$comment = ArrayHelper::getValue(ArrayHelper::getValue($sites, $s['site_id']), 'comment');
$siteId = $name.($comment?'('.$comment.')':'');
$siteTodayData[$siteId] = ArrayHelper::getValue($s, "amount");
}
foreach ($siteTodayMobilePayments as $s) {
$siteId = Payment::getTypeName(ArrayHelper::getValue($s, "type_id"));
$siteTodayData[$siteId] = ArrayHelper::getValue($s, "amount");
}
foreach ($sitePayments as $s) {
//$sTitle =
$name = ArrayHelper::getValue(ArrayHelper::getValue($sites, $s['site_id']), 'name');
$comment = ArrayHelper::getValue(ArrayHelper::getValue($sites, $s['site_id']), 'comment');
$siteId = $name.($comment?'('.$comment.')':'');
$site30daysData[$siteId] = ArrayHelper::getValue($s, "amount");
}
foreach ($mobilePayments as $s) {
$siteId = Payment::getTypeName(ArrayHelper::getValue($s, "type_id"));
$site30daysData[$siteId] = ArrayHelper::getValue($s, "amount");
}
$site30daysData["Apple"] = $iosPayments;
foreach ($siteAllPayments as $s) {
//$sTitle =
$name = ArrayHelper::getValue(ArrayHelper::getValue($sites, $s['site_id']), 'name');
$comment = ArrayHelper::getValue(ArrayHelper::getValue($sites, $s['site_id']), 'comment');
$siteId = $name.($comment?'('.$comment.')':'');
$siteAllData[$siteId] = ArrayHelper::getValue($s, "amount");
}
foreach ($mobileAllPayments as $s) {
$siteId = Payment::getTypeName(ArrayHelper::getValue($s, "type_id"));
$siteAllData[$siteId] = ArrayHelper::getValue($s, "amount");
}
$siteAllData["Apple"] = $iosAllPayment;
arsort($siteTodayData);
arsort($site30daysData);
arsort($siteAllData);
?>
<div class="row">
<div class="col-md-3">
<table class="table table-bordered">
<tr><td colspan="4"><b>За сегодня: <?= Yii::$app->formatter->asCurrency(ArrayHelper::getValue($today, 'sum', 0), 'RUB') ?> (Всего платежей - <?= ArrayHelper::getValue($today, 'bills', 0) ?>, ребилов - <?= ArrayHelper::getValue($today, 'rebills', 0) ?>)</b><br>
<?=\Yii::t('app', '{n,plural,=0{Подписок нет} =1{Одна подписка} one{# подписка} few{# подписки} many{# подписок} other{# подписки}}', ['n' => $todaySubs]);?>
</td></tr>
<tr>
<td></td>
<td><b>За последние 30 дней</b></td>
</tr>
<?php foreach ($paymentsData as $typeID => $items): ?>
<tr>
<td><?=Payment::getTypeName($typeID);?></td>
<?php foreach($items as $item): ?>
<td><?=\Yii::$app->formatter->asCurrency($item, "RUB");?></td>
<?php endforeach;?>
</tr>
<?php endforeach; ?>
<tr>
<th>Всего:</th>
<th><?=\Yii::$app->formatter->asCurrency($last30days+$iosPayments, "RUB");?></th>
</tr>
</table>
</div>
<div class="col-md-3">
<table class="table table-bordered">
<tr><th colspan="2">За сегодня</th></tr>
<?php foreach ($siteTodayData as $name => $amount): ?>
<tr>
<td><?=$name;?></td>
<td><?= Yii::$app->formatter->asCurrency($amount, 'RUB') ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="col-md-3">
<table class="table table-bordered">
<tr><th colspan="2">За 30 дней</th></tr>
<?php foreach ($site30daysData as $name => $amount): ?>
<tr>
<td><?=$name;?></td>
<td><?= Yii::$app->formatter->asCurrency($amount, 'RUB') ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div class="col-md-3">
<table class="table table-bordered">
<tr><th colspan="2">За всё время</th></tr>
<?php foreach ($siteAllData as $name => $amount): ?>
<tr>
<td><?=$name;?></td>
<td><?= Yii::$app->formatter->asCurrency($amount, 'RUB') ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
<?php
echo GridView::widget([
'dataProvider' => $dataProvider,
'rowOptions' => function (Payment $model) {
$payments = Payment::find()->where(['user_id' => $model->user_id])->andWhere(['<', 'id', $model->id])->count();
if ($payments) return ['class' => 'success'];
return [];
},
'beforeRow' => function ($model, $key, $index, $grid) use (&$day){
$cday = date("Y-m-d", strtotime($model->tm));
if($cday != $day && $index > 0) {
$sum = Payment::find()->select(new Expression('SUM(amount)'))->where([">=", "tm", $day." 00:00:00"])->andWhere(["<=", "tm", $day." 23:59:59"])->scalar();
return "<tr><td colspan='5'>За <b>".\Yii::$app->formatter->asDate($day, "d MMMM")."</b> заработано <b>".\Yii::$app->formatter->asCurrency($sum, "RUB")."</b></td></tr>";
}
$day = date("Y-m-d", strtotime($model->tm));
},
'afterRow' => function ($model, $key, $index, $grid) use (&$day, $dataProvider) {
$day = date("Y-m-d", strtotime($model->tm));
if(($index+1) == $dataProvider->totalCount) {
$sum = Payment::find()->select(new Expression('SUM(amount)'))->where([">=", "tm", $day." 00:00:00"])->andWhere(["<=", "tm", $day." 23:59:59"])->scalar();
return "<tr><td colspan='5'>За <b>".\Yii::$app->formatter->asDate($day, "d MMMM")."</b> заработано <b>".\Yii::$app->formatter->asCurrency($sum, "RUB")."</b></td></tr>";
}
},
'columns' => [
'id',
[
'attribute' => 'site_id',
'content' => function(Payment $model) {
if($model->type_id == Payment::TYPE_ANDROID) {
return "Play Market";
}
if($model->type_id == Payment::TYPE_APPLE) {
return "Apple Store";
}
return ArrayHelper::getValue($model, "site.name", "-");
}
],
[
'attribute' => 'tm',
'content' => function(Payment $model) {
return Yii::$app->formatter->asDatetime(strtotime($model->tm) - 3600, 'dd.MM.yyyy HH:mm');
}
],
[
'attribute' => 'user_id',
'content' => function(Payment $model) {
$user = ArrayHelper::getValue($model, 'user', null);
$city = '';
if (!$user || $user->ip == '') $city = '';
//else $city = SearchHelper::City($user->ip);
$paymentsCount = count(ArrayHelper::getValue($model, ['user', 'payments'], []));
if ($paymentsCount > 1) {
$paymentsSum = array_sum(ArrayHelper::getColumn($model->user->payments, 'amount'));
$paymentsSum = Yii::$app->formatter->asCurrency($paymentsSum, 'RUB');
$payments = '(Всего ' . $paymentsSum .', ' . Yii::t('app', '{n, plural, one{# платёж} few{# платежа} many{# платежей} other{# платежа}}', ['n' => $paymentsCount]) . ')';
} else {
$payments = '';
}
$username = null;
if ($user) {
$username = 'Пользователь #'.$user->id;
if(trim($user->email) != "") {
$username = $user->email;
}
}
return $user ? join(', ', array_filter([Html::a($username, Url::toRoute(['users/view', 'id' => $user->id])), $city, $payments])) : "Пользователь не известен";
}
],
[
'header' => 'Сумма',
'content' => function(Payment $model) {
return Yii::$app->formatter->asCurrency($model->amount, 'RUB');
}
],
[
'header' => 'Тип',
'content' => function(Payment $model) {
return Payment::getTypeName($model->type_id);
}
]
]
]);

View file

@ -0,0 +1,6 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
?>
<?=\yii\grid\GridView::widget(["dataProvider" => $dataProvider]); ?>

View file

@ -0,0 +1,20 @@
<?php
/* @var $this \yii\web\View */
$this->title = "Реферальная система";
?>
<table class="table">
<tr>
<th>Пользователь</th>
<th>Кол-во рефералов</th>
<th>Баланс</th>
</tr>
<?php foreach($refs as $r): ?>
<tr>
<td><?=$r->email;?></td>
<td><?=\app\models\User::find()->where(["ref_id" => $r->id])->count();?></td>
<td><?=$r->ref_balance;?></td>
</tr>
<?php endforeach; ?>
</table>

View file

@ -0,0 +1,34 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\Html;
?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'rowOptions' => function(\app\models\Repost $model) {
if ($model->status == 0) return ['class' => 'danger'];
return [];
},
'columns' => [
"id",
"tm",
[
"attribute" => "user_id",
"content" => function(\app\models\Repost $model) {
return Html::a($model->user->email, ["users/view", "id" => $model->user_id]);
}
],
[
"attribute" => "vk_id",
"content" => function(\app\models\Repost $model) {
$link = "https://vk.com/id".$model->vk_id;
return Html::a($link, $link);
}
],
"sms_count",
]
]) ?>

View file

@ -0,0 +1,41 @@
<?php
use yii\grid\ActionColumn;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
$this->title = 'Ретаргетинг';
?>
<h3>Статистика</h3>
<table class="table table-striped table-bordered">
<tr>
<th></th>
<th>Сегодня</th>
<th>Вчера</th>
<th>За последние 30 дней</th>
</tr>
<tr>
<td>Кол-во отправленных писем:</td>
<td><?= $todaySent ? $todaySent : 0 ?></td>
<td><?= $todayRead ? $todayRead : 0 ?></td>
<td><?= $todayClick ? $todayClick : 0 ?></td>
</tr>
<tr>
<td>Кол-во прочитанных писем:</td>
<td><?= $yesterdaySent ?></td>
<td><?= $yesterdayRead ?></td>
<td><?= $yesterdayClick ?></td>
</tr>
<tr>
<td>Кол-во переходов по ссылке:</td>
<td><?= $monthSent ?></td>
<td><?= $monthRead ?></td>
<td><?= $monthClick ?></td>
</tr>
</table>

View file

@ -0,0 +1,29 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\Url;
use yii\helpers\Html;
use app\models\User;
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
[
'format' => 'raw',
'attribute' => 'email',
'value' => function(User $model) {
return Html::a($model->email, Url::toRoute(['users/view', 'id' => $model->id]));
}
],
[
'attribute' => 'ban',
'value' => function(User $model) {
return User::getBanStatusText($model->ban);
}
]
]
]);

View file

@ -0,0 +1,31 @@
<?php
/* @var $this \yii\web\View */
/* @var $phones array */
$count = array_reduce($phones, function($acc, $data) {
return [
'all' => $acc['all'] += $data['all'],
'unconfirmed' => $acc['unconfirmed'] += $data['confirmed'],
'confirmed' => $acc['confirmed'] += $data['confirmed'],
'vip' => $acc['vip'] += $data['vip']
];
}, ['all' => 0, 'unconfirmed' => 0, 'confirmed' => 0, 'vip' => 0]);
?>
<h3>Всего заблокировано <?= $count['all'] ?> номеров. Подтверждено: <?= $count['confirmed'] ?>. VIP <?= $count['vip'] ?></h3>
<table class="table table-striped table-bordered">
<tr>
<th>Дата</th>
<th>Количество заблокированных мномеров</th>
</tr>
<?php foreach ($phones as $date => $data): ?>
<tr>
<td><?= $date ?></td>
<td>Всего: <?= $data['all'] ?>, подтверждено: <?= $data['confirmed'] ?>, VIP: <?= $data['vip'] ?>.</td>
</tr>
<?php endforeach; ?>
</table>

View file

@ -0,0 +1,44 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\UrlFilter */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use app\models\UrlFilter;
use yii\grid\GridView;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'url')->textInput() ?>
<?= $form->field($model, 'type')->dropDownList(UrlFilter::getTypes()) ?>
<?= Html::submitButton('Добавить', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
<hr>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
'url',
[
'attribute' => 'type',
'value' => function(UrlFilter $model) {
return UrlFilter::typeText($model->type);
}
],
[
'format' => 'raw',
'header' => 'Действия',
'value' => function(UrlFilter $model) {
return '<a href="' . Url::to(['settings/delete-domain', 'id' => $model->id]) . '" onclick="return confirm(\'Удалить домен?\')"><i class="icon-trash"></i></a>';
}
]
]
]) ?>

View file

@ -0,0 +1,35 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use app\models\UserFingerprint;
use \app\models\User;
use \yii\helpers\ArrayHelper;
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'hash',
[
'attribute' => 'user_ids',
'header' => 'Пользователи',
'value' => function ($data) {
$userIds = trim(ArrayHelper::getValue($data, 'user_ids'), '{}');
$userIds = preg_split('/,/', $userIds);
$users = User::find()->where(['id' => $userIds])->all();
return join(', ', ArrayHelper::getColumn($users, 'email'));
}
],
[
'attribute' => 'ips',
'header' => 'IP адреса',
'value' => function ($data) {
$ips = trim(ArrayHelper::getValue($data, 'ips'), '{}');
$ips = preg_split('/,/', $ips);
return join(', ', $ips);
}
],
]
]);

View file

@ -0,0 +1,73 @@
<?php
/* @var $this \yii\web\View */
use yii\helpers\Html;
use app\models\Settings;
?>
<?= Html::beginForm() ?>
<table class="table">
<tr>
<th colspan="2">Индексы поиска</th>
</tr>
<tr>
<td>Индекс поиска оператора</td>
<td><?=Html::textInput('search_index_operator', Settings::get('search_index_operator', 0), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска фото в Viber</td>
<td><?=Html::textInput('search_index_viber', Settings::get('search_index_viber', 7), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска во ВКонтакте VIP</td>
<td><?=Html::textInput('search_index_vk_vip', Settings::get('search_index_vk_vip', 0), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска во ВКонтакте</td>
<td><?=Html::textInput('search_index_vk', Settings::get('search_index_vk', 15), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Facebook</td>
<td><?=Html::textInput('search_index_fb', Settings::get('search_index_fb', 15), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска по Avito</td>
<td><?=Html::textInput('search_index_avito', Settings::get('search_index_avito', 15), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Google</td>
<td><?= Html::textInput('search_index_google', Settings::get('search_index_google', 7), ["class" => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска по Auto.ru</td>
<td><?= Html::textInput('search_index_avinfo', Settings::get('search_index_avinfo', 15), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Sprut</td>
<td><?= Html::textInput('search_index_sprut', Settings::get('search_index_sprut', 0), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Truecaller</td>
<td><?= Html::textInput('search_index_truecaller', Settings::get('search_index_truecaller', 15), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Numbuster</td>
<td><?= Html::textInput('search_index_numbuster', Settings::get('search_index_numbuster', 15), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Инстаграмме</td>
<td><?= Html::textInput('search_index_instagram', Settings::get('search_index_instagram', 20), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Антипарконе</td>
<td><?= Html::textInput('search_index_antiparkon', Settings::get('search_index_antiparkon', 5), ['class' => 'form-control']) ?></td>
</tr>
<tr>
<td>Индекс поиска в Телеграмме</td>
<td><?= Html::textInput('search_index_telegram', Settings::get('search_index_telegram', 7), ['class' => 'form-control']) ?></td>
</tr>
</table>
<?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
<?= Html::endForm() ?>

View file

@ -0,0 +1,55 @@
<?php
/* @var $this \yii\web\View */
/* @var $tab string */
/* @var $model \yii\db\ActiveRecord */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\bootstrap\Tabs;
use yii\helpers\Url;
$this->title = 'Настройки';
echo Tabs::widget([
'id' => 'SettingsTabsWidget',
'renderTabContent' => false,
'items' => [
[
'label' => 'Индексы поиска',
'url' => Url::toRoute(['settings/index', 'tab' => 'index']),
'active' => $tab == 'index'
],
[
'label' => 'Заблокированные пользователи',
'url' => Url::toRoute(['settings/index', 'tab' => 'bans']),
'active' => $tab == 'bans'
],
[
'label' => 'Домены',
'url' => Url::toRoute(['settings/index', 'tab' => 'domains']),
'active' => $tab == 'domains'
],
[
'label' => 'Статистика по фингерпринтам',
'url' => Url::toRoute(['settings/index', 'tab' => 'fingerprints']),
'active' => $tab == 'fingerprints'
],
[
'label' => 'Заблокированные номера',
'url' => Url::toRoute(['settings/index', 'tab' => 'blocked-phones']),
'active' => $tab == 'blocked-phones'
]
]
]);
echo '<div class="tab-content">';
switch ($tab) {
case 'index': echo $this->render('_search_index'); break;
case 'bans': echo $this->render('_bans', compact('dataProvider')); break;
case 'domains': echo $this->render('_domains', compact('model', 'dataProvider')); break;
case 'fingerprints': echo $this->render('_fingerprints', compact('dataProvider')); break;
case 'blocked-phones': echo $this->render('_blocked_phones', compact('phones')); break;
}
echo '</div>';

View file

@ -0,0 +1,27 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Site */
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin();?>
<?= $form->field($model, 'name')->textInput() ?>
<?= $form->field($model, 'comment')->textInput() ?>
<?= $form->field($model, 'is_demo')->checkbox() ?>
<?= $form->field($model, 'type_id')->dropDownList(["1" => "Обычный", 2 => "Новый тип поиска"]) ?>
<?= $form->field($model, 'phone')->textInput()->hint("Номер телефон для QIWI кошелька. Пароль должен быть Ag6K2oxG. Нужно отключать подтверждение по смс. По паспортным данных должен находится ИНН на nalog.ru") ?>
<?= $form->field($model, 'yandex_money_account')->textInput()->hint("№ кошелька ЯД. По паспортным данных должен находится ИНН на nalog.ru. Настройки -> Все остальное -> Уведомления. Указать http://yamoney.pmadm.ru/pay/result + поставить галочку.") ?>
<?= $form->field($model, 'vk_id')->textInput()->hint("Создаем приложение в контакте. Название: ДОМЕН. Тип: веб сайт. Адрес: https://ДОМЕН. Домены: ДОМЕН. Сюда берем ID приложения.") ?>
<?= $form->field($model, 'vk_secret')->textInput()->hint("Сюда берем Защищенный ключ") ?>
<?= $form->field($model, 'fb_id')->textInput()->hint("Создаем приложение на facebook. Отображаемое имя: ДОМЕН. Настройки -> Основное: Домены приложений: ДОМЕН. Добавляем платформу Веб сайт с адресом: https://ДОМЕН. Отсюда нам нужен Индентификатор приложения") ?>
<?= $form->field($model, 'fb_secret')->textInput()->hint("Сюда берем Секрет приложения. Проверка приложения -> Сделать приложение доступным для всех.") ?>
<?= $form->field($model, 'gg_id')->textInput()->hint("https://console.developers.google.com , Создаем проект с названием ДОМЕН (точку заменяем на -). Диспетчер API -> Учетные данные. Окно запроса доступа OAuth. Название продукта: ДОМЕН. Учетные данные -> Создать идентификатор клиента OAuth. Веб приложение. Название: ДОМЕН. Разрешенные источники: https://ДОМЕН. Разрешенные URL перенаправления: https://ДОМЕН/auth?authclient=google . Сюда берем идентификатор клиента без пробелов.") ?>
<?= $form->field($model, 'gg_secret')->textInput()->hint("Сюда берем секрет клиента ьез пробелов") ?>
<?= $form->field($model, 'platiru_id')->textInput()->hint("№ товара в магазине plati.ru") ?>
<?= Html::submitButton($model->isNewRecord ? 'Добавить' : 'Сохранить', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>

View file

@ -0,0 +1,8 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Site */
$this->title = 'Добавление сайта';
echo $this->render('_form', compact('model'));

View file

@ -0,0 +1,43 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\ActionColumn;
use yii\grid\GridView;
use yii\helpers\Html;
$this->title = 'Список сайтов';
echo Html::tag('p', Html::a('Добавить сайт', ['sites/create'], ['class' => 'btn btn-primary']));
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
'name',
'comment',
'is_demo',
[
'header' => 'Платежи',
'content' => function($model) use($payments) {
return \Yii::$app->formatter->asCurrency(\yii\helpers\ArrayHelper::getValue($payments, [$model->id, "sum"], 0), "RUB");
}
],
[
'header' => 'Поиски',
'content' => function($model) use($seaches) {
return \yii\helpers\ArrayHelper::getValue($seaches, [$model->id, "count"], 0);
}
],
[
'class' => ActionColumn::className(),
'template' => '{update} {delete}',
'buttons' => [
'set-demo' => function ($url, $model, $key) {
return $model->is_demo ? Html::a('Выключить demo', ['set-demo', 'id' => $model->id], ['class' => 'btn btn-danger']) : Html::a('Включить demo', ['set-demo', 'id' => $model->id], ['class' => 'btn btn-success']);
}
]
],
]
]);

View file

@ -0,0 +1,8 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Site */
$this->title = 'Редактирование сайта';
echo $this->render('_form', compact('model'));

View file

@ -0,0 +1,40 @@
<?php
/* @var $this \yii\web\View */
/* @var $type integer */
/* @var $date string */
/* @var $filter string */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\Html;
use yii\helpers\Url;
use app\models\ResultCache;
$this->title = 'Статистика по ' . ResultCache::getTypeName($type) . ' за ' . $date;
echo Html::dropDownList('filter', $filter, [
'all' => 'Все',
'found' => 'Найден',
'not_found' => 'Не найден'
]);
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterSelector' => 'select[name="filter"]',
'columns' => [
[
'format' => 'raw',
'header' => 'Номер телефона',
'value' => function ($row) {
return Html::a($row['phone'], Url::to('/' . preg_replace('/^7/', '8', $row['phone'])));
}
],
[
'header' => 'Найден',
'value' => function ($row) {
return $row['success'] ? 'Да' : 'Нет';
}
]
]
]);

View file

@ -0,0 +1,109 @@
<?php
/* @var $this \yii\web\View */
/* @var $sourcesStats array */
/* @var $start string */
/* @var $end string */
use yii\helpers\Html;
use yii\helpers\Url;
use app\models\ResultCache;
$this->title = 'Статистика';
$sourcesDays = array_keys($sourcesStats);
krsort($sourcesDays);
$types = [];
foreach ($sourcesStats as $key => $value) {
$types = array_merge($types, array_keys($value));
}
$types = array_filter(array_unique($types));
$sourcesToday = $sourcesDays[count($sourcesDays) - 1];
$sourcesYesterday = $sourcesDays[count($sourcesDays) - 2];
$latestRequestTime = function($date) {
$timestamp = (new DateTime($date))->getTimestamp();
switch (date('d', $timestamp)) {
case date('d', time()):
return '<span style="color: green;">' . date('(H:i)', $timestamp) . '</span>';
case date('d', strtotime('-1 day')):
return '<b><span style="color: red;">' . date('(вчера H:i)', $timestamp) . '</span></b>';
}
};
$viberTime = function($date) {
$hours = date('H');
$time = null;
if ($hours > 10 && $hours < 22) {
$time = '-30 minutes';
} else {
$time = '-1 hour';
}
if (strtotime($time) > (new DateTime($date))->getTimestamp()) {
return 'style="border-bottom: 2px red dashed;"';
}
return null;
};
?>
<table class="table table-striped table-bordered">
<tbody>
<tr>
<th>Дата</th>
<td>-</td>
<?php foreach ($sourcesDays as $day): ?>
<td><?= $day ?></td>
<?php endforeach; ?>
</tr>
<?php foreach ($types as $type): ?>
<tr>
<th><?= ResultCache::getTypeName($type) ?></th>
<?php foreach ($sourcesDays as $day): ?>
<?php if (isset($sourcesStats[$day][$type])): ?>
<?php if ($day == $sourcesToday && isset($sourcesStats[$sourcesYesterday][$type])): ?>
<?php if ($sourcesStats[$day][$type]['success']): ?>
<?php $data = (new \yii\db\Query())
->select(['phone', new \yii\db\Expression('MAX(tm) as tm')])
->from('cache')
->where(['type_id' => $type])
->andWhere(['and', ['<>', 'data', '[]'], ['<>', 'data', 'null']])
->groupBy('phone')
->orderBy(['tm' => SORT_DESC])
->one();
?>
<td><span <?= $type == ResultCache::TYPE_VIBER ? $viberTime($data['tm']) : '' ?>><?= Html::a($data['phone'], '/' . preg_replace('/^7/', '8', $data['phone'])) ?> <?= $latestRequestTime($data['tm']) ?></span></td>
<?php else: ?>
<td>-</td>
<?php endif; ?>
<td style="cursor: pointer;" onclick="location.href='<?= Url::to(['stats/detailed', 'type' => $type, 'date' => $day]) ?>'" title="Всего запросов: <?= $sourcesStats[$day][$type]['all'] ?>, из них успешных: <?= $sourcesStats[$day][$type]['success'] ?>">
<?php $todayPercent = round($sourcesStats[$sourcesToday][$type]['success'] / $sourcesStats[$sourcesToday][$type]['all'] * 100, 2, PHP_ROUND_HALF_DOWN); ?>
<?php $yesterdayPercent = round($sourcesStats[$sourcesYesterday][$type]['success'] / $sourcesStats[$sourcesYesterday][$type]['all'] * 100, 2, PHP_ROUND_HALF_DOWN); ?>
<span style="color: <?= $todayPercent > ($yesterdayPercent / 2) ? 'green' : 'red' ?>"><?= $todayPercent ?>%</span>
</td>
<?php else: ?>
<td style="cursor: pointer;" onclick="location.href='<?= Url::to(['stats/detailed', 'type' => $type, 'date' => $day]) ?>'" title="Всего запросов: <?= $sourcesStats[$day][$type]['all'] ?>, из них успешных: <?= $sourcesStats[$day][$type]['success'] ?>">
<?= round($sourcesStats[$day][$type]['success'] / $sourcesStats[$day][$type]['all'] * 100, 2, PHP_ROUND_HALF_DOWN) ?>%
</td>
<?php endif; ?>
<?php else: ?>
<?php if ($day == $sourcesToday): ?>
<td>-</td>
<?php endif; ?>
<td>-</td>
<?php endif; ?>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>

View file

@ -0,0 +1,24 @@
<?php
/* @var $this \yii\web\View */
use yii\helpers\Html;
/* @var $dataProvider \yii\data\ActiveDataProvider */
?>
<?=\yii\grid\GridView::widget([
"dataProvider" => $dataProvider,
"columns" => [
"id",
[
"attribute" => "user_id",
"content" => function($model) {
return Html::a($model->user_id, ["id" => $model->user_id, "users/view"]);
}
],
"transaction_id",
"original_transaction_id",
"tm_purchase:date",
"tm_expires:date"
]
]);

View file

@ -0,0 +1,10 @@
<?php
/* @var $this \yii\web\View */
/* @var $reply \app\models\TicketReply */
?>
<li class="list-group-item">
<div class="btn-group" style="width: 100%;">
<button data-action="send" data-text="<?=$reply->text;?>" type="button" class="btn btn-primary col-md-3"><i class="fa fa-send"></i> Отправить</button>
<button data-action="copy" data-text="<?=$reply->text;?>" type="button" class="btn btn-default col-md-9"><?=$reply->text;?></button>
</div>
</li>

View file

@ -0,0 +1,144 @@
<?php
/* @var $this \yii\web\View */
/* @var $tickets \yii\data\ActiveDataProvider */
/* @var $ticketsNotRead \yii\data\ActiveDataProvider */
use yii\grid\ActionColumn;
use yii\helpers\ArrayHelper;
use \app\models\Ticket;
use yii\helpers\Html;
use yii\helpers\Url;
$this->title = 'Список запросов';
echo \yii\grid\GridView::widget([
"dataProvider" => $ticketsNotRead,
"tableOptions" => [
"class" => "tickets"
],
"rowOptions" => function ($model, $key, $index, $grid) {
return ["onclick" => "location.href='".Url::toRoute(["tickets/view", "id" => $model->id])."'", "class" => "ticketRow"];
},
"caption" => "Открытые тикеты без ответа администратора",
"layout" => "{items}\n{summary}\n{pager}",
"columns" => [
"id",
"tm_create",
[
'attribute' => 'user_id',
'content' => function(Ticket $model) {
$email = ArrayHelper::getValue($model, 'user.email');
return $email?$email:"iOS пользователь";
}
],
[
'attribute' => 'subject_id',
'content' => function(Ticket $model) {
return ArrayHelper::getValue(Ticket::SUBJECTS, $model->subject_id, '-');
}
],
[
'attribute' => 'subject',
'content' => function(Ticket $model) {
return $model->subject;
}
],
[
'attribute' => 'status',
'content' => function(Ticket $model) {
return ArrayHelper::getValue(Ticket::STATUSES, $model->status);
}
],
[
'class' => ActionColumn::className(),
'template' => '{close} {reopen} {delete}',
'buttons' => [
'close' => function ($url, $model, $key) {
return $model->status!=4?Html::a("Закрыть", $url, [
"class" => "btn btn-xs btn-warning",
"onclick" => "event.stopPropagation();"
]):'';
},
'reopen' => function ($url, $model, $key) {
return $model->status==4?Html::a("Переоткрыть", $url, [
"class" => "btn btn-xs btn-warning",
"onclick" => "event.stopPropagation();"
]):'';
},
'delete' => function ($url, $model, $key) {
return Html::a("Удалить", $url, [
"class" => "btn btn-xs btn-danger",
"onclick" => "event.stopPropagation();"
]);
}
]
],
]
]);?>
<br><br>
<?php echo \yii\grid\GridView::widget([
"dataProvider" => $tickets,
"tableOptions" => [
"class" => "tickets"
],
"rowOptions" => function ($model, $key, $index, $grid) {
return ["onclick" => "location.href='".Url::toRoute(["tickets/view", "id" => $model->id])."'", "class" => "ticketRow"];
},
"caption" => "Все остальные тикеты",
"layout" => "{items}\n{summary}\n{pager}",
"columns" => [
"id",
"tm_create",
[
'attribute' => 'user_id',
'content' => function(Ticket $model) {
$email = ArrayHelper::getValue($model, 'user.email');
return $email?$email:"iOS пользователь";
}
],
[
'attribute' => 'subject_id',
'content' => function(Ticket $model) {
return ArrayHelper::getValue(Ticket::SUBJECTS, $model->subject_id, "-");
}
],
[
'attribute' => 'subject',
'content' => function(Ticket $model) {
return $model->subject;
}
],
[
'attribute' => 'status',
'content' => function(Ticket $model) {
return ArrayHelper::getValue(Ticket::STATUSES, $model->status);
}
],
[
'class' => ActionColumn::className(),
'template' => '{close} {reopen} {delete}',
'buttons' => [
'close' => function ($url, $model, $key) {
return $model->status!=4?Html::a("Закрыть", $url, [
"class" => "btn btn-xs btn-warning",
"onclick" => "event.stopPropagation();"
]):'';
},
'reopen' => function ($url, $model, $key) {
return $model->status==4?Html::a("Переоткрыть", $url, [
"class" => "btn btn-xs btn-warning",
"onclick" => "event.stopPropagation();"
]):'';
},
'delete' => function ($url, $model, $key) {
return Html::a("Удалить", $url, [
"class" => "btn btn-xs btn-danger",
"onclick" => "event.stopPropagation();"
]);
}
]
],
]
]);
?>

View file

@ -0,0 +1,172 @@
<?php
/* @var $this \yii\web\View */
/* @var $ticket \app\models\Ticket */
/* @var $comment \app\models\TicketComment */
/* @var $comments \yii\data\ActiveDataProvider */
/* @var $replies \app\models\TicketReply[] */
use \app\models\Ticket;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
$this->title = 'Запрос #' . $ticket->id;
$user = \app\models\User::find()->where(["id" => $ticket->user_id])->one();
?>
<div class="row">
<div class="col-md-12">
<div class="portlet light ">
<div class="portlet-title tabbable-line">
<div class="caption caption-md">
<i class="icon-globe theme-font hide"></i>
<span class="caption-subject font-blue-madison bold uppercase">Запрос #<?= $ticket->id ?></span>
</div>
</div>
<div class="portlet-body">
<table class="tickets">
<tr>
<th>Раздел</th>
<th>Сайт</th>
<th>Дата</th>
<th>Тема</th>
<th>Статус</th>
</tr>
<tr>
<td><?=ArrayHelper::getValue(Ticket::SUBJECTS, $ticket->subject_id);?></td>
<td><?=ArrayHelper::getValue($ticket, 'site.name');?></td>
<td><?=$ticket->tm_create;?></td>
<td><?=$ticket->subject;?></td>
<td><?=ArrayHelper::getValue(Ticket::STATUSES, $ticket->status);?></td>
</tr>
<?php if(trim($ticket->url) != ""): ?>
<tr>
<td colspan="5"><?=$ticket->url;?></td>
</tr>
<?php endif; ?>
</table>
<br />
<div class="clientticketreplyheader">
<table>
<tr><td style="padding: 5px; font-size: 13px;">
<?php if($ticket->user): ?>
<?php $email = $ticket->user->email;?>
<strong style="font-weight: bold"><?=Html::a($email?$email:"iOS пользователь", ["users/view", "id" => $ticket->user_id]);?></strong><?=$ticket->user->comment?", ".$ticket->user->comment:"";?><br>Клиент, <?=$ticket->user->ip;?>
<?php else: ?>
<strong>iOS</strong>
<?php endif;?>
</td><td><?=$ticket->is_payed?Html::tag("b", "ОПЛАЧЕНО"):"";?></td></tr>
</table>
</div>
<div class="clientticketreply">
<?=nl2br($ticket->text);?>
</div>
<br />
<?php foreach ($comments->getModels() as $c): ?>
<?php if(ArrayHelper::getValue($c, 'user.is_admin', false)): ?>
<div class="adminticketreplyheader">
<table style="width: 100%">
<tr><td style="padding: 5px; font-size: 13px;"><strong style="font-weight: bold">Администратор</strong></td><td style="padding: 5px; font-size: 13px; text-align: right;"><?=$c->tm_create;?></td></tr>
</table>
</div>
<div class="adminticketreply">
<?=nl2br($c->text);?>
<p style="margin-top: 5px; margin-bottom: 0; text-align: right; font-size: 10px;"><?=Html::a("Удалить", ["tickets/comment-delete", "id" => $c->id]);?></p>
</div>
<?php else: ?>
<div class="clientticketreplyheader">
<table style="width: 100%">
<tr><td style="padding: 5px; font-size: 13px;"><strong style="font-weight: bold"><?=Html::a($ticket->user->email, ["users/view", "id" => $ticket->user_id]);?></strong><br>Клиент</td><td style="padding: 5px; font-size: 13px; text-align: right;"><?=$c->tm_create;?></td></tr>
</table>
</div>
<div class="clientticketreply">
<?=nl2br($c->text);?>
<p style="margin-top: 5px; margin-bottom: 0; text-align: right; font-size: 10px;"><?=Html::a("Удалить", ["tickets/comment-delete", "id" => $c->id]);?></p>
</div>
<?php endif; ?>
<br />
<?php endforeach; ?>
<?php if($ticket->status != 4): ?>
<?=Html::a("Задача на разработку", ["tickets/develop", "id" => $ticket->id], ["class" => "btn btn-primary"]);?>
<?=Html::a("Игнорировать тикет", ["tickets/ignore", "id" => $ticket->id], ["class" => "btn btn-warning"]);?>
<?=Html::a("Закрыть тикет", ["tickets/close", "id" => $ticket->id], ["class" => "btn btn-warning"]);?>
<?=Html::a("Удалить тикет", ["tickets/delete", "id" => $ticket->id], ["class" => "btn btn-danger"]);?>
<br /><br />
<div class="row">
<div class="col-md-6">
<?php $form = ActiveForm::begin([
"action" => ["tickets/comment", "id" => $ticket->id]
]); ?>
<?= $form->field($comment, "text")->textarea(["rows" => 10]); ?>
<input value="Добавить" type="submit" class="ticket">
<?php ActiveForm::end(); ?>
</div>
<div class="col-md-6">
<label class="control-label">Быстрые ответы</label>
<ul class="list-group">
<?php foreach ($replies as $reply): ?>
<li class="list-group-item">
<div class="btn-group" style="width: 100%;">
<button data-action="send" data-text="<?=$reply->text;?>" type="button" class="btn btn-primary col-md-3"><i class="fa fa-send"></i> Отправить</button>
<button data-action="copy" data-text="<?=$reply->text;?>" type="button" class="btn btn-default col-md-9" style="overflow: hidden; text-overflow: ellipsis"><?=$reply->text;?></button>
</div>
</li>
<?php endforeach; ?>
<li class="list-group-item" id="newReply">
<div class="input-group">
<input class="form-control" id="replyText" placeholder="Введите быстрый ответ" type="text">
<span class="input-group-btn">
<button class="btn red" id="replyAdd" type="button">Добавить</button>
</span>
</div>
</li>
</ul>
</div>
</div>
<?php else: ?>
<?=Html::a("Переоткрыть", ["tickets/reopen", "id" => $ticket->id], ["class" => "btn btn-warning"]);?>
<?=Html::a("Удалить тикет", ["tickets/delete", "id" => $ticket->id], ["class" => "btn btn-danger"]);?>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php if(false):?><script><?php endif; ?>
<?php ob_start(); ?>
$('#replyAdd').click(function() {
var text = $('#replyText').val();
if(text.trim() === '') {
return false;
}
$.post('<?=Url::toRoute(["tickets/add-reply", "id" => $ticket->id]);?>', {
text: text
}, function(response) {
if(response !== '') {
$(response).insertBefore('#newReply');
}
}, 'html');
});
$( document ).on( "click", "[data-action=\"send\"]", function() {
var text = $(this).data("text");
$('#<?=Html::getInputId($comment, "text");?>').val(text);
$('input.ticket').click();
});
$( document ).on( "click", "[data-action=\"copy\"]", function() {
var text = $(this).data("text");
$('#<?=Html::getInputId($comment, "text");?>').val(text);
});
<?php $js = ob_get_contents(); ob_end_clean(); $this->registerJs($js); ?>

View file

@ -0,0 +1,55 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Token */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
use app\models\Token;
$this->title = 'Токены';
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'token')->textInput() ?>
<?= $form->field($model, 'type')->dropDownList(Token::getTypes()) ?>
<?= $form->field($model, 'server_id')->textInput(['type' => 'number']) ?>
<?= Html::submitButton('Добавить', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
<hr>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
[
'attribute' => 'type',
'value' => function (Token $model) {
return Token::getTypeName($model->type);
}
],
'server_id',
'token',
[
'attribute' => 'status',
'value' => function (Token $model) {
return Token::getStatusName($model->status);
}
],
'tm_ban',
[
'format' => 'raw',
'header' => 'Действия',
'value' => function(Token $model) {
return '<a href="' . Url::to(['tokens/delete', 'id' => $model->id]) . '" onclick="return confirm(\'Удалить токен?\')"><i class="icon-trash"></i></a>';
}
]
]
]) ?>

View file

@ -0,0 +1,245 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
/* @var $registrations array */
/* @var $tm_start string */
/* @var $tm_end string */
/* @var $email string */
/* @var $registrationConfirms array */
/* @var $isVIP boolean */
/* @var $isAdmin boolean */
/* @var $withChecks boolean */
use yii\grid\ActionColumn;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\jui\DatePicker;
use app\models\User;
use app\models\Payment;
$this->title = 'Пользователи';
?>
<div class="portlet light bordered">
<div class="portlet-title">
<div class="caption">Фильтры</div>
</div>
<div class="portlet-body form">
<?= Html::beginForm(['users/index'], 'GET') ?>
<div class="input-group input-medium">
<span class="input-group-addon">С</span>
<?= DatePicker::widget([
'name' => 'tm_start',
'value' => $tm_start,
'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control input-small']
]) ?>
<span class="input-group-addon">по</span>
<?= DatePicker::widget([
'name' => 'tm_end',
'value' => $tm_end,
'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control input-small']
]) ?>
<?= Html::hiddenInput('is_vip', $isVIP) ?>
<?= Html::hiddenInput('is_admin', $isAdmin) ?>
<?= Html::hiddenInput('with_checks', $withChecks) ?>
<span class="input-group-addon"></span>
<button type="submit" class="form-control btn btn-primary input-small">Показать</button>
</div>
<?= Html::endForm() ?>
<hr>
<?= Html::beginForm(['users/index'], 'GET') ?>
<div class="input-group input-medium">
<?= Html::textInput('email', $email, ['class' => 'form-control', 'style' => 'width: 370px;', 'placeholder' => 'Email пользователя']) ?>
<?= Html::hiddenInput('is_vip', $isVIP) ?>
<?= Html::hiddenInput('is_admin', $isAdmin) ?>
<?= Html::hiddenInput('with_checks', $withChecks) ?>
<span class="input-group-addon"></span>
<button type="submit" class="form-control btn btn-primary input-small">Показать</button>
</div>
<?= Html::endForm() ?>
<hr>
<?= Html::a('VIP', ['users/index',
'tm_start' => $tm_start,
'tm_end' => $tm_end,
'email' => $email,
'is_vip' => !$isVIP,
'is_admin' => $isAdmin,
'with_checks' => $withChecks
], ['class' => $isVIP ? 'btn btn-success' : 'btn btn-primary', 'style' => 'width: 145px;']) ?>
<?= Html::a('Администратор', ['users/index',
'tm_start' => $tm_start,
'tm_end' => $tm_end,
'email' => $email,
'is_vip' => $isVIP,
'is_admin' => !$isAdmin,
'with_checks' => $withChecks
], ['class' => $isAdmin ? 'btn btn-success' : 'btn btn-primary', 'style' => 'width: 170px;']) ?>
<?= Html::a('Есть проверки', ['users/index',
'tm_start' => $tm_start,
'tm_end' => $tm_end,
'email' => $email,
'is_vip' => $isVIP,
'is_admin' => $isAdmin,
'with_checks' => !$withChecks
], ['class' => $withChecks ? 'btn btn-success' : 'btn btn-primary', 'style' => 'width: 220px;']) ?>
</div>
</div>
<?php if (!$email): ?>
<div class="row">
<div class="col-md-4">
<table class="table table-striped table-bordered">
<tbody>
<?php foreach ($registrations as $type): ?>
<tr>
<th><?= $type['source'] ?$type['source']: 'email' ?></th>
<td><?= $type['count'] ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'rowOptions' => function(User $model) {
if ($model->is_confirm) return ['class' => 'success'];
},
'columns' => [
[
'attribute' => 'id',
'format' => 'raw',
'value' => function($model) {
return Html::a($model->id, ['users/view', 'id' => $model->id]);
}
],
[
'format' => 'raw',
'attribute' => 'email',
'value' => function(User $model) {
$socials = [];
foreach ($model->auth as $a) {
$link = null;
switch ($a->source) {
case 'vk':
$link = 'https://vk.com/id' . $a->source_id;
break;
case 'facebook':
$link = 'https://facebook.com/' . $a->source_id;
break;
}
if (is_null($link)) {
$source = $a->source;
if ($source == 'google') {
$source .= ' (' . count($model->contacts) . ')';
}
$socials[] = $source;
} else {
$socials[] = Html::a($a->source, $link);
}
}
$username = "";
if(trim($model->email) != "") $username = $model->email;
else {
if(preg_match("/-/", $model->uuid)) {
$username = "iOS (".$model->uuid.")";
} else {
$username = "Android (".$model->uuid.")";
}
}
return '<a href="' . Url::toRoute(['users/view', 'id' => $model->id]) . '">' . $username . '</a><br>' . join(', ', $socials);
}
],
'checks',
[
'header' => 'Общая сумма платежей',
'content' => function(User $model) {
return array_sum(array_map(function(Payment $payment) { return $payment->sum; }, $model->payments));
}
],
[
'header' => 'Дата регистрации',
'content' => function($model) {
return join("<br />", [
\Yii::$app->formatter->asDate($model->tm_create, 'dd.MM.yyyy'),
$model->ip
]);
}
],
[
'header' => 'Поисков<br>всего',
'content' => function($model) {
return count($model->requests);
}
],
[
'header' => '%',
'content' => function($model) {
$index = 0;
foreach($model->requests as $r) {
$index += array_sum(ArrayHelper::getColumn($r->results, 'index'));
}
return round(count($model->requests) ? ($index / count($model->requests)) : 0, 2);
}
],
[
'header' => 'Поисков<br>за сегодня',
'content' => function($model) {
return count(array_filter($model->requests, function($r) {
return date('Y-m-d', strtotime($r->tm)) == date('Y-m-d');
}));
}
],
[
'header' => '%<br>за сегодня',
'content' => function($model) {
$index = 0;
$requests = array_filter($model->requests, function($r) {
return date('Y-m-d', strtotime($r->tm)) == date('Y-m-d');
});
foreach($requests as $r) {
$index += array_sum(ArrayHelper::getColumn($r->results, 'index'));
}
return round(count($requests) ? ($index / count($requests)) : 0, 2);
}
],
'comment',
[
'class' => ActionColumn::className(),
'template' => '{set-vip} {set-admin}',
'buttons' => [
'set-vip' => function ($url, $model, $key) {
return $model->is_vip ? Html::a('Убрать VIP', ['set-vip', 'id' => $model->id], ['class' => 'btn btn-danger']) : Html::a('Поставить VIP', ['set-vip', 'id' => $model->id], ['class' => 'btn btn-success']);
},
'set-admin' => function ($url, $model, $key) {
return $model->is_admin ? Html::a('Убрать админа', ['set-admin', 'id' => $model->id], ['class' => 'btn btn-danger']) : Html::a('Поставить админа', ['set-admin', 'id' => $model->id], ['class' => 'btn btn-success']);
}
]
],
],
]);

View file

@ -0,0 +1,209 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\User */
/* @var $history \yii\data\ActiveDataProvider */
/* @var $payments \yii\data\ActiveDataProvider */
/* @var $auth \yii\data\ActiveDataProvider */
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\helpers\Html;
use app\components\SearchHelper;
use app\models\Payment;
use app\models\ResultCache;
use app\models\RequestResult;
use app\models\SearchRequest;
$this->title = 'Пользователь #' . $model->id;
$index = 0;
foreach($model->requests as $r) {
$index += array_sum(ArrayHelper::getColumn($r->results, 'index'));
}
$index = round(count($model->requests) ? ($index / count($model->requests)) : 0, 2);
$indexToday = 0;
$requests = array_filter($model->requests, function($r) {
return date('Y-m-d', strtotime($r->tm)) == date('Y-m-d');
});
foreach($requests as $r) {
$indexToday += array_sum(ArrayHelper::getColumn($r->results, 'index'));
}
$indexToday = round(count($requests) ? ($indexToday / count($requests)) : 0, 2);
?>
<div class="row">
<div class="col-md-12">
<div class="portlet light ">
<div class="portlet-title tabbable-line">
<div class="caption caption-md">
<i class="icon-globe theme-font hide"></i>
<span class="caption-subject font-blue-madison bold uppercase">Пользователь #<?= $model->id ?></span>
</div>
</div>
<div class="portlet-body">
<p>E-mail: <?= $model->email ?>, Пароль: <?= $model->password ?>, Дата регистрации: <?= $model->tm_create ?></p>
<p><b><?= Yii::t('app', 'Остаток: {n, plural, =0{проверок нет} one{# проверка} few{# проверки} many{# проверок} other{# проверок}}', ['n' => $model->checks]) ?>, Общая сумма платежей: <?= array_sum(array_map(function(Payment $payment) { return $payment->sum; }, $model->payments)) ?> рублей</b></p>
<p>Поисков всего: <?= count($model->requests) ?>, Средний индекс поиска: <?= $index ?>%, Поисков за сегодня: <?= count(array_filter($model->requests, function($r) {
return date('Y-m-d', strtotime($r->tm)) == date('Y-m-d');
})) ?>, Средний индекс поиска за сегодня: <?= $indexToday ?>%</p>
<?php if ($success = \Yii::$app->session->getFlash('success')): ?>
<div class="alert alert-success"><strong><?= $success ?></strong></div>
<?php endif; ?>
<div class="row">
<div class="col-md-3" style="margin-top: 25px;">
<?= Html::beginForm('', 'POST', ['class' => 'form-inline']) ?>
<div class="form-group">
<input name="checks" value="10" class="form-control input-small">
<button type="submit" class="btn btn-primary" style="display: inline-block">Начислить</button>
</div>
<?= Html::endForm() ?>
<?= $model->is_vip ? Html::a('Убрать VIP', ['set-vip', 'id' => $model->id], ['class' => 'btn btn-danger', 'style' => 'margin-top: 15px;']) : Html::a('Поставить VIP', ['set-vip', 'id' => $model->id], ['class' => 'btn btn-success', 'style' => 'margin-top: 15px;']) ?>
<?= $model->is_admin ? Html::a('Убрать админа', ['set-admin', 'id' => $model->id], ['class' => 'btn btn-danger', 'style' => 'margin-top: 15px;']) : Html::a('Поставить админа', ['set-admin', 'id' => $model->id], ['class' => 'btn btn-success', 'style' => 'margin-top: 15px;']) ?>
</div>
<div class="col-md-4">
<?php $form = \yii\widgets\ActiveForm::begin(['method' => 'POST']); ?>
<?= $form->field($model, 'comment')->textInput() ?>
<p><?= Html::submitButton('Сохранить комментарий', ['class' => 'btn btn-primary']) ?></p>
<?php \yii\widgets\ActiveForm::end(); ?>
</div>
</div>
<hr>
<h2>Платежи</h2>
<?= GridView::widget([
'dataProvider' => $payments,
'columns' => [
'id',
'tm',
'sum',
'amount',
[
'header' => 'Тип',
'attribute' => 'type_id',
'content' => function(Payment $model) {
switch ($model->type_id) {
case Payment::TYPE_QIWI: return "Qiwi Wallet";
case Payment::TYPE_YANDEX: return "Яндекс.Деньги Card";
case Payment::TYPE_WEBMONEY: return "WebMoney ";
case Payment::TYPE_QIWI_TERMINAL: return "Qiwi терминал";
case Payment::TYPE_YANDEX_WALLET: return "Яндекс.Деньги Wallet";
}
return "";
}
],
'operation_id',
'operation_label'
]
]) ?>
<hr>
<h2>История поиска</h2>
<?= GridView::widget([
'dataProvider' => $history,
'columns' => [
'tm',
[
'format' => 'raw',
'attribute' => 'phone',
'value' => function(SearchRequest $model) {
$phone = preg_replace('/^7/', '8', $model->phone);
return '<a href="/' . $phone . '">' . $phone . '</a>';
}
],
[
'attribute' => 'ip',
'value' => function(SearchRequest $model) {
return join(', ', [$model->ip, SearchHelper::City($model->ip)]);
}
],
[
'header' => 'Индекс поиска',
'value' => function(SearchRequest $model) {
if ($model->is_payed) {
return array_sum(array_map(function(RequestResult $result) {
return $result->index;
}, $model->results));
}
$names = $photos = [];
$caches = RequestResult::find()
->where(['request_id' => $model->id])
->andWhere(['not in', 'type_id', ResultCache::inactiveTypes()])->all();
foreach ($caches as $c) {
$data = Json::decode($c->data);
if (!$data) continue;
$names = ArrayHelper::merge($names, ArrayHelper::getColumn($data, 'name'));
$photos = ArrayHelper::merge($photos, ArrayHelper::getColumn($data, 'photo'));
}
$names = array_filter($names);
$photos = array_filter($photos);
$finds = [];
if ($names) $finds[] = 'Имя';
if ($photos) $finds[] = 'Фото';
return $finds ? join(', ', $finds) : 'Ничего не найдено';
}
],
[
'header' => 'Стоимость',
'value' => function(SearchRequest $model) {
$type = '';
switch ($model->is_payed) {
case 0: $type = 'Бесплатный (нет проверок)'; break;
case 1: $type = 'Платный'; break;
case 2: $type = 'Бесплатный (не нашли)'; break;
}
if (!$model->user_id) $type .= ', Аноним';
return $type;
}
],
]
]) ?>
<hr>
<h2>Лог авторизаций</h2>
<?= GridView::widget([
'dataProvider' => $auth,
'columns' => [
'id',
[
'attribute' => 'site_id',
'value' => function (\app\models\UserAuthLog $model) {
return ArrayHelper::getValue($model, 'site.name');
}
],
'ip',
'tm'
]
]) ?>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,22 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Wallet */
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use app\models\Site;
use app\models\Wallet;
$form = ActiveForm::begin(['method' => 'POST']);
echo $form->field($model, 'type_id')->dropDownList(Wallet::getWalletTypes());
echo $form->field($model, 'site_id')->dropDownList(ArrayHelper::map(Site::find()->all(), 'id', 'name'), ['prompt' => 'Нет']);
echo $form->field($model, 'wallet_id');
echo $form->field($model, 'login');
echo $form->field($model, 'password');
echo $form->field($model, 'phone');
echo $form->field($model, 'status')->checkbox();
echo $form->field($model, 'comment')->textarea();
echo Html::submitButton('Сохранить', ['class' => 'btn btn-success']);
$form::end();

View file

@ -0,0 +1,8 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Wallet */
$this->title = 'Добавление кошелька';
echo $this->render('_form', compact('model'));

View file

@ -0,0 +1,83 @@
<?php
/* @var $this \yii\web\View */
/* @var $dataProvider \yii\data\ActiveDataProvider */
use yii\grid\ActionColumn;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Url;
use app\models\Wallet;
$this->title = 'Кошельки';
$total = array_sum(ArrayHelper::getColumn($dataProvider->models, 'balance'));
?>
<?= Html::tag('p', Html::a('Добавить кошелёк', ['wallets/create'], ['class' => 'btn btn-primary'])) ?>
<b>Всего: <?= Yii::$app->formatter->asCurrency($total, 'RUB') ?></b><br><br>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'rowOptions' => function($model) {
if (is_null($model->tm_last_transaction_out)) return [];
if (time() - strtotime($model->tm_last_transaction_out) > 60 * 60 * 48) return ['class' => 'danger'];
return ['class' => 'success'];
},
'columns' => [
[
'attribute' => 'type_id',
'header' => 'Тип / сайт',
'content' => function($model) {
$type = "";
switch ($model->type_id) {
case Wallet::TYPE_YANDEX: $type = 'Яндекс.Деньги'; break;
case Wallet::TYPE_QIWI: $type = 'Qiwi кошелек'; break;
}
return join("<br />", [$type, ArrayHelper::getValue($model, ['site', 'name'])]);
}
],
[
'attribute' => 'wallet_id',
'header' => 'Кошелек / номер телефона',
'content' => function($model) {
$content = [$model->wallet_id];
if($model->type_id == Wallet::TYPE_YANDEX) {
$content[] = $model->phone;
}
return join("<br />", $content);
}
],
[
"header" => 'Логин / пароль',
"content" => function($model) {
return join("<br />", [$model->login, $model->password]);
}
],
[
"attribute" => 'balance',
"content" => function($model) {
return Yii::$app->formatter->asCurrency($model->balance, 'RUB');
}
],
'tm_last_balance',
[
"header" => 'Приход / Расход',
'content' => function($model) {
return join("<br />", [Yii::$app->formatter->asRelativeTime($model->tm_last_transaction), Yii::$app->formatter->asRelativeTime($model->tm_last_transaction_out)]);
}
],
[
"header" => 'Комментарий',
'content' => function($model) {
return nl2br($model->comment);
}
],
[
'class' => ActionColumn::className(),
'template' => '{view}',
],
],
]) ?>

View file

@ -0,0 +1,8 @@
<?php
/* @var $this \yii\web\View */
/* @var $model \app\models\Wallet */
$this->title = 'Редактирование кошелька';
echo $this->render('_form', compact('model'));