create project

This commit is contained in:
Kavalar 2024-04-24 18:02:58 +03:00
commit 17df2ce6a9
276 changed files with 15932 additions and 0 deletions

3
.bowerrc Normal file
View File

@ -0,0 +1,3 @@
{
"directory" : "vendor/bower-asset"
}

45
.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
# yii console commands
/yii
/yii_test
/yii_test.bat
# phpstorm project files
.idea
# netbeans project files
nbproject
# zend studio for eclipse project files
.buildpath
.project
.settings
# windows thumbnail cache
Thumbs.db
# composer vendor dir
/vendor
# composer itself is not needed
composer.phar
# Mac DS_Store Files
.DS_Store
# phpunit itself is not needed
phpunit.phar
# local phpunit config
/phpunit.xml
# vagrant runtime
/.vagrant
# ignore generated files
/frontend/web/index.php
/frontend/web/index-test.php
/frontend/web/robots.txt
/backend/web/index.php
/backend/web/index-test.php
/backend/web/robots.txt
/log

29
LICENSE.md Normal file
View File

@ -0,0 +1,29 @@
Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

60
README.md Normal file
View File

@ -0,0 +1,60 @@
<p align="center">
<a href="https://github.com/yiisoft" target="_blank">
<img src="https://avatars0.githubusercontent.com/u/993323" height="100px">
</a>
<h1 align="center">Yii 2 Advanced Project Template</h1>
<br>
</p>
Yii 2 Advanced Project Template is a skeleton [Yii 2](https://www.yiiframework.com/) application best for
developing complex Web applications with multiple tiers.
The template includes three tiers: front end, back end, and console, each of which
is a separate Yii application.
The template is designed to work in a team development environment. It supports
deploying the application in different environments.
Documentation is at [docs/guide/README.md](docs/guide/README.md).
[![Latest Stable Version](https://img.shields.io/packagist/v/yiisoft/yii2-app-advanced.svg)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
[![Total Downloads](https://img.shields.io/packagist/dt/yiisoft/yii2-app-advanced.svg)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
[![build](https://github.com/yiisoft/yii2-app-advanced/workflows/build/badge.svg)](https://github.com/yiisoft/yii2-app-advanced/actions?query=workflow%3Abuild)
DIRECTORY STRUCTURE
-------------------
```
common
config/ contains shared configurations
mail/ contains view files for e-mails
models/ contains model classes used in both backend and frontend
tests/ contains tests for common classes
console
config/ contains console configurations
controllers/ contains console controllers (commands)
migrations/ contains database migrations
models/ contains console-specific model classes
runtime/ contains files generated during runtime
backend
assets/ contains application assets such as JavaScript and CSS
config/ contains backend configurations
controllers/ contains Web controller classes
models/ contains backend-specific model classes
runtime/ contains files generated during runtime
tests/ contains tests for backend application
views/ contains view files for the Web application
web/ contains the entry script and Web resources
frontend
assets/ contains application assets such as JavaScript and CSS
config/ contains frontend configurations
controllers/ contains Web controller classes
models/ contains frontend-specific model classes
runtime/ contains files generated during runtime
tests/ contains tests for frontend application
views/ contains view files for the Web application
web/ contains the entry script and Web resources
widgets/ contains frontend widgets
vendor/ contains dependent 3rd-party packages
environments/ contains environment-based overrides
```

88
Vagrantfile vendored Normal file
View File

@ -0,0 +1,88 @@
require 'yaml'
require 'fileutils'
required_plugins_installed = nil
required_plugins = %w( vagrant-hostmanager vagrant-vbguest )
required_plugins.each do |plugin|
unless Vagrant.has_plugin? plugin
system "vagrant plugin install #{plugin}"
required_plugins_installed = true
end
end
# IF plugin[s] was just installed - restart required
if required_plugins_installed
# Get CLI command[s] and call again
system 'vagrant' + ARGV.to_s.gsub(/\[\"|\", \"|\"\]/, ' ')
exit
end
domains = {
frontend: 'y2aa-frontend.test',
backend: 'y2aa-backend.test'
}
config = {
local: './vagrant/config/vagrant-local.yml',
example: './vagrant/config/vagrant-local.example.yml'
}
# copy config from example if local config not exists
FileUtils.cp config[:example], config[:local] unless File.exist?(config[:local])
# read config
options = YAML.load_file config[:local]
# check github token
if options['github_token'].nil? || options['github_token'].to_s.length != 40
puts "You must place REAL GitHub token into configuration:\n/yii2-app-advanced/vagrant/config/vagrant-local.yml"
exit
end
# vagrant configurate
Vagrant.configure(2) do |config|
# select the box
config.vm.box = 'bento/ubuntu-18.04'
# should we ask about box updates?
config.vm.box_check_update = options['box_check_update']
config.vm.provider 'virtualbox' do |vb|
# machine cpus count
vb.cpus = options['cpus']
# machine memory size
vb.memory = options['memory']
# machine name (for VirtualBox UI)
vb.name = options['machine_name']
end
# machine name (for vagrant console)
config.vm.define options['machine_name']
# machine name (for guest machine console)
config.vm.hostname = options['machine_name']
# network settings
config.vm.network 'private_network', ip: options['ip']
# sync: folder 'yii2-app-advanced' (host machine) -> folder '/app' (guest machine)
config.vm.synced_folder './', '/app', owner: 'vagrant', group: 'vagrant'
# disable folder '/vagrant' (guest machine)
config.vm.synced_folder '.', '/vagrant', disabled: true
# hosts settings (host machine)
config.vm.provision :hostmanager
config.hostmanager.enabled = true
config.hostmanager.manage_host = true
config.hostmanager.ignore_private_ip = false
config.hostmanager.include_offline = true
config.hostmanager.aliases = domains.values
# provisioners
config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone'], options['ip']]
config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false
config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always'
# post-install message (vagrant console)
config.vm.post_up_message = "Frontend URL: http://#{domains[:frontend]}\nBackend URL: http://#{domains[:backend]}"
end

4
backend/Dockerfile Normal file
View File

@ -0,0 +1,4 @@
FROM yiisoftware/yii2-php:8.1-apache
# Change document root for Apache
RUN sed -i -e 's|/app/web|/app/backend/web|g' /etc/apache2/sites-available/000-default.conf

View File

@ -0,0 +1,23 @@
<?php
namespace backend\assets;
use yii\web\AssetBundle;
/**
* Main backend application asset bundle.
*/
class AppAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap5\BootstrapAsset',
];
}

15
backend/codeception.yml Normal file
View File

@ -0,0 +1,15 @@
namespace: backend\tests
actor_suffix: Tester
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
bootstrap: _bootstrap.php
settings:
colors: true
memory_limit: 1024M
modules:
config:
Yii2:
configFile: 'config/codeception-local.php'

4
backend/config/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
codeception-local.php
main-local.php
params-local.php
test-local.php

View File

@ -0,0 +1 @@
<?php

54
backend/config/main.php Normal file
View File

@ -0,0 +1,54 @@
<?php
$params = array_merge(
require __DIR__ . '/../../common/config/params.php',
require __DIR__ . '/../../common/config/params-local.php',
require __DIR__ . '/params.php',
require __DIR__ . '/params-local.php'
);
return [
'id' => 'app-backend',
'basePath' => dirname(__DIR__),
'controllerNamespace' => 'backend\controllers',
'bootstrap' => ['log'],
'modules' => [
'company' => [
'class' => 'backend\modules\company\Company',
],
],
'components' => [
'request' => [
'csrfParam' => '_csrf-backend',
],
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true],
],
'session' => [
// this is the name of the session cookie used for login on the backend
'name' => 'advanced-backend',
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => \yii\log\FileTarget::class,
'levels' => ['error', 'warning'],
],
],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
],
'params' => $params,
];

View File

@ -0,0 +1,4 @@
<?php
return [
'adminEmail' => 'admin@example.com',
];

15
backend/config/test.php Normal file
View File

@ -0,0 +1,15 @@
<?php
return [
'id' => 'app-backend-tests',
'components' => [
'assetManager' => [
'basePath' => __DIR__ . '/../web/assets',
],
'urlManager' => [
'showScriptName' => true,
],
'request' => [
'cookieValidationKey' => 'test',
],
],
];

View File

@ -0,0 +1,104 @@
<?php
namespace backend\controllers;
use common\models\LoginForm;
use Yii;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
/**
* Site controller
*/
class SiteController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* {@inheritdoc}
*/
public function actions()
{
return [
'error' => [
'class' => \yii\web\ErrorAction::class,
],
];
}
/**
* Displays homepage.
*
* @return string
*/
public function actionIndex()
{
return $this->render('index');
}
/**
* Login action.
*
* @return string|Response
*/
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$this->layout = 'blank';
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
}
$model->password = '';
return $this->render('login', [
'model' => $model,
]);
}
/**
* Logout action.
*
* @return Response
*/
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
}

1
backend/models/.gitkeep Normal file
View File

@ -0,0 +1 @@
*

View File

@ -0,0 +1,24 @@
<?php
namespace backend\modules\company;
/**
* company module definition class
*/
class Company extends \yii\base\Module
{
/**
* {@inheritdoc}
*/
public $controllerNamespace = 'backend\modules\company\controllers';
/**
* {@inheritdoc}
*/
public function init()
{
parent::init();
// custom initialization code goes here
}
}

View File

@ -0,0 +1,134 @@
<?php
namespace backend\modules\company\controllers;
use backend\modules\company\models\Company;
use backend\modules\company\models\CompanySearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* CompanyController implements the CRUD actions for Company model.
*/
class CompanyController extends Controller
{
/**
* @inheritDoc
*/
public function behaviors()
{
return array_merge(
parent::behaviors(),
[
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
]
);
}
/**
* Lists all Company models.
*
* @return string
*/
public function actionIndex()
{
$searchModel = new CompanySearch();
$dataProvider = $searchModel->search($this->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Company model.
* @param int $id ID
* @return string
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Company model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return string|\yii\web\Response
*/
public function actionCreate()
{
$model = new Company();
if ($this->request->isPost) {
if ($model->load($this->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
$model->loadDefaultValues();
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing Company model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param int $id ID
* @return string|\yii\web\Response
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
]);
}
/**
* Deletes an existing Company model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* @param int $id ID
* @return \yii\web\Response
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Company model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param int $id ID
* @return Company the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Company::findOne(['id' => $id])) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace backend\modules\company\controllers;
use yii\web\Controller;
/**
* Default controller for the `company` module
*/
class DefaultController extends Controller
{
/**
* Renders the index view for the module
* @return string
*/
public function actionIndex()
{
return $this->render('index');
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace backend\modules\company\models;
class Company extends \common\models\Company
{
}

View File

@ -0,0 +1,73 @@
<?php
namespace backend\modules\company\models;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use backend\modules\company\models\Company;
/**
* CompanySearch represents the model behind the search form of `backend\modules\company\models\Company`.
*/
class CompanySearch extends Company
{
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['id', 'inn', 'created_at', 'updated_at', 'status'], 'integer'],
[['name', 'address'], 'safe'],
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$query = Company::find();
// add conditions that should always apply here
$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;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'inn' => $this->inn,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'status' => $this->status,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'address', $this->address]);
return $dataProvider;
}
}

View File

@ -0,0 +1,33 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/** @var yii\web\View $this */
/** @var backend\modules\company\models\Company $model */
/** @var yii\widgets\ActiveForm $form */
?>
<div class="company-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'inn')->textInput() ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'address')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'created_at')->textInput() ?>
<?= $form->field($model, 'updated_at')->textInput() ?>
<?= $form->field($model, 'status')->textInput() ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@ -0,0 +1,39 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/** @var yii\web\View $this */
/** @var backend\modules\company\models\CompanySearch $model */
/** @var yii\widgets\ActiveForm $form */
?>
<div class="company-search">
<?php $form = ActiveForm::begin([
'action' => ['index'],
'method' => 'get',
]); ?>
<?= $form->field($model, 'id') ?>
<?= $form->field($model, 'inn') ?>
<?= $form->field($model, 'name') ?>
<?= $form->field($model, 'address') ?>
<?= $form->field($model, 'created_at') ?>
<?php // echo $form->field($model, 'updated_at') ?>
<?php // echo $form->field($model, 'status') ?>
<div class="form-group">
<?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
<?= Html::resetButton('Reset', ['class' => 'btn btn-outline-secondary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@ -0,0 +1,20 @@
<?php
use yii\helpers\Html;
/** @var yii\web\View $this */
/** @var backend\modules\company\models\Company $model */
$this->title = 'Create Company';
$this->params['breadcrumbs'][] = ['label' => 'Companies', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="company-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

View File

@ -0,0 +1,49 @@
<?php
use backend\modules\company\models\Company;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\grid\ActionColumn;
use yii\grid\GridView;
/** @var yii\web\View $this */
/** @var backend\modules\company\models\CompanySearch $searchModel */
/** @var yii\data\ActiveDataProvider $dataProvider */
$this->title = 'Companies';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="company-index">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::a('Create Company', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'inn',
'name',
'address',
'created_at',
//'updated_at',
//'status',
[
'class' => ActionColumn::className(),
'urlCreator' => function ($action, Company $model, $key, $index, $column) {
return Url::toRoute([$action, 'id' => $model->id]);
}
],
],
]); ?>
</div>

View File

@ -0,0 +1,21 @@
<?php
use yii\helpers\Html;
/** @var yii\web\View $this */
/** @var backend\modules\company\models\Company $model */
$this->title = 'Update Company: ' . $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Companies', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Update';
?>
<div class="company-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

View File

@ -0,0 +1,42 @@
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
/** @var yii\web\View $this */
/** @var backend\modules\company\models\Company $model */
$this->title = $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Companies', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
\yii\web\YiiAsset::register($this);
?>
<div class="company-view">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::a('Update', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Delete', ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
</p>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'inn',
'name',
'address',
'created_at',
'updated_at',
'status',
],
]) ?>
</div>

View File

@ -0,0 +1,12 @@
<div class="company-default-index">
<h1><?= $this->context->action->uniqueId ?></h1>
<p>
This is the view content for action "<?= $this->context->action->id ?>".
The action belongs to the controller "<?= get_class($this->context) ?>"
in the "<?= $this->context->module->id ?>" module.
</p>
<p>
You may customize this page by editing the following file:<br>
<code><?= __FILE__ ?></code>
</p>
</div>

2
backend/runtime/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -0,0 +1,10 @@
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
require_once YII_APP_BASE_PATH . '/vendor/autoload.php';
require_once YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php';
require_once YII_APP_BASE_PATH . '/common/config/bootstrap.php';
require_once __DIR__ . '/../config/bootstrap.php';

0
backend/tests/_data/.gitignore vendored Normal file
View File

View File

@ -0,0 +1,13 @@
<?php
return [
[
'username' => 'erau',
'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI',
// password_0
'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne',
'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490',
'created_at' => '1392559490',
'updated_at' => '1392559490',
'email' => 'sfriesen@jenkins.info',
],
];

2
backend/tests/_output/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

1
backend/tests/_support/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_generated

View File

@ -0,0 +1,26 @@
<?php
namespace backend\tests;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void verify($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class FunctionalTester extends \Codeception\Actor
{
use _generated\FunctionalTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,26 @@
<?php
namespace backend\tests;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void verify($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
use _generated\UnitTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,5 @@
suite_namespace: backend\tests\functional
actor: FunctionalTester
modules:
enabled:
- Yii2

View File

@ -0,0 +1,44 @@
<?php
namespace backend\tests\functional;
use backend\tests\FunctionalTester;
use common\fixtures\UserFixture;
/**
* Class LoginCest
*/
class LoginCest
{
/**
* Load fixtures before db transaction begin
* Called in _before()
* @see \Codeception\Module\Yii2::_before()
* @see \Codeception\Module\Yii2::loadFixtures()
* @return array
*/
public function _fixtures()
{
return [
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'login_data.php'
]
];
}
/**
* @param FunctionalTester $I
*/
public function loginUser(FunctionalTester $I)
{
$I->amOnRoute('/site/login');
$I->fillField('Username', 'erau');
$I->fillField('Password', 'password_0');
$I->click('login-button');
$I->see('Logout (erau)', 'form button[type=submit]');
$I->dontSeeLink('Login');
$I->dontSeeLink('Signup');
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Here you can initialize variables via \Codeception\Util\Fixtures class
* to store data in global array and use it in Cests.
*
* ```php
* // Here _bootstrap.php
* \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
* ```
*
* In Cests
*
* ```php
* \Codeception\Util\Fixtures::get('user1');
* ```
*/

View File

@ -0,0 +1,2 @@
suite_namespace: backend\tests\unit
actor: UnitTester

View File

@ -0,0 +1,16 @@
<?php
/**
* Here you can initialize variables via \Codeception\Util\Fixtures class
* to store data in global array and use it in Tests.
*
* ```php
* // Here _bootstrap.php
* \Codeception\Util\Fixtures::add('user1', ['name' => 'davert']);
* ```
*
* In Tests
*
* ```php
* \Codeception\Util\Fixtures::get('user1');
* ```
*/

View File

@ -0,0 +1,33 @@
<?php
/** @var yii\web\View $this */
/** @var string $content */
use backend\assets\AppAsset;
use yii\helpers\Html;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>" class="h-100">
<head>
<meta charset="<?= Yii::$app->charset ?>">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<?php $this->registerCsrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body class="d-flex flex-column h-100">
<?php $this->beginBody() ?>
<main role="main">
<div class="container">
<?= $content ?>
</div>
</main>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage();

View File

@ -0,0 +1,81 @@
<?php
/** @var \yii\web\View $this */
/** @var string $content */
use backend\assets\AppAsset;
use common\widgets\Alert;
use yii\bootstrap5\Breadcrumbs;
use yii\bootstrap5\Html;
use yii\bootstrap5\Nav;
use yii\bootstrap5\NavBar;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>" class="h-100">
<head>
<meta charset="<?= Yii::$app->charset ?>">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<?php $this->registerCsrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body class="d-flex flex-column h-100">
<?php $this->beginBody() ?>
<header>
<?php
NavBar::begin([
'brandLabel' => Yii::$app->name,
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar navbar-expand-md navbar-dark bg-dark fixed-top',
],
]);
$menuItems = [
['label' => 'Home', 'url' => ['/site/index']],
];
if (Yii::$app->user->isGuest) {
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
}
echo Nav::widget([
'options' => ['class' => 'navbar-nav me-auto mb-2 mb-md-0'],
'items' => $menuItems,
]);
if (Yii::$app->user->isGuest) {
echo Html::tag('div',Html::a('Login',['/site/login'],['class' => ['btn btn-link login text-decoration-none']]),['class' => ['d-flex']]);
} else {
echo Html::beginForm(['/site/logout'], 'post', ['class' => 'd-flex'])
. Html::submitButton(
'Logout (' . Yii::$app->user->identity->username . ')',
['class' => 'btn btn-link logout text-decoration-none']
)
. Html::endForm();
}
NavBar::end();
?>
</header>
<main role="main" class="flex-shrink-0">
<div class="container">
<?= Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>
<?= Alert::widget() ?>
<?= $content ?>
</div>
</main>
<footer class="footer mt-auto py-3 text-muted">
<div class="container">
<p class="float-start">&copy; <?= Html::encode(Yii::$app->name) ?> <?= date('Y') ?></p>
<p class="float-end"><?= Yii::powered() ?></p>
</div>
</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage();

View File

@ -0,0 +1,27 @@
<?php
/** @var yii\web\View $this */
/** @var string $name */
/** @var string $message */
/** @var Exception $exception*/
use yii\helpers\Html;
$this->title = $name;
?>
<div class="site-error">
<h1><?= Html::encode($this->title) ?></h1>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>
<p>
The above error occurred while the Web server was processing your request.
</p>
<p>
Please contact us if you think this is a server error. Thank you.
</p>
</div>

View File

@ -0,0 +1,53 @@
<?php
/** @var yii\web\View $this */
$this->title = 'My Yii Application';
?>
<div class="site-index">
<div class="jumbotron text-center bg-transparent">
<h1 class="display-4">Congratulations!</h1>
<p class="lead">You have successfully created your Yii-powered application.</p>
<p><a class="btn btn-lg btn-success" href="https://www.yiiframework.com">Get started with Yii</a></p>
</div>
<div class="body-content">
<div class="row">
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-outline-secondary" href="https://www.yiiframework.com/doc/">Yii Documentation &raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-outline-secondary" href="https://www.yiiframework.com/forum/">Yii Forum &raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-outline-secondary" href="https://www.yiiframework.com/extensions/">Yii Extensions &raquo;</a></p>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,32 @@
<?php
/** @var yii\web\View $this */
/** @var yii\bootstrap5\ActiveForm $form */
/** @var \common\models\LoginForm $model */
use yii\bootstrap5\ActiveForm;
use yii\bootstrap5\Html;
$this->title = 'Login';
?>
<div class="site-login">
<div class="mt-5 offset-lg-3 col-lg-6">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to login:</p>
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
<div class="form-group">
<?= Html::submitButton('Login', ['class' => 'btn btn-primary btn-block', 'name' => 'login-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>

2
backend/web/assets/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

90
backend/web/css/site.css Normal file
View File

@ -0,0 +1,90 @@
main > .container {
padding: 70px 15px 20px;
}
.footer {
background-color: #f5f5f5;
font-size: .9em;
height: 60px;
}
.footer > .container {
padding-right: 15px;
padding-left: 15px;
}
.not-set {
color: #c55;
font-style: italic;
}
/* add sorting icons to gridview sort links */
a.asc:after, a.desc:after {
content: '';
left: 3px;
display: inline-block;
width: 0;
height: 0;
border: solid 5px transparent;
margin: 4px 4px 2px 4px;
background: transparent;
}
a.asc:after {
border-bottom: solid 7px #212529;
border-top-width: 0;
}
a.desc:after {
border-top: solid 7px #212529;
border-bottom-width: 0;
}
.grid-view th,
.grid-view td:last-child {
white-space: nowrap;
}
.grid-view .filters input,
.grid-view .filters select {
min-width: 50px;
}
.hint-block {
display: block;
margin-top: 5px;
color: #999;
}
.error-summary {
color: #a94442;
background: #fdf7f7;
border-left: 3px solid #eed3d7;
padding: 10px 20px;
margin: 0 0 15px 0;
}
/* align the logout "link" (button in form) of the navbar */
.nav li > form > button.logout {
padding-top: 7px;
color: rgba(255, 255, 255, 0.5);
}
@media(max-width:767px) {
.nav li > form > button.logout {
display:block;
text-align: left;
width: 100%;
padding: 10px 0;
}
}
.nav > li > form > button.logout:focus,
.nav > li > form > button.logout:hover {
text-decoration: none;
color: rgba(255, 255, 255, 0.75);
}
.nav > li > form > button.logout:focus {
outline: none;
}

BIN
backend/web/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

9
codeception.yml Normal file
View File

@ -0,0 +1,9 @@
# global codeception file to run tests from all apps
include:
- common
- frontend
- backend
paths:
output: console/runtime/output
settings:
colors: true

20
common/classes/Debug.php Executable file
View File

@ -0,0 +1,20 @@
<?php
namespace common\classes;
class Debug
{
public static function prn($content)
{
echo '<pre style="background: lightgray; border: 1px solid black; padding: 2px">';
print_r($content);
echo '</pre>';
}
public static function dd($content)
{
echo '<pre style="background: lightgray; border: 1px solid black; padding: 2px">';
print_r($content);
echo '</pre>';
die();
}
}

15
common/codeception.yml Normal file
View File

@ -0,0 +1,15 @@
namespace: common\tests
actor_suffix: Tester
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
bootstrap: _bootstrap.php
settings:
colors: true
memory_limit: 1024M
modules:
config:
Yii2:
configFile: 'config/codeception-local.php'

4
common/config/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
codeception-local.php
main-local.php
params-local.php
test-local.php

View File

@ -0,0 +1,33 @@
<?php
/**
* This class only exists here for IDE (PHPStorm/Netbeans/...) autocompletion.
* This file is never included anywhere.
* Adjust this file to match classes configured in your application config, to enable IDE autocompletion for custom components.
* Example: A property phpdoc can be added in `__Application` class as `@property \vendor\package\Rollbar|__Rollbar $rollbar` and adding a class in this file
* ```php
* // @property of \vendor\package\Rollbar goes here
* class __Rollbar {
* }
* ```
*/
class Yii {
/**
* @var \yii\web\Application|\yii\console\Application|__Application
*/
public static $app;
}
/**
* @property yii\rbac\DbManager $authManager
* @property \yii\web\User|__WebUser $user
*
*/
class __Application {
}
/**
* @property app\models\User $identity
*/
class __WebUser {
}

View File

@ -0,0 +1,5 @@
<?php
Yii::setAlias('@common', dirname(__DIR__));
Yii::setAlias('@frontend', dirname(dirname(__DIR__)) . '/frontend');
Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend');
Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console');

13
common/config/main.php Normal file
View File

@ -0,0 +1,13 @@
<?php
return [
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
'components' => [
'cache' => [
'class' => \yii\caching\FileCache::class,
],
],
];

9
common/config/params.php Normal file
View File

@ -0,0 +1,9 @@
<?php
return [
'adminEmail' => 'admin@example.com',
'supportEmail' => 'support@example.com',
'senderEmail' => 'noreply@example.com',
'senderName' => 'Example.com mailer',
'user.passwordResetTokenExpire' => 3600,
'user.passwordMinLength' => 8,
];

11
common/config/test.php Normal file
View File

@ -0,0 +1,11 @@
<?php
return [
'id' => 'app-common-tests',
'basePath' => dirname(__DIR__),
'components' => [
'user' => [
'class' => \yii\web\User::class,
'identityClass' => 'common\models\User',
],
],
];

View File

@ -0,0 +1,10 @@
<?php
namespace common\fixtures;
use yii\test\ActiveFixture;
class UserFixture extends ActiveFixture
{
public $modelClass = 'common\models\User';
}

View File

@ -0,0 +1,16 @@
<?php
use yii\helpers\Html;
/** @var yii\web\View $this */
/** @var common\models\User $user */
$verifyLink = Yii::$app->urlManager->createAbsoluteUrl(['site/verify-email', 'token' => $user->verification_token]);
?>
<div class="verify-email">
<p>Hello <?= Html::encode($user->username) ?>,</p>
<p>Follow the link below to verify your email:</p>
<p><?= Html::a(Html::encode($verifyLink), $verifyLink) ?></p>
</div>

View File

@ -0,0 +1,12 @@
<?php
/** @var yii\web\View $this */
/** @var common\models\User $user */
$verifyLink = Yii::$app->urlManager->createAbsoluteUrl(['site/verify-email', 'token' => $user->verification_token]);
?>
Hello <?= $user->username ?>,
Follow the link below to verify your email:
<?= $verifyLink ?>

View File

@ -0,0 +1,24 @@
<?php
use yii\helpers\Html;
/** @var \yii\web\View $this view component instance */
/** @var \yii\mail\MessageInterface $message the message being composed */
/** @var string $content main view render result */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
<?= $content ?>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage();

View File

@ -0,0 +1,12 @@
<?php
/** @var \yii\web\View $this view component instance */
/** @var \yii\mail\MessageInterface $message the message being composed */
/** @var string $content main view render result */
?>
<?php $this->beginPage() ?>
<?php $this->beginBody() ?>
<?= $content ?>
<?php $this->endBody() ?>
<?php $this->endPage() ?>

View File

@ -0,0 +1,16 @@
<?php
use yii\helpers\Html;
/** @var yii\web\View $this */
/** @var common\models\User $user */
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
?>
<div class="password-reset">
<p>Hello <?= Html::encode($user->username) ?>,</p>
<p>Follow the link below to reset your password:</p>
<p><?= Html::a(Html::encode($resetLink), $resetLink) ?></p>
</div>

View File

@ -0,0 +1,12 @@
<?php
/** @var yii\web\View $this */
/** @var common\models\User $user */
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
?>
Hello <?= $user->username ?>,
Follow the link below to reset your password:
<?= $resetLink ?>

View File

@ -0,0 +1,73 @@
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "addresses".
*
* @property int $id
* @property string $address
* @property int $company_id
* @property string|null $name
*
* @property Check[] $checks
* @property Company $company
*/
class Addresses extends \yii\db\ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'addresses';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['address', 'company_id'], 'required'],
[['company_id'], 'integer'],
[['address', 'name'], 'string', 'max' => 255],
[['company_id'], 'exist', 'skipOnError' => true, 'targetClass' => Company::class, 'targetAttribute' => ['company_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'address' => 'Адрес',
'company_id' => 'Компания',
'name' => 'Название',
];
}
/**
* Gets query for [[Checks]].
*
* @return \yii\db\ActiveQuery
*/
public function getChecks()
{
return $this->hasMany(Check::class, ['addresses_id' => 'id']);
}
/**
* Gets query for [[Company]].
*
* @return \yii\db\ActiveQuery
*/
public function getCompany()
{
return $this->hasOne(Company::class, ['id' => 'company_id']);
}
}

111
common/models/Check.php Normal file
View File

@ -0,0 +1,111 @@
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "check".
*
* @property int $id
* @property string $number
* @property int $company_id
* @property string $additional
* @property string $title
* @property int $addresses_id
* @property int|null $status
*
* @property Addresses $addresses
* @property Company $company
*/
class Check extends \yii\db\ActiveRecord
{
const STATUS_NEW = 1;
const STATUS_PRINTED = 2;
const STATUS_PAID = 3;
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::STATUS_NEW => 'Новый',
self::STATUS_PRINTED => 'Напечатан',
self::STATUS_PAID => 'Оплачен',
];
}
/**
* @return string[]
*/
public static function getStatusColor(): array
{
return [
self::STATUS_NEW => '#FFA500',
self::STATUS_PRINTED => '#008080',
self::STATUS_PAID => '#32CD32',
];
}
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'check';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['number', 'company_id', 'addresses_id'], 'required'],
[['company_id', 'addresses_id', 'status'], 'integer'],
[['number', 'title'], 'string', 'max' => 255],
[['additional'], 'string'],
[['addresses_id'], 'exist', 'skipOnError' => true, 'targetClass' => Addresses::class, 'targetAttribute' => ['addresses_id' => 'id']],
[['company_id'], 'exist', 'skipOnError' => true, 'targetClass' => Company::class, 'targetAttribute' => ['company_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'number' => 'Номер',
'company_id' => 'Компания',
'additional' => 'Дополнительная информация',
'title' => 'Заголовок',
'addresses_id' => 'Отделение',
'status' => 'Статус',
];
}
/**
* Gets query for [[Addresses]].
*
* @return \yii\db\ActiveQuery
*/
public function getAddresses(): \yii\db\ActiveQuery
{
return $this->hasOne(Addresses::class, ['id' => 'addresses_id']);
}
/**
* Gets query for [[Company]].
*
* @return \yii\db\ActiveQuery
*/
public function getCompany(): \yii\db\ActiveQuery
{
return $this->hasOne(Company::class, ['id' => 'company_id']);
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "check_product".
*
* @property int $check_id
* @property int $product_id
* @property int|null $quantity
*
* @property Check $check
* @property Product $product
*/
class CheckProduct extends \yii\db\ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'check_product';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['check_id', 'product_id'], 'required'],
[['check_id', 'product_id', 'quantity'], 'integer'],
[['check_id', 'product_id'], 'unique', 'targetAttribute' => ['check_id', 'product_id']],
[['check_id'], 'exist', 'skipOnError' => true, 'targetClass' => Check::class, 'targetAttribute' => ['check_id' => 'id']],
[['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::class, 'targetAttribute' => ['product_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'check_id' => 'Check ID',
'product_id' => 'Product ID',
'quantity' => 'Quantity',
];
}
/**
* Gets query for [[Check]].
*
* @return \yii\db\ActiveQuery
*/
public function getCheck()
{
return $this->hasOne(Check::class, ['id' => 'check_id']);
}
/**
* Gets query for [[Product]].
*
* @return \yii\db\ActiveQuery
*/
public function getProduct()
{
return $this->hasOne(Product::class, ['id' => 'product_id']);
}
}

125
common/models/Company.php Normal file
View File

@ -0,0 +1,125 @@
<?php
namespace common\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
/**
* This is the model class for table "company".
*
* @property int $id
* @property string $inn
* @property int $user_id
* @property string $name
* @property string|null $address
* @property int|null $created_at
* @property int|null $updated_at
* @property int|null $status
*
* @property Addresses[] $addresses
* @property Check[] $checks
* @property Product[] $products
*/
class Company extends \yii\db\ActiveRecord
{
const STATUS_ACTIVE = 1;
const STATUS_INACTIVE = 0;
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::STATUS_ACTIVE => 'Активна',
self::STATUS_INACTIVE => 'Не активна',
];
}
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'company';
}
public function behaviors()
{
return [
[
'class' => TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => new Expression('NOW()'),
],
];
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['inn', 'name', 'user_id'], 'required'],
[['created_at', 'updated_at'], 'safe'],
[['status', 'user_id'], 'integer'],
[['name', 'address', 'inn'], 'string', 'max' => 255],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'inn' => 'ИНН',
'name' => 'Название',
'address' => 'Адрес',
'created_at' => 'Дата создания',
'updated_at' => 'Дата редактирования',
'status' => 'Статус',
'user_id' => 'Пользователь',
];
}
/**
* Gets query for [[Addresses]].
*
* @return \yii\db\ActiveQuery
*/
public function getAddresses()
{
return $this->hasMany(Addresses::class, ['company_id' => 'id']);
}
/**
* Gets query for [[Checks]].
*
* @return \yii\db\ActiveQuery
*/
public function getChecks()
{
return $this->hasMany(Check::class, ['company_id' => 'id']);
}
/**
* Gets query for [[Products]].
*
* @return \yii\db\ActiveQuery
*/
public function getProducts()
{
return $this->hasMany(Product::class, ['company_id' => 'id']);
}
public static function getMyCompany()
{
$companies = self::find()->where(['user_id' => Yii::$app->user->id])->all();
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace common\models;
use common\classes\Debug;
use Yii;
use yii\base\Model;
/**
* Login form
*/
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
private $_user;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// rememberMe must be a boolean value
['rememberMe', 'boolean'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
*
* @return bool whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
}
return false;
}
/**
* Finds user by [[username]]
*
* @return User|null
*/
protected function getUser()
{
if ($this->_user === null) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}

