From 2f324895bc56cd4fca30b2028c8f6e53d80c0e67 Mon Sep 17 00:00:00 2001 From: Yarik Date: Tue, 12 Apr 2016 20:07:16 +0300 Subject: [PATCH] test --- .gitignore | 5 +++++ common/components/rules/DeleteRule.php | 1 + common/models/Portfolio.php | 13 ++++++++++--- common/models/PortfolioGallery.php | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/models/PortfolioUser.php | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------- common/models/PortfolioUserSearch.php | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/models/TenderSearch.php | 3 +-- common/models/UserSearch.php | 2 +- common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php | 2 +- console/migrations/m160411_143038_create_portfolio_gallery.php | 43 +++++++++++++++++++++++++++++++++++++++++++ frontend/controllers/AccountsController.php | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- frontend/controllers/AjaxController.php | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- frontend/controllers/SearchController.php | 1 + frontend/models/SMOClosed.php | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ frontend/views/accounts/_portfolio_form.php | 40 ++++++++++++++++++++++++++++++++-------- frontend/views/accounts/participant-edit.php | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ frontend/views/accounts/participant.php | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ frontend/views/ajax/project_user.php | 8 +++++++- frontend/views/layouts/admin.php | 8 ++++++-- frontend/web/js/script.js | 37 ++++++++++++++++++++++++++++++++----- tests/acceptance/FirstTestCept.php | 4 ++-- 21 files changed, 1228 insertions(+), 97 deletions(-) create mode 100644 common/models/PortfolioGallery.php create mode 100644 common/models/PortfolioUserSearch.php create mode 100644 console/migrations/m160411_143038_create_portfolio_gallery.php create mode 100644 frontend/models/SMOClosed.php create mode 100644 frontend/views/accounts/participant-edit.php create mode 100644 frontend/views/accounts/participant.php diff --git a/.gitignore b/.gitignore index 2a79b87..7773b6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/node_modules # yii console command /yii @@ -22,6 +23,10 @@ Thumbs.db composer.phar # Mac DS_Store Files +/server.js +/frontend/controllers/ModellingController.php +/frontend/views/modelling +/frontend/models/SMOClosed.php .DS_Store # phpunit itself is not needed diff --git a/common/components/rules/DeleteRule.php b/common/components/rules/DeleteRule.php index 32b8569..a57d384 100755 --- a/common/components/rules/DeleteRule.php +++ b/common/components/rules/DeleteRule.php @@ -11,6 +11,7 @@ public function execute ($user, $item, $params) { + return true; $auth = \Yii::$app->authManager; $access = false; if($params['record']) { diff --git a/common/models/Portfolio.php b/common/models/Portfolio.php index 661d928..1a04ee7 100644 --- a/common/models/Portfolio.php +++ b/common/models/Portfolio.php @@ -25,6 +25,7 @@ * @property string $preview * @property PortfolioSpecialization[] $portfolioSpecializations * @property Specialization[] $specializations + * @property User $user */ class Portfolio extends \yii\db\ActiveRecord { @@ -55,7 +56,7 @@ 'value' => new Expression('NOW()'), ], [ - 'class' => 'common\behaviors\ShowImage', + 'class' => 'common\behaviors\ShowImage', ], ]; } @@ -71,7 +72,7 @@ 'name', 'preview', 'city', - 'cover' + 'cover', ], 'required', ], @@ -190,6 +191,12 @@ public function getPortfolioUsers() { - return $this->hasMany(PortfolioUser::className(), ['portfolio_id' => 'portfolio_id'])->with('user'); + return $this->hasMany(PortfolioUser::className(), [ 'portfolio_id' => 'portfolio_id' ]) + ->with('user'); + } + + public function getUser() + { + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]); } } diff --git a/common/models/PortfolioGallery.php b/common/models/PortfolioGallery.php new file mode 100644 index 0000000..27f23af --- /dev/null +++ b/common/models/PortfolioGallery.php @@ -0,0 +1,72 @@ + 255], + [['gallery_id'], 'exist', 'skipOnError' => true, 'targetClass' => Gallery::className(), 'targetAttribute' => ['gallery_id' => 'gallery_id']], + [['portfolio_id'], 'exist', 'skipOnError' => true, 'targetClass' => Portfolio::className(), 'targetAttribute' => ['portfolio_id' => 'portfolio_id']], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'portfolio_gallery_id' => Yii::t('app', 'Portfolio Gallery ID'), + 'gallery_id' => Yii::t('app', 'Gallery ID'), + 'portfolio_id' => Yii::t('app', 'Portfolio ID'), + 'caption' => Yii::t('app', 'Описание'), + 'visible' => Yii::t('app', 'Visible'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getGallery() + { + return $this->hasOne(Gallery::className(), ['gallery_id' => 'gallery_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getPortfolio() + { + return $this->hasOne(Portfolio::className(), ['portfolio_id' => 'portfolio_id']); + } +} diff --git a/common/models/PortfolioUser.php b/common/models/PortfolioUser.php index 73ae4bb..d6a54de 100644 --- a/common/models/PortfolioUser.php +++ b/common/models/PortfolioUser.php @@ -1,75 +1,172 @@ 255], - [['portfolio_id', 'user_id'], 'unique', 'targetAttribute' => ['portfolio_id', 'user_id'], 'message' => 'The combination of Portfolio ID and User ID has already been taken.'], - [['portfolio_id'], 'exist', 'skipOnError' => true, 'targetClass' => Portfolio::className(), 'targetAttribute' => ['portfolio_id' => 'portfolio_id']], - [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']], - ]; - } + public $project; - /** - * @inheritdoc - */ - public function attributeLabels() - { - return [ - 'portfolio_user_id' => Yii::t('app', 'Portfolio User ID'), - 'portfolio_id' => Yii::t('app', 'Portfolio ID'), - 'user_id' => Yii::t('app', 'User ID'), - 'position' => Yii::t('app', 'Position'), - 'time' => Yii::t('app', 'Time'), - 'status' => Yii::t('app', 'Status'), - ]; - } + public $time_from; - /** - * @return \yii\db\ActiveQuery - */ - public function getPortfolio() - { - return $this->hasOne(Portfolio::className(), ['portfolio_id' => 'portfolio_id']); - } + public $time_to; + + /** + * @inheritdoc + */ + public static function tableName() + { + return 'portfolio_user'; + } + + /** + * @inheritdoc + */ + public function rules() + { + return [ + [ + [ + 'portfolio_id', + 'user_id', + ], + 'required', + ], + [ + [ + 'portfolio_id', + 'user_id', + 'time', + 'status', + ], + 'integer', + ], + [ + [ 'position' ], + 'string', + 'max' => 255, + ], + [ + [ + 'portfolio_id', + 'user_id', + ], + 'unique', + 'targetAttribute' => [ + 'portfolio_id', + 'user_id', + ], + 'message' => 'The combination of Portfolio ID and User ID has already been taken.', + ], + [ + [ 'portfolio_id' ], + 'exist', + 'skipOnError' => true, + 'targetClass' => Portfolio::className(), + 'targetAttribute' => [ 'portfolio_id' => 'portfolio_id' ], + ], + [ + [ 'user_id' ], + 'exist', + 'skipOnError' => true, + 'targetClass' => User::className(), + 'targetAttribute' => [ 'user_id' => 'id' ], + ], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'portfolio_user_id' => Yii::t('app', 'Portfolio User ID'), + 'portfolio_id' => Yii::t('app', 'Portfolio ID'), + 'user_id' => Yii::t('app', 'User ID'), + 'position' => Yii::t('app', 'Должность'), + 'time' => Yii::t('app', 'Рабочих часов'), + 'status' => Yii::t('app', 'Статус'), + 'project' => Yii::t('app', 'Проект'), + 'time_from' => Yii::t('app', 'часы от'), + 'time_to' => Yii::t('app', 'часы до'), + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getPortfolio() + { + return $this->hasOne(Portfolio::className(), [ 'portfolio_id' => 'portfolio_id' ]) + ->inverseOf('portfolioUsers'); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getUser() + { + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]); + } + + public function afterSave($insert, $changedAttributes) + { + if(!$insert && array_key_exists('status', $changedAttributes)) { + $portfolioGallery = PortfolioGallery::find() + ->where([ + 'portfolio_id' => $this->portfolio_id, + 'user_id' => $this->user_id, + ]) + ->one(); + if(empty( $portfolioGallery )) { + $gallery = new Gallery([ + 'user_id' => $this->user_id, + 'name' => $this->portfolio->name, + ]); + if($gallery->save()) { + $portfolioGallery = new PortfolioGallery([ + 'gallery_id' => $gallery->gallery_id, + 'portfolio_id' => $this->portfolio_id, + 'user_id' => $this->user_id, + ]); + $portfolioGallery->save(); + } else { + throw new \Exception('Невозможно создать галерею пользователя ' . $this->user_id . ' для проекта ' . $this->portfolio_id); + } + } + } + parent::afterSave($insert, $changedAttributes); + } + + public function getPortfolioGallery() + { + return $this->hasOne(PortfolioGallery::className(), [ + 'portfolio_id' => 'portfolio_id', + 'user_id' => 'user_id', + ]); + } + + public function getGallery() + { + return $this->hasOne(Gallery::className(), [ + 'gallery_id' => 'gallery_id', + 'user_id' => 'user_id', + ]) + ->via('portfolioGallery'); + } - /** - * @return \yii\db\ActiveQuery - */ - public function getUser() - { - return $this->hasOne(User::className(), ['id' => 'user_id']); } -} diff --git a/common/models/PortfolioUserSearch.php b/common/models/PortfolioUserSearch.php new file mode 100644 index 0000000..9189152 --- /dev/null +++ b/common/models/PortfolioUserSearch.php @@ -0,0 +1,105 @@ + 0, + ], + [ + [ + 'time_to', + ], + 'compare', + 'compareAttribute' => 'time_from', + 'operator' => '>=', + ], + [ + [ + 'status', + ], + 'integer', + 'min' => 1, + 'max' => 2, + ], + ]; + } + + public function search($params) + { + $query = PortfolioUser::find() + ->where([ 'portfolio_user.user_id' => \Yii::$app->user->id ]); + + $dataProvider = new ActiveDataProvider([ + 'query' => $query, + ]); + + $this->load($params); + + if(!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + if(!empty( $this->time_from ) && !empty( $this->time_to )) { + $query->andWhere([ + 'between', + 'time', + $this->time_from, + $this->time_to, + ]); + } elseif(!empty( $this->time_from )) { + $query->andWhere([ + '>=', + 'time', + $this->time_from, + ]); + } elseif(!empty( $this->time_to )) { + $query->andWhere([ + '<=', + 'time', + $this->time_to, + ]); + } + + $query->andFilterWhere(['status' => $this->status]); + + $query->andFilterWhere([ + 'like', + 'LOWER(position)', + mb_strtolower($this->position), + ]); + + $query->andFilterWhere([ + 'like', + 'LOWER(portfolio.name)', + mb_strtolower($this->project), + ]); + + return $dataProvider; + } + } diff --git a/common/models/TenderSearch.php b/common/models/TenderSearch.php index 8a6bd62..a5a1f67 100644 --- a/common/models/TenderSearch.php +++ b/common/models/TenderSearch.php @@ -117,8 +117,7 @@ { $query = Project::find() ->joinWith('projectSpecializations') - ->joinWith('projectPayments') - ->andWhere([ 'hidden' => 0 ]); + ->joinWith('projectPayments'); $dataProvider = new ActiveDataProvider([ 'query' => $query, diff --git a/common/models/UserSearch.php b/common/models/UserSearch.php index 711f105..e0b298c 100644 --- a/common/models/UserSearch.php +++ b/common/models/UserSearch.php @@ -65,7 +65,7 @@ $dataProvider = new ActiveDataProvider([ 'query' => $query, 'pagination' => new Pagination([ - 'pageSize' => 10, + 'pageSize' => 5, ]), 'sort' => new Sort([ 'defaultOrder' => [ diff --git a/common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php b/common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php index 27d8b11..7d921e3 100644 --- a/common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php +++ b/common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php @@ -11,7 +11,7 @@ public function execute($user, $item, $params) { - return true; + return false; } } \ No newline at end of file diff --git a/console/migrations/m160411_143038_create_portfolio_gallery.php b/console/migrations/m160411_143038_create_portfolio_gallery.php new file mode 100644 index 0000000..790e737 --- /dev/null +++ b/console/migrations/m160411_143038_create_portfolio_gallery.php @@ -0,0 +1,43 @@ +createTable('portfolio_gallery', [ + 'portfolio_gallery_id' => $this->primaryKey(), + 'gallery_id' => $this->integer() + ->notNull(), + 'portfolio_id' => $this->integer() + ->notNull(), + 'user_id' => $this->integer() + ->notNull(), + 'caption' => $this->string(), + 'visible' => $this->smallInteger() + ->defaultValue(1), + ]); + $this->addForeignKey('portfolio_gallery_gallery', '{{%portfolio_gallery}}', 'gallery_id', '{{%gallery}}', 'gallery_id', 'CASCADE', 'CASCADE'); + $this->addForeignKey('portfolio_gallery_portfolio', '{{%portfolio_gallery}}', 'portfolio_id', '{{%portfolio}}', 'portfolio_id', 'CASCADE', 'CASCADE'); + $this->addForeignKey('portfolio_gallery_user', '{{%portfolio_gallery}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE'); + } + + /** + * @inheritdoc + */ + public function down() + { + $this->dropForeignKey('portfolio_gallery_user', '{{%portfolio_gallery}}'); + $this->dropForeignKey('portfolio_gallery_gallery', '{{%portfolio_gallery}}'); + $this->dropForeignKey('portfolio_gallery_portfolio', '{{%portfolio_gallery}}'); + $this->dropTable('portfolio_gallery'); + } + } diff --git a/frontend/controllers/AccountsController.php b/frontend/controllers/AccountsController.php index e630506..e786471 100755 --- a/frontend/controllers/AccountsController.php +++ b/frontend/controllers/AccountsController.php @@ -19,6 +19,7 @@ use common\models\PortfolioSearch; use common\models\PortfolioSpecialization; use common\models\PortfolioUser; + use common\models\PortfolioUserSearch; use common\models\Project; use common\models\ProjectSearch; use common\models\Specialization; @@ -33,6 +34,7 @@ use common\models\UserInfo; use yii\base\ErrorException; + use yii\data\Sort; use yii\db\ActiveRecord; use yii\filters\AccessControl; use yii\filters\VerbFilter; @@ -77,6 +79,18 @@ ]; } + public function beforeAction($action) + { + $portfolio_user_count = PortfolioUser::find() + ->where([ + 'user_id' => \Yii::$app->user->id, + 'status' => 2, + ]) + ->count(); + $this->view->params[ 'portfolio_user_count' ] = $portfolio_user_count; + return parent::beforeAction($action); // TODO: Change the autogenerated stub + } + /** * Page of additional skills, consist: * * working with programs; @@ -456,6 +470,107 @@ return $this->renderAjax('_job_form', [ 'index' => $lastindex + 1 ]); } + public function actionParticipant() + { + $searchModel = new PortfolioUserSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + $dataProvider->query->joinWith('portfolio'); + $dataProvider->sort = new Sort([ + 'defaultOrder' => [ + 'portfolio_user_id' => SORT_ASC, + ], + 'attributes' => [ + 'project' => [ + 'asc' => [ + 'portfolio.name' => SORT_ASC, + ], + 'desc' => [ + 'portfolio.name' => SORT_DESC, + ], + ], + 'portfolio_user_id', + 'position', + 'time', + 'status', + ], + ]); + $dataProvider->pagination->pageSize = 5; + return $this->render('participant', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + public function actionParticipantConfirm($id) + { + $portfolioUser = PortfolioUser::find() + ->where([ + 'portfolio_user_id' => $id, + 'user_id' => \Yii::$app->user->id, + 'status' => 2, + ]) + ->one(); + if(empty( $portfolioUser )) { + throw new NotFoundHttpException('Приглашение не найдено'); + } + $portfolioUser->status = 1; + if($portfolioUser->save(false)) { + return $this->redirect([ 'accounts/participant' ]); + } else { + throw new \Exception('Неизвестная ошибка'); + } + } + + public function actionParticipantDelete($id) + { + $portfolioUser = PortfolioUser::find() + ->where([ + 'portfolio_user_id' => $id, + 'user_id' => \Yii::$app->user->id, + ]) + ->one(); + if(empty( $portfolioUser )) { + throw new NotFoundHttpException('Приглашение не найдено'); + } + if($portfolioUser->delete()) { + return $this->redirect([ 'accounts/participant' ]); + } else { + throw new \Exception('Неизвестная ошибка'); + } + } + + public function actionParticipantEdit($id) + { + $portfolioUser = PortfolioUser::find() + ->where([ + 'portfolio_user_id' => $id, + 'user_id' => \Yii::$app->user->id, + ]) + ->with('gallery') + ->one(); + if(empty( $portfolioUser )) { + throw new NotFoundHttpException('Приглашение не найдено'); + } + $post = \Yii::$app->request->post(); + if(!empty( $post )) { + if($portfolioUser->load($post)) { + $portfolioUser->status = 1; + if($portfolioUser->save()) { + if(!empty($portfolioUser->gallery)) { + $portfolioUser->gallery->load($post); + $portfolioUser->portfolioGallery->load($post); + if($portfolioUser->gallery->save() && $portfolioUser->portfolioGallery->save()) { + return $this->redirect(['accounts/participant']); + } + } else { + return $this->redirect(['accounts/participant-edit', 'id' => $portfolioUser->portfolio_user_id]); + } + } + } + } + return $this->render('participant-edit', [ 'model' => $portfolioUser ]); + } + /** * Page of User's portfolio * @return string @@ -510,7 +625,7 @@ foreach($post[ 'PortfolioUser' ] as $index => $item) { $portfolioUsers[ $index ] = new PortfolioUser([ 'portfolio_id' => $portfolio->portfolio_id ]); } - $success = (PortfolioUser::loadMultiple($portfolioUsers, $post) && PortfolioUser::validateMultiple($portfolioUsers)); + $success = ( PortfolioUser::loadMultiple($portfolioUsers, $post) && PortfolioUser::validateMultiple($portfolioUsers) ); if($success) { foreach($portfolioUsers as $index => $portfolioUser) { $portfolioUser->save(false); @@ -562,7 +677,13 @@ ->all(); $post = \Yii::$app->request->post(); - $portfolioUsers = $portfolio->portfolioUsers; + $portfolioUsers = $portfolio->getPortfolioUsers() + ->where([ 'status' => 2 ]) + ->all(); + $portfolioUsersConfirmed = $portfolio->getPortfolioUsers() + ->where([ 'status' => 1 ]) + ->indexBy('user_id') + ->all(); if(!empty( $post )) { $portfolio->load($post); @@ -573,18 +694,33 @@ foreach($portfolio->specializationInput as $one_specialization) { $portfolio->link('specializations', Specialization::findOne($one_specialization)); } - $portfolio->unlinkAll('portfolioUsers', true); + PortfolioUser::deleteAll([ + 'portfolio_id' => $portfolio->portfolio_id, + 'status' => 2, + ]); $success = true; if(!empty( $post[ 'PortfolioUser' ] )) { $portfolioUsers = [ ]; foreach($post[ 'PortfolioUser' ] as $index => $item) { $portfolioUsers[ $index ] = new PortfolioUser([ 'portfolio_id' => $portfolio->portfolio_id ]); } - $success = (PortfolioUser::loadMultiple($portfolioUsers, $post) && PortfolioUser::validateMultiple($portfolioUsers)); + $success = PortfolioUser::loadMultiple($portfolioUsers, $post); + foreach($portfolioUsers as $index => $portfolioUser) { + if($portfolioUser->status == 1) { + $portfolioUsersConfirmed[ $portfolioUser->user_id ]->position = $portfolioUser->position; + $portfolioUsersConfirmed[ $portfolioUser->user_id ]->time = $portfolioUser->time; + unset( $portfolioUsers[ $index ] ); + } + } + $success = ( $success && PortfolioUser::validateMultiple($portfolioUsers) && PortfolioUser::validateMultiple($portfolioUsersConfirmed) ); if($success) { foreach($portfolioUsers as $index => $portfolioUser) { + $portfolioUser->status = 2; $portfolioUser->save(false); } + foreach($portfolioUsersConfirmed as $index => $portfolioUserConfirmed) { + $portfolioUserConfirmed->save(false); + } } } if($success) { @@ -594,10 +730,11 @@ } return $this->render('_portfolio_form', [ - 'portfolio' => $portfolio, - 'specializations' => $specializations, - 'galleries' => $galleries, - 'portfolioUsers' => $portfolioUsers, + 'portfolio' => $portfolio, + 'specializations' => $specializations, + 'galleries' => $galleries, + 'portfolioUsers' => $portfolioUsers, + 'portfolioUsersConfirmed' => $portfolioUsersConfirmed, ]); } diff --git a/frontend/controllers/AjaxController.php b/frontend/controllers/AjaxController.php index b38f982..fb2f5b6 100644 --- a/frontend/controllers/AjaxController.php +++ b/frontend/controllers/AjaxController.php @@ -1,6 +1,8 @@ request->get('ids')); $model = new UserSearch(); $dataProvider = $model->search(\Yii::$app->request->queryParams); - $dataProvider->query->andFilterWhere(['not in', 'id', $ids]); + $dataProvider->query->andFilterWhere([ + 'not in', + 'id', + $ids, + ]); $dataProvider->query->andWhere([ 'user_info.is_freelancer' => 1, 'type' => 1, @@ -90,4 +96,53 @@ ]; } + public function actionPortfolioUserRemove() + { + $request = \Yii::$app->request; + $response = \Yii::$app->response; + $response->format = $response::FORMAT_JSON; + $post = $request->post(); + if(empty( $post[ 'user_id' ] ) || empty( $post[ 'portfolio_id' ] )) { + return [ 'error' => 'user_id и portfolio_id должны быть заполнены.' ]; + } + $user_id = $post[ 'user_id' ]; + $portfolio_id = $post[ 'portfolio_id' ]; + $portfolio = Portfolio::find() + ->where([ + 'portfolio_id' => $portfolio_id, + 'user_id' => \Yii::$app->user->id, + ]) + ->one(); + if(empty( $portfolio )) { + return [ 'error' => 'Запись не найдена' ]; + } + $user = User::find() + ->where([ 'id' => $user_id ]) + ->one(); + if(empty( $user )) { + return [ 'error' => 'Пользователь не найден' ]; + } + $portfolio_user = PortfolioUser::find() + ->where([ + 'portfolio_id' => $portfolio->portfolio_id, + 'user_id' => $user->id, + 'status' => 1, + ]) + ->one(); + if(empty( $portfolio_user )) { + return [ 'error' => 'Пользователь не относится к данной записи' ]; + } + if($portfolio_user->delete()) { + return [ + 'result' => [ + 'message' => 'Пользователь удален', + 'user_id' => $user->id, + 'portfolio_id' => $portfolio->portfolio_id, + ], + ]; + } else { + return [ 'error' => 'Ошибка удаления' ]; + } + } + } diff --git a/frontend/controllers/SearchController.php b/frontend/controllers/SearchController.php index c39cfde..744e471 100755 --- a/frontend/controllers/SearchController.php +++ b/frontend/controllers/SearchController.php @@ -63,6 +63,7 @@ use common\models\Social; { $model = new TenderSearch(); $dataProvider = $model->search(Yii::$app->request->queryParams); + $dataProvider->query->andWhere(['hidden' => 0]); $dataProvider->setPagination([ 'pageSize' => 10, ]); diff --git a/frontend/models/SMOClosed.php b/frontend/models/SMOClosed.php new file mode 100644 index 0000000..7990939 --- /dev/null +++ b/frontend/models/SMOClosed.php @@ -0,0 +1,353 @@ +n)) { + throw new InvalidParamException('Кількість СМО має бути цілим невід\'ємним числом'); + } else { + $this->k[ 0 ] = 0; + for($i = 1; $i <= $this->n; $i++) { + for($j = 1; $j <= $this->n; $j++) { + $this->p[ $i ][ $j ] = 0; + $this->r[ $i ] = 1; + $this->mu[ $i ] = 0; + } + } + } + } + + public function attributeLabels() + { + return [ + 'n' => 'Кількість систем масового обслуговування (n)', + 'N' => 'Кількість вимог в мережі масового обслуговування (N)', + 'p' => 'Матриця ймовірностей (pi,j)', + 'K' => 'Показники системи масового обслуговування (K)', + 'r' => 'Кількість каналів обслуговування (r)', + 'mu' => 'Інтенсивність обслуговування каналом (1/μ)', + 'e' => 'Коефіцієнт передачі (e)', + 'b' => 'Початкова СМО (e = 1)', + 'k' => 'Масив вимог', + 'probs' => 'Допоміжні функції pi(k)', + 'SMO' => 'Ймовірність перебування j вимоги в i-тій СМО PСМОi(j)', + 'C' => 'Нормуючий множник (C(N))', + 'L' => 'Середня кількість вимог у черзі СМОi (Li)', + 'R' => 'Середня кількість зайнятих пристроїв у СМОi (Ri)', + 'M' => 'Середня кількість вимог у СМОi (Mi)', + 'La' => 'Інтенсивність вихідного потоку вимог у СМОii)', + 'T' => 'Середній час перебування вимоги у СМОi (Ti)', + 'Q' => 'Середній час очікування у черзі СМОi (Qi)', + ]; + } + + public function rules() + { + return [ + [ + [ 'b' ], + 'required', + ], + [ + [ + 'N', + ], + 'integer', + 'min' => 1, + ], + [ + [ 'n' ], + 'integer', + 'min' => 2, + 'max' => 3, + 'message' => 'На даний момент допустимі значення кількості СМО лише 2 або 3', + ], + [ + [ + 'p', + 'mu', + ], + 'safe', + ], + [ + [ 'r' ], + 'each', + 'rule' => [ + 'integer', + 'min' => 1, + ], + ], + [ + [ 'mu' ], + 'each', + 'rule' => [ + 'number', + 'min' => 0, + ], + ], + [ + [ 'b' ], + 'integer', + 'min' => 1, + ], + [ + [ 'b' ], + 'compare', + 'compareAttribute' => 'n', + 'operator' => '<=', + ], + [ + [ 'b' ], + 'default', + 'value' => 1, + ], + ]; + } + + public function buildk() + { + if(!empty($this->N)) { + for($i = 1; $i <= $this->N; $i++) { + $this->k[$i] = $i; + } + } + } + + public function buildE($antiloop = true) + { + $this->e[ $this->b ] = 1; + for($k = 1; $k <= $this->n; $k++) { + if($k == $this->b) { + continue; + } else { + $this->e[ $k ] = ''; + } + } + foreach($this->p as $i => $vals) { + foreach($vals as $j => $val) { + if($j == $this->b) { + continue; + } + if($val != 0) { + $this->e[ $j ] .= '{' . $i . '};'; + } + } + } + do { + $iteration = 0; + $found = 0; + foreach($this->e as $i => $val) { + if(!preg_match('/\{\d\}/', $val)) { + foreach($this->e as $j => $value) { + if(preg_match('/\{' . $i . '\}/', $this->e[ $j ])) { + $this->e[ $j ] = preg_replace('/\{' . $i . '\}/', ( $this->p[ $i ][ $j ] * $val ), $this->e[ $j ]); + $found = 1; + } + } + } + } + if($antiloop) { + $iteration++; + } + } while($found && $iteration < 100); + foreach($this->e as $i => $val) { + if(strpos($val, ';') !== false) { + $this->e[ $i ] = array_sum(explode(';', $val)); + } + } + } + + public function buildProbs() + { + for($q = 1; $q <= $this->n; $q++) { + foreach($this->k as $k) { + $prob = pow($this->e[ $q ] * $this->mu[ $q ], $k); + if($k <= $this->r[ $q ]) { + $prob = $prob * 1 / $this->factorial($k); + } else { + $prob = $prob * 1 / $this->factorial($this->r[ $q ]) * pow($this->r[ $q ], ( $k - $this->r[ $q ] )); + } + $this->probs[ $q ][ $k ] = $prob; + unset( $prob ); + } + } + } + + public function factorial($x) + { + $x = intval($x); + if(!is_int($x) || $x < 0) { + throw new Exception('Factorial must be greater than 0'); + } + $res = 1; + for($i = 1; $i <= $x; $i++) { + $res *= $i; + } + return $res; + } + + public function buildC() + { + $result = 0; + if($this->n == 2) { + for($a = 0; $a <= $this->N; $a++) { + $result += $this->probs[1][$a] * $this->probs[2][$this->N - $a]; + } + } elseif($this->n == 3) { + for($a = 0; $a <= $this->N; $a++) { + $sum = 0; + for($b = 0; $b <= ( $this->N - $a ); $b++) { + $sum += $this->findSum($b, $a); + } + $result += $sum * $this->probs[ 1 ][ $a ]; + unset( $sum ); + } + } + $this->C = pow($result, ( -1 )); + } + + public function findSum($b, $a) + { + return $this->probs[ 2 ][ $b ] * $this->probs[ 3 ][ $this->N - $a - $b ]; + } + + public function buildSMO() + { + for($q = 1; $q <= $this->n; $q++) { + foreach($this->k as $k) { + $sum = 0; + if($this->n == 2) { + if($q == 1) { + $sum += $this->probs[1][$k]*$this->probs[2][$this->N - $k]; + } elseif($q == 2) { + $sum += $this->probs[1][$this->N - $k]*$this->probs[2][$k]; + } + } elseif($this->n == 3) { + for($a = 0; $a <= ($this->N - $k); $a++) { + if($q == 1) { + $sum += $this->probs[1][$k]*$this->probs[2][$a]*$this->probs[3][($this->N - $k - $a)]; + } elseif($q == 2) { + $sum += $this->probs[1][$a]*$this->probs[2][$k]*$this->probs[3][($this->N - $k - $a)]; + } elseif($q ===3) { + $sum += $this->probs[1][$a]*$this->probs[2][($this->N - $k - $a)]*$this->probs[3][$k]; + } + } + } + $this->SMO[$q][$k] = $sum*$this->C; + unset($sum); + } + } + } + + public function testSMO() + { + $message = ''; + foreach($this->SMO as $K => $vals) { + $message .= 'SUM of SMO'.$K.': '; + $sum = 0; + foreach($vals as $val) { + $sum += $val; + } + $message .= $sum.';
'; + unset($sum); + } + return $message; + } + + public function buildL() + { + for($i = 1; $i <= $this->n; $i++) { + $sum = 0; + for($j = ($this->r[$i] + 1); $j <= $this->N; $j++) { // Maybe error + $sum += ($j - $this->r[$i]) * $this->SMO[$i][$j]; + } + $this->L[$i] = $sum; + unset($sum); + } + } + + public function buildR() + { + for($i = 1; $i <= $this->n; $i++) { + $sum = 0; + for($j = 0; $j <= ($this->r[$i] - 1); $j++) { + $sum += ($this->r[$i] - $j) * $this->SMO[$i][$j]; + } + $sum = $this->r[$i] - $sum; + $this->R[$i] = $sum; + unset($sum); + } + } + + public function buildM() + { + for($i = 1; $i <= $this->n; $i++) { + $this->M[$i] = $this->L[$i] + $this->R[$i]; + } + } + + public function buildLa() + { + for($i = 1; $i <= $this->n; $i++) { + $this->La[$i] = $this->R[$i] * pow($this->mu[$i], (-1)); + } + } + + public function buildT() + { + for($i = 1; $i <= $this->n; $i++) { + $this->T[$i] = $this->M[$i] / $this->La[$i]; + } + } + + public function buildQ() + { + for($i = 1; $i <= $this->n; $i++) { + $this->Q[$i] = $this->L[$i] / $this->La[$i]; + } + } + } \ No newline at end of file diff --git a/frontend/views/accounts/_portfolio_form.php b/frontend/views/accounts/_portfolio_form.php index fe706b9..5270f8a 100644 --- a/frontend/views/accounts/_portfolio_form.php +++ b/frontend/views/accounts/_portfolio_form.php @@ -1,13 +1,16 @@

