diff --git a/components/LanguageBehavior.php b/components/LanguageBehavior.php index aa31ac82..2c57d292 100644 --- a/components/LanguageBehavior.php +++ b/components/LanguageBehavior.php @@ -42,6 +42,7 @@ public function applyLanguage($event): void Yii::$app->session->set('lang', $language); Yii::$app->language = $language; + // inite taşınacak foreach(Yii::$app->params['roles'] as $role => $roleDesc) { Yii::$app->params['roles'][$role] = Yii::t('app', $roleDesc); } diff --git a/components/MyMenu.php b/components/MyMenu.php index e55b6a5d..fb94a4fc 100644 --- a/components/MyMenu.php +++ b/components/MyMenu.php @@ -133,7 +133,7 @@ public static function getNavItems(): array public static function getLeftMenuItems(): array { if (Yii::$app->user->identity->user->superadmin) { - $businesses = Business::find()->orderBy('name')->all(); + $businesses = Business::find()->active()->orderBy('name')->all(); $items = []; foreach ($businesses as $business) { $isExpanded = ($business->slug === Yii::$app->request->get('slug')) ? true : false; @@ -152,16 +152,16 @@ public static function getLeftMenuItems(): array $businessStats = Yii::$app->cache->get($cacheKey); if ($businessStats === false) { $businessStats = [ - 'appointments' => $business->getAppointments()->count(), - 'resources' => $business->getResources()->count(), - 'rules' => $business->getRules()->count(), - 'services' => $business->getServices()->count(), + 'appointments' => $business->getAppointments()->active()->count(), + 'resources' => $business->getResources()->andWhere(['deleted_at' => null])->count(), + 'rules' => $business->getRules()->andWhere(['deleted_at' => null])->count(), + 'services' => $business->getServices()->andWhere(['deleted_at' => null])->count(), 'users' => [], ]; foreach (Yii::$app->params['roles'] as $key=>$value) { - $businessStats['users'][$key] = $business->getUsers($key)->count(); + $businessStats['users'][$key] = $business->getUsersByRole($key)->count(); } - Yii::$app->cache->set($cacheKey, $businessStats, 18400); + Yii::$app->cache->set($cacheKey, $businessStats, 86400); } $contents = [ @@ -172,7 +172,7 @@ public static function getLeftMenuItems(): array ], [ 'label' => Yii::t('app', 'Appointments').' '.$businessStats['appointments'].'', - 'url' => MyUrl::to(['business/appointment/'.$business->slug]), + 'url' => MyUrl::to(['appointment/view/'.$business->slug]), 'class' => $highlightedAction === 'appointment' ? 'list-group-item-info' : '', ], ]; diff --git a/config/i18n.php b/config/i18n.php index cb230b0e..90ffbfd5 100644 --- a/config/i18n.php +++ b/config/i18n.php @@ -9,7 +9,7 @@ // array, required, list of language codes that the extracted messages // should be translated to. For example, ['zh-CN', 'de']. 'languages' => [ - 'tr', + 'tr', // 'af', 'ar', 'az', 'be', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'el', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hi', // 'pt-BR', 'ro', 'hr', 'hu', 'hy', 'id', 'it', 'ja', 'ka', 'kk', 'ko', 'kz', 'lt', 'lv', 'ms', 'nb-NO', 'nl', // 'pl', 'pt', 'ru', 'sk', 'sl', 'sr', 'sr-Latn', 'sv', 'tg', 'th', 'tr', 'uk', 'uz', 'uz-Cy', 'vi', 'zh-CN', diff --git a/config/routes.php b/config/routes.php index 7b09f807..ac588a70 100644 --- a/config/routes.php +++ b/config/routes.php @@ -3,6 +3,8 @@ $langPattern = implode('|', array_keys($params['supportedLanguages'])); $roles = implode('|', array_keys($params['roles'])); +$businessActions = 'update|user|resource|rule|service'; + return [ '' => 'site/index', @@ -15,12 +17,15 @@ "/site/login/" => 'site/login', "/business/user//" => 'business/user', - "/business//" => 'business/', + "/business///" => 'business/', + "/business//" => 'business/', "/user/add///" => 'user/add', "/user/add//" => 'user/add', "/user//" => 'user/', + "/appointment//" => 'appointment/', + "//" => '/', '' => 'site/reroute', diff --git a/controllers/BusinessController.php b/controllers/BusinessController.php index d594171e..f1fce555 100644 --- a/controllers/BusinessController.php +++ b/controllers/BusinessController.php @@ -5,8 +5,12 @@ use app\components\LanguageBehavior; use app\components\MyUrl; use app\models\Business; +use app\models\Resource; +use app\models\Rule; +use app\models\Service; use app\models\User; use app\models\UserBusiness; +use Exception; use Throwable; use yii\base\InvalidConfigException; use yii\data\ActiveDataProvider; @@ -15,6 +19,8 @@ use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; use yii; +use yii\helpers\Inflector; + /** * BusinessController implements the CRUD actions for Business model. @@ -42,10 +48,22 @@ public function behaviors(): array ); } + private function findModel($slug = null, $id = null) + { + if ($slug === null && $id === null) { + throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.')); + } + $condition = $id ? ['id' => $id] : ['slug' => $slug]; + $model = Business::find()->active()->andWhere($condition)->one(); + if (!$model) { + throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.')); + } + return $model; + } + public function actionCreate(): yii\web\Response|string { $model = new Business(); - if ($this->request->isPost) { if ($model->load($this->request->post()) && $model->save()) { UserBusiness::addUserBusiness(Yii::$app->user->identity->user->id, $model->id, UserBusiness::ROLE_ADMIN); @@ -55,10 +73,7 @@ public function actionCreate(): yii\web\Response|string } else { $model->loadDefaultValues(); } - - return $this->render('create', [ - 'model' => $model, - ]); + return $this->render('create', ['model' => $model,]); } /** @@ -66,100 +81,67 @@ public function actionCreate(): yii\web\Response|string */ public function actionUpdate($slug): yii\web\Response|string { - $model = $this->findModel($slug); - - if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) { - Yii::$app->session->setFlash('info', Yii::t('app', 'Business updated')); - //return $this->goBack(); + $model = $this->findModel(slug:$slug); + if (!$model) { + throw new NotFoundHttpException(Yii::t('app','Business not found.')); + } + if ($this->request->isPost && $model->load($this->request->post())) { + if ($model->save()) { + Yii::$app->session->setFlash('info', Yii::t('app', 'Business updated')); + return $this->redirect(MyUrl::to(['business/update/'.$model->slug])); + } else { + Yii::$app->session->setFlash('error', Yii::t('app', 'Error updating business.')); + } } - return $this->render('update', ['model' => $model,]); } - /** - * @throws Throwable - * @throws NotFoundHttpException - */ - public function actionDelete($id): yii\web\Response + private function softDeleteRelations($model) { - $this->findModel($id)->softDelete(); - - return $this->goBack(); + foreach (['resources', 'services', 'rules'] as $relation) { + foreach ($model->$relation() as $related) { + if (!$related->softDelete()) { + return false; + } + } + } + $userBusinesses = UserBusiness::find()->where(['business_id' => $model->id]); + foreach ($userBusinesses as $userBusiness) { + if (!$userBusiness->delete()) { + return false; + } + } + return true; } /** + * @throws Throwable * @throws NotFoundHttpException */ - protected function findModel($slug): ?Business - { - if (($model = Business::findOne(['slug' => $slug])) !== null) { - return $model; - } - - throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.')); - } - - private function saveUserBusiness($model, $userBusiness, $user, $role): bool - { - if ($userBusiness->save()) { - Yii::$app->session->setFlash('info', Yii::t('app', '{user} role changed to {role} in {business}.', ['user' => $user->fullname, 'role' => $role, 'business' => $model->name])); - return true; - } else { - Yii::$app->session->setFlash('error', Yii::t('app', 'Error changing {user} role in {business}.', ['user' => $user->fullname, 'business' => $model->name])); - return false; - } - } - - private function removeUserFromBusiness($model, $userBusiness, $user): bool - { - if (!$userBusiness) { - Yii::$app->session->setFlash('warning', Yii::t('app', '{user} not in {business}.', ['user' => $user->fullname, 'business' => $model->name])); - return false; - } - - if ($userBusiness->softDelete()) { - Yii::$app->session->setFlash('info', Yii::t('app', '{user} removed from {business}.', ['user' => $user->fullname, 'business' => $model->name])); - return true; - } else { - Yii::$app->session->setFlash('error', Yii::t('app', 'Error removing {user} from {business}.', ['user' => $user->fullname, 'business' => $model->name])); - return false; - } - } - - private function assignUserToBusiness($model, $userBusiness, $user, $role): bool - { - if ($userBusiness && $userBusiness->role === $role) { - Yii::$app->session->setFlash('warning', Yii::t('app', '{user} already in {business} {role} role.', ['user' => $user->fullname, 'business' => $model->name, 'role' => $role])); - return false; - } - - if (!$userBusiness) { - $userBusiness = new UserBusiness(['user_id' => $user->id, 'business_id' => $model->id, 'role' => $role]); - } else { - $userBusiness->role = $role; - } - - return $this->saveUserBusiness($model, $userBusiness, $user, $role); - } - - private function changeUserRole($model, $userBusiness, $user, $postRole): bool + public function actionDelete($id): yii\web\Response { - if (!in_array($postRole, array_keys(Yii::$app->params['roles']))) { - Yii::$app->session->setFlash('error', Yii::t('app', 'Invalid role.')); - return false; + $model = $this->findModel(id:$id); + if (!$model) { + throw new NotFoundHttpException(Yii::t('app','Business not found.')); } - - if (!$userBusiness) { - $userBusiness = new UserBusiness(['user_id' => $user->id, 'business_id' => $model->id, 'role' => $postRole]); - } else { - if ($userBusiness->role === $postRole) { - Yii::$app->session->setFlash('warning', Yii::t('app', '{user} already in {business} {role} role.', ['user' => $user->fullname, 'business' => $model->name, 'role' => $postRole])); - return false; + $transaction = Yii::$app->db->beginTransaction(); + try { + if ($model->appointments->active()->count() > 0) { + throw new Exception(Yii::t('app', 'Cannot delete business with active appointments.')); + } + if (!$this->softDeleteRelations($model)) { + throw new Exception(Yii::t('app', 'Error deleting related entities.')); + } + if (!$model->softDelete()) { + throw new Exception(Yii::t('app', 'Error deleting business.')); } - $userBusiness->role = $postRole; + $transaction->commit(); + Yii::$app->session->setFlash('info', Yii::t('app', 'Business deleted')); + } catch (Exception $e) { + $transaction->rollBack(); + Yii::$app->session->setFlash('error', $e->getMessage()); } - - return $this->saveUserBusiness($model, $userBusiness, $user, $postRole); + return $this->goBack(); } /** @@ -170,26 +152,33 @@ private function handleBusinessUserChange($model, $role): bool { $userId = $this->request->post('id'); if (!$userId) { - throw new BadRequestHttpException(Yii::t('app', 'Posted values are missing.')); + throw new BadRequestHttpException(Yii::t('app', 'User ID is missing.')); } - $user = User::findOne($userId); + $user = User::find()->where(['id'=>$userId])->active()->one(); if (!$user) { throw new NotFoundHttpException(Yii::t('app', 'User not found.')); } + if (!Yii::$app->user->identity->user->superadmin && Yii::$app->user->identity->user->id === $user->id) { + throw new BadRequestHttpException(Yii::t('app', 'You cannot change your own business role.')); + } $postRole = $this->request->post('role') ?? '__addnew__'; - $userBusiness = UserBusiness::findOne(['user_id' => $user->id, 'business_id' => $model->id]); + $userBusiness = UserBusiness::find()->where(['user_id' => $user->id, 'business_id' => $model->id])->one(); if ($postRole === 'delete') { - return $this->removeUserFromBusiness($model, $userBusiness, $user); + return $userBusiness ? $userBusiness->delete() : false; } if ($postRole === '__addnew__') { - return $this->assignUserToBusiness($model, $userBusiness, $user, $role); + return $userBusiness ? $userBusiness->reassignUserBusiness($role) : UserBusiness::addUserBusiness($user->id, $model->id, $role); + } + + if (!array_key_exists($postRole, Yii::$app->params['roles'])) { + throw new BadRequestHttpException(Yii::t('app', 'Invalid role.')); } - return $this->changeUserRole($model, $userBusiness, $user, $postRole); + return $userBusiness ? $userBusiness->reassignUserBusiness($postRole) : UserBusiness::addUserBusiness($user->id, $model->id, $postRole); } /** @@ -197,93 +186,147 @@ private function handleBusinessUserChange($model, $role): bool * @throws NotFoundHttpException * @throws BadRequestHttpException */ - public function actionUser($role, $slug): string + public function actionUser($role, $slug) { - if (!($model = Business::find()->where(['slug' => $slug])->one())) { + $model = Business::find()->where(['slug' => $slug])->one(); + if (!$model) { throw new NotFoundHttpException(Yii::t('app', 'Business not found.')); } - if (!in_array($role, array_keys(Yii::$app->params['roles']))) { + if (!array_key_exists($role, Yii::$app->params['roles'])) { throw new BadRequestHttpException(Yii::t('app', 'Invalid role.')); } if ($this->request->isPost) { - $this->handleBusinessUserChange($model, $role); + try { + $this->handleBusinessUserChange($model, $role); + Yii::$app->session->setFlash('info', Yii::t('app', 'User role updated.')); + return $this->redirect(MyUrl::to(['business/user/'.$role.'/'.$model->slug])); + } catch (Exception $e) { + Yii::$app->session->setFlash('error', $e->getMessage()); + } } - $dataProvider = new ActiveDataProvider([ - 'query' => $model->getUsers($role), - 'pagination' => ['pageSize' => 10], - 'sort' => [ - 'defaultOrder' => [ - 'first_name' => SORT_ASC, // Adjust according to your User model attributes and needs - ] - ], - ]); + return $this->render('business_users', [ 'model' => $model, - 'dataProvider' => $dataProvider, + 'dataProvider' => new ActiveDataProvider([ + 'query' => $model->getUsersByRole($role)->active(), + 'pagination' => ['pageSize' => 10], + ]), 'role' => $role, ]); + + } + + private function handleDeleteRelation($slug, $id, $relatedModel, $relation) + { + if ($this->request->get('delete')) { + if ($this->request->get('delete')!==$id) { + throw new BadRequestHttpException(Yii::t('app', 'Posted values are missing.')); + } + if ($relatedModel->isNewRecord) { + throw new NotFoundHttpException(Yii::t('app', 'Relation not found.')); + } + if ($relatedModel->softDelete()) { + Yii::$app->session->setFlash('info', Yii::t('app', 'Relation deleted.')); + return $this->redirect(MyUrl::to(["business/$relation/$slug"])); + } + Yii::$app->session->setFlash('error', Yii::t('app', 'Error deleting relation.').implode(' ', $relatedModel->getErrorSummary(true))); + } else { + $relatedModel->load(Yii::$app->request->post()); + if ($relatedModel->validate() && $relatedModel->save()) { + Yii::$app->session->setFlash('info', Yii::t('app', 'Relation saved.')); + return $this->redirect(MyUrl::to(["business/$relation/$slug"])); + } + Yii::$app->session->setFlash('error', Yii::t('app', 'Error saving relation.').implode(' ', $relatedModel->getErrorSummary(true))); + } } - public function actionResource($slug): string + public function actionResource($slug, $id = null) { if (!($model = Business::find()->where(['slug' => $slug])->one())) { throw new NotFoundHttpException(Yii::t('app', 'Business not found.')); } - - $dataProvider = new ActiveDataProvider([ - 'query' => $model->getResources(), - 'pagination' => ['pageSize' => 10], - 'sort' => [ - 'defaultOrder' => [ - 'name' => SORT_ASC, // Adjust according to your Resource model attributes and needs - ] - ], - ]); - return $this->render('business_resources', [ + + $resource = Resource::find()->where(['id' => $id])->one() ?? new Resource(['business_id' => $model->id]); + + if ($id && $resource->isNewRecord) { + Yii::$app->session->setFlash('warning', Yii::t('app', 'URL inconsistency detected. Are you trying to load a bookmarked page?')); + } + + if ($this->request->isPost) { + $this->handleDeleteRelation($slug, $id, $resource, 'resource'); + } + + return $this->render('business_relations', [ 'model' => $model, - 'dataProvider' => $dataProvider, + 'dataProvider' => new ActiveDataProvider([ + 'query' => $model->getResources()->andWhere(['deleted_at' => null]), + 'pagination' => ['pageSize' => 10], + ]), + 'relation' => 'resource', + 'relationModel' => $resource, + 'relationTitle' => Yii::t('app', 'Resources'), + 'relationCreateTitle' => Yii::t('app', 'Create Resource'), + 'relationColumns' => ['name', 'resource_type'], ]); } - public function actionRule($slug): string + public function actionRule($slug, $id = null) { if (!($model = Business::find()->where(['slug' => $slug])->one())) { throw new NotFoundHttpException(Yii::t('app', 'Business not found.')); } - $dataProvider = new ActiveDataProvider([ - 'query' => $model->getRules(), - 'pagination' => ['pageSize' => 10], - 'sort' => [ - 'defaultOrder' => [ - 'name' => SORT_ASC, // Adjust according to your Resource model attributes and needs - ] - ], - ]); - return $this->render('business_rules', [ + $rule = Rule::find()->where(['id' => $id])->one() ?? new Rule(['business_id' => $model->id]); + + if ($id && $rule->isNewRecord) { + Yii::$app->session->setFlash('warning', Yii::t('app', 'URL inconsistency detected. Are you trying to load a bookmarked page?')); + } + + if ($this->request->isPost) { + $this->handleDeleteRelation($slug, $id, $rule, 'rule'); + } + + return $this->render('business_relations', [ 'model' => $model, - 'dataProvider' => $dataProvider, + 'dataProvider' => new ActiveDataProvider([ + 'query' => $model->getRules()->andWhere(['deleted_at' => null]), + 'pagination' => ['pageSize' => 10], + ]), + 'relation' => 'rule', + 'relationModel' => $rule, + 'relationTitle' => Yii::t('app', 'Rules'), + 'relationCreateTitle' => Yii::t('app', 'Create Rule'), + 'relationColumns' => ['name', 'ruleset'], ]); } - public function actionService($slug): string + public function actionService($slug, $id = null) { if (!($model = Business::find()->where(['slug' => $slug])->one())) { throw new NotFoundHttpException(Yii::t('app', 'Business not found.')); } - $dataProvider = new ActiveDataProvider([ - 'query' => $model->getServices(), - 'pagination' => ['pageSize' => 10], - 'sort' => [ - 'defaultOrder' => [ - 'name' => SORT_ASC, // Adjust according to your Resource model attributes and needs - ] - ], - ]); - return $this->render('business_services', [ + $service = Service::find()->where(['id' => $id])->one() ?? new Service(['business_id' => $model->id]); + + if ($id && $service->isNewRecord) { + Yii::$app->session->setFlash('warning', Yii::t('app', 'URL inconsistency detected. Are you trying to load a bookmarked page?')); + } + + if ($this->request->isPost) { + $this->handleDeleteRelation($slug, $id, $service, 'service'); + } + + return $this->render('business_relations', [ 'model' => $model, - 'dataProvider' => $dataProvider, + 'dataProvider' => new ActiveDataProvider([ + 'query' => $model->getServices()->andWhere(['deleted_at' => null]), + 'pagination' => ['pageSize' => 10], + ]), + 'relation' => 'service', + 'relationModel' => $service, + 'relationTitle' => Yii::t('app', 'Services'), + 'relationCreateTitle' => Yii::t('app', 'Create Service'), + 'relationColumns' => ['name', 'resource_type', 'expert_type', 'duration'], ]); } diff --git a/controllers/SiteController.php b/controllers/SiteController.php index 537d51c6..97463e85 100644 --- a/controllers/SiteController.php +++ b/controllers/SiteController.php @@ -235,7 +235,7 @@ public function actionVerifygsm(): Response|array|string public function actionIndex(): Response|string { if (!Yii::$app->user->isGuest) { - $authidentity = Yii::$app->user->identity; + $authidentity = Yii::$app->user->identity; $messages = []; if (!$authidentity->user->tcnoverified) { @@ -314,7 +314,7 @@ public function actionLogin($s = null): Response|array|string $sms_otp = Authidentity::generateSmsPin($model->gsm); Yii::$app->session->setFlash('info', "*********** $sms_otp ************"); if ($sms_otp !== false) { - if ($sms_otp !==true ) { sleep(1); /* send sms via external api call, to be implemented */ } + if ($sms_otp !==true ) { sleep(0); /* send sms via external api call, to be implemented */ } $model->scenario=LoginForm::SCENARIO_SMS_VALIDATE; } else { $model->addError('gsm', Yii::t('app', 'Unable to send an SMS')); diff --git a/controllers/UserController.php b/controllers/UserController.php index 92c1dc8e..20a6ffa8 100644 --- a/controllers/UserController.php +++ b/controllers/UserController.php @@ -56,7 +56,7 @@ public function behaviors(): array */ public function actionAdd(): Response|array|string { - if (!Yii::$app->request->get('slug') || !($business = Business::findOne(['slug' => Yii::$app->request->get('slug')]))) { + if (!Yii::$app->request->get('slug') || !($business = Business::find()->where(['slug' => Yii::$app->request->get('slug')])->active()->one())) { throw new Exception(Yii::t('app', 'Invalid business.')); } if (!Yii::$app->request->get('role') || !in_array(Yii::$app->request->get('role'), array_keys(Yii::$app->params['roles']))) { @@ -149,7 +149,7 @@ public function actionUpdate($id = null): Response|array|string Yii::$app->session->set('oldUrl', Yii::$app->request->referrer); } - if (!($user = User::findOne($id))) { + if (!($user = User::find()->where(['id'=>$id])->active()->one())) { throw new Exception(Yii::t('app', 'User not found.')); } @@ -235,7 +235,7 @@ public function actionSearch(): string throw new Exception('Invalid role.'); } - if (!($business = Business::findOne($business_id))) { + if (!($business = Business::find()->where(['id'=>$business_id])->active()->one())) { throw new Exception('Invalid business.'); } diff --git a/messages/tr/app.php b/messages/tr/app.php index 9a1e68f5..bc1d768d 100644 --- a/messages/tr/app.php +++ b/messages/tr/app.php @@ -17,81 +17,89 @@ * NOTE: this file must be saved in UTF-8 encoding. */ return [ - 'Actions' => 'İşlemler', 'Add New User' => 'Yeni Kullanıcı', + 'Add Service' => '@@Servis Ekle@@', 'Add User' => 'Kullanıcı Ekle', 'Admin' => 'Yönetici', - 'Admins' => 'Yöneticiler', 'An error occurred.' => 'Bir şeyler ters gitti.', 'Appointment ID' => '', 'Appointment SAAS' => 'Randevu SAAS', 'Appointments' => 'Randevular', - 'Are you sure you want to add this user?' => '', - 'Business' => 'İşletme', + 'Are you sure you want to add this user?' => 'Bu kullanıcıyı eklemek istediğinize emin misiniz?', + 'Are you sure you want to delete this resource?' => 'Bu kaynağı silmek istediğinize emin misiniz?', + 'Are you sure you want to delete this rule?' => '', + 'Are you sure you want to delete this service?' => '', 'Business ID' => 'İşletme Id', 'Business Name' => 'İşletme Adı', 'Business Settings' => 'İşletme Ayarları', + 'Business created' => 'İşletme oluşturuldu', + 'Business deleted' => '', 'Business not found.' => 'İşletme bulunamadı.', 'Business updated' => 'İşletme güncellendi', 'Businesses' => 'İşletmeler', + 'Cannot delete business with active appointments.' => '', 'Change Password' => 'Parola değiştir', 'Check your e-mail for a login link.' => 'Giriş bağlantısı için e-postanızı kontrol edin.', 'Click here to verify.' => 'Onaylamak için buraya tıklayın.', 'Coming soon...' => 'Çok yakında...', + 'Create' => 'Ekle', 'Create Business' => 'Yeni İşletme', 'Create New Appointment' => 'Yeni Randevu Oluştur', - 'Create New Business' => 'Yeni İşletme Ekle', - 'Create New User' => 'Yeni Kullanıcı Ekle', + 'Create Resource' => 'Yeni Kaynak', + 'Create Rule' => '', 'Created At' => 'Oluşturulma Zamanı', 'Customer' => 'Müşteri', - 'Customers' => 'Müşteriler', 'Date' => 'Tarih', 'Delete' => 'Sil', 'Deleted At' => 'Silinme Zamanı', 'Duration' => '', 'E-mail' => 'E-posta', 'E-mail not registered or invalid password.' => 'Geçersiz e-posta veya parola', + 'Edit' => 'Düzenle', 'End Time' => '', - 'Error adding {user} to {business}.' => '', - 'Error changing {user} role in {business}.' => '', - 'Error creating {user}.' => '', - 'Error removing {user} from {business}.' => '', + 'Error adding {user} to {business}.' => '{user} {business} ilişkilendirilirken hata oluştu.', + 'Error changing {user} role in {business}.' => '@@@@', + 'Error creating {user}.' => '{user} oluşturulamadı.', + 'Error deleting business.' => '', + 'Error deleting related entities.' => '', + 'Error deleting resource.' => '', + 'Error deleting rule.' => '', + 'Error deleting service.' => '', + 'Error removing {user} from {business}.' => '@@@@', + 'Error saving resource.' => 'Kaynak kaydedilemedi', + 'Error saving rule.' => '', + 'Error saving service.' => '', + 'Error updating business.' => '', 'Event' => '', 'Event Type' => '', 'Expert' => 'Uzman', - 'Expert Type' => '', - 'Experts' => 'Uzmanlar', + 'Expert Type' => 'Uzman Tipi', 'Expires' => '', 'Extra' => '', 'First Name' => 'Ad', 'Force Reset' => '', 'Full Name' => 'Tam Ad', - 'Full language support for all pages.' => '', 'GSM Number' => 'Cep Telefonu', 'Guest' => 'Misafir', 'ID' => '', 'Id Type' => '', 'Identifier' => '', - 'Incorrect password.' => 'Hatalı parola', - 'Invalid business.' => '', - 'Invalid role.' => '', + 'Invalid business.' => 'Geçersiz işletme.', + 'Invalid role.' => 'Geçersiz rol.', 'Ip Address' => 'IP Adresi', 'Last Name' => 'Soyad', 'Last Used At' => '', 'Latest Changes' => 'Son Değişiklikler', 'Link' => 'Bağlantı', - 'List Businesses' => 'İşletmeler', - 'List Users' => 'Kullanıcılar', 'Log out successful. See you soon.' => 'Çıkış başarılı. Tekrar görüşmek dileğiyle.', - 'Logging support for all changes in base models.' => '', - 'Login' => 'Giriş', 'Login successful.' => 'Giriş başarılı', 'Login with Link' => 'Bağlantı ile Giriş', 'Login with Password' => 'Parola ile Giriş', 'Login with SMS' => 'SMS ile Giriş', 'Login/verification successful.' => 'Giriş/doğrulama başarılı.', 'Logout' => 'Çıkış', - 'Name' => 'Ad', + 'Logs automatically retrieved every 5 minutes' => 'Her 5 dakikada bir güncellenir', + 'Name' => '@@Ad@@', 'New User' => 'Yeni Kullanıcı', 'No Role' => 'Rol Yok', 'OTP' => 'OTP', @@ -105,28 +113,35 @@ 'Please update your profile.' => 'Lütfen bilgilerinizi kontrol edin.', 'Please verify your GSM number.' => 'Lütfen GSM numaranızı onaylatın.', 'Please verify your e-mail.' => 'Lütfen e-posta adresinizi onaylatın.', - 'Posted values are missing.' => '', - 'Preparation for user access level support.' => '', + 'Posted values are missing.' => 'Form öğeleri eksik.', 'Request Login with SMS' => 'SMS ile Giriş Talep', - 'Reset' => 'Sıfırla', - 'Reset User Password' => 'Kullanıcı Parola Değiştir', + 'Resource' => 'Kaynak', 'Resource ID' => '', - 'Resource Type' => '', + 'Resource Type' => 'Kaynak Tipi', + 'Resource deleted.' => '', + 'Resource not found.' => '', + 'Resource saved.' => 'Kaynak kaydedildi.', 'Resources' => 'Kaynaklar', 'Role' => 'Rol', + 'Rule Name' => 'Kural Adı', + 'Rule Set' => 'Kural Seti', + 'Rule deleted.' => '', + 'Rule not found.' => '', + 'Rule saved.' => '', 'Rules' => 'Kurallar', 'SMS' => 'SMS', 'SMS OTP' => 'SMS OTP', 'SMS Verify' => 'SMS Doğrula', 'Save' => 'Kaydet', - 'Search' => 'Ara', 'Search users...' => 'Kullanıcı ara...', 'Secret' => 'Şifre', - 'Secretaries' => 'Sekreterler', 'Secretary' => 'Sekreter', 'Send Link' => 'Bağlantı Gönder', 'Send SMS' => 'SMS Gönder', - 'Server/service timezone independent solid global date/time.' => '', + 'Service Name' => '', + 'Service deleted.' => '', + 'Service not found.' => '', + 'Service saved.' => '', 'Services' => 'Hizmetler', 'Sign Up' => 'Kayıt Ol', 'Start Time' => '', @@ -141,6 +156,7 @@ 'Timezone' => 'Saat dilimi', 'Token invalid or expired.' => 'Anahtar geçersiz veya eskimiş.', 'Type' => 'Tip', + 'URL inconsistency detected. Are you trying to load a bookmarked page?' => '', 'Unable to authenticate' => 'Giriş yapılamadı', 'Unable to create Auth credentials.' => '', 'Unable to create User.' => 'Kullanıcı oluşturulamadı.', @@ -148,13 +164,16 @@ 'Unable to send an SMS' => 'SMS gönderilemedi', 'Unable to update password.' => 'Parola güncellenemedi.', 'Unknown error:' => 'Bilinmeyen hata:', + 'Update' => 'Güncelle', 'Update User' => 'Kullanıcı Güncelle', 'Updated At' => '', 'User Agent' => '', 'User ID' => '', + 'User ID is missing.' => '', 'User Information' => 'Kullanıcı Bilgileri', 'User has been registered successfully.' => 'Yeni kullanıcı başarıyla kaydedildi ve oturum açıldı.', - 'User not found.' => '', + 'User not found.' => 'Kullanıcı bulunamadı.', + 'User role updated.' => '', 'Users' => 'Kullanıcılar', 'Verify GSM' => 'GSM numaranızı onaylatın', 'Welcome' => 'Hoşgeldiniz', @@ -163,9 +182,10 @@ 'Your GSM number is not verified.' => 'GSM numaranız onaylanmadı', 'Your T.C. No is not verified.' => 'T.C. kimlik numaranız onaylanmadı', 'Your e-mail address is not verified.' => 'E-posta adresiniz onaylanmadı', - '{user} already in {business} {role} role.' => '{user} zaten {business} {role} rolünde.', + '{user} already in {business} {role} role.' => '@@{user} zaten {business} {role} rolünde.@@', '{user} created and added to {business} {role} role.' => '{user} oluşturuldu ve {business} {role} rolü eklendi.', - '{user} not in {business}.' => '{user} {business} ile ilişkili değil.', - '{user} removed from {business}.' => '{user} ile {business} ilişiği kesildi.', - '{user} role changed to {role} in {business}.' => '{user} {business} rolü {role} olarak değiştirildi.', + '{user} has been updated successfully.' => '{user} başarıyla güncellendi.', + '{user} not in {business}.' => '@@{user} {business} ile ilişkili değil.@@', + '{user} removed from {business}.' => '@@{user} ile {business} ilişiği kesildi.@@', + '{user} role changed to {role} in {business}.' => '@@{user} {business} rolü {role} olarak değiştirildi.@@', ]; diff --git a/models/Appointment.php b/models/Appointment.php index 0e76f5b0..c7d9f7f5 100644 --- a/models/Appointment.php +++ b/models/Appointment.php @@ -6,10 +6,8 @@ use yii\base\InvalidConfigException; use yii\db\ActiveQuery; use yii\db\ActiveRecord; -use app\models\query\AppointmentQuery; -use app\models\query\AppointmentResourceQuery; -use app\models\query\AppointmentUserQuery; -use app\models\query\BusinessQuery; +use app\models\queries\AppointmentQuery; +use app\models\queries\BusinessQuery; use app\components\LogBehavior; /** @@ -28,6 +26,7 @@ class Appointment extends ActiveRecord { use traits\SoftDeleteTrait; + use traits\BusinessCacheTrait; public static function tableName(): string { @@ -74,7 +73,7 @@ public function behaviors(): array /** * @throws InvalidConfigException */ - public function getResources(): ActiveQuery|AppointmentResourceQuery + public function getResources(): ActiveQuery { return $this->hasMany(Resource::class, ['id' => 'resource_id']) ->viaTable(AppointmentResource::tableName(), ['appointment_id' => 'id']); @@ -83,7 +82,7 @@ public function getResources(): ActiveQuery|AppointmentResourceQuery /** * @throws InvalidConfigException */ - public function getUsers(): ActiveQuery|AppointmentUserQuery + public function getUsers(): ActiveQuery { return $this->hasMany(User::class, ['id' => 'user_id']) ->viaTable(AppointmentUser::tableName(), ['appointment_id' => 'id']); diff --git a/models/AppointmentResource.php b/models/AppointmentResource.php index fb8c4679..28f8b7cc 100644 --- a/models/AppointmentResource.php +++ b/models/AppointmentResource.php @@ -68,13 +68,9 @@ public function getAppointment(): ActiveQuery|AppointmentQuery return $this->hasOne(Appointment::class, ['id' => 'appointment_id'])->inverseOf('appointmentResources'); } - public function getResource(): ActiveQuery|ResourceQuery + public function getResource(): ActiveQuery { return $this->hasOne(Resource::class, ['id' => 'resource_id'])->inverseOf('appointmentResources'); } - public static function find(): AppointmentResourceQuery - { - return new AppointmentResourceQuery(get_called_class()); - } } diff --git a/models/AppointmentUser.php b/models/AppointmentUser.php index 8643efb0..19c50bdc 100644 --- a/models/AppointmentUser.php +++ b/models/AppointmentUser.php @@ -5,9 +5,8 @@ use Yii; use yii\db\ActiveQuery; use yii\db\ActiveRecord; -use app\models\query\AppointmentQuery; -use app\models\query\AppointmentUserQuery; -use app\models\query\UserQuery; +use app\models\queries\AppointmentQuery; +use app\models\queries\UserQuery; use app\components\LogBehavior; @@ -75,8 +74,4 @@ public function getUser(): ActiveQuery|UserQuery return $this->hasOne(User::class, ['id' => 'user_id'])->inverseOf('appointmentUsers'); } - public static function find(): AppointmentUserQuery - { - return new AppointmentUserQuery(get_called_class()); - } } diff --git a/models/Authidentity.php b/models/Authidentity.php index 74b05eb3..0d8db17c 100644 --- a/models/Authidentity.php +++ b/models/Authidentity.php @@ -9,8 +9,7 @@ use yii\db\ActiveRecord; use yii\db\Expression; use yii\web\IdentityInterface; -use app\models\query\AuthidentityQuery; -use app\models\query\UserQuery; +use app\models\queries\UserQuery; use app\components\LogBehavior; @@ -88,11 +87,6 @@ public function getUser(): ActiveQuery|UserQuery return $this->hasOne(User::class, ['id' => 'user_id'])->inverseOf('authidentities'); } - public static function find(): AuthidentityQuery - { - return new AuthidentityQuery(get_called_class()); - } - public static function findIdentityByAccessToken($token, $type = null): Authidentity|null { // Function required by Yii2 User interface $candidates = Authidentity::find() @@ -173,7 +167,7 @@ public function validatePassword($password): bool */ public static function generateEmailToken($email): string|null { - if ($user = User::findOne(['email' => $email])) { + if ($user = User::find()->where(['email' => $email])->active()->one()) { if (self::getActiveTokenCount($user->id, self::AUTHTYPE_EMAIL_TOKEN) > 2) { return true; } @@ -199,7 +193,7 @@ public static function generateEmailToken($email): string|null */ public static function generateSmsPin($gsm): string|bool { - if ($user = User::findOne(['gsm' => $gsm])) { + if ($user = User::find()->where(['gsm' => $gsm])->active()->one()) { if (self::getActiveTokenCount($user->id, self::AUTHTYPE_SMS_OTP)) { return true; } diff --git a/models/Business.php b/models/Business.php index fd27fcc0..04a31f26 100644 --- a/models/Business.php +++ b/models/Business.php @@ -2,14 +2,11 @@ namespace app\models; +use app\models\queries\UserQuery; use DateTimeZone; use Yii; -use app\models\query\AppointmentQuery; -use app\models\query\BusinessQuery; -use app\models\query\PermissionQuery; -use app\models\query\ResourceQuery; -use app\models\query\RuleQuery; -use app\models\query\ServiceQuery; +use app\models\queries\AppointmentQuery; +use app\models\queries\BusinessQuery; use app\components\LogBehavior; use yii\base\InvalidConfigException; use yii\db\ActiveQuery; @@ -106,35 +103,50 @@ public function getAppointments(): ActiveQuery|AppointmentQuery return $this->hasMany(Appointment::class, ['business_id' => 'id'])->inverseOf('business'); } - public function getResources(): ActiveQuery|ResourceQuery + public function getResources(): ActiveQuery { return $this->hasMany(Resource::class, ['business_id' => 'id'])->inverseOf('business'); } - public function getRules(): ActiveQuery|RuleQuery + public function getRules(): ActiveQuery { return $this->hasMany(Rule::class, ['business_id' => 'id'])->inverseOf('business'); } - public function getServices(): ActiveQuery|ServiceQuery + public function getServices(): ActiveQuery { return $this->hasMany(Service::class, ['business_id' => 'id'])->inverseOf('business'); } - /** - * @throws InvalidConfigException - */ - public function getUsers($role = null): ActiveQuery + public function getUserBusinesses(): ActiveQuery { - $query = $this->hasMany(User::class, ['id' => 'user_id']) + return $this->hasMany(UserBusiness::class, ['business_id' => 'id'])->inverseOf('business'); + } + + public function getUsers() + { + return $this->hasMany(User::class, ['id' => 'user_id']) ->viaTable(UserBusiness::tableName(), ['business_id' => 'id']); - if ($role !== null) { - $userIDs = UserBusiness::find() - ->select('user_id') - ->where(['role' => $role, 'business_id' => $this->id]); - $query->andWhere(['id' => $userIDs]); + } + + public function getUsersByRole($role) + { + if (!array_key_exists($role, Yii::$app->params['roles'])) { + throw new InvalidConfigException('Invalid role'); } + + $query = $this->getUsers(); + + $userIDs = UserBusiness::find() + ->select('user_id') + ->where([ + 'role' => $role, + 'business_id' => $this->id + ]) + ->asArray()->column(); + + $query->andWhere(['id' => $userIDs]); return $query; } @@ -144,17 +156,18 @@ public static function find(): BusinessQuery return new BusinessQuery(get_called_class()); } - public function getPermissions(): ActiveQuery|PermissionQuery + public function getPermissions(): ActiveQuery { return $this->hasMany(Permission::class, ['business_id' => 'id'])->inverseOf('business'); } - public function getAvailableUsers($role): query\UserQuery + public function getAvailableUsers($role) { $linkedUserIds = UserBusiness::find() ->select('user_id') -// ->where(['business_id' => $this->id, 'role' => $role]); - ->where(['business_id' => $this->id]); + ->where(['business_id' => $this->id]) + ->asArray() + ->column(); return User::find() ->where(['not in', 'id', $linkedUserIds]) diff --git a/models/LogBase.php b/models/LogBase.php index 9a29ed1d..16496c84 100644 --- a/models/LogBase.php +++ b/models/LogBase.php @@ -3,7 +3,6 @@ namespace app\models; use Yii; -use app\models\query\LogBaseQuery; use yii\db\ActiveRecord; /** @@ -127,13 +126,4 @@ public static function log($event_type, array $data): void $log->save(); } - /** - * {@inheritdoc} - * @return LogBaseQuery the active query used by this AR class. - */ - public static function find(): LogBaseQuery - { - return new LogBaseQuery(get_called_class()); - } - } diff --git a/models/Login.php b/models/Login.php index 501701e8..8f82048a 100644 --- a/models/Login.php +++ b/models/Login.php @@ -57,11 +57,6 @@ public function getUser(): ActiveQuery|UserQuery return $this->hasOne(User::class, ['id' => 'user_id'])->inverseOf('logins'); } - public static function find(): LoginQuery - { - return new LoginQuery(get_called_class()); - } - public static function log($id_type, $identifier, $success): void { $login = new self(); diff --git a/models/Permission.php b/models/Permission.php index d7f877e0..0b8800ec 100644 --- a/models/Permission.php +++ b/models/Permission.php @@ -3,7 +3,6 @@ namespace app\models; use Yii; -use app\models\query\PermissionQuery; use app\models\query\UserQuery; use app\models\query\BusinessQuery; use yii\db\ActiveQuery; @@ -64,8 +63,4 @@ public static function hasPermission($userId, $permission): bool return self::find()->where(['user_id' => $userId, 'permission' => $permission])->exists(); } - public static function find(): PermissionQuery - { - return new PermissionQuery(get_called_class()); - } } diff --git a/models/Resource.php b/models/Resource.php index 7639e3a9..5b9286dc 100644 --- a/models/Resource.php +++ b/models/Resource.php @@ -5,7 +5,6 @@ use Yii; use app\models\query\AppointmentQuery; use app\models\query\BusinessQuery; -use app\models\query\ResourceQuery; use app\components\LogBehavior; use yii\base\InvalidConfigException; use yii\db\ActiveQuery; @@ -26,6 +25,7 @@ class Resource extends ActiveRecord { use traits\SoftDeleteTrait; + use traits\BusinessCacheTrait; public static function tableName(): string { @@ -84,8 +84,4 @@ public function getBusiness(): ActiveQuery|BusinessQuery return $this->hasOne(Business::class, ['id' => 'business_id'])->inverseOf('resources'); } - public static function find(): ResourceQuery - { - return new ResourceQuery(get_called_class()); - } } diff --git a/models/Rule.php b/models/Rule.php index 7882d584..ac254f05 100644 --- a/models/Rule.php +++ b/models/Rule.php @@ -3,8 +3,7 @@ namespace app\models; use Yii; -use app\models\query\RuleQuery; -use app\models\query\BusinessQuery; +use app\models\queries\BusinessQuery; use app\components\LogBehavior; use yii\db\ActiveQuery; use yii\db\ActiveRecord; @@ -22,6 +21,7 @@ class Rule extends ActiveRecord { use traits\SoftDeleteTrait; + use traits\BusinessCacheTrait; public static function tableName(): string { @@ -69,8 +69,4 @@ public function getBusiness(): ActiveQuery|BusinessQuery return $this->hasOne(Business::class, ['id' => 'business_id'])->inverseOf('rules'); } - public static function find(): RuleQuery - { - return new RuleQuery(get_called_class()); - } } diff --git a/models/Service.php b/models/Service.php index cd20c740..02e400be 100644 --- a/models/Service.php +++ b/models/Service.php @@ -3,7 +3,6 @@ namespace app\models; use Yii; -use app\models\query\ServiceQuery; use app\models\query\BusinessQuery; use app\components\LogBehavior; use yii\db\ActiveQuery; @@ -25,6 +24,8 @@ class Service extends ActiveRecord { use traits\SoftDeleteTrait; + use traits\BusinessCacheTrait; + public static function tableName(): string { @@ -48,7 +49,7 @@ public function attributeLabels(): array return [ 'id' => Yii::t('app', 'ID'), 'business_id' => Yii::t('app', 'Business ID'), - 'name' => Yii::t('app', 'Name'), + 'name' => Yii::t('app', 'Service Name'), 'resource_type' => Yii::t('app', 'Resource Type'), 'expert_type' => Yii::t('app', 'Expert Type'), 'duration' => Yii::t('app', 'Duration'), @@ -75,8 +76,4 @@ public function getBusiness(): ActiveQuery|BusinessQuery return $this->hasOne(Business::class, ['id' => 'business_id'])->inverseOf('services'); } - public static function find(): ServiceQuery - { - return new ServiceQuery(get_called_class()); - } } diff --git a/models/User.php b/models/User.php index 15d0f901..e48694a2 100644 --- a/models/User.php +++ b/models/User.php @@ -3,12 +3,8 @@ namespace app\models; use Yii; -use app\models\query\UserQuery; -use app\models\query\AuthidentityQuery; -use app\models\query\LoginQuery; -use app\models\query\BusinessQuery; -use app\models\query\PermissionQuery; -use app\models\query\AppointmentUserQuery; +use app\models\queries\UserQuery; +use app\models\queries\BusinessQuery; use app\components\LogBehavior; use yii\base\InvalidConfigException; use yii\db\ActiveQuery; @@ -88,18 +84,18 @@ public function attributeLabels(): array /** * @throws InvalidConfigException */ - public function getAppointments(): ActiveQuery|AppointmentUserQuery + public function getAppointments(): ActiveQuery { return $this->hasMany(Appointment::class, ['id' => 'appointment_id']) ->viaTable(AppointmentUser::tableName(), ['user_id' => 'id']); } - public function getAuthidentities(): ActiveQuery|AuthidentityQuery + public function getAuthidentities(): ActiveQuery { return $this->hasMany(Authidentity::class, ['user_id' => 'id'])->inverseOf('user'); } - public function getLogins(): ActiveQuery|LoginQuery + public function getLogins(): ActiveQuery { return $this->hasMany(Login::class, ['user_id' => 'id'])->inverseOf('user'); } @@ -113,7 +109,7 @@ public function getBusinesses(): ActiveQuery|BusinessQuery ->viaTable(UserBusiness::tableName(), ['user_id' => 'id']); } - public function getPermissions(): ActiveQuery|PermissionQuery + public function getPermissions(): ActiveQuery { return $this->hasMany(Permission::class, ['user_id' => 'id'])->inverseOf('user'); } diff --git a/models/UserBusiness.php b/models/UserBusiness.php index 4894fa38..0d70308f 100644 --- a/models/UserBusiness.php +++ b/models/UserBusiness.php @@ -2,12 +2,12 @@ namespace app\models; +use InvalidArgumentException; use Yii; use yii\db\ActiveQuery; use yii\db\ActiveRecord; -use app\models\query\UserBusinessQuery; -use app\models\query\UserQuery; -use app\models\query\BusinessQuery; +use app\models\queries\UserQuery; +use app\models\queries\BusinessQuery; use app\components\LogBehavior; @@ -16,13 +16,12 @@ * @property int $user_id * @property int $business_id * @property string $created_at - * @property string|null $deleted_at * @property Business $business * @property User $user */ class UserBusiness extends ActiveRecord { - use traits\SoftDeleteTrait; + use traits\BusinessCacheTrait; const ROLE_ADMIN = 'admin'; const ROLE_SECRETARY = 'secretary'; @@ -39,7 +38,7 @@ public function rules(): array return [ [['user_id', 'business_id'], 'required'], [['user_id', 'business_id'], 'integer'], - [['created_at', 'deleted_at'], 'safe'], + [['created_at'], 'safe'], [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::class, 'targetAttribute' => ['user_id' => 'id']], [['business_id'], 'exist', 'skipOnError' => true, 'targetClass' => Business::class, 'targetAttribute' => ['business_id' => 'id']], ]; @@ -53,7 +52,6 @@ public function attributeLabels(): array 'role' => Yii::t('app', 'Role'), 'business_id' => Yii::t('app', 'Business ID'), 'created_at' => Yii::t('app', 'Created At'), - 'deleted_at' => Yii::t('app', 'Deleted At'), ]; } @@ -63,34 +61,26 @@ public function behaviors(): array 'logBehavior' => [ 'class' => LogBehavior::class, 'eventTypeCreate' => LogBase::EVENT_USER_BUSINESS_ADDED, - 'eventTypeUpdate' => LogBase::EVENT_USER_BUSINESS_UPDATED, + 'eventTypeUpdate' => null, 'eventTypeDelete' => LogBase::EVENT_USER_BUSINESS_DELETED, ], ]; } - public function getBusiness(): ActiveQuery|BusinessQuery + public function reassignUserBusiness($role): bool { - return $this->hasOne(Business::class, ['id' => 'business_id']); - } - - public function getUser(): ActiveQuery|UserQuery - { - return $this->hasOne(User::class, ['id' => 'user_id']); + $this->role = $role; + return $this->save(false, ['role']); } public static function addUserBusiness($userId, $businessId, $role): bool { - $userBusiness = static::findOne(['user_id' => $userId, 'business_id' => $businessId]); + $userBusiness = static::find()->where(['user_id' => $userId, 'business_id' => $businessId])->one(); if ($userBusiness) { - if($userBusiness->deleted_at) { - $userBusiness->deleted_at = null; - return $userBusiness->save(); - } else { - return false; - } + throw new InvalidArgumentException('User already assigned to business'); } + $userBusiness = new UserBusiness([ 'user_id' => $userId, 'business_id' => $businessId, @@ -99,36 +89,30 @@ public static function addUserBusiness($userId, $businessId, $role): bool return $userBusiness->save(); } - public function afterSave($insert, $changedAttributes): void - { - parent::afterSave($insert, $changedAttributes); - $cacheKey = 'business_'.$this->business_id.'_stats'; - Yii::$app->cache->delete($cacheKey); - } - public static function deleteUserBusiness($userId, $businessId): bool { - if (!Yii::$app->user->identity->user->superadmin && Yii::$app->user->identity->user->id === $userId) { - return false; - } - - $userBusiness = static::findOne(['user_id' => $userId, 'business_id' => $businessId, 'deleted_at' => null]); + $userBusiness = static::find()->where(['user_id' => $userId, 'business_id' => $businessId])->one(); if ($userBusiness) { - return $userBusiness->softDelete(); + return $userBusiness->delete(); } return false; } - public static function find(): UserBusinessQuery - { - return new UserBusinessQuery(get_called_class()); - } - public static function exists($business_id, $user_id): bool { return static::find() - ->where(['business_id' => $business_id, 'user_id' => $user_id, 'deleted_at' => null]) + ->where(['business_id' => $business_id, 'user_id' => $user_id]) ->exists(); } + public function getBusiness(): ActiveQuery|BusinessQuery + { + return $this->hasOne(Business::class, ['id' => 'business_id']); + } + + public function getUser(): ActiveQuery|UserQuery + { + return $this->hasOne(User::class, ['id' => 'user_id']); + } + } diff --git a/models/query/AppointmentQuery.php b/models/queries/AppointmentQuery.php similarity index 75% rename from models/query/AppointmentQuery.php rename to models/queries/AppointmentQuery.php index 5c0d385f..227e9aaa 100644 --- a/models/query/AppointmentQuery.php +++ b/models/queries/AppointmentQuery.php @@ -1,13 +1,16 @@ andWhere('[[status]]=1'); - }*/ - + use SoftDeleteQueryTrait; + public function all($db = null): User|array { return parent::all($db); @@ -22,4 +23,5 @@ public function one($db = null): User|array|null { return parent::one($db); } + } diff --git a/models/query/AppointmentResourceQuery.php b/models/query/AppointmentResourceQuery.php deleted file mode 100644 index 4f83ef62..00000000 --- a/models/query/AppointmentResourceQuery.php +++ /dev/null @@ -1,20 +0,0 @@ -andWhere('[[status]]=1'); - }*/ - - /** - * {@inheritdoc} - * @return LogBase[]|array - */ - public function all($db = null): array - { - return parent::all($db); - } - - public function one($db = null): array|ActiveRecord|null - { - return parent::one($db); - } -} diff --git a/models/query/LoginQuery.php b/models/query/LoginQuery.php deleted file mode 100644 index db65e15a..00000000 --- a/models/query/LoginQuery.php +++ /dev/null @@ -1,20 +0,0 @@ -business_id.'_stats'; + Yii::$app->cache->delete($cacheKey); + } + + public function afterSave($insert, $changedAttributes): void + { + parent::afterSave($insert, $changedAttributes); + $this->deleteCache(); + } + + public function afterDelete(): void + { + parent::afterDelete(); + $this->deleteCache(); + } + + +} diff --git a/models/traits/SoftDeleteQueryTrait.php b/models/traits/SoftDeleteQueryTrait.php new file mode 100644 index 00000000..0064782b --- /dev/null +++ b/models/traits/SoftDeleteQueryTrait.php @@ -0,0 +1,19 @@ +andWhere(['deleted_at' => null]); + } + + public function deleted(): ActiveQuery + { + return $this->andWhere(['not', ['deleted_at' => null]]); + } + +} diff --git a/models/traits/SoftDeleteTrait.php b/models/traits/SoftDeleteTrait.php index 0d9f15fd..63445127 100644 --- a/models/traits/SoftDeleteTrait.php +++ b/models/traits/SoftDeleteTrait.php @@ -7,40 +7,31 @@ trait SoftDeleteTrait { - /** - * Softly deletes a record by setting its `deleted_at` attribute to the current timestamp. - */ public function softDelete(): bool { if ($this->hasAttribute('deleted_at')) { $this->deleted_at = new Expression('NOW()'); return $this->save(false, ['deleted_at']); } - return false; } - /** - * Modifies the ActiveQuery used by the model to exclude soft-deleted records by default. - */ - public static function find(): ActiveQuery + public function softUndelete(): bool { - return parent::find()->andWhere(['deleted_at' => null]); + if ($this->hasAttribute('deleted_at')) { + $this->deleted_at = null; + return $this->save(false, ['deleted_at']); + } + return false; } - /** - * Adds a method to the ActiveQuery for including soft-deleted records in the results. - */ - public static function findIncludingDeleted(): ActiveQuery + public static function findActive($condition) { - return parent::find(); + return static::find()->andWhere($condition)->andWhere(['deleted_at' => null]); } - /** - * Adds a method to the ActiveQuery for exclusively querying soft-deleted records. - */ - public static function findOnlyDeleted(): ActiveQuery + public static function findDeleted($condition) { - return parent::find()->andWhere(['not', ['deleted_at' => null]]); + return static::find()->andWhere($condition)->andWhere(['not', ['deleted_at' => null]]); } } diff --git a/models/traits/UserTrait.php b/models/traits/UserTrait.php index cc7c223b..38426a6b 100644 --- a/models/traits/UserTrait.php +++ b/models/traits/UserTrait.php @@ -13,7 +13,7 @@ public function commonRules(): array [['gsmverified', 'emailverified', 'tcnoverified'], 'boolean'], [['status', 'status_message'], 'string', 'max' => 255], [['first_name', 'last_name'], 'string', 'max' => 100], - [['tcno'], 'string', 'max' => 11, 'min' => 11], + [['tcno'], 'string', 'max' => 11], // [['gsm'], 'string', 'max' => 10, 'min' => 10], [['email'], 'email'], [['email'], 'unique', 'targetClass' => '\app\models\User', 'message' => 'This email has already been taken.', @@ -30,7 +30,6 @@ public function commonRules(): array $query->andWhere(['<>', 'id', $id]); } }], - ]; } diff --git a/views/business/_relation_widget.php b/views/business/_relation_widget.php new file mode 100644 index 00000000..b2af108a --- /dev/null +++ b/views/business/_relation_widget.php @@ -0,0 +1,65 @@ + "ResourceGrid".$model->id, + 'timeout' => 10000, + 'enablePushState' => false, + 'clientOptions' => ['method' => 'POST'] +]); + +$slug = $model->slug; +$relation = true ? $relation : ''; + +try { + $content = GridView::widget([ + 'dataProvider' => $dataProvider, + 'columns' => [ + ...$relationColumns, + [ + 'class' => 'yii\grid\Column', + 'content' => function ($model, $key, $index, $column) use ($relation, $slug) {/** @var string $relation */ + $editUrl = MyUrl::to(["business/$relation/$slug/$model->id"]); + $deleteUrl = MyUrl::to(["business/$relation/$slug/$model->id", 'delete' => $model->id]); + $editButton = Html::a(Yii::t('app', 'Edit'), $editUrl, [ + 'class' => 'btn btn-light border border-primary btn-sm mb-1', + 'data' => [ + 'pjax' => 0, + ] + ]); + $deleteButton = Html::a(Yii::t('app', 'Delete'), $deleteUrl, [ + 'class' => 'btn btn-danger btn-sm mb-1 ml-2', + 'data' => [ + 'confirm' => Yii::t('app', 'Are you sure you want to delete this resource?'), + 'method' => 'post', + 'pjax' => 0, + ], + ]); + return "$editButton $deleteButton"; + }, + ], + ], + 'pager' => [ + 'class' => yii\bootstrap5\LinkPager::class, + ], + + ]); +} catch (Throwable $e) { +} + +echo Card::widget([ + 'title' => $relationTitle, + 'content' => $content, +]); + +Pjax::end(); \ No newline at end of file diff --git a/views/business/_resource_form.php b/views/business/_resource_form.php new file mode 100644 index 00000000..5d2ea3de --- /dev/null +++ b/views/business/_resource_form.php @@ -0,0 +1,21 @@ +field($relationModel, 'name')->textInput(['maxlength' => true]); +$content .= $form->field($relationModel, 'resource_type')->textInput(['maxlength' => true]); +$content .= Html::submitButton( + $relationModel->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), + ['class' => 'btn btn-primary'] +); +echo Card::widget([ + 'title' => '', + 'content' => $content, +]); +ActiveForm::end(); \ No newline at end of file diff --git a/views/business/_resource_widget.php b/views/business/_resource_widget.php deleted file mode 100644 index f37a50f8..00000000 --- a/views/business/_resource_widget.php +++ /dev/null @@ -1,49 +0,0 @@ - "ResourceGrid".$model->id, // unique ID for the Pjax widget to target this specific grid - 'timeout' => 10000, // timeout in milliseconds, adjust as needed - 'enablePushState' => false, // do not change URL - 'clientOptions' => ['method' => 'POST'] // use POST method for the requests, adjust as needed -]); - -$slug = $model->slug; - -try { - $content = GridView::widget([ - 'dataProvider' => $dataProvider, - 'columns' => [ - 'name', - 'resource_type', - [ - 'class' => 'yii\grid\Column', - 'content' => function ($model, $key, $index, $column) use ($slug) { - $url2 = MyUrl::to(["user/update/$model->id"]); - return - Html::a(Yii::t('app', 'Edit'), $url2, ['class' => 'btn btn-light border border-primary btn-sm mb-1']); - }, - ], - ], - 'pager' => [ - 'class' => yii\bootstrap5\LinkPager::class, // Use Bootstrap 5 LinkPager - ], - - ]); -} catch (Throwable $e) { -} - -echo Card::widget([ - 'title' => $model->name.' '.Yii::t('app', 'Resources'), - 'content' => $content, -]); - -Pjax::end(); - diff --git a/views/business/_rule_form.php b/views/business/_rule_form.php new file mode 100644 index 00000000..c795c3a5 --- /dev/null +++ b/views/business/_rule_form.php @@ -0,0 +1,21 @@ +field($relationModel, 'name')->textInput(['maxlength' => true]); +$content .= $form->field($relationModel, 'ruleset')->textInput(['maxlength' => true]); +$content .= Html::submitButton( + $relationModel->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), + ['class' => 'btn btn-primary'] +); +echo Card::widget([ + 'title' => '', + 'content' => $content, +]); +ActiveForm::end(); \ No newline at end of file diff --git a/views/business/_rule_widget.php b/views/business/_rule_widget.php deleted file mode 100644 index 41cc908a..00000000 --- a/views/business/_rule_widget.php +++ /dev/null @@ -1,49 +0,0 @@ - "RuleGrid".$model->id, // unique ID for the Pjax widget to target this specific grid - 'timeout' => 10000, // timeout in milliseconds, adjust as needed - 'enablePushState' => false, // do not change URL - 'clientOptions' => ['method' => 'POST'] // use POST method for the requests, adjust as needed -]); - -$slug = $model->slug; - -try { - $content = GridView::widget([ - 'dataProvider' => $dataProvider, - 'columns' => [ - 'name', - 'ruleset', - [ - 'class' => 'yii\grid\Column', - 'content' => function ($model, $key, $index, $column) use ($slug) { - $url2 = MyUrl::to(["user/update/$model->id"]); - return - Html::a(Yii::t('app', 'Edit'), $url2, ['class' => 'btn btn-light border border-primary btn-sm mb-1']); - }, - ], - ], - 'pager' => [ - 'class' => yii\bootstrap5\LinkPager::class, - ], - - ]); -} catch (Throwable $e) { -} - -echo Card::widget([ - 'title' => $model->name.' '.Yii::t('app', 'Rules'), - 'content' => $content, -]); - -Pjax::end(); - diff --git a/views/business/_service_form.php b/views/business/_service_form.php new file mode 100644 index 00000000..36a782e0 --- /dev/null +++ b/views/business/_service_form.php @@ -0,0 +1,48 @@ +getResources()->andWhere(['deleted_at' => null])->all(), 'resource_type', 'resource_type'); +//$expertTypes = ArrayHelper::map(ExpertType::find()->all(), 'id', 'name'); + +$form = ActiveForm::begin(); +$content = $form->field($relationModel, 'name')->textInput(['maxlength' => true]); +//$content .= $form->field($relationModel, 'resource_type')->textInput(['maxlength' => true]); +$content .= $form->field($relationModel, 'resource_type')->dropDownList($resourceTypes, ['prompt' => Yii::t('app', 'Select Resource Type')]); +$content .= $form->field($relationModel, 'expert_type')->textInput(['maxlength' => true]); +//$content .= $form->field($relationModel, 'duration')->textInput(['maxlength' => true]); +//$content .= ''; + +// Add a Bootstrap 5 range slider for duration +$content .= $form->field($relationModel, 'duration')->input('range', [ + 'min' => 5, + 'max' => 300, + 'step' => 1, + 'oninput' => 'updateDurationValue(this.value)', + 'class' => 'form-range' +]); +// Display the current value of the slider +$content .= '
' . Html::encode($relationModel->duration ?: 5) . '
'; + +$content .= Html::submitButton( + $relationModel->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), + ['class' => 'btn btn-primary'] +); +echo Card::widget([ + 'title' => '', + 'content' => $content, +]); +ActiveForm::end(); +// Include JavaScript to update the display as the slider value changes +$this->registerJs(" + function updateDurationValue(value) { + document.getElementById('duration-value-display').textContent = value; + } +", \yii\web\View::POS_HEAD); diff --git a/views/business/_service_widget.php b/views/business/_service_widget.php deleted file mode 100644 index 600c7074..00000000 --- a/views/business/_service_widget.php +++ /dev/null @@ -1,51 +0,0 @@ - "ServiceGrid".$model->id, // unique ID for the Pjax widget to target this specific grid - 'timeout' => 10000, // timeout in milliseconds, adjust as needed - 'enablePushState' => false, // do not change URL - 'clientOptions' => ['method' => 'POST'] // use POST method for the requests, adjust as needed -]); - -$slug = $model->slug; - -try { - $content = GridView::widget([ - 'dataProvider' => $dataProvider, - 'columns' => [ - 'name', - 'resource_type', - 'expert_type', - 'duration', - [ - 'class' => 'yii\grid\Column', - 'content' => function ($model, $key, $index, $column) use ($slug) { - $url2 = MyUrl::to(["user/update/$model->id"]); - return - Html::a(Yii::t('app', 'Edit'), $url2, ['class' => 'btn btn-light border border-primary btn-sm mb-1']); - }, - ], - ], - 'pager' => [ - 'class' => yii\bootstrap5\LinkPager::class, - ], - - ]); -} catch (Throwable $e) { -} - -echo Card::widget([ - 'title' => $model->name.' '.Yii::t('app', 'Services'), - 'content' => $content, -]); - -Pjax::end(); - diff --git a/views/business/_user_widget.php b/views/business/_user_widget.php index 809c8e4e..52ec58c5 100644 --- a/views/business/_user_widget.php +++ b/views/business/_user_widget.php @@ -10,10 +10,10 @@ /** @var \app\models\Business $model */ Pjax::begin([ - 'id' => "UsersGrid".$model->id, // unique ID for the Pjax widget to target this specific grid - 'timeout' => 10000, // timeout in milliseconds, adjust as needed - 'enablePushState' => false, // do not change URL - 'clientOptions' => ['method' => 'POST'] // use POST method for the requests, adjust as needed + 'id' => "UsersGrid".$model->id, + 'timeout' => 10000, + 'enablePushState' => false, + 'clientOptions' => ['method' => 'POST'] ]); $slug = $model->slug; diff --git a/views/business/business_relations.php b/views/business/business_relations.php new file mode 100644 index 00000000..22f522a7 --- /dev/null +++ b/views/business/business_relations.php @@ -0,0 +1,30 @@ +title = Html::encode($model->name).' '.$relationTitle; +?> + +
+
+ render('_relation_widget', [ + 'model' => $model, + 'dataProvider' => $dataProvider, + 'relationColumns' => $relationColumns, + 'relationTitle' => $relationTitle, + 'relation' => $relation + ]) + ?> + render("_{$relation}_form", ['model' => $model, 'relationModel' => $relationModel]) ?> + isNewRecord) ? Html::a($relationCreateTitle, MyUrl::to(["business/$relation/$model->slug"]), ['class' => 'btn btn-primary']) : '' ?> +
+
diff --git a/views/business/business_resources.php b/views/business/business_resources.php deleted file mode 100644 index f3b2e561..00000000 --- a/views/business/business_resources.php +++ /dev/null @@ -1,17 +0,0 @@ -title = Html::encode($model->name).' '.Yii::t('app', 'Resources'); -?> - -
-
- render('_resource_widget', ['model' => $model, 'dataProvider' => $dataProvider]) ?> -render('_resource_search_widget', ['model' => $model]) ?> */ ?> - slug"]), ['class' => 'btn btn-primary btn-outline-light']) ?> -
-
diff --git a/views/business/business_rules.php b/views/business/business_rules.php deleted file mode 100644 index 446b6212..00000000 --- a/views/business/business_rules.php +++ /dev/null @@ -1,17 +0,0 @@ -title = Html::encode($model->name).' '.Yii::t('app', 'Rules'); -?> - -
-
- render('_rule_widget', ['model' => $model, 'dataProvider' => $dataProvider]) ?> -render('_resource_search_widget', ['model' => $model]) ?> */ ?> - slug"]), ['class' => 'btn btn-primary btn-outline-light']) ?> -
-
diff --git a/views/business/business_services.php b/views/business/business_services.php deleted file mode 100644 index 56b34dff..00000000 --- a/views/business/business_services.php +++ /dev/null @@ -1,17 +0,0 @@ -title = Html::encode($model->name).' '.Yii::t('app', 'Services'); -?> - -
-
- render('_service_widget', ['model' => $model, 'dataProvider' => $dataProvider]) ?> -render('_resource_search_widget', ['model' => $model]) ?> */ ?> - slug"]), ['class' => 'btn btn-primary btn-outline-light']) ?> -
-
diff --git a/views/business/business_users.php b/views/business/business_users.php index d5d5aff3..c0d321d7 100644 --- a/views/business/business_users.php +++ b/views/business/business_users.php @@ -4,7 +4,6 @@ /** @var \app\models\Business $model */ /** @var \yii\data\ActiveDataProvider $dataProvider */ -/** @var string $role */ $this->title = Html::encode($model->name).' '.Yii::t('app', Yii::$app->params['roles'][$role]); ?>