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'));

13
modules/api/ApiModule.php Normal file
View file

@ -0,0 +1,13 @@
<?php
namespace app\modules\api;
use yii\base\Module;
class ApiModule extends Module
{
public $controllerNamespace = 'app\modules\api\controllers';
public $defaultRoute = 'search';
public $layout = null;
}

View file

@ -0,0 +1,435 @@
<?php
namespace app\modules\api\controllers;
use app\models\Payment;
use app\models\User;
use app\models\UserSub;
use Exception;
use Yii;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
use ReceiptValidator\iTunes\Validator as iTunesValidator;
use ReceiptValidator\GooglePlay\Validator as PlayValidator;
class BuyController extends Controller
{
public function actionStatus()
{
/*
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if (!$uuid) {
throw new BadRequestHttpException();
}
$user = User::find()->select(["id", "balance", "checks"])->where(["uuid" => $uuid])->one();
if (!$user) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
$user = User::find()->select(["id", "balance", "checks"])->where(["uuid" => $uuid])->one();
}
*/
$f = fopen(\Yii::getAlias('@runtime') . '/apple.log', 'a+');
$data = Json::decode(\Yii::$app->request->getRawBody());
//$data = Yii::$app->request->getBodyParams();
//$receiptBase64Data = ArrayHelper::getValue($data, "receipt");//'ewoJInNpZ25hdHVyZSIgPSAiQXBNVUJDODZBbHpOaWtWNVl0clpBTWlKUWJLOEVkZVhrNjNrV0JBWHpsQzhkWEd1anE0N1puSVlLb0ZFMW9OL0ZTOGNYbEZmcDlZWHQ5aU1CZEwyNTBsUlJtaU5HYnloaXRyeVlWQVFvcmkzMlc5YVIwVDhML2FZVkJkZlcrT3kvUXlQWkVtb05LeGhudDJXTlNVRG9VaFo4Wis0cFA3MHBlNWtVUWxiZElWaEFBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NHVVVrVTNaV0FTMU1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEE1TURZeE5USXlNRFUxTmxvWERURTBNRFl4TkRJeU1EVTFObG93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNclJqRjJjdDRJclNkaVRDaGFJMGc4cHd2L2NtSHM4cC9Sd1YvcnQvOTFYS1ZoTmw0WElCaW1LalFRTmZnSHNEczZ5anUrK0RyS0pFN3VLc3BoTWRkS1lmRkU1ckdYc0FkQkVqQndSSXhleFRldngzSExFRkdBdDFtb0t4NTA5ZGh4dGlJZERnSnYyWWFWczQ5QjB1SnZOZHk2U01xTk5MSHNETHpEUzlvWkhBZ01CQUFHamNqQndNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVOaDNvNHAyQzBnRVl0VEpyRHRkREM1RllRem93RGdZRFZSMFBBUUgvQkFRREFnZUFNQjBHQTFVZERnUVdCQlNwZzRQeUdVakZQaEpYQ0JUTXphTittVjhrOVRBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUVhU2JQanRtTjRDL0lCM1FFcEszMlJ4YWNDRFhkVlhBZVZSZVM1RmFaeGMrdDg4cFFQOTNCaUF4dmRXLzNlVFNNR1k1RmJlQVlMM2V0cVA1Z204d3JGb2pYMGlreVZSU3RRKy9BUTBLRWp0cUIwN2tMczlRVWU4Y3pSOFVHZmRNMUV1bVYvVWd2RGQ0TndOWXhMUU1nNFdUUWZna1FRVnk4R1had1ZIZ2JFL1VDNlk3MDUzcEdYQms1MU5QTTN3b3hoZDNnU1JMdlhqK2xvSHNTdGNURXFlOXBCRHBtRzUrc2s0dHcrR0szR01lRU41LytlMVFUOW5wL0tsMW5qK2FCdzdDMHhzeTBiRm5hQWQxY1NTNnhkb3J5L0NVdk02Z3RLc21uT09kcVRlc2JwMGJzOHNuNldxczBDOWRnY3hSSHVPTVoydG04bnBMVW03YXJnT1N6UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdSaGRHVXRjSE4wSWlBOUlDSXlNREV5TFRBMExUTXdJREE0T2pBMU9qVTFJRUZ0WlhKcFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkltOXlhV2RwYm1Gc0xYUnlZVzV6WVdOMGFXOXVMV2xrSWlBOUlDSXhNREF3TURBd01EUTJNVGM0T0RFM0lqc0tDU0ppZG5KeklpQTlJQ0l5TURFeU1EUXlOeUk3Q2draWRISmhibk5oWTNScGIyNHRhV1FpSUQwZ0lqRXdNREF3TURBd05EWXhOemc0TVRjaU93b0pJbkYxWVc1MGFYUjVJaUE5SUNJeElqc0tDU0p2Y21sbmFXNWhiQzF3ZFhKamFHRnpaUzFrWVhSbExXMXpJaUE5SUNJeE16TTFOems0TXpVMU9EWTRJanNLQ1NKd2NtOWtkV04wTFdsa0lpQTlJQ0pqYjIwdWJXbHVaRzF2WW1Gd2NDNWtiM2R1Ykc5aFpDSTdDZ2tpYVhSbGJTMXBaQ0lnUFNBaU5USXhNVEk1T0RFeUlqc0tDU0ppYVdRaUlEMGdJbU52YlM1dGFXNWtiVzlpWVhCd0xrMXBibVJOYjJJaU93b0pJbkIxY21Ob1lYTmxMV1JoZEdVdGJYTWlJRDBnSWpFek16VTNPVGd6TlRVNE5qZ2lPd29KSW5CMWNtTm9ZWE5sTFdSaGRHVWlJRDBnSWpJd01USXRNRFF0TXpBZ01UVTZNRFU2TlRVZ1JYUmpMMGROVkNJN0Nna2ljSFZ5WTJoaGMyVXRaR0YwWlMxd2MzUWlJRDBnSWpJd01USXRNRFF0TXpBZ01EZzZNRFU2TlRVZ1FXMWxjbWxqWVM5TWIzTmZRVzVuWld4bGN5STdDZ2tpYjNKcFoybHVZV3d0Y0hWeVkyaGhjMlV0WkdGMFpTSWdQU0FpTWpBeE1pMHdOQzB6TUNBeE5Ub3dOVG8xTlNCRmRHTXZSMDFVSWpzS2ZRPT0iOwoJImVudmlyb25tZW50IiA9ICJTYW5kYm94IjsKCSJwb2QiID0gIjEwMCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9';
$type = ArrayHelper::getValue($data, "notification_type");
$env = ArrayHelper::getValue($data, "environment");
fwrite($f, print_r($data, true) . "\n");
if(!in_array($type, ["INTERACTIVE_RENEWAL", "RENEWAL"])) return [];
$p = ArrayHelper::getValue($data, "latest_receipt_info");
$uuid = ArrayHelper::getValue($p, "unique_vendor_identifier");
fwrite($f, print_r($p, true) . "\n");
$originalTransactionID = (string)ArrayHelper::getValue($p, "original_transaction_id");
$sub = UserSub::find()->where(["original_transaction_id" => $originalTransactionID])->one();
$user = null;
if($sub) {
$user = User::find()->where(["id" => $sub->user_id])->one();
}
$transactionID = (string)ArrayHelper::getValue($p, "transaction_id");
$productID = (string)ArrayHelper::getValue($p, "product_id");
$payment = Payment::find()->where(["operation_id" => $transactionID])->one();
if (!$payment) {
$payment = new Payment();
$payment->user_id = ArrayHelper::getValue($user, "id", null);
$payment->tm = new Expression('NOW()');
if ($env == "PROD") {
$payment->type_id = Payment::TYPE_APPLE;
} else {
$payment->type_id = Payment::TYPE_TESTAPPLE;
}
$payment->operation_label = $productID;
$payment->operation_id = $transactionID;
$sum = 0;
$checks = 0;
if (preg_match("/com\.wcaller\.Wcaller\.search(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 1:
$sum = 149;
break;
case 10:
$sum = 749;
break;
case 100:
$sum = 3490;
break;
case 300:
$sum = 8990;
break;
case 30:
$sum = 1390;
break;
}
$checks = $m[1];
}
$isSubscribe = false;
if (preg_match("/com\.wcaller\.Wcaller\.sub\.month\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 2750;
break;
case 10:
$sum = 199;
break;
case 15:
$sum = 299;
break;
case 50:
$sum = 499;
break;
case 999:
$sum = 1690;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if (preg_match("/com\.wcaller\.Wcaller\.sub\.6month\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 6190;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if (preg_match("/com\.wcaller\.Wcaller\.sub\.week\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 499;
break;
case 999:
$sum = 249;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if($checks == 0 || $checks == 999) $checks = -1;
$payment->sum = $sum;
$payment->amount = $sum * 0.59;
if ($payment->save()) {
if ($isSubscribe) {
$sub = new UserSub();
$sub->user_id = $user->id;
$sub->transaction_id = ArrayHelper::getValue($p, "transaction_id");
$sub->original_transaction_id = ArrayHelper::getValue($p, "original_transaction_id");
$sub->tm_purchase = \Yii::$app->formatter->asDatetime(ArrayHelper::getValue($p, "purchase_date"), "yyyy-MM-dd HH:mm:ss");
$sub->tm_expires = \Yii::$app->formatter->asDatetime(ArrayHelper::getValue($p, "expires_date")/1000, "yyyy-MM-dd HH:mm:ss");
$sub->status = ArrayHelper::getValue($p, "is_trial_period")?0:1;
$sub->save();
}
$user->checks = $checks;
$user->save();
}
}
fclose($f);
return "OK";
}
public function actionIndex()
{
$userId = \Yii::$app->getRequest()->post("id", false);
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if (!$uuid && !$userId) {
throw new BadRequestHttpException();
}
if ($userId) {
$user = User::find()->select(["id", "balance", "checks"])->where(["id" => $userId])->one();
} else {
$user = User::find()->select(["id", "balance", "checks"])->where(["uuid" => $uuid])->one();
}
if (!$user) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
$user = User::find()->select(["id", "balance", "checks"])->where(["uuid" => $uuid])->one();
}
$isAndroid = Yii::$app->getRequest()->getHeaders()->get('isandroid', false);
if ($isAndroid) {
$client = new \Google_Client();
$client->setApplicationName('nomergg');
$client->setAuthConfig(\Yii::getAlias('@runtime') . '/nomergg-2842ed9066f5.json');
$client->setScopes([\Google_Service_AndroidPublisher::ANDROIDPUBLISHER]);
$validator = new PlayValidator(new \Google_Service_AndroidPublisher($client));
$packageName = \Yii::$app->request->post("packageName");
$productId = \Yii::$app->request->post("productId");
$orderId = \Yii::$app->request->post("orderId");
$purchaseToken = \Yii::$app->request->post("purchaseToken");
try {
$response = $validator->setPackageName($packageName)
->setProductId($productId)
->setPurchaseToken($purchaseToken)
->validatePurchase();
if (preg_match("/com\.nomergg\.app\.search(\d+)/", $productId, $m)) {
$user->checks += $m[1];
if ($user->save()) {
$payment = new Payment();
$payment->user_id = $user->id;
$payment->tm = new Expression('NOW()');
$payment->type_id = Payment::TYPE_ANDROID;
$payment->operation_id = (string)$orderId;
$payment->operation_label = $productId;
$sum = 0;
switch ($m[1]) {
case 1:
$sum = 98;
break;
case 10:
$sum = 880;
break;
case 100:
$sum = 6800;
break;
case 30:
$sum = 2340;
break;
case 20:
$sum = 1660;
break;
}
$payment->sum = $sum;
$payment->amount = $sum * 0.7;
$payment->save();
}
}
} catch (Exception $e) {
var_dump($e->getMessage());
// example message: Error calling GET ....: (404) Product not found for this application.
}
} else {
$f = fopen(\Yii::getAlias('@runtime') . '/ios.log', 'a+');
fwrite($f, $uuid . "\n");
$validator = new iTunesValidator(iTunesValidator::ENDPOINT_PRODUCTION);
$data = Json::decode(\Yii::$app->request->getRawBody());
//$data = Yii::$app->request->getBodyParams();
$source = ArrayHelper::getValue($data, "source", "");
$receiptBase64Data = ArrayHelper::getValue($data, "receipt");//'ewoJInNpZ25hdHVyZSIgPSAiQXBNVUJDODZBbHpOaWtWNVl0clpBTWlKUWJLOEVkZVhrNjNrV0JBWHpsQzhkWEd1anE0N1puSVlLb0ZFMW9OL0ZTOGNYbEZmcDlZWHQ5aU1CZEwyNTBsUlJtaU5HYnloaXRyeVlWQVFvcmkzMlc5YVIwVDhML2FZVkJkZlcrT3kvUXlQWkVtb05LeGhudDJXTlNVRG9VaFo4Wis0cFA3MHBlNWtVUWxiZElWaEFBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NHVVVrVTNaV0FTMU1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEE1TURZeE5USXlNRFUxTmxvWERURTBNRFl4TkRJeU1EVTFObG93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNclJqRjJjdDRJclNkaVRDaGFJMGc4cHd2L2NtSHM4cC9Sd1YvcnQvOTFYS1ZoTmw0WElCaW1LalFRTmZnSHNEczZ5anUrK0RyS0pFN3VLc3BoTWRkS1lmRkU1ckdYc0FkQkVqQndSSXhleFRldngzSExFRkdBdDFtb0t4NTA5ZGh4dGlJZERnSnYyWWFWczQ5QjB1SnZOZHk2U01xTk5MSHNETHpEUzlvWkhBZ01CQUFHamNqQndNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVOaDNvNHAyQzBnRVl0VEpyRHRkREM1RllRem93RGdZRFZSMFBBUUgvQkFRREFnZUFNQjBHQTFVZERnUVdCQlNwZzRQeUdVakZQaEpYQ0JUTXphTittVjhrOVRBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUVhU2JQanRtTjRDL0lCM1FFcEszMlJ4YWNDRFhkVlhBZVZSZVM1RmFaeGMrdDg4cFFQOTNCaUF4dmRXLzNlVFNNR1k1RmJlQVlMM2V0cVA1Z204d3JGb2pYMGlreVZSU3RRKy9BUTBLRWp0cUIwN2tMczlRVWU4Y3pSOFVHZmRNMUV1bVYvVWd2RGQ0TndOWXhMUU1nNFdUUWZna1FRVnk4R1had1ZIZ2JFL1VDNlk3MDUzcEdYQms1MU5QTTN3b3hoZDNnU1JMdlhqK2xvSHNTdGNURXFlOXBCRHBtRzUrc2s0dHcrR0szR01lRU41LytlMVFUOW5wL0tsMW5qK2FCdzdDMHhzeTBiRm5hQWQxY1NTNnhkb3J5L0NVdk02Z3RLc21uT09kcVRlc2JwMGJzOHNuNldxczBDOWRnY3hSSHVPTVoydG04bnBMVW03YXJnT1N6UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdSaGRHVXRjSE4wSWlBOUlDSXlNREV5TFRBMExUTXdJREE0T2pBMU9qVTFJRUZ0WlhKcFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkltOXlhV2RwYm1Gc0xYUnlZVzV6WVdOMGFXOXVMV2xrSWlBOUlDSXhNREF3TURBd01EUTJNVGM0T0RFM0lqc0tDU0ppZG5KeklpQTlJQ0l5TURFeU1EUXlOeUk3Q2draWRISmhibk5oWTNScGIyNHRhV1FpSUQwZ0lqRXdNREF3TURBd05EWXhOemc0TVRjaU93b0pJbkYxWVc1MGFYUjVJaUE5SUNJeElqc0tDU0p2Y21sbmFXNWhiQzF3ZFhKamFHRnpaUzFrWVhSbExXMXpJaUE5SUNJeE16TTFOems0TXpVMU9EWTRJanNLQ1NKd2NtOWtkV04wTFdsa0lpQTlJQ0pqYjIwdWJXbHVaRzF2WW1Gd2NDNWtiM2R1Ykc5aFpDSTdDZ2tpYVhSbGJTMXBaQ0lnUFNBaU5USXhNVEk1T0RFeUlqc0tDU0ppYVdRaUlEMGdJbU52YlM1dGFXNWtiVzlpWVhCd0xrMXBibVJOYjJJaU93b0pJbkIxY21Ob1lYTmxMV1JoZEdVdGJYTWlJRDBnSWpFek16VTNPVGd6TlRVNE5qZ2lPd29KSW5CMWNtTm9ZWE5sTFdSaGRHVWlJRDBnSWpJd01USXRNRFF0TXpBZ01UVTZNRFU2TlRVZ1JYUmpMMGROVkNJN0Nna2ljSFZ5WTJoaGMyVXRaR0YwWlMxd2MzUWlJRDBnSWpJd01USXRNRFF0TXpBZ01EZzZNRFU2TlRVZ1FXMWxjbWxqWVM5TWIzTmZRVzVuWld4bGN5STdDZ2tpYjNKcFoybHVZV3d0Y0hWeVkyaGhjMlV0WkdGMFpTSWdQU0FpTWpBeE1pMHdOQzB6TUNBeE5Ub3dOVG8xTlNCRmRHTXZSMDFVSWpzS2ZRPT0iOwoJImVudmlyb25tZW50IiA9ICJTYW5kYm94IjsKCSJwb2QiID0gIjEwMCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9';
fwrite($f, print_r($data, true) . "\n");
//return [""$receiptBase64Data;
try {
$response = $validator->validate($receiptBase64Data, "63baa92164f4400699f78f32dded316f");
} catch (Exception $e) {
throw new BadRequestHttpException($e->getMessage());
}
if ($response->isValid()) {
$data = $response->getReceipt();
fwrite($f, print_r($data, true) . "\n");
//print_r($data);
$products = $data["in_app"];
foreach ($products as $p) {
$transactionID = (string)ArrayHelper::getValue($p, "transaction_id");
$productID = (string)ArrayHelper::getValue($p, "product_id");
$payment = Payment::find()->where(["operation_id" => $transactionID])->one();
if (!$payment) {
$payment = new Payment();
$payment->user_id = $user->id;
$payment->tm = new Expression('NOW()');
if (ArrayHelper::getValue($data, "receipt_type") == "ProductionSandbox") {
$payment->type_id = Payment::TYPE_TESTAPPLE;
} else {
$payment->type_id = Payment::TYPE_APPLE;
}
$payment->operation_label = $productID;
$payment->operation_id = $transactionID;
$payment->source = $source;
$sum = 0;
$checks = 0;
if (preg_match("/com\.wcaller\.Wcaller\.search(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 1:
$sum = 149;
break;
case 10:
$sum = 749;
break;
case 100:
$sum = 3490;
break;
case 300:
$sum = 8990;
break;
case 30:
$sum = 1390;
break;
}
$checks = $m[1];
}
$isSubscribe = false;
if (preg_match("/com\.wcaller\.Wcaller\.sub\.month\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 2750;
break;
case 10:
$sum = 199;
break;
case 15:
$sum = 299;
break;
case 50:
$sum = 499;
break;
case 999:
$sum = 1690;
}
$checks = $m[1];
$isSubscribe = true;
}
if (preg_match("/com\.wcaller\.Wcaller\.sub\.6month\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 6190;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if (preg_match("/com\.wcaller\.Wcaller\.sub\.week\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 499;
break;
case 999:
$sum = 249;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if($checks == 0 || $checks == 999) $checks = -1;
$payment->sum = $sum;
$payment->amount = $sum * 0.59;
if ($payment->save()) {
if ($isSubscribe) {
$sub = new UserSub();
$sub->user_id = $user->id;
$sub->transaction_id = ArrayHelper::getValue($p, "transaction_id");
$sub->original_transaction_id = ArrayHelper::getValue($p, "original_transaction_id");
$sub->tm_purchase = \Yii::$app->formatter->asDatetime(ArrayHelper::getValue($p, "purchase_date"), "yyyy-MM-dd HH:mm:ss");
$sub->tm_expires = \Yii::$app->formatter->asDatetime(ArrayHelper::getValue($p, "expires_date"), "yyyy-MM-dd HH:mm:ss");
$sub->status = ArrayHelper::getValue($p, "is_trial_period")?0:1;
$sub->save();
}
$user->checks += $checks;
$user->save();
}
} else {
if($payment->user_id != $user->id) {
$payment->user_id = $user->id;
$payment->save();
}
$sub = UserSub::find()->where(["transaction_id" => ArrayHelper::getValue($p, "transaction_id")])->one();
if($sub && $sub->user_id != $user->id) {
$sub->user_id = $user->id;
$sub->save();
$checks = null;
if (preg_match("/com\.wcaller\.Wcaller\.sub\.month\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 2750;
break;
case 10:
$sum = 199;
break;
case 15:
$sum = 299;
break;
case 50:
$sum = 499;
break;
case 999:
$sum = 1690;
}
$checks = $m[1];
$isSubscribe = true;
}
if (preg_match("/com\.wcaller\.Wcaller\.sub\.6month\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 6190;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if (preg_match("/com\.wcaller\.Wcaller\.sub\.week\.(\d+)/", $productID, $m)) {
switch ($m[1]) {
case 0:
$sum = 499;
break;
case 999:
$sum = 249;
break;
}
$checks = $m[1];
$isSubscribe = true;
}
if($checks == 0 || $checks == 999) $checks = -1;
$user->checks = $checks;
$user->save();
}
}
}
//product_id
//echo 'Receipt is valid.' . PHP_EOL;
//echo 'Receipt data = ' . print_r($response->getReceipt()) . PHP_EOL;
} else {
fwrite($f, "invalid data\n");
}
fclose($f);
}
return [
"id" => $user->id,
"balance" => $user->balance,
"checks" => $user->checks
];
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace app\modules\api\controllers;
use app\models\Call;
use app\models\User;
use Yii;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\helpers\Url;
use yii\rest\Controller;
class CallController extends Controller {
public function actionIndex() {
$body = \Yii::$app->request->getRawBody();
$body = Json::decode($body);
$call = new Call();
$call->cuid = ArrayHelper::getValue($body, 'cuid');
$call->status = ArrayHelper::getValue($body, 'status');
$call->duration = ArrayHelper::getValue($body, 'duration');
$call->phone = ArrayHelper::getValue($body, 'number');
$call->tm = new Expression('NOW()');
$call->save();
if($call->status == "dtmf-1") {
$user = User::find()->where(["email" => $call->phone])->one();
if(!$user) {
$code = sprintf("%'.04d", rand(0, 9999));
$user = new User();
$user->email = $call->phone;
$user->password = $code;
$user->auth_key = \Yii::$app->getSecurity()->generateRandomString();
$user->checks = 3;
if($user->save()) {
$user->checks = 3;
$user->save();
$url = Url::to(['https://smsc.ru/sys/send.php',
'login' => 'admeo',
'psw' => 'admeosmsc',
'phones' => $call->phone,
'mes' => "Probiv nomera telefona(3 besplatnye proverki):\nhttps://num.gg\nlogin:".$user->email."\npass:".$user->password,
'charset' => 'utf-8',
'sender' => 'num.gg'
], 'https');
file_get_contents($url);
}
}
}
}
}

View file

@ -0,0 +1,84 @@
<?php
namespace app\modules\api\controllers;
use app\models\TmpVk;
use app\models\Vk;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
use yii\web\ForbiddenHttpException;
class CheckController extends Controller {
private $tokens = [
"vMnP2BEx1vlKk7cLAKCBgbNVuBArl3xb" => "antiparkon"
];
public function actionIndex($phone, $token) {
if(!array_key_exists($token, $this->tokens)) throw new ForbiddenHttpException("Bad token");
if(!preg_match("/^79([0-9]{9})$/", $phone)) throw new BadRequestHttpException("Invalid phone number");
return ["success" => 1];
$success = 0;
$ch = curl_init('http://ssd.nomer.io/api/' . $phone . '?token=NWBpdeqbbAFJMVYJU6XAfhyydeyhgX');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$phones = [];
if ($httpCode == 200) { // Все ок, берем данные
$response = Json::decode($response);
foreach ($response as $r) {
if(isset($r["type"])) {
switch ($r["type"]) {
case "profile_id":
$success = 1;
break;
case "phone":
$phones[] = $r["data"];
break;
}
}
}
}
if($success) {
return ["success" => $success];
}
$ids = [];
foreach ($phones as $_phone) {
$vk = TmpVk::find()->where(['phone' => $_phone])->all();
if(count($vk)) {
$success = 1;
$ids = ArrayHelper::merge($ids, ArrayHelper::getColumn($vk, "id"));
}
}
$vkrows = Vk::find()->where(["or",
["phone1" => $phone],
["phone2" => $phone],
])->all();
$ids = ArrayHelper::merge($ids, ArrayHelper::getColumn($vkrows, "id"));
if(count($ids)) {
$success = 1;
}
$photos = [];
$socData = @file_get_contents("https://api.vk.com/method/users.get?user_ids=" . join(",", $ids) . "&fields=photo_id,photo_max,photo_max_orig&lang=ru&access_token=8f95fab19fb8d3d41bdeeb28f0112cb2cd3c86a93fc66acbd29f327d1aa3f196540bfe10dcd4ca97baf37");
if($socData) {
$socData = Json::decode($socData);
$socData = $socData["response"];
$photos = ArrayHelper::getColumn($socData, "photo_max_orig");
}
return ["success" => $success, "photos" => $photos];
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace app\modules\api\controllers;
use app\models\Ticket;
use app\models\User;
use Yii;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
class ContactController extends Controller {
public $enableCsrfValidation = false;
public function actionIndex() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if(!$uuid) {
throw new BadRequestHttpException();
}
$user = User::find()->where(["uuid" => $uuid])->one();
$ticket = new Ticket();
$ticket->detachBehavior("user_id");
$ticket->user_id = $user->id;
$rawBody = \Yii::$app->request->getRawBody();
$email = \Yii::$app->request->post("email", null);
if($email) {
$message = \Yii::$app->request->post("message");
} else {
$data = Json::decode($rawBody);
$message = ArrayHelper::getValue($data,"message");
$email = ArrayHelper::getValue($data,"email");
}
$ticket->text = $message."\n\n".$email;
$ticket->tm_create = new Expression('NOW()');
$ticket->subject_id = 1;
$ticket->subject = "Сообщение из iOS приложения";
$ticket->save(false);
return ["success" => \Yii::$app->mailer->compose()
->setTextBody("E-mail: ".$email."\n\n\n".$message)
->setFrom('noreply@'.\Yii::$app->name)
->setTo("support@nomer.io")
->setSubject(\Yii::$app->name." - обратная связь")
->send()];
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace app\modules\api\controllers;
use app\models\Free;
use app\models\User;
use Yii;
use yii\db\Expression;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
class FreeController extends Controller {
public function actionIndex() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if(!$uuid) {
throw new BadRequestHttpException();
}
$typeID = \Yii::$app->request->get("type_id");
if(!in_array($typeID, Free::types())) {
throw new BadRequestHttpException();
}
$user = User::find()->where(["uuid" => $uuid])->one();
if(!$user) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
}
$free = Free::find()->where(["uuid" => $uuid, "type_id" => $typeID])->one();
if($free) return ["success" => 0];
else {
$free = new Free();
$free->uuid = $uuid;
$free->user_id = $user->id;
$free->tm = new Expression('NOW()');
$free->type_id = $typeID;
if($free->type_id == Free::TYPE_INSTALL) {
$free->checks = 1;
} else if($free->type_id == Free::TYPE_RATE) {
$free->checks = 2;
}
if($free->save()) {
$user->checks += $free->checks;
$user->save();
}
return ["success" => 1];
}
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace app\modules\api\controllers;
use app\models\RequestResult;
use app\models\ResultCache;
use app\models\SearchRequest;
use app\models\User;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
class HistoryController extends Controller {
public function actionIndex() {
$userId = Yii::$app->request->get("id", false);
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if(!$uuid && !$userId) {
throw new BadRequestHttpException();
}
/* @var $user User */
if($userId) {
$user = User::find()->where(["id" => $userId])->one();
if($uuid) {
$user->uuid = $uuid;
$user->save();
}
} elseif($uuid) {
$user = User::find()->where(compact('uuid'))->one();
if (!$user) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
}
}
$data = [];
foreach(SearchRequest::find()->where(["user_id" => $user->id])->orderBy(["id" => SORT_DESC])->limit(20)->all() as $sr) {
$operatorRow = RequestResult::find()->where(["request_id" => $sr->id, "type_id" => ResultCache::TYPE_OPERATOR])->one();
$operator = [];
if($operatorRow) {
$operator = Json::decode($operatorRow->data);
}
$names = [];
$namesRows = RequestResult::find()->where(["request_id" => $sr->id, "type_id" => [
ResultCache::TYPE_TRUECALLER,
ResultCache::TYPE_NUMBUSTER
]])->all();
foreach ($namesRows as $namesRow) {
$nameData = Json::decode($namesRow->data);
$names = ArrayHelper::merge($names, ArrayHelper::getColumn($nameData, "name"));
}
$names = array_unique($names);
if(count($names) < 2) {
$namesRows = RequestResult::find()->where(["request_id" => $sr->id, "type_id" => [
ResultCache::TYPE_FACEBOOK,
ResultCache::TYPE_VK_2012,
ResultCache::TYPE_VK_OPEN,
ResultCache::TYPE_VIBER,
ResultCache::TYPE_TELEGRAM,
ResultCache::TYPE_VK,
ResultCache::TYPE_AVITO,
]])->all();
foreach ($namesRows as $namesRow) {
$nameData = Json::decode($namesRow->data);
$names = ArrayHelper::merge($names, ArrayHelper::getColumn($nameData, "name"));
}
}
$names = array_unique($names);
$names = array_splice($names, 0, 2);
$data[] = [
"id" => $sr->id,
"phone" => $sr->phone,
"names" => $names,
"is_payed" => $sr->is_payed?1:0,
"index" => array_sum(ArrayHelper::getColumn($sr->results, "index")),
"operator" => ArrayHelper::getValue($operator,"operator", "не известно"),
"region" => ArrayHelper::getValue($operator,"region", "не известно"),
];
}
return $data;
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace app\modules\api\controllers;
use app\models\User;
use app\models\UserSub;
use Yii;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
class InfoController extends Controller {
public function actionIndex() {
$userId = \Yii::$app->getRequest()->get("id", false);
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if(!$uuid && !$userId) {
throw new BadRequestHttpException();
}
if($userId) {
$user = User::find()->select(["id", "balance", "checks", "email"])->where(["id" => $userId])->one();
} else {
$user = User::find()->select(["id", "balance", "checks", "email"])->where(["uuid" => $uuid])->one();
}
$isAndroid = Yii::$app->getRequest()->getHeaders()->get('isandroid', false);
if(!$user && !$isAndroid) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
$user = User::find()->select(["id", "balance", "checks", "email"])->where(["uuid" => $uuid])->one();
}
$sub = UserSub::find()->where(["user_id" => $user->id])->andWhere([">=", "tm_expires", new Expression("NOW()")])->orderBy(["tm_expires" => SORT_DESC])->one();
$expire = ArrayHelper::getValue($sub, "tm_expires", null);
$checks = $user->checks;
if(strtotime($expire) < time() && $checks < 0) {
$user->checks = 0;
$user->save();
$checks = 0;
}
if($checks < 0) $checks = -1;
return [
"id" => $user->id,
"balance" => $user->balance,
"checks" => $checks,
"email" => $user->email,
"isSubscribe" => $expire?1:0,
"subscribe" => $expire?Yii::$app->formatter->asDate($expire, 'd MMMM'):null
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace app\modules\api\controllers;
use app\models\User;
use Yii;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
class NotifyController extends Controller {
public function actionIndex($token) {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if(!$uuid) {
throw new BadRequestHttpException();
}
$user = User::find()->where(["uuid" => $uuid])->one();
if($user) {
$user->token = $token;
if(!$user->save()) {
return $user->getErrors();
} else {
return true;
}
} else {
return false;
}
}
}

View file

@ -0,0 +1,275 @@
<?php
namespace app\modules\api\controllers;
use app\models\User;
use app\models\UserSub;
use Yii;
use yii\db\Expression;
use yii\rest\Controller;
class PlansController extends Controller {
public function actionIndex() {
$userAgent = \Yii::$app->getRequest()->getUserAgent();
if(preg_match("/Nomer\/2\.5\.7/", $userAgent) || preg_match("/Nomer\/2\.5\.8/", $userAgent) ) {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$user = User::find()->where(["uuid" => $uuid])->one();
if(!$user) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
}
$sub = UserSub::find()->where(["user_id" => $user->id])->andWhere([">=", "tm_expires", new Expression("NOW()")])->orderBy(["tm_expires" => SORT_DESC])->one();
if($sub) {
return [];
}
/*
$packs = [
[
"count" => -1,
"product_id" => "com.wcaller.Wcaller.sub.month.0",
"type" => "sub",
"caption" => "Безлимит на месяц",
"subtitle" => "в неделю",
"special" => 0,
"style" => 0 // Большая кнопка
],
[
"count" => -2,
"product_id" => "com.wcaller.Wcaller.sub.6month.0",
"type" => "sub6",
"caption" => "Безлимит на пол года",
"subtitle" => "в неделю",
"special" => 0,
"style" => 0 // Большая кнопка
],
];
*/
$packs = [
[
"count" => -2,
"product_id" => "com.wcaller.Wcaller.sub.month.0",
"type" => "sub",
"caption" => "3 дня - БЕСПЛАТНО",
"subtitle" => "",
"special" => 0,
"style" => 1,
],
[
"count" => -1,
"product_id" => "com.wcaller.Wcaller.sub.6month.0",
"type" => "sub6",
"caption" => "Лучшая цена",
"subtitle" => "0.49$ в день",
"special" => 0,
"style" => 1 // Большая кнопка
],
];
/*
$packs = [
[
"count" => -2,
"product_id" => "com.wcaller.Wcaller.sub.month.0",
"type" => "sub",
"caption" => "3 дня - БЕСПЛАТНО",
"subtitle" => "",
"special" => 0,
"style" => 1,
],
[
"count" => -1,
"product_id" => "com.wcaller.Wcaller.sub.6month.0",
"type" => "sub6",
"caption" => "Лучшая цена",
"subtitle" => "0.49$ в день",
"special" => 0,
"style" => 1 // Большая кнопка
],
];
*/
return $packs;
} elseif(preg_match("/Nomer\/2\.5/", $userAgent)) {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$user = User::find()->where(["uuid" => $uuid])->one();
/*
$packs = [
[
"count" => -2,
"product_id" => "com.wcaller.Wcaller.sub.week.999",
"type" => "sub",
"caption" => "Полный безлимит",
"subtitle" => "Все провеки бесплатно",
"special" => 0,
"style" => 1,
],
[
"count" => -1,
"product_id" => "com.wcaller.Wcaller.sub.6month.0",
"type" => "sub6",
"caption" => "Лучшая цена",
"subtitle" => "0.49$ в день",
"special" => 0,
"style" => 1 // Большая кнопка
],
];
*/
$packs = [
[
"count" => -2,
"product_id" => "com.wcaller.Wcaller.sub.month.0",
"type" => "sub",
"caption" => "3 дня - БЕСПЛАТНО",
"subtitle" => "",
"special" => 0,
"style" => 1,
],
[
"count" => -1,
"product_id" => "com.wcaller.Wcaller.sub.6month.0",
"type" => "sub6",
"caption" => "Лучшая цена",
"subtitle" => "0.49$ в день",
"special" => 0,
"style" => 1 // Большая кнопка
],
];
/*
$packs = [
[
"count" => -2,
"product_id" => "com.wcaller.Wcaller.sub.month.999",
"type" => "sub",
"caption" => "БЕСПЛАТНО",
"subtitle" => "безлимит на месяц",
"special" => 0,
"style" => 1,
],
[
"count" => -1,
"product_id" => "com.wcaller.Wcaller.sub.6month.0",
"type" => "sub6",
"caption" => "Лучшая цена",
"subtitle" => "0.49$ в день",
"special" => 0,
"style" => 1 // Большая кнопка
],
];
*/
if(!$user) return $packs;
$sub = UserSub::find()->where(["user_id" => $user->id])->andWhere([">=", "tm_expires", new Expression("NOW()")])->orderBy(["tm_expires" => SORT_DESC])->one();
if($sub && $user->checks == 0) {
$packs = [
[
"count" => 1,
"product_id" => "com.wcaller.Wcaller.search1",
"type" => "inapp",
],
[
"count" => 10,
"product_id" => "com.wcaller.Wcaller.search10",
"type" => "inapp",
],
[
"count" => 30,
"product_id" => "com.wcaller.Wcaller.search30",
"type" => "inapp",
],
];
} elseif($sub && $user->checks < 0) {
$packs = [];
}
return $packs;
} elseif(preg_match("/Nomer\/2\.3/", $userAgent) || preg_match("/Nomer\/2\.4/", $userAgent)) {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$user = User::find()->where(["uuid" => $uuid])->one();
$packs = [
/*
[
"count" => 1,
"product_id" => "com.wcaller.Wcaller.search1",
"type" => "inapp",
],
*/
[
"count" => 10,
"product_id" => "com.wcaller.Wcaller.sub.month.10",
"type" => "sub",
"special" => 1
],
[
"count" => 15,
"product_id" => "com.wcaller.Wcaller.sub.month.15",
"type" => "sub",
"special" => 0
],
[
"count" => 50,
"product_id" => "com.wcaller.Wcaller.sub.month.50",
"type" => "sub",
"special" => 0
],
];
if(!$user) return $packs;
$sub = UserSub::find()->where(["user_id" => $user->id])->andWhere([">=", "tm_expires", new Expression("NOW()")])->orderBy(["tm_expires" => SORT_DESC])->one();
if($sub) {
$packs = [
[
"count" => 1,
"product_id" => "com.wcaller.Wcaller.search1",
"type" => "inapp",
],
[
"count" => 10,
"product_id" => "com.wcaller.Wcaller.search10",
"type" => "inapp",
],
[
"count" => 30,
"product_id" => "com.wcaller.Wcaller.search30",
"type" => "inapp",
],
];
}
return $packs;
}
$plans = [
[
"count" => 1,
"product_id" => "com.wcaller.Wcaller.search1",
],
[
"count" => 10,
"product_id" => "com.wcaller.Wcaller.search10",
],
[
"count" => 30,
"product_id" => "com.wcaller.Wcaller.search30",
]
/*
[
"count" => 100,
"product_id" => "com.nomer.app.search100",
],
[
"count" => 300,
"product_id" => "com.nomer.app.search300",
]
*/
];
return $plans;
}
}

View file

@ -0,0 +1,51 @@
<?php
namespace app\modules\api\controllers;
use app\models\TmpVk;
use app\models\Vk;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
class PonomeruController extends Controller {
public function actionIndex($phone) {
if(!in_array(\Yii::$app->request->getUserIP(), ["46.20.39.121", "82.204.203.174"])) die("Превед медвед :)");
$phone = preg_replace("/\D/", "", $phone);
$phone = preg_replace("/^8/", "7", $phone);
$response = [];
$profiles = [];
$vkOpen = Vk::find()->where(["or", ["phone1" => $phone], ["phone2" => $phone]])->all();
$vk2012 = TmpVk::find()->where(['phone' => $phone])->all();
$profiles = ArrayHelper::merge($profiles, ArrayHelper::getColumn($vkOpen, "id"));
$profiles = ArrayHelper::merge($profiles, ArrayHelper::getColumn($vk2012, "id"));
if(count($profiles)) {
$socData = @file_get_contents("https://api.vk.com/method/users.get?user_ids=" . join(",", $profiles) . "&fields=photo_id,photo_max,photo_max_orig&lang=ru&access_token=8f95fab19fb8d3d41bdeeb28f0112cb2cd3c86a93fc66acbd29f327d1aa3f196540bfe10dcd4ca97baf37");
if($socData) {
$socData = Json::decode($socData);
$socData = $socData["response"];
foreach($socData as $p) {
$row = [
"id" => ArrayHelper::getValue($p, "uid"),
"name" => ArrayHelper::getValue($p, "first_name")." ".ArrayHelper::getValue($p, "last_name"),
];
$photo = @file_get_contents(ArrayHelper::getValue($p, "photo_max_orig"));
if($photo) {
$row["photo"] = base64_encode($photo);
}
$response[] = $row;
}
}
}
return $response;
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace app\modules\api\controllers;
use app\models\RequestResult;
use app\models\ResultCache;
use app\models\SearchRequest;
use app\models\User;
use Yii;
use yii\base\Exception;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
use yii\web\Response;
class ResultController extends Controller {
public function actionIndex($id) {
//\Yii::$app->response->format = Response::FORMAT_RAW;
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$user_id = \Yii::$app->request->get("user_id", false);
if(!$uuid && !$user_id) {
throw new BadRequestHttpException();
}
if($user_id) {
$user = User::find()->where(["id" => $user_id])->one();
} else {
$user = User::find()->where(["uuid" => $uuid])->one();
}
if(!$user) {
throw new BadRequestHttpException();
}
$searchRequest = SearchRequest::find()->where(["id" => $id, "user_id" => $user->id])->one();
if(!$searchRequest) {
throw new BadRequestHttpException();
}
$results = [];
$resultsData = RequestResult::find()->where(["request_id" => $id])->all();
foreach($resultsData as $r) {
try {
$data = Json::decode($r->data);
if($r->type_id == ResultCache::TYPE_VIBER) {
$data = [$data];
}
sort($data);
if($r->type_id == ResultCache::TYPE_AVITO) {
foreach ($data as $i => $row) {
$base64images = [];
if (isset($row["images"])) {
$images = explode(",", $row["images"]);
foreach ($images as $image) {
if(file_exists(Yii::$app->params['files'] . '/' . $image)) {
$i = @file_get_contents(Yii::$app->params['files'] . '/' . $image);
if($i) {
$b64 = @base64_encode($i);
if($b64) {
$base64images[] = $b64;
}
}
}
}
}
/*
$ijson = json_encode($base64images);
if($ijson) {
$data[$i]["images"] = $base64images;
}
*/
}
}
$result = [
"type" => ResultCache::getTypeSysname($r->type_id),
"elements" => $data
];
if($r->type_id == ResultCache::TYPE_AVINFO_API) {
$result["avinfo"] = $data;
$result["type"] = "avinfo";
}
if($r->type_id == ResultCache::TYPE_GIBDD) {
$result["gibdd"] = $data;
$result["type"] = "avinfo";
}
if($r->type_id == ResultCache::TYPE_ANTIPARKON) {
$result["antiparkon"] = $data;
$result["type"] = "avinfo";
}
$results[] = $result;
} catch (Exception $e) {
}
}
return $results;
}
}

View file

@ -0,0 +1,154 @@
<?php
namespace app\modules\api\controllers;
use app\components\SearchHelper;
use app\models\BlockPhone;
use app\models\SearchRequest;
use app\models\User;
use Yii;
use yii\base\Exception;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
class SearchController extends Controller{
public function actionIndex() {
$phone = \Yii::$app->request->get('phone');
$phone = preg_replace('/\D/', '', $phone);
if (mb_strlen($phone) == 10) {
$phone = '7' . $phone;
} else {
$phone = preg_replace('/^8/', '7', $phone);
}
$source = null;
$userId = Yii::$app->request->get("id", false);
$isAndroid = Yii::$app->getRequest()->getHeaders()->get('isandroid', false);
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
if(!$uuid && !$userId) {
throw new BadRequestHttpException();
}
/* @var $user User */
if($userId) {
$user = User::find()->where(["id" => $userId])->one();
if($uuid) {
$user->uuid = $uuid;
$user->save();
}
} elseif($uuid) {
$user = User::find()->where(compact('uuid'))->one();
if (!$user) {
$user = new User();
$user->email = null;
$user->uuid = $uuid;
$user->save();
}
}
$count = SearchRequest::find()->where(["user_id" => $user->id])->count(1);
if(!$user->is_vip) {
$block = BlockPhone::find()->where(["phone" => $phone, "status" => [1]])->one();
if(!is_null($block)) {
return ['id' => -1];
}
}
$limit = 1;
$countSeaches = 0;
if($user->checks == 0) {
$results = 0;
$freePhones = [];
$users = User::find()->where(["uuid" => $user->uuid])->all();
foreach($users as $u) {
$searchRequests = SearchRequest::find()->where(["user_id" => $u->id])->andWhere([">", "tm", date("Y-m-d H:i:s", strtotime("-7 days"))])->all();
foreach ($searchRequests as $s) {
if($s->is_has_name && $s->is_has_photo && !in_array($s->phone, $freePhones)) {
$countSeaches++;
$freePhones[] = $s->phone;
}
if($countSeaches == $limit) break;
}
}
if($countSeaches >= $limit) return ['id' => 0];
}
$isCache = 0;
//$searchRequest = SearchRequest::find()->where(["user_id" => $user->id, "phone" => $phone])->orderBy(["id" => SORT_DESC])->one();
$searchRequest = false;
$refresh = \Yii::$app->request->get("refresh", 0);
if($phone == "79645552229") {
$refresh = 1;
}
if(!$refresh) {
$searchRequest = SearchRequest::find()->with('results')->where([
"user_id" => $user->id,
"phone" => $phone,
"is_payed" => [1, 2]
])->orderBy(["id" => SORT_DESC])->one();
if($searchRequest) {
$isCache = 1;
}
}
if(!$searchRequest) {
$isCache = 0;
$searchRequest = new SearchRequest();
$searchRequest->ip = \Yii::$app->request->userIP;
$searchRequest->ua = \Yii::$app->request->userAgent;
$searchRequest->phone = $phone;
$searchRequest->tm = new Expression('NOW()');
$searchRequest->user_id = $user->id;
$searchRequest->refresh = true;
if($isAndroid) {
$searchRequest->source_id = SearchRequest::SOURCE_ANDROID;
} else {
$searchRequest->source_id = SearchRequest::SOURCE_IOS;
}
if($user->checks < 0) {
$searchRequest->is_payed = 1;
} elseif($user->checks > 0) {
$user->checks--;
$searchRequest->is_payed = 1;
} elseif($user->balance >= \Yii::$app->params["cost"]) {
$user->balance -= \Yii::$app->params["cost"];
$searchRequest->is_payed = 1;
} elseif(!$isAndroid) {
$searchRequest->is_payed = 1;
} elseif($countSeaches == 0) {
$searchRequest->is_payed = 1;
}
$user->save();
$searchRequest->save();
}
// if($uuid == "AA4AD41A-E2CE-4A7B-8AA0-FCE2EFAE52EE") $count = 0;
$result = [
'id' => $searchRequest->id,
'mobile' => null,
'is_payed' => (int)$searchRequest->is_payed,
'is_cache' => $isCache,
'is_first' => $count?0:1
];
$operator = SearchHelper::Operator($phone);
if($operator) {
$result['mobile'] = $operator;
}
return $result;
}
}

View file

@ -0,0 +1,168 @@
<?php
namespace app\modules\api\controllers;
use app\models\Auth;
use app\models\User;
use Yii;
use yii\db\Expression;
use yii\rest\Controller;
class SigninController extends Controller {
public function actionExit() {
/*
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$user = User::find()->where(["uuid" => $uuid])->andWhere(["IS NOT", "email", null])->one();
if($user) {
$user->uuid = null;
$user->save();
}
$userFree = User::find()->select(["id", "checks"])->where(["uuid" => $uuid])->andWhere(["email" => null])->one();
if(!$userFree) {
$userFree = new User();
$userFree->email = null;
$userFree->uuid = $uuid;
$userFree->save();
}
return $userFree;
*/
return ["success" => 1];
}
public function actionReg() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$email = \Yii::$app->request->post("email");
$password = \Yii::$app->request->post("password");
$user = User::find()->where(["email" => $email])->one();
if($user) {
return ["error" => 1];
} else {
$user = new User();
$user->email = $email;
$user->password = $password;
$user->uuid = $uuid;
$user->save();
return $user;
}
}
public function actionIndex() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$email = \Yii::$app->request->post("email");
$password = \Yii::$app->request->post("password");
$user = User::find()->where(["email" => $email])->one();
if($user && $user->validatePassword($password)) {
$user->uuid = $uuid;
$user->save();
return [
"id" => $user->id,
"checks" => $user->checks,
"email" => $user->email
];
}
return [
"id" => 0,
"checks" => 0
];
}
public function actionGoogle() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$id = \Yii::$app->request->post("id");
$email = \Yii::$app->request->post("email");
$user = User::find()->where(["email" => $email])->one();
if(!$user) {
$password = Yii::$app->security->generateRandomString(6);
$user = new User([
'email' => mb_strtolower($email),
'password' => $password,
'is_confirm' => true,
'tm_confirm' => new Expression('NOW()')
]);
$user->uuid = $uuid;
if ($user->save()) {
$auth = new Auth([
'user_id' => $user->id,
'source' => "google",
'source_id' => (string)$id,
]);
$auth->save();
}
}
return [
"id" => $user->id,
"checks" => $user->checks
];
}
public function actionVk() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$id = \Yii::$app->request->post("id");
$email = \Yii::$app->request->post("email");
$user = User::find()->where(["email" => $email])->one();
if(!$user) {
$password = Yii::$app->security->generateRandomString(6);
$user = new User([
'email' => mb_strtolower($email),
'password' => $password,
'is_confirm' => true,
'tm_confirm' => new Expression('NOW()')
]);
$user->uuid = $uuid;
if ($user->save()) {
$auth = new Auth([
'user_id' => $user->id,
'source' => "vk",
'source_id' => (string)$id,
]);
$auth->save();
}
}
return [
"id" => $user->id,
"checks" => $user->checks
];
}
public function actionFacebook() {
$uuid = Yii::$app->getRequest()->getHeaders()->get('uuid', false);
$id = \Yii::$app->request->post("id");
$email = \Yii::$app->request->post("email");
$user = User::find()->where(["email" => $email])->one();
if(!$user) {
$password = Yii::$app->security->generateRandomString(6);
$user = new User([
'email' => mb_strtolower($email),
'password' => $password,
'is_confirm' => true,
'tm_confirm' => new Expression('NOW()')
]);
$user->uuid = $uuid;
if ($user->save()) {
$auth = new Auth([
'user_id' => $user->id,
'source' => "facebook",
'source_id' => (string)$id,
]);
$auth->save();
}
}
return [
"id" => $user->id,
"checks" => $user->checks
];
}
}

View file

@ -0,0 +1,241 @@
<?php
namespace app\modules\api\controllers;
use app\components\SearchHelper;
use app\models\RequestResult;
use app\models\ResultCache;
use app\models\SearchRequest;
use app\models\Settings;
use app\models\TmpVk;
use app\models\Vk;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;
use yii\rest\Controller;
use yii\web\Response;
class TelegramController extends Controller
{
public function actionIndex($phone)
{
\Yii::$app->response->format = Response::FORMAT_JSON;
$searchRequest = new SearchRequest();
$searchRequest->phone = $phone;
$searchRequest->source_id = SearchRequest::SOURCE_TELEGRAM;
$searchRequest->save();
$id = $searchRequest->id;
$result = [
"phones" => [$phone],
"emails" => [],
"profiles" => [],
"public" => [],
"phone" => $phone,
"open" => [],
"elements" => [],
"valid" => []
];
$profiles = [];
$ch = curl_init('http://ssd.nomer.io/api/'.$phone.'?token=NWBpdeqbbAFJMVYJU6XAfhyydeyhgX');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 200) { // Все ок, берем данные
$response = Json::decode($response);
foreach($response as $r) {
switch($r["type"]) {
case "phone":
$result["phones"][] = $r["data"];
break;
case "profile_id":
$result["profiles"][] = $r["data"];
$profiles[] = $r["data"];
if(isset($r["isValid"]) && $r["isValid"] == 1) {
$result["valid"][] = $r["data"];
}
break;
case "email":
if (strpos($r["data"], '@') !== false) {
$result["emails"][] = $r["data"];
}
break;
}
}
}
$result["phones"] = array_unique($result["phones"]);
foreach($result["phones"] as $_phone) {
$vk = TmpVk::find()->where(['phone' => $phone])->all();
foreach($vk as $v) {
$profile_id = $v["id"];
$result["public"][] = $profile_id;
$profiles[] = $profile_id;
}
}
$vkrows = Vk::find()->where(["or",
["phone1" => $phone],
["phone2" => $phone],
])->all();
foreach ($vkrows as $vkrow) {
$profiles[] = $vkrow["id"];
// $result["public"][] = $vkrow["id"];
$result["open"][] = $vkrow["id"];
$result["phones"][] = $vkrow["phone1"];
$result["phones"][] = $vkrow["phone2"];
$result["phones"][] = $vkrow["phone3"];
$result["phones"][] = $vkrow["phone4"];
}
$result["emails"] = array_unique($result["emails"]);
$result["phones"] = array_unique(array_filter($result["phones"]));
$phones = $result['phones'];
// Получаем оператора и регион
$operator = SearchHelper::Operator($searchRequest->phone);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_OPERATOR])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_OPERATOR;
$requestResult->data = Json::encode($operator);
$requestResult->index = 0;
$requestResult->save();
}
$items = [];
// Telegram
$telegramItems = SearchHelper::Telegram($phones);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_TELEGRAM])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_TELEGRAM;
$requestResult->data = Json::encode($telegramItems);
$requestResult->index = count($telegramItems)?Settings::get("search_index_telegram", 7):0;
$requestResult->save();
}
$items = ArrayHelper::merge($items, $telegramItems);
// Viber
$viberItems = SearchHelper::Viber($phones);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_VIBER])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_VIBER;
$requestResult->data = Json::encode($viberItems);
$requestResult->index = count($viberItems)?Settings::get("search_index_viber", 7):0;
$requestResult->save();
}
$items = ArrayHelper::merge($items, $viberItems);
// Numbuster
$numbusterItems = SearchHelper::Numbuster($phones);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_NUMBUSTER])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_NUMBUSTER;
$requestResult->data = Json::encode($numbusterItems);
$requestResult->index = count($numbusterItems)?Settings::get("search_index_numbuster", 7):0;
$requestResult->save();
}
$items = ArrayHelper::merge($items, $numbusterItems);
// Truecaller
$truecallerItems = SearchHelper::Truecaller($phones);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_TRUECALLER])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_TRUECALLER;
$requestResult->data = Json::encode($truecallerItems);
$requestResult->index = count($truecallerItems)?Settings::get("search_index_truecaller", 7):0;
$requestResult->save();
}
$items = ArrayHelper::merge($items, $truecallerItems);
// Vk
$vkItems = SearchHelper::Vk($phones);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_VK_2012])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_VK_2012;
$requestResult->data = Json::encode($vkItems);
$requestResult->index = count($vkItems)?Settings::get("search_index_vk", 20):0;
$requestResult->save();
}
$items = ArrayHelper::merge($items, $vkItems);
// Avito
$avitoItems = SearchHelper::Avito($phones);
$requestResult = RequestResult::find()->where(["request_id" => $id, "type_id" => ResultCache::TYPE_AVITO])->one();
if(is_null($requestResult)) {
$requestResult = new RequestResult();
$requestResult->request_id = $id;
$requestResult->type_id = ResultCache::TYPE_AVITO;
$requestResult->data = Json::encode($avitoItems);
$requestResult->index = count($avitoItems)?Settings::get("search_index_avito", 15):0;
$requestResult->save();
}
$items = ArrayHelper::merge($items, $avitoItems);
if(count(ArrayHelper::getColumn($items, "name"))) {
$searchRequest->is_has_name = true;
}
if(count(ArrayHelper::getColumn($items, "photo"))) {
$searchRequest->is_has_photo = true;
}
$searchRequest->save();
sort($items);
$names = array_unique(array_filter(array_map(function ($data) {
return ArrayHelper::getValue($data, 'name');
}, $items)));
sort($names);
$photo = false;
foreach ($items as $item) {
if (isset($item['photo'])) {
$photo = $item['photo'];
break;
}
}
return compact('names', 'photo');
}
}