Добавить пользователя

'add_project_user_link' ]) ?>

+

Отправлено предложение:

render('@frontend/views/ajax/project_user', ['model' => $portfolioUser, 'user' => $portfolioUser->user]); - } + echo $this->render('@frontend/views/ajax/project_user', [ + 'model' => $portfolioUser, + 'user' => $portfolioUser->user, + ]); + } ?>
+ +

Подтвержденные:

+
+ render('@frontend/views/ajax/project_user', [ + 'model' => $portfolioUserConfirmed, + 'user' => $portfolioUserConfirmed->user, + ]); + } + ?> +
+
diff --git a/frontend/views/accounts/participant-edit.php b/frontend/views/accounts/participant-edit.php new file mode 100644 index 0000000..d5824b9 --- /dev/null +++ b/frontend/views/accounts/participant-edit.php @@ -0,0 +1,64 @@ +title = 'Редактирование участия в проекте'; + $this->params[ 'breadcrumbs' ][] = $this->title; +?> +
title ?>
+
+

Редактировать информацию о себе:

+ status != 1) { + ?> + + +
+ field($model, 'position') + ->textInput(); + echo $form->field($model, 'time') + ->input('number'); + ?> +
+

Добавить фотографию в личный альбом данного проекта:

+ status == 1 && !empty($model->gallery)) { + echo $form->field($model->portfolioGallery, 'caption')->textInput(); + echo Html::tag('div', ImageUploader::widget([ + 'model' => $model->gallery, + 'field' => 'photo', + 'size' => [ + [ + 'width' => 152, + 'height' => 108, + ], + ], + 'multi' => true, + 'gallery' => $model->gallery->photo, + 'name' => 'Загрузить фото галереи', + ]), [ 'class' => 'admin-gallery-photos-load-wr style' ]); + } else { + echo Html::tag('p', 'Для добавления фотографий Вы должны подтвердить свое участие'); + } + ?> +