97
common/models/Product.php Normal file
View File

@ -0,0 +1,97 @@
<?php
namespace common\models;
use Yii;
use function Symfony\Component\String\s;
/**
* This is the model class for table "product".
*
* @property int $id
* @property string $title
* @property string $article
* @property int $company_id
* @property int|null $type
* @property int|null $price
* @property int|null $status
*
* @property Company $company
*/
class Product extends \yii\db\ActiveRecord
{
const STATUS_ACTIVE = 1;
const STATUS_INACTIVE = 0;
const TYPE_PIECE = 1;
const TYPE_WEIGHT = 2;
/**
* @return string[]
*/
public static function getType(): array
{
return [
self::TYPE_PIECE => 'шт.',
self::TYPE_WEIGHT => 'кг.',
];
}
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::STATUS_ACTIVE => 'Активна',
self::STATUS_INACTIVE => 'Не активна',
];
}
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'product';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['title', 'article', 'company_id'], 'required'],
[['company_id', 'type', 'price', 'status'], 'integer'],
[['title', 'article'], 'string', 'max' => 255],
[['company_id'], 'exist', 'skipOnError' => true, 'targetClass' => Company::class, 'targetAttribute' => ['company_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'title' => 'Название',
'article' => 'Артикул',
'company_id' => 'Компания',
'type' => 'Тип',
'price' => 'Цена',
'status' => 'Статус',
];
}
/**
* Gets query for [[Company]].
*
* @return \yii\db\ActiveQuery
*/
public function getCompany()
{
return $this->hasOne(Company::class, ['id' => 'company_id']);
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "product_category".
*
* @property int $id
* @property string $title
* @property int|null $parent_id
* @property int $company_id
* @property int|null $status
*
* @property Company $company
*/
class ProductCategory extends \yii\db\ActiveRecord
{
const STATUS_ACTIVE = 1;
const STATUS_NOACTIVE = 0;
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'product_category';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['title', 'company_id'], 'required'],
[['parent_id', 'company_id', 'status'], 'integer'],
[['title'], 'string', 'max' => 255],
[['company_id'], 'exist', 'skipOnError' => true, 'targetClass' => Company::class, 'targetAttribute' => ['company_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'title' => 'Название',
'parent_id' => 'Родительская категория',
'company_id' => 'Компания',
'status' => 'Статус',
];
}
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::STATUS_ACTIVE => "Активна",
self::STATUS_NOACTIVE => "Не активна"
];
}
/**
* Gets query for [[Company]].
*
* @return \yii\db\ActiveQuery
*/
public function getCompany()
{
return $this->hasOne(Company::class, ['id' => 'company_id']);
}
}

