diff --git a/Gruntfile.coffee b/Gruntfile.coffee
new file mode 100644
index 0000000..c663c91
--- /dev/null
+++ b/Gruntfile.coffee
@@ -0,0 +1,62 @@
+module.exports = (grunt) ->
+
+ # Project configuration.
+ grunt.initConfig
+ pkg: grunt.file.readJSON('package.json')
+
+ config:
+ src: 'assets/coffee'
+ dest: 'assets/js'
+
+ clean:
+ build:
+ src: [ 'frontend/web/stylesheet','backend/web/stylesheet' ]
+
+ compass:
+ frontend:
+ options:
+ sassDir: 'frontend/web/scss'
+ cssDir: 'frontend/web/stylesheet'
+ backend:
+ options:
+ sassDir: 'backend/web/scss'
+ cssDir: 'backend/web/stylesheet'
+
+ coffee:
+ frontend:
+ options:
+ sourceMap: true
+ bare: false
+ join: true
+ files:
+ 'frontend/web/js/frontend.js': ['frontend/web/coffee/**/*.coffee']
+ backend:
+ options:
+ sourceMap: true
+ bare: false
+ join: true
+ files:
+ 'backend/web/js/backend.js': ['backend/web/coffee/**/*.coffee']
+
+ watch:
+ options:
+ spawn: false
+ interrupt: true
+ atBegin: true
+ interval: 500
+ coffeewatch:
+ files: ['frontend/web/coffee/**/*.coffee','backend/web/coffee/**/*.coffee']
+ tasks: ['any-newer:coffee']
+ sasswatch:
+ files: ['frontend/web/scss/*.scss','backend/web/scss/*.scss']
+ tasks: ['compass']
+
+
+ #grunt.loadNpmTasks 'grunt-contrib-compass'
+
+ require('matchdep').filterDev('grunt-*').forEach grunt.loadNpmTasks
+
+ # Tasks
+ #grunt.registerTask 'default', ['concurrent:compile']
+ grunt.registerTask 'default', ['compass','coffee']
+ #grunt.registerTask 'production', ['clean', 'concurrent:compile', 'concurrent:optimize']
\ No newline at end of file
diff --git a/backend/components/AdminMenuStructure.php b/backend/components/AdminMenuStructure.php
index ae957ec..153b0ff 100644
--- a/backend/components/AdminMenuStructure.php
+++ b/backend/components/AdminMenuStructure.php
@@ -40,6 +40,7 @@ class AdminMenuStructure{
$items[] = ['label' => 'Kedvezmények', 'url' => ['/discount/index'] ];
$items[] = ['label' => 'Termék kategóriák', 'url' => ['/product-category/index'] ];
$items[] = ['label' => 'Bérlet típusok', 'url' => ['/ticket-type/index'] ];
+ $items[] = ['label' => 'Termékek', 'url' => ['/product/index'] ];
if ( count($items) > 0 ){
$userMainMenu = ['label' => 'Beállítások', 'url' => null,
diff --git a/backend/controllers/ProductController.php b/backend/controllers/ProductController.php
new file mode 100644
index 0000000..3ce635f
--- /dev/null
+++ b/backend/controllers/ProductController.php
@@ -0,0 +1,125 @@
+ [
+ 'class' => VerbFilter::className(),
+ 'actions' => [
+ 'delete' => ['post'],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Lists all Product models.
+ * @return mixed
+ */
+ public function actionIndex()
+ {
+ $searchModel = new ProductSearch();
+ $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
+
+ return $this->render('index', [
+ 'searchModel' => $searchModel,
+ 'dataProvider' => $dataProvider,
+ ]);
+ }
+
+ /**
+ * Displays a single Product model.
+ * @param integer $id
+ * @return mixed
+ */
+ public function actionView($id)
+ {
+ return $this->render('view', [
+ 'model' => $this->findModel($id),
+ ]);
+ }
+
+ /**
+ * Creates a new Product model.
+ * If creation is successful, the browser will be redirected to the 'view' page.
+ * @return mixed
+ */
+ public function actionCreate()
+ {
+ $model = new Product();
+ $accounts = Account::readAccounts(null);
+
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect(['view', 'id' => $model->id_product]);
+ } else {
+ return $this->render('create', [
+ 'model' => $model,
+ 'accounts' => $accounts,
+ ]);
+ }
+ }
+
+ /**
+ * Updates an existing Product model.
+ * If update is successful, the browser will be redirected to the 'view' page.
+ * @param integer $id
+ * @return mixed
+ */
+ public function actionUpdate($id)
+ {
+ $model = $this->findModel($id);
+
+ if ($model->load(Yii::$app->request->post()) && $model->save()) {
+ return $this->redirect(['view', 'id' => $model->id_product]);
+ } else {
+ return $this->render('update', [
+ 'model' => $model,
+ ]);
+ }
+ }
+
+ /**
+ * Deletes an existing Product model.
+ * If deletion is successful, the browser will be redirected to the 'index' page.
+ * @param integer $id
+ * @return mixed
+ */
+ public function actionDelete($id)
+ {
+ $this->findModel($id)->delete();
+
+ return $this->redirect(['index']);
+ }
+
+ /**
+ * Finds the Product model based on its primary key value.
+ * If the model is not found, a 404 HTTP exception will be thrown.
+ * @param integer $id
+ * @return Product the loaded model
+ * @throws NotFoundHttpException if the model cannot be found
+ */
+ protected function findModel($id)
+ {
+ if (($model = Product::findOne($id)) !== null) {
+ return $model;
+ } else {
+ throw new NotFoundHttpException('The requested page does not exist.');
+ }
+ }
+}
diff --git a/backend/models/ProductSearch.php b/backend/models/ProductSearch.php
new file mode 100644
index 0000000..a528662
--- /dev/null
+++ b/backend/models/ProductSearch.php
@@ -0,0 +1,76 @@
+ $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;
+ }
+
+ $query->andFilterWhere([
+ 'id_product' => $this->id_product,
+ 'id_product_type' => $this->id_product_type,
+ 'id_account' => $this->id_account,
+ 'purchase_price' => $this->purchase_price,
+ 'sale_price' => $this->sale_price,
+ 'profit_margins' => $this->profit_margins,
+ 'status' => $this->status,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ]);
+
+ $query->andFilterWhere(['like', 'product_number', $this->product_number])
+ ->andFilterWhere(['like', 'barcode', $this->barcode])
+ ->andFilterWhere(['like', 'description', $this->description]);
+
+ return $dataProvider;
+ }
+}
diff --git a/backend/views/product/_form.php b/backend/views/product/_form.php
new file mode 100644
index 0000000..941c04d
--- /dev/null
+++ b/backend/views/product/_form.php
@@ -0,0 +1,42 @@
+
+
+
diff --git a/backend/views/product/_search.php b/backend/views/product/_search.php
new file mode 100644
index 0000000..aba1bcc
--- /dev/null
+++ b/backend/views/product/_search.php
@@ -0,0 +1,49 @@
+
+
+
+
+ ['index'],
+ 'method' => 'get',
+ ]); ?>
+
+ = $form->field($model, 'id_product') ?>
+
+ = $form->field($model, 'id_product_type') ?>
+
+ = $form->field($model, 'id_account') ?>
+
+ = $form->field($model, 'product_number') ?>
+
+ = $form->field($model, 'barcode') ?>
+
+ field($model, 'purchase_price') ?>
+
+ field($model, 'sale_price') ?>
+
+ field($model, 'profit_margins') ?>
+
+ field($model, 'status') ?>
+
+ field($model, 'description') ?>
+
+ field($model, 'created_at') ?>
+
+ field($model, 'updated_at') ?>
+
+
+ = Html::submitButton(Yii::t('common/ticket_type', 'Search'), ['class' => 'btn btn-primary']) ?>
+ = Html::resetButton(Yii::t('common/ticket_type', 'Reset'), ['class' => 'btn btn-default']) ?>
+
+
+
+
+
diff --git a/backend/views/product/create.php b/backend/views/product/create.php
new file mode 100644
index 0000000..c9d4e28
--- /dev/null
+++ b/backend/views/product/create.php
@@ -0,0 +1,23 @@
+title = Yii::t('common/ticket_type', 'Create Product');
+$this->params['breadcrumbs'][] = ['label' => Yii::t('common/ticket_type', 'Products'), 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+
= Html::encode($this->title) ?>
+
+ = $this->render('_form', [
+ 'model' => $model,
+ 'accounts' => $accounts,
+ ]) ?>
+
+
diff --git a/backend/views/product/index.php b/backend/views/product/index.php
new file mode 100644
index 0000000..41ee9c3
--- /dev/null
+++ b/backend/views/product/index.php
@@ -0,0 +1,47 @@
+title = Yii::t('common/ticket_type', 'Products');
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+
= Html::encode($this->title) ?>
+ render('_search', ['model' => $searchModel]); ?>
+
+
+ = Html::a(Yii::t('common/ticket_type', 'Create Product'), ['create'], ['class' => 'btn btn-success']) ?>
+
+
+ = GridView::widget([
+ 'dataProvider' => $dataProvider,
+ 'columns' => [
+ [
+ 'attribute' => 'id_product_type',
+ 'value' => 'productCategoryName',
+ ],
+ [
+ 'attribute' => 'id_account',
+ 'value' => 'accountName',
+ ],
+ 'product_number',
+ 'barcode',
+ 'purchase_price',
+ 'sale_price',
+ 'profit_margins',
+ 'status',
+ 'description',
+ 'created_at:datetime',
+ 'updated_at:datetime',
+
+ ['class' => 'yii\grid\ActionColumn'],
+ ],
+ ]); ?>
+
+
diff --git a/backend/views/product/update.php b/backend/views/product/update.php
new file mode 100644
index 0000000..2b6f0a3
--- /dev/null
+++ b/backend/views/product/update.php
@@ -0,0 +1,23 @@
+title = Yii::t('common/ticket_type', 'Update {modelClass}: ', [
+ 'modelClass' => 'Product',
+]) . ' ' . $model->id_product;
+$this->params['breadcrumbs'][] = ['label' => Yii::t('common/ticket_type', 'Products'), 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->id_product, 'url' => ['view', 'id' => $model->id_product]];
+$this->params['breadcrumbs'][] = Yii::t('common/ticket_type', 'Update');
+?>
+
+
+
= Html::encode($this->title) ?>
+
+ = $this->render('_form', [
+ 'model' => $model,
+ ]) ?>
+
+
diff --git a/backend/views/product/view.php b/backend/views/product/view.php
new file mode 100644
index 0000000..214365d
--- /dev/null
+++ b/backend/views/product/view.php
@@ -0,0 +1,46 @@
+title = $model->id_product;
+$this->params['breadcrumbs'][] = ['label' => Yii::t('common/ticket_type', 'Products'), 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+
+
+
= Html::encode($this->title) ?>
+
+
+ = Html::a(Yii::t('common/ticket_type', 'Update'), ['update', 'id' => $model->id_product], ['class' => 'btn btn-primary']) ?>
+ = Html::a(Yii::t('common/ticket_type', 'Delete'), ['delete', 'id' => $model->id_product], [
+ 'class' => 'btn btn-danger',
+ 'data' => [
+ 'confirm' => Yii::t('common/ticket_type', 'Are you sure you want to delete this item?'),
+ 'method' => 'post',
+ ],
+ ]) ?>
+
+
+ = DetailView::widget([
+ 'model' => $model,
+ 'attributes' => [
+ 'id_product',
+ 'id_product_type',
+ 'id_account',
+ 'product_number',
+ 'barcode',
+ 'purchase_price',
+ 'sale_price',
+ 'profit_margins',
+ 'status',
+ 'description',
+ 'created_at',
+ 'updated_at',
+ ],
+ ]) ?>
+
+
diff --git a/common/models/Account.php b/common/models/Account.php
index 125a73c..b50733f 100644
--- a/common/models/Account.php
+++ b/common/models/Account.php
@@ -108,4 +108,21 @@ class Account extends \yii\db\ActiveRecord
return $this->status == self::STATUS_DELETED;
}
+ /**
+ * $param int $forceIncludeAccount id account, that should be included in list, even if it is inactive
+ * */
+ public static function readAccounts($forceIncludeAccount = null){
+ $accounts = null;
+
+ if ( $forceIncludeAccount == null){
+ $accounts = Account::find()->andWhere(['status' => Account::STATUS_ACTIVE])->all();
+ }else{
+ $accounts = Account::find()->andWhere( ['or', ['status' => Account::STATUS_ACTIVE], ['id_account' => $forceIncludeAccount ] ])->all();
+ }
+
+ return $accounts;
+ }
+
+
+
}
diff --git a/common/models/Product.php b/common/models/Product.php
new file mode 100644
index 0000000..41600ab
--- /dev/null
+++ b/common/models/Product.php
@@ -0,0 +1,107 @@
+ 20],
+ [['description'], 'string', 'max' => 255]
+ ];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id_product' => Yii::t('common/product', 'Id Product'),
+ 'id_product_type' => Yii::t('common/product', 'Id Product Type'),
+ 'id_account' => Yii::t('common/product', 'Id Account'),
+ 'product_number' => Yii::t('common/product', 'Product Number'),
+ 'barcode' => Yii::t('common/product', 'Barcode'),
+ 'purchase_price' => Yii::t('common/product', 'Purchase Price'),
+ 'sale_price' => Yii::t('common/product', 'Sale Price'),
+ 'profit_margins' => Yii::t('common/product', 'Profit Margins'),
+ 'status' => Yii::t('common/product', 'Status'),
+ 'description' => Yii::t('common/product', 'Description'),
+ 'created_at' => Yii::t('common/product', 'Created At'),
+ 'updated_at' => Yii::t('common/product', 'Updated At'),
+ ];
+ }
+
+
+ public function getAccount() {
+ return $this->hasOne ( Account::className (), [
+ 'id_account' => 'id_account'
+ ] );
+ }
+ public function getAccountName() {
+ return $this->account->name;
+ }
+
+ public function getProductCategory() {
+ return $this->hasOne ( ProductCategory::className (), [
+ 'id_product_category' => 'id_product_category'
+ ] );
+ }
+ public function getProductCategoryName() {
+ return $this->productCategory->name;
+ }
+
+ /**
+ * @formatter:on
+ */
+ static function statuses() {
+ return [
+ self::STATUS_ACTIVE => Yii::t ( 'common/product', 'Active' ),
+ self::STATUS_DELETED => Yii::t ( 'common/product', 'Inactive' )
+ ];
+ }
+ public function getStatusHuman() {
+ $result = null;
+ $s = self::statuses ( );
+ if (array_key_exists ( $this->status, $s )) {
+ $result = $s [$this->status];
+ }
+ return $result;
+ }
+
+}
diff --git a/common/models/TicketType.php b/common/models/TicketType.php
index 11a86d4..ed620c9 100644
--- a/common/models/TicketType.php
+++ b/common/models/TicketType.php
@@ -123,7 +123,7 @@ class TicketType extends \common\models\BaseFitnessActiveRecord {
}
public function getStatusHuman() {
$result = null;
- $s = self::statuses ( $this->status );
+ $s = self::statuses ( );
if (array_key_exists ( $this->status, $s )) {
$result = $s [$this->status];
}
diff --git a/composer.lock b/composer.lock
index e7e2ee1..d09a533 100644
--- a/composer.lock
+++ b/composer.lock
@@ -459,21 +459,21 @@
},
{
"name": "yiisoft/yii2-bootstrap",
- "version": "2.0.4",
+ "version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/yii2-bootstrap.git",
- "reference": "1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0"
+ "reference": "1464f93834b1d5edb1f5625f7ffd6c3723fa4923"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/yiisoft/yii2-bootstrap/zipball/1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0",
- "reference": "1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0",
+ "url": "https://api.github.com/repos/yiisoft/yii2-bootstrap/zipball/1464f93834b1d5edb1f5625f7ffd6c3723fa4923",
+ "reference": "1464f93834b1d5edb1f5625f7ffd6c3723fa4923",
"shasum": ""
},
"require": {
"bower-asset/bootstrap": "3.3.* | 3.2.* | 3.1.*",
- "yiisoft/yii2": ">=2.0.4"
+ "yiisoft/yii2": ">=2.0.6"
},
"type": "yii2-extension",
"extra": {
@@ -505,7 +505,7 @@
"bootstrap",
"yii2"
],
- "time": "2015-05-10 22:08:17"
+ "time": "2015-09-23 17:48:24"
},
{
"name": "yiisoft/yii2-composer",
diff --git a/console/migrations/m150922_133505_add__table__product.php b/console/migrations/m150922_133505_add__table__product.php
new file mode 100644
index 0000000..4e5bb00
--- /dev/null
+++ b/console/migrations/m150922_133505_add__table__product.php
@@ -0,0 +1,49 @@
+db->driverName === 'mysql') {
+ // http://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('{{%product}}', [
+ 'id_product' => $this->primaryKey(),
+ 'id_product_type' => $this->integer()->notNull(),
+ 'id_account' => $this->integer()->notNull(),
+ 'product_number' => $this->string(20),
+ 'barcode' => $this->string(20),
+ 'purchase_price' => $this->integer(),
+ 'sale_price' => $this->integer(),
+ 'profit_margins' => $this->integer(),
+ 'status' => $this->smallInteger()->notNull()->defaultValue(10),
+ 'description' => $this->string(255),
+ 'created_at' => $this->timestamp()->notNull(),
+ 'updated_at' => $this->timestamp()->notNull(),
+ ], $tableOptions);
+ }
+
+ public function down()
+ {
+ echo "m150922_133505_add__table__product cannot be reverted.\n";
+
+ return false;
+ }
+
+ /*
+ // Use safeUp/safeDown to run migration code within a transaction
+ public function safeUp()
+ {
+ }
+
+ public function safeDown()
+ {
+ }
+ */
+}