+ end(); + ?> +

+
\ No newline at end of file diff --git a/frontend/views/accounts/participant.php b/frontend/views/accounts/participant.php new file mode 100644 index 0000000..e7b93e9 --- /dev/null +++ b/frontend/views/accounts/participant.php @@ -0,0 +1,131 @@ +title = 'Портфолио участник'; + $this->params[ 'breadcrumbs' ][] = $this->title; +?> +
title ?>
+
+ [ 'class' => 'style admin-all-pages-wr' ], + 'dataProvider' => $dataProvider, + 'filterModel' => $searchModel, + 'columns' => [ + [ + 'attribute' => 'project', + 'content' => function($model, $key, $index, $column) { + /** + * @var PortfolioUser $model + */ + $type = $model->portfolio->user->type; + $type_string = ( $type == 2 ) ? 'company' : 'performer'; + return Html::a($model->portfolio->name, [ + $type_string . '/portfolio-view', + $type_string . '_id' => $model->portfolio->user_id, + 'portfolio_id' => $model->portfolio->portfolio_id, + ], [ + 'target' => '_blank', + ]); + }, + ], + [ + 'attribute' => 'position', + 'value' => function($model, $key, $index, $column) { + /** + * @var PortfolioUser $model + * @var DataColumn $column + * @var int $key + * @var int $index + */ + if(empty( $model[ $column->attribute ] )) { + return NULL; + } else { + return $model[ $column->attribute ]; + } + }, + ], + [ + 'attribute' => 'time', + 'filter' => Html::tag('div', Html::activeInput('text', $searchModel, 'time_from', [ 'class' => 'form-control' ]), [ 'style' => 'width:70px;display:inline-block' ]) . Html::tag('div', Html::tag('i', '', [ + 'class' => 'glyphicon glyphicon-resize-horizontal', + 'style' => 'left:3px', + ]), [ 'style' => 'width:20px;display:inline-block;' ]) . Html::tag('div', Html::activeInput('text', $searchModel, 'time_to', [ 'class' => 'form-control' ]), [ 'style' => 'width:70px;display:inline-block' ]) . ( ( $searchModel->hasErrors('time_from') ) ? Html::error($searchModel, 'time_from', [ 'class' => 'help-block' ]) : '' ) . ( ( $searchModel->hasErrors('time_to') ) ? Html::error($searchModel, 'time_to', [ 'class' => 'help-block' ]) : '' ), + 'filterOptions' => [ + 'class' => ( $searchModel->hasErrors('time_from') || $searchModel->hasErrors('time_to') ) ? 'has-error' : '', + 'style' => 'width: 200px', + ], + ], + [ + 'attribute' => 'status', + 'filter' => [ + 1 => 'Подтверждено', + 2 => 'Ожидание', + ], + 'value' => function($model) { + if($model->status == 1) { + return 'Подтвержден'; + } elseif($model->status == 2) { + return 'В ожидании'; + } else { + return 'Неизвестный'; + } + }, + ], + [ + 'class' => ActionColumn::className(), + 'buttons' => [ + 'confirm' => function($url, $model, $key) { + return ( $model->status == 2 ) ? Html::a(Html::img('/images/tick.png', [ + 'width' => '15px', + 'height' => '15px', + ]), [ + 'accounts/participant-confirm', + 'id' => $model->portfolio_user_id, + ], [ + 'title' => 'Подтвердить', + 'aria-label' => 'Подтвердить', + 'data-confirm' => 'Вы уверены, что хотите подтвердить участие в данном проекте?', + 'data-method' => 'post', + 'data-pjax' => 0, + ]) : ''; + }, + 'edit' => function($url, $model, $key) { + return Html::a(Html::img('/images/ico_pencil.png'), [ + 'accounts/participant-edit', + 'id' => $model->portfolio_user_id, + ], [ + 'title' => 'Редактировать', + 'aria-label' => 'Редактировать', + 'data-pjax' => 0, + ]); + }, + 'deny' => function($url, $model, $key) { + return Html::a(Html::img('/images/delete-ico.png'), [ + 'accounts/participant-delete', + 'id' => $model->portfolio_user_id, + ], [ + 'title' => 'Удалить', + 'aria-label' => 'Удалить', + 'data-confirm' => 'Вы уверены, что хотите отказаться от участия в данном проекте?', + 'data-method' => 'post', + 'data-pjax' => 0, + ]); + }, + ], + 'template' => '{confirm}{edit}{deny}', + ], + ], + ]); ?> +
diff --git a/frontend/views/ajax/project_user.php b/frontend/views/ajax/project_user.php index 5ee44c7..6fa28f6 100644 --- a/frontend/views/ajax/project_user.php +++ b/frontend/views/ajax/project_user.php @@ -10,7 +10,7 @@ use yii\web\View; ?> -
+
status == 1) { echo 'data-portfolio="'.$model->portfolio_id.'"'; } ?>>
@@ -18,6 +18,12 @@

name, ['performer/common', 'performer_id' => $user->id], ['target' => '_blank'])?>

id}]user_id", ['value' => $user->id])?> + status == 1) { + echo Html::activeHiddenInput($model, "[{$user->id}]status", ['value' => $model->status]); + } + ?> + id}]user_id", ['value' => $user->id])?>
Yii::t('app', 'Должность: ')])?> diff --git a/frontend/views/layouts/admin.php b/frontend/views/layouts/admin.php index 29d1f58..5972666 100755 --- a/frontend/views/layouts/admin.php +++ b/frontend/views/layouts/admin.php @@ -17,7 +17,6 @@ $this->beginContent('@app/views/layouts/main.php');