222
common/models/User.php Normal file
View File

@ -0,0 +1,222 @@
<?php
namespace common\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
/**
* User model
*
* @property integer $id
* @property string $username
* @property string $password_hash
* @property string $password_reset_token
* @property string $verification_token
* @property string $email
* @property string $auth_key
* @property integer $status
* @property integer $created_at
* @property integer $updated_at
* @property string $password write-only password
*/
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_INACTIVE = 9;
const STATUS_ACTIVE = 10;
/**
* {@inheritdoc}
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
TimestampBehavior::class,
];
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_DELETED]],
];
}
/**
* {@inheritdoc}
*/
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* {@inheritdoc}
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* @param string $username
* @return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
}
/**
* Finds user by password reset token
*
* @param string $token password reset token
* @return static|null
*/
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token,
'status' => self::STATUS_ACTIVE,
]);
}
/**
* Finds user by verification email token
*
* @param string $token verify email token
* @return static|null
*/
public static function findByVerificationToken($token)
{
return static::findOne([
'verification_token' => $token,
'status' => self::STATUS_INACTIVE
]);
}
/**
* Finds out if password reset token is valid
*
* @param string $token password reset token
* @return bool
*/
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$timestamp = (int)substr($token, strrpos($token, '_') + 1);
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
return $timestamp + $expire >= time();
}
/**
* {@inheritdoc}
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* {@inheritdoc}
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* {@inheritdoc}
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* @param string $password password to validate
* @return bool if password provided is valid for current user
*/
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
/**
* Generates password hash from password and sets it to the model
*
* @param string $password
*/
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
/**
* Generates "remember me" authentication key
*/
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Generates new token for email verification
*/
public function generateEmailVerificationToken()
{
$this->verification_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
/**
* @return \yii\db\ActiveQuery
*/
public function getMyCompany(): \yii\db\ActiveQuery
{
return $this->hasMany(Company::class, ['user_id' => 'id']);
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace common\services;
use common\models\Company;
use Yii;
use yii\helpers\ArrayHelper;
class CompanyService
{
public Company $model;
function __construct()
{
$this->model = new Company();
}
/**
* @param int|null $id
* @return array
*/
public function getCompaniesByUser(int $id = null): array
{
return $this->model->find()->where(['user_id' => $id ?? Yii::$app->user->id])->all();
}
/**
* @param int|null $id
* @return array
*/
public function getCompaniesByUserArr(int $id = null): array
{
return ArrayHelper::map($this->getCompaniesByUser($id), 'id', 'name');
}
/**
* @param int $id
* @return Company|null
*/
public function getCompany(int $id): ?Company
{
return $this->model->findOne($id);
}
/**
* @param int|null $id
* @return array
*/
public function getAddressesByUser(int $id = null): array
{
$companies = $this->getCompaniesByUser($id);
return $this->model->find()->where(['id' => ArrayHelper::getColumn($companies, 'id')])->all();
}
/**
* @param int|null $id
* @return array
*/
public function getAddressesByUserArr(int $id = null): array
{
return ArrayHelper::map($this->getAddressesByUser($id), 'id', 'address');
}
}

View File

@ -0,0 +1,9 @@
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../../vendor/yiisoft/yii2/Yii.php';
require __DIR__ . '/../config/bootstrap.php';

View File

@ -0,0 +1,14 @@
<?php
return [
[
'username' => 'bayer.hudson',
'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR',
//password_0
'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO',
'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317',
'created_at' => '1402312317',
'updated_at' => '1402312317',
'email' => 'nicole.paucek@schultz.info',
],
];

2
common/tests/_output/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

1
common/tests/_support/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_generated

View File

@ -0,0 +1,26 @@
<?php
namespace common\tests;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void verify($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
use _generated\UnitTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,7 @@
suite_namespace: common\tests\unit
actor: UnitTester
bootstrap: false
modules:
enabled:
- Yii2:
part: fixtures

View File

@ -0,0 +1,67 @@
<?php
namespace common\tests\unit\models;
use Yii;
use common\models\LoginForm;
use common\fixtures\UserFixture;
/**
* Login form test
*/
class LoginFormTest extends \Codeception\Test\Unit
{
/**
* @var \common\tests\UnitTester
*/
protected $tester;
/**
* @return array
*/
public function _fixtures()
{
return [
'user' => [
'class' => UserFixture::class,
'dataFile' => codecept_data_dir() . 'user.php'
]
];
}
public function testLoginNoUser()
{
$model = new LoginForm([
'username' => 'not_existing_username',
'password' => 'not_existing_password',
]);
verify($model->login())->false();
verify(Yii::$app->user->isGuest)->true();
}
public function testLoginWrongPassword()
{
$model = new LoginForm([
'username' => 'bayer.hudson',
'password' => 'wrong_password',
]);
verify($model->login())->false();
verify( $model->errors)->arrayHasKey('password');
verify(Yii::$app->user->isGuest)->true();
}
public function testLoginCorrect()
{
$model = new LoginForm([
'username' => 'bayer.hudson',
'password' => 'password_0',
]);
verify($model->login())->true();
verify($model->errors)->arrayHasNotKey('password');
verify(Yii::$app->user->isGuest)->false();
}
}

76
common/widgets/Alert.php Normal file
View File

@ -0,0 +1,76 @@
<?php
namespace common\widgets;
use Yii;
/**
* Alert widget renders a message from session flash. All flash messages are displayed
* in the sequence they were assigned using setFlash. You can set message as following:
*
* ```php
* Yii::$app->session->setFlash('error', 'This is the message');
* Yii::$app->session->setFlash('success', 'This is the message');
* Yii::$app->session->setFlash('info', 'This is the message');
* ```
*
* Multiple messages could be set as follows:
*
* ```php
* Yii::$app->session->setFlash('error', ['Error 1', 'Error 2']);
* ```
*
* @author Kartik Visweswaran <kartikv2@gmail.com>
* @author Alexander Makarov <sam@rmcreative.ru>
*/
class Alert extends \yii\bootstrap5\Widget
{
/**
* @var array the alert types configuration for the flash messages.
* This array is setup as $key => $value, where:
* - key: the name of the session flash variable
* - value: the bootstrap alert type (i.e. danger, success, info, warning)
*/
public $alertTypes = [
'error' => 'alert-danger',
'danger' => 'alert-danger',
'success' => 'alert-success',
'info' => 'alert-info',
'warning' => 'alert-warning'
];
/**
* @var array the options for rendering the close button tag.
* Array will be passed to [[\yii\bootstrap\Alert::closeButton]].
*/
public $closeButton = [];
/**
* {@inheritdoc}
*/
public function run()
{
$session = Yii::$app->session;
$flashes = $session->getAllFlashes();
$appendClass = isset($this->options['class']) ? ' ' . $this->options['class'] : '';
foreach ($flashes as $type => $flash) {
if (!isset($this->alertTypes[$type])) {
continue;
}
foreach ((array) $flash as $i => $message) {
echo \yii\bootstrap5\Alert::widget([
'body' => $message,
'closeButton' => $this->closeButton,
'options' => array_merge($this->options, [
'id' => $this->getId() . '-' . $type . '-' . $i,
'class' => $this->alertTypes[$type] . $appendClass,
]),
]);
}
$session->removeFlash($type);
}
}
}

58
composer.json Normal file
View File

@ -0,0 +1,58 @@
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Project Template",
"keywords": ["yii2", "framework", "advanced", "project template"],
"homepage": "https://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "https://www.yiiframework.com/forum/",
"wiki": "https://www.yiiframework.com/wiki/",
"irc": "ircs://irc.libera.chat:6697/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "stable",
"require": {
"php": ">=7.4.0",
"yiisoft/yii2": "~2.0.45",
"yiisoft/yii2-bootstrap5": "~2.0.2",
"yiisoft/yii2-symfonymailer": "~2.0.3",
"hail812/yii2-adminlte3": "~1.1"
},
"require-dev": {
"yiisoft/yii2-debug": "~2.1.0",
"yiisoft/yii2-gii": "~2.2.0",
"yiisoft/yii2-faker": "~2.0.0",
"phpunit/phpunit": "~9.5.0",
"codeception/codeception": "^5.0.0 || ^4.0",
"codeception/lib-innerbrowser": "^4.0 || ^3.0 || ^1.1",
"codeception/module-asserts": "^3.0 || ^1.1",
"codeception/module-yii2": "^1.1",
"codeception/module-filesystem": "^3.0 || ^2.0 || ^1.1",
"codeception/verify": "^3.0 || ^2.2",
"symfony/browser-kit": "^6.0 || >=2.7 <=4.2.4"
},
"autoload-dev": {
"psr-4": {
"common\\tests\\": ["common/tests/", "common/tests/_support"],
"backend\\tests\\": ["backend/tests/", "backend/tests/_support"],
"frontend\\tests\\": ["frontend/tests/", "frontend/tests/_support"]
}
},
"config": {
"allow-plugins": {
"yiisoft/yii2-composer" : true
},
"process-timeout": 1800,
"fxp-asset": {
"enabled": false
}
},
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
}

5867
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

3
console/config/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
main-local.php
params-local.php
test-local.php

View File

@ -0,0 +1 @@
<?php

36
console/config/main.php Normal file
View File

@ -0,0 +1,36 @@
<?php
$params = array_merge(
require __DIR__ . '/../../common/config/params.php',
require __DIR__ . '/../../common/config/params-local.php',
require __DIR__ . '/params.php',
require __DIR__ . '/params-local.php'
);
return [
'id' => 'app-console',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'console\controllers',
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
'controllerMap' => [
'fixture' => [
'class' => \yii\console\controllers\FixtureController::class,
'namespace' => 'common\fixtures',
],
],
'components' => [
'log' => [
'targets' => [
[
'class' => \yii\log\FileTarget::class,
'levels' => ['error', 'warning'],
],
],
],
],
'params' => $params,
];

View File

@ -0,0 +1,5 @@
<?php
return [
'adminEmail' => 'admin@example.com',
];

4
console/config/test.php Normal file
View File

@ -0,0 +1,4 @@
<?php
return [
];

View File

View File

@ -0,0 +1,33 @@
<?php
use yii\db\Migration;
class m130524_201442_init extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
// https://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
}
$this->createTable('{{%user}}', [
'id' => $this->primaryKey(),
'username' => $this->string()->notNull()->unique(),
'auth_key' => $this->string(32)->notNull(),
'password_hash' => $this->string()->notNull(),
'password_reset_token' => $this->string()->unique(),
'email' => $this->string()->notNull()->unique(),
'status' => $this->smallInteger()->notNull()->defaultValue(10),
'created_at' => $this->integer()->notNull(),
'updated_at' => $this->integer()->notNull(),
], $tableOptions);
}
public function down()
{
$this->dropTable('{{%user}}');
}
}

View File

@ -0,0 +1,16 @@
<?php
use \yii\db\Migration;
class m190124_110200_add_verification_token_column_to_user_table extends Migration
{
public function up()
{
$this->addColumn('{{%user}}', 'verification_token', $this->string()->defaultValue(null));
}
public function down()
{
$this->dropColumn('{{%user}}', 'verification_token');
}
}

View File

@ -0,0 +1,33 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%company}}`.
*/
class m240110_152351_create_company_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%company}}', [
'id' => $this->primaryKey(),
'inn' => $this->string(255)->notNull(),
'name' => $this->string(255)->notNull(),
'address' => $this->string(255),
'created_at' => $this->dateTime(),
'updated_at' => $this->dateTime(),
'status' => $this->integer(1)->defaultValue(1)
]);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('{{%company}}');
}
}

View File

@ -0,0 +1,52 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%addresses}}`.
*/
class m240110_153348_create_addresses_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%addresses}}', [
'id' => $this->primaryKey(),
'address' => $this->string(255)->notNull(),
'company_id' => $this->integer(11)->notNull(),
'name' => $this->string(255),
]);
$this->createIndex('idx-addresses-company_id', 'addresses', 'company_id');
$this->addForeignKey(
'fk-addresses-company_id',
'addresses',
'company_id',
'company',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey(
'fk-addresses-company_id',
'addresses'
);
// drops index for column `author_id`
$this->dropIndex(
'idx-addresses-company_id',
'addresses'
);
$this->dropTable('{{%addresses}}');
}
}

View File

@ -0,0 +1,55 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%product}}`.
*/
class m240110_154916_create_product_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%product}}', [
'id' => $this->primaryKey(),
'title' => $this->string(255)->notNull(),
'article' => $this->string(255)->notNull(),
'company_id' => $this->integer(11)->notNull(),
'type' => $this->integer(1)->defaultValue(1),
'price' => $this->integer(11)->defaultValue(0),
'status' => $this->integer(1)->defaultValue(1),
]);
$this->createIndex('idx-product-company_id', 'product', 'company_id');
$this->addForeignKey(
'fk-product-company_id',
'product',
'company_id',
'company',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey(
'fk-product-company_id',
'product'
);
// drops index for column `author_id`
$this->dropIndex(
'idx-product-company_id',
'product'
);
$this->dropTable('{{%product}}');
}
}

View File

@ -0,0 +1,75 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%check}}`.
*/
class m240110_155920_create_check_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%check}}', [
'id' => $this->primaryKey(),
'number' => $this->string(255)->notNull(),
'company_id' => $this->integer(11)->notNull(),
'addresses_id' => $this->integer(11)->notNull(),
'status' => $this->integer(1)->defaultValue(1),
]);
$this->createIndex('idx-check-company_id', 'check', 'company_id');
$this->addForeignKey(
'fk-check-company_id',
'check',
'company_id',
'company',
'id',
'CASCADE'
);
$this->createIndex('idx-check-addresses_id', 'check', 'addresses_id');
$this->addForeignKey(
'fk-check-addresses_id',
'check',
'addresses_id',
'addresses',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey(
'fk-check-company_id',
'check'
);
// drops index for column `author_id`
$this->dropIndex(
'idx-check-company_id',
'check'
);
$this->dropForeignKey(
'fk-check-addresses_id',
'check'
);
// drops index for column `author_id`
$this->dropIndex(
'idx-check-addresses_id',
'check'
);
$this->dropTable('{{%check}}');
}
}

View File

@ -0,0 +1,92 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%check_product}}`.
* Has foreign keys to the tables:
*
* - `{{%check}}`
* - `{{%product}}`
*/
class m240110_161944_create_junction_table_for_check_and_product_tables extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%check_product}}', [
'check_id' => $this->integer(11)->notNull(),
'product_id' => $this->integer(11)->notNull(),
'quantity' => $this->integer(11)->defaultValue(1),
'PRIMARY KEY(check_id, product_id)',
]);
// creates index for column `check_id`
$this->createIndex(
'{{%idx-check_product-check_id}}',
'{{%check_product}}',
'check_id'
);
// add foreign key for table `{{%check}}`
$this->addForeignKey(
'{{%fk-check_product-check_id}}',
'{{%check_product}}',
'check_id',
'{{%check}}',
'id',
'CASCADE'
);
// creates index for column `product_id`
$this->createIndex(
'{{%idx-check_product-product_id}}',
'{{%check_product}}',
'product_id'
);
// add foreign key for table `{{%product}}`
$this->addForeignKey(
'{{%fk-check_product-product_id}}',
'{{%check_product}}',
'product_id',
'{{%product}}',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
// drops foreign key for table `{{%check}}`
$this->dropForeignKey(
'{{%fk-check_product-check_id}}',
'{{%check_product}}'
);
// drops index for column `check_id`
$this->dropIndex(
'{{%idx-check_product-check_id}}',
'{{%check_product}}'
);
// drops foreign key for table `{{%product}}`
$this->dropForeignKey(
'{{%fk-check_product-product_id}}',
'{{%check_product}}'
);
// drops index for column `product_id`
$this->dropIndex(
'{{%idx-check_product-product_id}}',
'{{%check_product}}'
);
$this->dropTable('{{%check_product}}');
}
}

View File

@ -0,0 +1,44 @@
<?php
use yii\db\Migration;
/**
* Class m240110_223124_add_user_id_column_at_company_table
*/
class m240110_223124_add_user_id_column_at_company_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('company', 'user_id', $this->integer(11)->notNull());
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('company', 'user_id');
}
/*
// Use up()/down() to run migration code without a transaction.
public function up()
{
}
public function down()
{
echo "m240110_223124_add_user_id_column_at_company_table cannot be reverted.\n";
return false;
}
*/
}

View File

@ -0,0 +1,40 @@
<?php
use yii\db\Migration;
/**
* Class m240117_203610_add_additional_column_at_check_table
*/
class m240117_203610_add_additional_column_at_check_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('check', 'additional', $this->text()->after('company_id'));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('check', 'additional');
}
/*
// Use up()/down() to run migration code without a transaction.
public function up()
{
}
public function down()
{
echo "m240117_203610_add_additional_column_at_check_table cannot be reverted.\n";
return false;
}
*/
}

View File

@ -0,0 +1,40 @@
<?php
use yii\db\Migration;
/**
* Class m240117_205124_add_title_column_at_check_table
*/
class m240117_205124_add_title_column_at_check_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('check', 'title', $this->text()->after('company_id'));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('check', 'title');
}
/*
// Use up()/down() to run migration code without a transaction.
public function up()
{
}
public function down()
{
echo "m240117_205124_add_title_column_at_check_table cannot be reverted.\n";
return false;
}
*/
}

View File

@ -0,0 +1,57 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%product_category}}`.
*/
class m240212_213157_create_product_category_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%product_category}}', [
'id' => $this->primaryKey(),
'title' => $this->string('255')->notNull(),
'parent_id' => $this->integer(11)->defaultValue(0),
'company_id' => $this->integer(11)->notNull(),
'status' => $this->integer(1)->defaultValue(1),
]);
$this->createIndex(
'idx-product_category-company_id',
'product_category',
'company_id'
);
// add foreign key for table `user`
$this->addForeignKey(
'fk-product_category-company_id',
'product_category',
'company_id',
'company',
'id',
'CASCADE'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey(
'fk-product_category-company_id',
'product_category'
);
// drops index for column `author_id`
$this->dropIndex(
'idx-product_category-company_id',
'product_category'
);
$this->dropTable('{{%product_category}}');
}
}

Some files were not shown because too many files have changed in this diff Show More