improve customer api & gui

This commit is contained in:
Roland Schneider 2021-10-02 22:21:14 +02:00
parent 1d065cc729
commit f98dcb656f
44 changed files with 893 additions and 298 deletions

View File

@ -13,6 +13,7 @@ use yii\widgets\ActiveForm;
<?php $form = ActiveForm::begin(); ?> <?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'theme')->dropDownList(\common\models\EventType::themes()) ?>
<div class="form-group"> <div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('event-type', 'Create') : Yii::t('event-type', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> <?= Html::submitButton($model->isNewRecord ? Yii::t('event-type', 'Create') : Yii::t('event-type', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

View File

@ -26,7 +26,13 @@ $this->params['breadcrumbs'][] = $this->title;
'name', 'name',
'created_at:datetime', 'created_at:datetime',
'updated_at:datetime', 'updated_at:datetime',
[
'attribute' => 'theme',
'label' => 'Színtéma',
'value' => function ($model, $key, $index, $column){
return isset($model['theme']) ? "Színtéma " . ($model['theme']+1) : "";
}
],
['class' => 'yii\grid\ActionColumn', ['class' => 'yii\grid\ActionColumn',
'template' => '{view} {update}' 'template' => '{view} {update}'
], ],

View File

@ -30,6 +30,10 @@ $this->params['breadcrumbs'][] = $this->title;
'attributes' => [ 'attributes' => [
'id', 'id',
'name', 'name',
[
'label'=> 'Színtéma',
'value' => ( isset($model->theme) ? 'Színtéma ' . ($model->theme+1) : '-' )
],
'created_at', 'created_at',
'updated_at', 'updated_at',
], ],

View File

@ -22,7 +22,7 @@ class Helper {
*/ */
public static function calcStartDatimeDaysSinceToday($start, $format = "datetime" ){ public static function calcStartDatimeDaysSinceToday($start, $format = "datetime" ){
$now = time(); $now = time();
if ( $format == "datetime"){ if ( $format == "datetime"){
$format = "Y-m-d H:i"; $format = "Y-m-d H:i";
}else if ( $format == "date") { }else if ( $format == "date") {
@ -30,10 +30,10 @@ class Helper {
}else{ }else{
//use format //use format
} }
$d = \DateTime::createFromFormat( $format , $start)->getTimeStamp(); $d = \DateTime::createFromFormat( $format , $start)->getTimeStamp();
$days_between = ceil(abs( $now - $d) / 86400 ); $days_between = ceil(abs( $now - $d) / 86400 );
return $days_between; return $days_between;
} }
@ -52,8 +52,8 @@ class Helper {
*/ */
public static function restrictIfNotAdminTheStartDate($query,$date, $fields = ['transfer.paid_at','transfer.created_at'], $format = 'datetime'){ public static function restrictIfNotAdminTheStartDate($query,$date, $fields = ['transfer.paid_at','transfer.created_at'], $format = 'datetime'){
$result = null; $result = null;
$needFix = false; $needFix = false;
if ( !isset($date) || empty($date)){ if ( !isset($date) || empty($date)){
$needFix = true; $needFix = true;
@ -63,19 +63,19 @@ class Helper {
$needFix = true; $needFix = true;
} }
} }
if ( $needFix == true ){ if ( $needFix == true ){
$d = Helper::getReceptionVisibilityDays(); $d = Helper::getReceptionVisibilityDays();
$time = date( "Y-m-d H:i:s", strtotime("today -$d day") ); $time = date( "Y-m-d H:i:s", strtotime("today -$d day") );
$conditions = []; $conditions = [];
foreach ($fields as $f ){ foreach ($fields as $f ){
$conditions[] = ['>=', $f, $time]; $conditions[] = ['>=', $f, $time];
} }
if ( count($conditions) > 1 ){ if ( count($conditions) > 1 ){
$andWhereCond = []; $andWhereCond = [];
$andWhereCond[0] = "or"; $andWhereCond[0] = "or";
@ -87,26 +87,26 @@ class Helper {
}else if ( count($conditions) == 1 ){ }else if ( count($conditions) == 1 ){
$andWhereCond = $conditions[0]; $andWhereCond = $conditions[0];
} }
// $start_date_condition = ['or',[ '>=', 'transfer.created_at', $time ] ,[ '>=', 'transfer.paid_at', $time] ]; // $start_date_condition = ['or',[ '>=', 'transfer.created_at', $time ] ,[ '>=', 'transfer.paid_at', $time] ];
if ( isset($andWhereCond)){ if ( isset($andWhereCond)){
$query->andWhere( $andWhereCond ); $query->andWhere( $andWhereCond );
} }
} }
return $result; return $result;
} }
public static function getDateTimeString( ){ public static function getDateTimeString( ){
return date("Y-m-d H:i:s"); return date("Y-m-d H:i:s");
} }
public static function getDateString( ){ public static function getDateString( ){
return date("Y-m-d"); return date("Y-m-d");
} }
public static function getArrayValue($arr,$key,$def){ public static function getArrayValue($arr,$key,$def){
$result = $def; $result = $def;
if ( array_key_exists($key, $arr)){ if ( array_key_exists($key, $arr)){
@ -114,8 +114,8 @@ class Helper {
} }
return $result; return $result;
} }
public static function hufRound($m) { public static function hufRound($m) {
$result = round ( $m / 5, 0 ) * 5; $result = round ( $m / 5, 0 ) * 5;
return $result; return $result;
@ -128,18 +128,18 @@ class Helper {
* @param $end * @param $end
*/ */
public static function notInInterval($query, $field, $start, $end) { public static function notInInterval($query, $field, $start, $end) {
$query->andFilterWhere ( [ $query->andFilterWhere ( [
'or', 'or',
[ [
'<', '<',
$field, $field,
isset ( $start ) ? $start : '1900-01-01' isset ( $start ) ? $start : '1900-01-01'
], ],
[ [
'>=', '>=',
$field, $field,
isset ( $end ) ? $end : '3000-01-01' isset ( $end ) ? $end : '3000-01-01'
] ]
] ); ] );
} }
@ -150,21 +150,21 @@ class Helper {
* @param string $end the end date * @param string $end the end date
*/ */
public static function notPaid($query, $field, $start, $end) { public static function notPaid($query, $field, $start, $end) {
$query->andFilterWhere ( [ $query->andFilterWhere ( [
'or', 'or',
[ [
'<', '<',
$field, $field,
isset ( $start ) ? $start : '1900-01-01' isset ( $start ) ? $start : '1900-01-01'
], ],
[ [
'>=', '>=',
$field, $field,
isset ( $end ) ? $end : '3000-01-01' isset ( $end ) ? $end : '3000-01-01'
], ],
[ [
"transfer.status" => Transfer::STATUS_NOT_PAID "transfer.status" => Transfer::STATUS_NOT_PAID
] ]
] ); ] );
} }
@ -175,15 +175,15 @@ class Helper {
* @param string $end the end date * @param string $end the end date
*/ */
public static function inInterval($query, $field, $start, $end) { public static function inInterval($query, $field, $start, $end) {
$query->andFilterWhere ( [ $query->andFilterWhere ( [
'>=', '>=',
$field, $field,
$start $start
] ); ] );
$query->andFilterWhere ( [ $query->andFilterWhere ( [
'<', '<',
$field, $field,
$end $end
] ); ] );
} }
@ -194,53 +194,53 @@ class Helper {
* @return array the query 'in interval' rule * @return array the query 'in interval' rule
*/ */
public static function queryInIntervalRule($field, $start, $end) { public static function queryInIntervalRule($field, $start, $end) {
return [ return [
'and', 'and',
[ [
'>=', '>=',
$field, $field,
$start $start
], ],
[ [
'<', '<',
$field, $field,
$end $end
] ]
]; ];
} }
public static function queryExpireRule($field_start, $field_end, $start, $end) { public static function queryExpireRule($field_start, $field_end, $start, $end) {
return [ return [
'and', 'and',
[ [
'<', '<',
$field_start, $field_start,
$end $end
], ],
[ [
'>=', '>=',
$field_end, $field_end,
$start $start
], ],
[ [
'<=', '<=',
$field_end, $field_end,
$end $end
] ]
]; ];
} }
public static function queryValidRule($field_start, $field_end, $start, $end) { public static function queryValidRule($field_start, $field_end, $start, $end) {
return [ return [
'and', 'and',
[ [
'<', '<',
$field_start, $field_start,
$end $end
], ],
[ [
'>=', '>=',
$field_end, $field_end,
$start $start
] ]
]; ];
} }
public static function sqlInIntervalRule($field, $paramStart, $paramEnd) { public static function sqlInIntervalRule($field, $paramStart, $paramEnd) {
@ -270,35 +270,35 @@ class Helper {
public static function queryAccountConstraint($query, $field) { public static function queryAccountConstraint($query, $field) {
if (! RoleDefinition::isAdmin ()) { if (! RoleDefinition::isAdmin ()) {
$query->innerJoin ( "user_account_assignment", $field . ' = user_account_assignment.id_account' ); $query->innerJoin ( "user_account_assignment", $field . ' = user_account_assignment.id_account' );
$query->andWhere ( [ $query->andWhere ( [
'user_account_assignment.id_user' => Yii::$app->user->id 'user_account_assignment.id_user' => Yii::$app->user->id
] ); ] );
} }
} }
public static function roleLabels() { public static function roleLabels() {
return [ return [
'reception' => Yii::t ( 'common/role', 'Reception' ), 'reception' => Yii::t ( 'common/role', 'Reception' ),
'admin' => Yii::t ( 'common/role', 'Administrator' ), 'admin' => Yii::t ( 'common/role', 'Administrator' ),
'employee' => Yii::t ( 'common/role', 'Alkalmazott' ) 'employee' => Yii::t ( 'common/role', 'Alkalmazott' )
]; ];
} }
public static function roleDefinitions() { public static function roleDefinitions() {
return [ return [
'employee' => [ 'employee' => [
'canAllow' => [ 'canAllow' => [
'employee' 'employee'
] ]
], ],
'admin' => [ 'admin' => [
'canAllow' => [ 'canAllow' => [
'admin', 'admin',
'reception', 'reception',
'employee' 'employee'
] ]
], ],
'reception' => [ 'reception' => [
'canAllow' => [ ] 'canAllow' => [ ]
] ]
]; ];
} }
public static function flash($mode, $message) { public static function flash($mode, $message) {
@ -322,26 +322,26 @@ class Helper {
public static function isUserCartVisibilityAll() { public static function isUserCartVisibilityAll() {
return \Yii::$app->params ['user_cart_item_visibility'] == 'all'; return \Yii::$app->params ['user_cart_item_visibility'] == 'all';
} }
public static function getBackendSkin() { public static function getBackendSkin() {
return \Yii::$app->params ['backend_skin'] ; return \Yii::$app->params ['backend_skin'] ;
} }
public static function getCompany() { public static function getCompany() {
return \Yii::$app->params ['company'] ; return \Yii::$app->params ['company'] ;
} }
public static function getCompanyName() { public static function getCompanyName() {
return \Yii::$app->params ['company_name'] ; return \Yii::$app->params ['company_name'] ;
} }
public static function isCompanyMovar() { public static function isCompanyMovar() {
return \Yii::$app->params ['company'] == 'movar'; return \Yii::$app->params ['company'] == 'movar';
} }
public static function isCompanyGyor() { public static function isCompanyGyor() {
return \Yii::$app->params ['company'] == 'gyor'; return \Yii::$app->params ['company'] == 'gyor';
} }
public static function isUserCartOn() { public static function isUserCartOn() {
return \Yii::$app->params ['user_cart_on'] == true; return \Yii::$app->params ['user_cart_on'] == true;
} }
@ -353,26 +353,26 @@ class Helper {
public static function isTicketTypeDoorAllowedCheckOn() { public static function isTicketTypeDoorAllowedCheckOn() {
return \Yii::$app->params ['ticket_type_door_allowed_check_on'] == true; return \Yii::$app->params ['ticket_type_door_allowed_check_on'] == true;
} }
public static function getProductSaleDefaultFocus() { public static function getProductSaleDefaultFocus() {
return \Yii::$app->params ['product_sale_default_focus'] ; return \Yii::$app->params ['product_sale_default_focus'] ;
} }
public static function isProductVisibilityAccount() { public static function isProductVisibilityAccount() {
return \Yii::$app->params ['product_visiblity'] == 'account'; return \Yii::$app->params ['product_visiblity'] == 'account';
} }
public static function isAccountStateClosePreloadMoney() { public static function isAccountStateClosePreloadMoney() {
return \Yii::$app->params ['account_state_close_preload_money'] == true; return \Yii::$app->params ['account_state_close_preload_money'] == true;
} }
public static function isAccountStateOpenSendMail() { public static function isAccountStateOpenSendMail() {
return \Yii::$app->params ['mail_account_state_open'] == true; return \Yii::$app->params ['mail_account_state_open'] == true;
} }
public static function isAccountStateCloseSendMail() { public static function isAccountStateCloseSendMail() {
return \Yii::$app->params ['mail_account_state_close'] == true; return \Yii::$app->params ['mail_account_state_close'] == true;
} }
public static function getReceptionVisibilityDays() { public static function getReceptionVisibilityDays() {
return \Yii::$app->params ['reception_visibility_days'] ; return \Yii::$app->params ['reception_visibility_days'] ;
} }
@ -399,12 +399,16 @@ class Helper {
public static function isReceptionTransferIndexEnabled(){ public static function isReceptionTransferIndexEnabled(){
return !Helper::isReceptionTransferListToday(); return !Helper::isReceptionTransferListToday();
} }
public static function getGroupTrainingUrl(){
return \Yii::$app->params['group_training.url'];
}
public static function getRealUserIp() { public static function getRealUserIp() {
$client = @$_SERVER ['HTTP_CLIENT_IP']; $client = @$_SERVER ['HTTP_CLIENT_IP'];
$forward = @$_SERVER ['HTTP_X_FORWARDED_FOR']; $forward = @$_SERVER ['HTTP_X_FORWARDED_FOR'];
$remote = $_SERVER ['REMOTE_ADDR']; $remote = $_SERVER ['REMOTE_ADDR'];
if (filter_var ( $client, FILTER_VALIDATE_IP )) { if (filter_var ( $client, FILTER_VALIDATE_IP )) {
$ip = $client; $ip = $client;
} elseif (filter_var ( $forward, FILTER_VALIDATE_IP )) { } elseif (filter_var ( $forward, FILTER_VALIDATE_IP )) {
@ -412,10 +416,10 @@ class Helper {
} else { } else {
$ip = $remote; $ip = $remote;
} }
return $ip; return $ip;
} }
public static function url_get_contents ($Url) { public static function url_get_contents ($Url) {
if (!function_exists('curl_init')){ if (!function_exists('curl_init')){
die('CURL is not installed!'); die('CURL is not installed!');
@ -427,14 +431,14 @@ class Helper {
curl_close($ch); curl_close($ch);
return $output; return $output;
} }
public static function getGeoIp() { public static function getGeoIp() {
$ip = Helper::getRealUserIp (); $ip = Helper::getRealUserIp ();
$details = json_decode ( Helper::url_get_contents( "http://ipinfo.io/{$ip}/json" ) ); $details = json_decode ( Helper::url_get_contents( "http://ipinfo.io/{$ip}/json" ) );
return $details; return $details;
} }
public static function mkYiiSortItem($field, $column){ public static function mkYiiSortItem($field, $column){
return [ return [
$field => [ $field => [
@ -454,7 +458,7 @@ class Helper {
} }
return $result; return $result;
} }
public static function setBit($val,$index,$bit_on){ public static function setBit($val,$index,$bit_on){
$flag = +$val; $flag = +$val;
if ( $bit_on ){ if ( $bit_on ){
@ -471,7 +475,7 @@ class Helper {
return $result ; return $result ;
} }
public static function generateRandomString($length = 6,$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWX' ) { public static function generateRandomString($length = 6,$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWX' ) {
$charactersLength = strlen($characters); $charactersLength = strlen($characters);
$randomString = ''; $randomString = '';
@ -480,7 +484,7 @@ class Helper {
} }
return $randomString; return $randomString;
} }
public static function getWebUrl(){ public static function getWebUrl(){
if ( \Yii::$app->params['development'] == true ){ if ( \Yii::$app->params['development'] == true ){
return "http://localhost/fitness-web"; return "http://localhost/fitness-web";
@ -529,5 +533,5 @@ class Helper {
return $result; return $result;
} }
} }

View File

@ -64,5 +64,6 @@ return [
'ticket_type_door_allowed_check_on' => false, 'ticket_type_door_allowed_check_on' => false,
'warn_ticket_expire_in_days_count' => 3, 'warn_ticket_expire_in_days_count' => 3,
'warn_ticket_expire_in_usage_count' => 3, 'warn_ticket_expire_in_usage_count' => 3,
'inventory.products.only.active' => true 'inventory.products.only.active' => true,
'group_training.url' => 'https://fitnessadmin.hu'
]; ];

View File

@ -0,0 +1,40 @@
<?php
namespace common\helpers;
class AppArrayHelper
{
public static function objectArrayToMap($array, $funcGetId, $funcGetValue){
$result = [];
foreach ($array as $item ){
$id = $funcGetId($item);
$value = $funcGetValue($item);
$result[$id] = $value;
}
return $result;
}
/**
* Map an array of object by object id
* [obj1,obj2] => [obj1.id => obj1,obj2.id => obj2]
* @param $array
* @return array
*/
public static function objectArrayToMapById($array){
return AppArrayHelper::objectArrayToMap(
$array,
function ($item){
return $item->id;
},
function ($item){
return $item;
}
);
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace common\helpers;
class AppDateTimeHelper
{
public static function convertMySqlDatetimeToPhpInteger($dateString){
if (!isset($dateString) || empty($dateString)){
return null;
}
$unixTime = strtotime($dateString . " UTC");
return $unixTime;
}
}

View File

@ -1,25 +1,28 @@
<?php <?php
use yii\helpers\Html;
use yii\helpers\Url; use frontend\models\PasswordChangeModel;
use common\components\Helper;
/* @var $model PasswordChangeModel */
?> ?>
<h1 style="font-size: 12px;">Kedves <?php echo $model->customer->name?>!</h1> <div>Kedves <?php echo $model->customer->name ?>!</div>
<p style="font-size: 12px;"> <p>
Az Ön új jelszava: Az Ön új jelszava:
</p> </p>
<ul style="font-size: 12px;"> <p>
<li> <?php echo $model->plainPassword ?>
"<?php echo $model->plainPassword ?>" </p>
</li> <p>A bejelentkezéshez kattintson a következő linkre: <a
</ul> href="<?php echo $model->groupTrainingUrl ?>"><?php echo $model->groupTrainingUrl ?></a></p>
<p style="font-size: 12px;"> <p>
Üdvözlettel: Üdvözlettel:
</p> </p>
<p style="font-size: 12px;"> <p>
<?php echo $model->companyName ?> <?php echo $model->companyName ?>
</p> </p>
<p> <p>
Ez egy automatikus e-mail üzenet, amelyre nem tud válaszolni. Ez egy automatikus e-mail üzenet, amelyre nem tud válaszolni.
</p> </p>
<?php <?php
?> ?>

View File

@ -161,7 +161,8 @@ class Event extends ActiveRecord
* @return EventRegistration[]|ActiveQuery * @return EventRegistration[]|ActiveQuery
*/ */
public function getActiveEventRegistrations(){ public function getActiveEventRegistrations(){
return $this->hasMany(EventRegistration::class,['id_event' => 'id'])->andWhere( return $this->hasMany(EventRegistration::class,['id_event' => 'id'])
->andWhere(
[ [
'event_registration.canceled_at' => null, 'event_registration.canceled_at' => null,
'event_registration.deleted_at' => null, 'event_registration.deleted_at' => null,
@ -169,19 +170,6 @@ class Event extends ActiveRecord
); );
} }
/**
* @return EventRegistration[]|ActiveQuery
*/
public function getActiveEventRegistrationsForCustomer(){
return $this->hasMany(EventRegistration::class,['id_event' => 'id'])->andWhere(
[
'event_registration.canceled_at' => null,
'event_registration.deleted_at' => null,
'event_registration.id_customer' => \Yii::$app->user->id
]
);
}
/** /**
* @return integer * @return integer
*/ */

View File

@ -57,45 +57,52 @@ class EventRegistration extends \yii\db\ActiveRecord
public function behaviors() public function behaviors()
{ {
return ArrayHelper::merge( [ return ArrayHelper::merge([
[ [
'class' => TimestampBehavior::className(), 'class' => TimestampBehavior::className(),
'value' => function(){ return date('Y-m-d H:i:s' ); } 'value' => function () {
return date('Y-m-d H:i:s');
}
] ]
], ],
parent::behaviors()); parent::behaviors());
} }
public function getEvent(){ public function getEvent()
return $this->hasOne($this->getEventClass(),['id' => 'id_event']); {
return $this->hasOne($this->getEventClass(), ['id' => 'id_event']);
} }
public function getCustomer(){ public function getCustomer()
return $this->hasOne($this->getCustomerClass(),['id' => 'id_customer']); {
return $this->hasOne($this->getCustomerClass(), ['id' => 'id_customer']);
} }
public function getEventClass(){ public function getEventClass()
{
return Event::class; return Event::class;
} }
public function getCustomerClass(){ public function getCustomerClass()
{
return Customer::class; return Customer::class;
} }
/** /**
* @param EventRegistration $eventRegistration * @param EventRegistration $eventRegistration
*/ */
public static function isActive($eventRegistration){ public static function isActive($eventRegistration)
if ( !isset($eventRegistration ) ){ {
if (!isset($eventRegistration)) {
return false; return false;
} }
if ( isset($eventRegistration->canceled_at ) ){ if (isset($eventRegistration->canceled_at)) {
return false; return false;
} }
if ( isset($eventRegistration->deleted_at ) ){ if (isset($eventRegistration->deleted_at)) {
return false; return false;
} }
@ -105,32 +112,40 @@ class EventRegistration extends \yii\db\ActiveRecord
/** /**
* @param EventRegistration $eventRegistration * @param EventRegistration $eventRegistration
*/ */
public static function isForCustomer($eventRegistration,$idCustomer){ public static function isForCustomer($eventRegistration, $idCustomer)
if ( !isset($eventRegistration ) ){ {
if (!isset($eventRegistration)) {
return false; return false;
} }
if ( !isset($eventRegistration->id_customer ) ){ if (!isset($eventRegistration->id_customer)) {
return false; return false;
} }
return $eventRegistration->id_customer == $idCustomer; return $eventRegistration->id_customer == $idCustomer;
} }
/** /**
* @param EventRegistration[] $eventRegistrations * @param EventRegistration[] $eventRegistrations
*/ */
public static function filterActive($eventRegistrations){ public static function filterActive($eventRegistrations)
return array_filter($eventRegistrations, EventRegistration::class.'::isActive' ); {
if (!isset($eventRegistrations)) {
return [];
}
return array_filter($eventRegistrations, EventRegistration::class . '::isActive');
} }
/** /**
* @param EventRegistration[] $eventRegistrations * @param EventRegistration[] $eventRegistrations
*/ */
public static function filterForCustomer($eventRegistrations,$idCustomer){ public static function filterForCustomer($eventRegistrations, $idCustomer)
{
$result = []; $result = [];
foreach ($eventRegistrations as $eventRegistration){ if (isset($eventRegistrations)) {
if ( EventRegistration::isForCustomer($eventRegistration,$idCustomer)){ foreach ($eventRegistrations as $eventRegistration) {
$result[] = $eventRegistration; if (EventRegistration::isForCustomer($eventRegistration, $idCustomer)) {
$result[] = $eventRegistration;
}
} }
} }
return $result; return $result;

View File

@ -11,6 +11,7 @@ use yii\helpers\ArrayHelper;
* *
* @property integer $id * @property integer $id
* @property string $name * @property string $name
* @property string $theme
* @property string $created_at * @property string $created_at
* @property string $updated_at * @property string $updated_at
*/ */
@ -30,9 +31,10 @@ class EventType extends \yii\db\ActiveRecord
public function rules() public function rules()
{ {
return [ return [
[['name'], 'required'], [['name','theme'], 'required'],
[['name'], 'unique'], [['name'], 'unique'],
[['name'], 'string', 'max' => 255] [['name'], 'string', 'max' => 255],
[['theme'], 'string', 'max' => 50]
]; ];
} }
@ -104,4 +106,12 @@ class EventType extends \yii\db\ActiveRecord
// TODO: implement bossiness logic to select ticket // TODO: implement bossiness logic to select ticket
return $possibleTickets[0]; return $possibleTickets[0];
} }
static function themes() {
$themes = [];
for ($x = 0; $x < 10; $x++) {
$themes[$x] = "Színtéma " . ($x+1);
}
return $themes;
}
} }

View File

@ -2,6 +2,7 @@
namespace common\models; namespace common\models;
use common\helpers\AppArrayHelper;
use Yii; use Yii;
use yii\behaviors\TimestampBehavior; use yii\behaviors\TimestampBehavior;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;

View File

@ -3,10 +3,12 @@
namespace common\modules\event\manager; namespace common\modules\event\manager;
use common\models\Event; use common\models\Event;
use common\models\EventRegistration;
use common\modules\event\models\timetable\TimeTableMonth; use common\modules\event\models\timetable\TimeTableMonth;
use common\modules\event\models\timetable\TimeTableMonthDay; use common\modules\event\models\timetable\TimeTableMonthDay;
use common\modules\event\models\timetable\TimeTableMonthWeek; use common\modules\event\models\timetable\TimeTableMonthWeek;
use customerapi\models\available\EventInterval; use customerapi\models\available\EventInterval;
use customerapi\models\details\EventRegistrationView;
use DateTime; use DateTime;
use Exception; use Exception;
use yii\db\Query; use yii\db\Query;
@ -23,13 +25,14 @@ class EventManager
* @throws \yii\base\Exception on any error * @throws \yii\base\Exception on any error
* @throws StaleObjectException * @throws StaleObjectException
*/ */
public function deleteEvent($id){ public function deleteEvent($id)
{
$event = Event::findOne($id); $event = Event::findOne($id);
if ( !isset($event)){ if (!isset($event)) {
throw new \yii\base\Exception("Event $id not found"); throw new \yii\base\Exception("Event $id not found");
} }
$registrations = $event->eventRegistrations; $registrations = $event->eventRegistrations;
if ( !isset($registrations) || count($registrations) === 0 ){ if (!isset($registrations) || count($registrations) === 0) {
$event->delete(); $event->delete();
} else { } else {
$event->deleted_at = time(); $event->deleted_at = time();
@ -43,7 +46,7 @@ class EventManager
* @return TimeTableMonth * @return TimeTableMonth
* @throws Exception * @throws Exception
*/ */
public function loadTimeTable($interval , $activeOrDisplayInterval = "active" ) public function loadTimeTable($interval, $activeOrDisplayInterval = "active")
{ {
$timeTable = new TimeTableMonth(); $timeTable = new TimeTableMonth();
@ -73,11 +76,11 @@ class EventManager
$timeTable->weeks[$weekNumber]->$weekDayName = $timeTableMonthDay; $timeTable->weeks[$weekNumber]->$weekDayName = $timeTableMonthDay;
} }
if ( $activeOrDisplayInterval == "active"){ if ($activeOrDisplayInterval == "active") {
$dateTimeFrom = $interval->firstActiveDate; $dateTimeFrom = $interval->firstActiveDate;
$to = clone $interval->lastActiveDate; $to = clone $interval->lastActiveDate;
$dateTimeTo = $to->modify('+1 day'); $dateTimeTo = $to->modify('+1 day');
}else{ } else {
// active // active
$dateTimeFrom = $interval->firstDisplayDate; $dateTimeFrom = $interval->firstDisplayDate;
$to = clone $interval->lastDisplayDate; $to = clone $interval->lastDisplayDate;
@ -85,7 +88,7 @@ class EventManager
} }
// get events between active dates // get events between active dates
$events =$this->getEvents($dateTimeFrom,$dateTimeTo); $events = $this->getEvents($dateTimeFrom, $dateTimeTo);
// set events per day // set events per day
/** @var Event $event */ /** @var Event $event */
@ -108,8 +111,8 @@ class EventManager
/** /**
* Get all active events between the to dates * Get all active events between the to dates
* @param DateTime $fromInc from date inclusive (>=) * @param DateTime $fromInc from date inclusive (>=)
* @param DateTime $toExcl to date exclusive (<) * @param DateTime $toExcl to date exclusive (<)
* @return Event[] * @return Event[]
*/ */
public function getEvents($fromInc, $toExcl) public function getEvents($fromInc, $toExcl)
@ -150,18 +153,61 @@ class EventManager
public function getEventsForDay($date) public function getEventsForDay($date)
{ {
$start = clone $date; $start = clone $date;
$start->setTime(0,0); $start->setTime(0, 0);
$to = clone $start; $to = clone $start;
$to->modify('+1 day'); $to->modify('+1 day');
return $this->getEvents($start,$to); return $this->getEvents($start, $to);
} }
public function getEvent($id){ public function getEvent($id)
{
return Event::findOne($id); return Event::findOne($id);
} }
public function findActiveRegistrations($idEvent, $idCustomer = null)
{
$registrations = EventRegistrationView::find()->andWhere(['id_event' => $idEvent, 'id_customer' => \Yii::$app->user->id])->all();
$allActiveRegistrations = EventRegistration::filterActive($registrations);
if (isset($idCustomer)) {
$allActiveRegistrations = EventRegistration::filterForCustomer($allActiveRegistrations, \Yii::$app->user->id);
}
return $allActiveRegistrations;
}
public function findActiveEvent($idEvent, $interval, $withRelatedObjects = false)
{
$paramEventStartMax = (clone $interval->lastActiveDate);
$paramEventStartMax = $paramEventStartMax->modify('+1 day');
$paramEventStartMax = $paramEventStartMax->getTimestamp();
$query = Event::find()
->andWhere(['event.id' => $idEvent])
->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()])
->andWhere(['<', 'event.start', $paramEventStartMax])
->andWhere(['event.active' => '1']);
if ($withRelatedObjects) {
$query = $query->innerJoinWith('trainer')
->innerJoinWith('eventType')
->innerJoinWith('room');
}
return $query->one();
}
public function findActiveEvents($interval)
{
$paramEventStartMax = (clone $interval->lastActiveDate);
$paramEventStartMax = $paramEventStartMax->modify('+1 day');
$paramEventStartMax = $paramEventStartMax->getTimestamp();
return Event::find()
->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()])
->andWhere(['<', 'event.start', $paramEventStartMax])
->andWhere(['event.active' => '1'])->all();
}
} }

View File

@ -0,0 +1,42 @@
<?php
use yii\db\Migration;
/**
* Class m210930_101018_alter_table_event_type_add_field_color
*/
class m210930_101018_alter_table_event_type_add_field_color extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn("event_type",'theme',$this->string(50));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
echo "m210930_101018_alter_table_event_type_add_field_color cannot be reverted.\n";
return false;
}
/*
// Use up()/down() to run migration code without a transaction.
public function up()
{
}
public function down()
{
echo "m210930_101018_alter_table_event_type_add_field_color cannot be reverted.\n";
return false;
}
*/
}

View File

@ -47,11 +47,13 @@ export class FakeBackendInterceptor implements HttpInterceptor {
let eventTypes: EventType[] = [ let eventTypes: EventType[] = [
{ {
id: 1, id: 1,
name: 'Típus 1' name: 'Típus 1',
theme: '0'
}, },
{ {
id: 2, id: 2,
name: 'Típus 2' name: 'Típus 2',
theme: '0'
} }
]; ];

View File

@ -39,6 +39,7 @@ import {environment} from "../environments/environment";
import {AppState} from "./state/app.state"; import {AppState} from "./state/app.state";
import {NgxsReduxDevtoolsPluginModule} from "@ngxs/devtools-plugin"; import {NgxsReduxDevtoolsPluginModule} from "@ngxs/devtools-plugin";
import {NgxsLoggerPluginModule} from "@ngxs/logger-plugin"; import {NgxsLoggerPluginModule} from "@ngxs/logger-plugin";
import { EventDatePipe } from './pipes/event-time.pipe';
@ -66,6 +67,7 @@ registerLocaleData(localeHu, 'hu');
GuestLayoutComponent, GuestLayoutComponent,
SecuredLayoutComponent, SecuredLayoutComponent,
PasswordChangeComponent, PasswordChangeComponent,
EventDatePipe,
], ],
imports: [ imports: [

View File

@ -0,0 +1,26 @@
import { Injectable } from '@angular/core';
import * as moment from "moment";
@Injectable({
providedIn: 'root'
})
export class AppService {
constructor() { }
formatDateTime(datetime: number, date:boolean, time: boolean) {
let format ;
if ( date && time ){
format = 'YYYY.MM.DD HH:mm';
} else if (date){
format = 'YYYY.MM.DD';
} else {
format = 'HH:mm';
}
return this.dateToMoment(datetime).utc().format(format);
}
dateToMoment(date: number) {
return moment.unix(date);
}
}

View File

@ -1,6 +1,6 @@
import {Component, forwardRef, OnInit} from '@angular/core'; import {Component, forwardRef, OnInit} from '@angular/core';
import {EventService, EventType} from "../../services/event.service"; import {EventService, EventType} from "../../services/event.service";
import {ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR} from "@angular/forms"; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
const FIT_EVENT_TYPES_VALUE_ACCESSOR: any = { const FIT_EVENT_TYPES_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
@ -22,10 +22,8 @@ export class FitEventTypesComponent implements OnInit, ControlValueAccessor {
private onChange: Function; private onChange: Function;
private onTouched: Function; private onTouched: Function;
public value: string; public value: string;
constructor(private eventService: EventService) { constructor(private eventService: EventService) {
this.onChange = (_: any) => { }; this.onChange = (_: any) => { };
this.onTouched = () => { }; this.onTouched = () => { };
@ -34,7 +32,7 @@ export class FitEventTypesComponent implements OnInit, ControlValueAccessor {
ngOnInit() { ngOnInit() {
this.eventService.findAllEventTypes() this.eventService.findAllEventTypes()
.subscribe(value => { .subscribe(value => {
this.types = [{ id: -1, name: 'Minden Típus'}].concat( value); this.types = [{ id: -1, name: 'Minden Típus', theme: '' }].concat( value);
this._setValue(this.types[0].id); this._setValue(this.types[0].id);
} }
); );

View File

@ -6,7 +6,8 @@
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" [collapse]="isCollapsed" > <div class="collapse navbar-collapse justify-content-end d-lg-flex"
[collapse]="isCollapsed" >
<ul class="navbar-nav ml-auto"> <ul class="navbar-nav ml-auto">
<ng-container *ngFor="let item of items" > <ng-container *ngFor="let item of items" >
<li *ngIf="isVisible(item)" class="nav-item " [routerLinkActive]="'active'"> <li *ngIf="isVisible(item)" class="nav-item " [routerLinkActive]="'active'">

View File

@ -13,7 +13,7 @@ export class FitNavigationComponent implements OnInit {
items: MenuItem[] = [ items: MenuItem[] = [
{ {
route: '/home', route: '/home',
label: 'Home', label: 'Órarend',
roles: ['*'] roles: ['*']
}, },
// { // {

View File

@ -1,22 +1,22 @@
<div <div
(click)="selectEvent()" (click)="selectEvent()"
class="event d-flex flex-direction-row py-1 px-1 mb-2 border-radius-1 small text-white " class="event d-flex flex-direction-row py-1 px-1 mb-2 border-radius-1 small text-white {{getEventThemeClass()}}"
title="Test Event 2" title="Test Event 2"
[class.bg-dark]="maySelect()"
[class.bg-primary]="isRegistered()"
[class.bg-secondary]="isDisabled()"
> >
<!-- [class.bg-dark]="maySelect()"-->
<!-- [class.bg-primary]="isRegistered()"-->
<!-- [class.bg-secondary]="isDisabled()"-->
<div class=" event-bar-container flex-grow-0 flex-shrink-0 d-flex" style="flex-basis: 10px;"> <div class=" event-bar-container flex-grow-0 flex-shrink-0 d-flex" style="flex-basis: 10px;">
<div class="event-bar flex-grow-1 flex-shrink-1 my-1 border-radius-1 " style=" background-color: var(--bs-blue)"></div> <div class="event-bar flex-grow-1 flex-shrink-1 my-1 border-radius-1 bg-white" ></div>
</div> </div>
<div class="event-info-container flex-grow-1 flex-shrink-1 " style="flex-basis: 0;" > <div class="event-info-container flex-grow-1 flex-shrink-1 " style="flex-basis: 0;" >
<div class="event-info ms-1" style="white-space: pre-wrap"> <div class="event-info ms-1" style="white-space: pre-wrap">
<div class="app-font-size-sm app-font-weight-normal ">{{formatTime()}}</div> <div class="app-font-size-sm app-font-weight-normal ">{{event.start | eventDate:'time' }}</div>
<div class="app-font-size-sm app-font-weight-bold">{{event.eventType.name}}</div> <div class="app-font-size-sm app-font-weight-bold">{{event.eventType.name}}</div>
<ng-container *ngIf="hasTrainer()"> <ng-container *ngIf="hasTrainer()">
<div class="app-font-size-sm app-font-weight-normal " style="max-width: 100%; word-break: break-word">{{formatTrainer()}} very long name</div> <div class="app-font-size-sm app-font-weight-normal " style="max-width: 100%; word-break: break-word">{{formatTrainer()}}</div>
</ng-container> </ng-container>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Event} from "../../services/event.service"; import {Event} from "../../services/event.service";
import {dateToMoment, MonthCalendarEvent} from "../month-calendar/month-calendar.component"; import { MonthCalendarEvent} from "../month-calendar/month-calendar.component";
@Component({ @Component({
selector: 'app-month-calendar-event', selector: 'app-month-calendar-event',
@ -21,10 +21,6 @@ export class MonthCalendarEventComponent implements OnInit {
ngOnInit() { ngOnInit() {
} }
formatTime() {
return dateToMoment(this.event.start).utc().format('HH:mm');
}
hasTrainer() { hasTrainer() {
return !!this.event.trainer; return !!this.event.trainer;
} }
@ -42,7 +38,7 @@ export class MonthCalendarEventComponent implements OnInit {
} }
maySelect() { maySelect() {
return this.event.registrations?.length == 0 && this.event.hasFreeSeats; return this.isRegistered() ? true : this.event.hasFreeSeats;
} }
isRegistered() { isRegistered() {
@ -50,6 +46,30 @@ export class MonthCalendarEventComponent implements OnInit {
} }
isDisabled() { isDisabled() {
return false; return !this.isRegistered() && !this.event.hasFreeSeats;
}
getEventThemeClass(): string {
const theme = this.event?.eventType?.theme;
let styleClass = "bg-dark";
if (this.isDisabled()) {
styleClass = "bg-secondary";
} else {
if (theme != null && theme.length > 0) {
if (this.isRegistered()) {
styleClass += " event-theme-active-" + theme;
} else {
styleClass += " event-theme-normal-" + theme;
}
} else {
if (this.isRegistered()) {
styleClass += " bg-primary";
} else {
styleClass += " bg-dark";
}
}
}
return styleClass;
} }
} }

View File

@ -15,11 +15,11 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-3 col-12 app-font-weight-bold"><span class="title">Edzés kezdési időpontja</span></div> <div class="col-lg-3 col-12 app-font-weight-bold"><span class="title">Edzés kezdési időpontja</span></div>
<div class="col-lg-6 col-12"><span>{{event.start * 1000 | date:'yyyy.MM.dd HH:mm'}}</span></div> <div class="col-lg-6 col-12"><span>{{event.start | eventDate:'datetime'}}</span></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-3 col-12 app-font-weight-bold"><span class="title">Edzés vége</span></div> <div class="col-lg-3 col-12 app-font-weight-bold"><span class="title">Edzés vége</span></div>
<div class="col-lg-6 col-12"><span>{{event.end * 1000 | date:'yyyy.MM.dd HH:mm'}}</span></div> <div class="col-lg-6 col-12"><span>{{event.end | eventDate: 'datetime'}}</span></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-3 col-12 app-font-weight-bold"><span class="title">Férőhelyek száma</span></div> <div class="col-lg-3 col-12 app-font-weight-bold"><span class="title">Férőhelyek száma</span></div>

View File

@ -41,8 +41,8 @@ export class EventDetailsComponent implements OnInit {
ngOnInit() { ngOnInit() {
let idEvent = +this.route.snapshot.paramMap.get('idEvent'); let idEvent = +this.route.snapshot.paramMap.get('idEvent');
this.eventService.findEvent(idEvent).subscribe( this.eventService.findEvent(idEvent).subscribe(
value => { event => {
this.event = value; this.event = event;
this.eventForm.patchValue({"idEvent": this.event.id}) this.eventForm.patchValue({"idEvent": this.event.id})
} }
); );
@ -74,7 +74,7 @@ export class EventDetailsComponent implements OnInit {
this.eventService.register(request) this.eventService.register(request)
.subscribe( .subscribe(
value => { value => {
this.toastr.success('Sikeresen Foglalás', 'Foglalás'); this.toastr.success('Sikeres Foglalás', 'Foglalás');
this.goBack(); this.goBack();
}, },
@ -106,6 +106,7 @@ export class EventDetailsComponent implements OnInit {
this.eventService.cancelRegistration(event.registrations[0].id) this.eventService.cancelRegistration(event.registrations[0].id)
.subscribe( .subscribe(
() => { () => {
this.toastr.success("Sikeres lemondás", "Lemondás")
this.goBack(); this.goBack();
}, },
() => { () => {

View File

@ -25,6 +25,18 @@
<div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Terem</span></div> <div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Terem</span></div>
<div class="col-lg-9 col-sm-12"><span>{{registration.event?.room?.name }}</span></div> <div class="col-lg-9 col-sm-12"><span>{{registration.event?.room?.name }}</span></div>
</div> </div>
<div class="row">
<div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Regisztráció időpontja</span></div>
<div class="col-lg-9 col-sm-12"><span>{{registration.created_at | eventDate:'datetime' }}</span></div>
</div>
<div class="row" *ngIf="registrationService.isCanceled(registration)">
<div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Regisztráció lemondásának időpontja</span></div>
<div class="col-lg-9 col-sm-12"><span>{{registration.canceled_at | eventDate:'datetime' }}</span></div>
</div>
<div class="row" *ngIf="registrationService.isDeleted(registration)">
<div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Regisztráció törlésének időpontja</span></div>
<div class="col-lg-9 col-sm-12"><span>{{registration.deleted_at | eventDate:'datetime' }}</span></div>
</div>
<div class="row"> <div class="row">
<div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Státusz</span></div> <div class="col-lg-3 col-sm-12 app-font-weight-bold"><span class="title">Státusz</span></div>
<div class="col-lg-9 col-sm-12"> <div class="col-lg-9 col-sm-12">

View File

@ -1,16 +1,28 @@
<!-- <app-fit-weekday-selector [days]="(availableEvents | async)?.days" ></app-fit-weekday-selector>--> <!-- <app-fit-weekday-selector [days]="(availableEvents | async)?.days" ></app-fit-weekday-selector>-->
<ng-container *ngIf="registrations | async"> <ng-container *ngIf="registrations | async">
<div class="row text-white mb-2 mx-1 align-middle" *ngFor="let registration of (registrations | async); let i = index; " <ng-container *ngIf="!(registrations | async)?.length">
(click)="showRegistration(registration)" Jelenleg nincsen aktív foglalása
[class.mt-2]="i == 0" </ng-container>
> <ng-container *ngIf="(registrations | async)?.length">
<div class="col-12 col-md-9 bg-dark d-flex d-flex align-items-center py-2 " > <div class="row text-white mb-2 mx-1 align-middle"
{{(registration.event.start * 1000) | date:'yyyy.MM.dd HH:mm'}} - {{registration.event.eventType.name}} *ngFor="let registration of (registrations | async); let i = index; "
- {{registration.event.trainer.name}} (click)="showRegistration(registration)"
</div> [class.mt-2]="i == 0"
<div class="col-3 bg-dark py-2 d-none d-md-block text-end" > >
<div class="col-12 col-md-9 bg-dark d-lg-flex align-items-lg-center py-2 ">
<fa-icon [classes]="['text-success','me-2']" *ngIf="registrationService.isActive(registration)"
[icon]="faCalendarCheck"></fa-icon>
<fa-icon [classes]="['text-warning','me-2']" *ngIf="registrationService.isCanceled(registration)"
[icon]="faCalendarMinus"></fa-icon>
<fa-icon [classes]="['text-danger','me-2']" *ngIf="registrationService.isDeleted(registration)"
[icon]="faCalendarTimes"></fa-icon>
{{ registration.event.start | eventDate: 'datetime' }} - {{registration.event.eventType.name}}
- {{registration.event.trainer.name}}
</div>
<div class="col-3 bg-dark py-2 d-none d-md-block text-end">
<a class="btn btn-primary float-right">Részletek</a> <a class="btn btn-primary float-right">Részletek</a>
</div> </div>
</div> </div>
</ng-container>
</ng-container> </ng-container>

View File

@ -3,6 +3,9 @@ import {Observable} from "rxjs";
import {EventService, Registration} from "../../services/event.service"; import {EventService, Registration} from "../../services/event.service";
import {NavigationService} from "../../services/navigation.service"; import {NavigationService} from "../../services/navigation.service";
import {flatMap, map, mergeMap} from "rxjs/operators"; import {flatMap, map, mergeMap} from "rxjs/operators";
import {RegistrationService} from "../../services/reservation.service";
import { faCalendarCheck, faCalendarMinus, faCalendarTimes } from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'app-registrations', selector: 'app-registrations',
@ -10,9 +13,14 @@ import {flatMap, map, mergeMap} from "rxjs/operators";
styleUrls: ['./registrations.component.scss'] styleUrls: ['./registrations.component.scss']
}) })
export class RegistrationsComponent implements OnInit { export class RegistrationsComponent implements OnInit {
faCalendarCheck = faCalendarCheck;
faCalendarMinus = faCalendarMinus;
faCalendarTimes = faCalendarTimes;
registrations: Observable<Registration[]>; registrations: Observable<Registration[]>;
constructor(private eventService: EventService, private navigationService: NavigationService) { } constructor(private eventService: EventService,
private navigationService: NavigationService,
public registrationService: RegistrationService) { }
ngOnInit() { ngOnInit() {
this.registrations = this.eventService.findRegistrations() this.registrations = this.eventService.findRegistrations()

View File

@ -0,0 +1,19 @@
import { Pipe, PipeTransform } from '@angular/core';
import {AppService} from "../app.service";
@Pipe({
name: 'eventDate'
})
export class EventDatePipe implements PipeTransform {
constructor(private appService: AppService) {
}
transform(unixtime: number, format: 'date' | 'time' | 'datetime' ): unknown {
const date = format == 'date' || format == 'datetime';
const time = format == 'time' || format == 'datetime';
return this.appService.formatDateTime(unixtime,date,time);
}
}

View File

@ -88,6 +88,7 @@ export interface Room {
export interface EventType { export interface EventType {
id: number; id: number;
name: string; name: string;
theme: string;
} }
export interface DayToDisplay { export interface DayToDisplay {

View File

@ -8,13 +8,13 @@ export class RegistrationService {
constructor() { } constructor() { }
public isCanceled(registration: Registration){
return registration.canceled_at != null;
}
public isDeleted(registration: Registration){ public isDeleted(registration: Registration){
return registration.deleted_at != null; return registration.deleted_at != null;
} }
public isCanceled(registration: Registration){
return !this.isDeleted(registration) && registration.canceled_at != null;
}
public isActive(registration: Registration){ public isActive(registration: Registration){
return !this.isDeleted(registration) && !this.isCanceled(registration) return !this.isDeleted(registration) && !this.isCanceled(registration)

View File

@ -1,6 +1,7 @@
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
$font-size-xs: 0.625rem; $font-size-xs: 0.625rem;
$font-size-sm: 1rem; $font-size-sm: 1rem;
$font-size-md: 1.25rem; $font-size-md: 1.25rem;
@ -54,6 +55,7 @@ $btn-border-radius: $border-radius-0;
@import '~ngx-toastr/toastr'; @import '~ngx-toastr/toastr';
@import "styles/bootstrap-custom"; @import "styles/bootstrap-custom";
@import "styles/fonts"; @import "styles/fonts";
@import "styles/event.themes";
html{ html{
height: 100%; height: 100%;
} }
@ -65,3 +67,6 @@ body{
background-repeat: repeat-y; background-repeat: repeat-y;
} }

View File

@ -0,0 +1,52 @@
$event-color-yellow: #ECB809; // - sárga
$event-color-burgundy :#AE173B; // - bordó
$event-color-pink :#DF429B; // - pink
$event-color-purple :#B929B1; // - lila
$event-color-turquoise :#3EBFAE; // - türkiz
$event-color-blue :#6594D1; // - kék
$event-color-orange :#F1591A; // - narancs
$event-color-green :#30B211; // - zöld
$event-color-red :#E82A36; // - piros
$event-color-brown :#98701E; // - barna
$event-theme-0: $event-color-yellow; // - sárga
$event-theme-1 :$event-color-burgundy; // - bordó
$event-theme-2 :$event-color-pink; // - pink
$event-theme-3 :$event-color-purple; // - lila
$event-theme-4 :$event-color-turquoise; // - türkiz
$event-theme-5 :$event-color-blue; // - kék
$event-theme-6 :$event-color-orange; // - narancs
$event-theme-7 :$event-color-green; // - zöld
$event-theme-8 :$event-color-red; // - piros
$event-theme-9 :$event-color-brown; // - barna
$event-themes: (
"0": $event-theme-0,
"1": $event-theme-1,
"2": $event-theme-2,
"3": $event-theme-3,
"4": $event-theme-4,
"5": $event-theme-5,
"6": $event-theme-6,
"7": $event-theme-7,
"8": $event-theme-8,
"9": $event-theme-9
);
@each $name, $color in $event-themes {
@debug "event theme - divider offset:";
.event-theme-normal-#{$name} {
.event-bar{
background-color: #{$color} !important;
}
}
.event-theme-active-#{$name}{
background-color: #{$color} !important;
}
}

View File

@ -9,12 +9,18 @@
namespace customerapi\controllers; namespace customerapi\controllers;
use common\helpers\AppArrayHelper;
use common\models\Event; use common\models\Event;
use common\models\EventRegistration; use common\models\EventRegistration;
use common\models\EventType; use common\models\EventType;
use common\models\Trainer;
use common\modules\event\manager\EventManager;
use customerapi\manager\EventRegistrationManager; use customerapi\manager\EventRegistrationManager;
use customerapi\models\available\EventInterval; use customerapi\models\available\EventInterval;
use customerapi\models\available\EventAvailable; use customerapi\models\available\EventAvailable;
use customerapi\models\available\EventTypeAvailable;
use customerapi\models\available\RoomAvailable;
use customerapi\models\available\TrainerAvailable;
use customerapi\models\DayToDisplay; use customerapi\models\DayToDisplay;
use customerapi\models\details\EventDetailsView; use customerapi\models\details\EventDetailsView;
use customerapi\models\details\EventRegistrationView; use customerapi\models\details\EventRegistrationView;
@ -23,6 +29,7 @@ use customerapi\models\details\RoomDetailsView;
use customerapi\models\details\TrainerDetailsView; use customerapi\models\details\TrainerDetailsView;
use DateTime; use DateTime;
use Exception; use Exception;
use yii\db\ActiveQuery;
use yii\db\Query; use yii\db\Query;
use yii\web\Response; use yii\web\Response;
@ -58,37 +65,42 @@ class EventController extends \customerapi\controllers\CustomerApiController
$dates[] = $dayToDisplay; $dates[] = $dayToDisplay;
} }
// get events between active dates $eventManager = new EventManager();
$query = EventAvailable::find(); $events = $eventManager->findActiveEvents($interval);
$query = $query->select( $trainers = AppArrayHelper::objectArrayToMapById( TrainerAvailable::find()->all() );
[ $rooms = AppArrayHelper::objectArrayToMapById( RoomAvailable::find()->all() );
'{{event}}.*', $eventTypes = AppArrayHelper::objectArrayToMapById( EventTypeAvailable::find()->all() );
// 'COUNT({{event_registration}}.id) AS reservationCount'
]);
$paramEventStartMax = clone $interval->lastActiveDate;
$paramEventStartMax = $paramEventStartMax->modify('+1 day');
$paramEventStartMax = $paramEventStartMax->getTimestamp();
$events = $query
->innerJoinWith('trainer') $availableEvents = [];
->innerJoinWith('eventType')
->innerJoinWith('room') /** @var $event /common/models/Event $event */
->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()]) foreach ($events as $event ){
->andWhere(['<', 'event.start', $paramEventStartMax]) $availableEvent = EventAvailable::fromEvent($event);
->andWhere(['event.active' => '1']) $availableEvent->trainer = $trainers[$event->id_trainer];
->all(); $availableEvent->room = $rooms[$event->id_room];
$availableEvent->eventType = $eventTypes[$event->id_event_type];
$totalRegistrations = $eventManager->findActiveRegistrations($event->id);
$customerRegistration = EventRegistration::filterForCustomer($totalRegistrations,\Yii::$app->user->id);
$availableEvent->registrationCount = count($totalRegistrations);
$availableEvent->eventRegistrations = $customerRegistration;
$availableEvent->hasFreeSeats = $availableEvent->registrationCount < $availableEvent->seat_count;
$availableEvents[] = $availableEvent;
}
// set events per day // set events per day
/** @var EventAvailable $event */ /** @var EventAvailable $event */
foreach ($events as $event) { foreach ($availableEvents as $event) {
$eventDay = new DateTime(); $eventDay = new DateTime();
$eventDay->setTimestamp($event->start); $eventDay->setTimestamp($event->start);
$eventDay->setTime(0, 0); $eventDay->setTime(0, 0);
$event->reservationCount = $event->getEventRegistrationCount();
$event->hasFreeSeats = $event->reservationCount < $event->seat_count;
/** @var DayToDisplay $date */ /** @var DayToDisplay $date */
foreach ($dates as $date) { foreach ($dates as $date) {
if ($date->date === $eventDay->getTimestamp()) { if ($date->date === $eventDay->getTimestamp()) {
@ -122,11 +134,13 @@ class EventController extends \customerapi\controllers\CustomerApiController
$paramEventStartMax = $paramEventStartMax->modify('+1 day'); $paramEventStartMax = $paramEventStartMax->modify('+1 day');
$paramEventStartMax = $paramEventStartMax->getTimestamp(); $paramEventStartMax = $paramEventStartMax->getTimestamp();
/** @var ActiveQuery $query */
return $query return $query
->innerJoinWith('trainer') ->innerJoinWith('trainer')
->innerJoinWith('eventType') ->innerJoinWith('eventType')
->innerJoinWith('room') ->innerJoinWith('room')
->joinWith('activeEventRegistrations','event.id = activeEventRegistrations.id_event') ->joinWith('activeEventRegistrations')
->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()]) ->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()])
->andWhere(['<', 'event.start', $paramEventStartMax]) ->andWhere(['<', 'event.start', $paramEventStartMax])
->andWhere(['event.active' => '1']); ->andWhere(['event.active' => '1']);
@ -141,14 +155,10 @@ class EventController extends \customerapi\controllers\CustomerApiController
public function actionEvent($id_event) public function actionEvent($id_event)
{ {
$interval = EventInterval::createInterval(); $interval = EventInterval::createInterval();
$manger = new EventManager();
try { try {
$query = Event::find();
$query = $this->buildEventQuery($query, $interval);
$query = $query->andWhere(['event.id' => $id_event]);
/** @var Event $event */ /** @var Event $event */
$event = $query->one(); $event = $manger->findActiveEvent($id_event,$interval);
$result = new EventDetailsView(); $result = new EventDetailsView();
$result->id = $event->id; $result->id = $event->id;
$result->start = $event->start; $result->start = $event->start;

View File

@ -29,7 +29,7 @@ class EventRegistrationController extends CustomerApiController
public function actionIndex() public function actionIndex()
{ {
$registrationManager = new EventRegistrationManager(); $registrationManager = new EventRegistrationManager();
return $this->asJson( $registrationManager->findCustomerRegistrationsWithEvent() ); return $this->asJson( $registrationManager->findCustomerRegistrationsWithEvent(\Yii::$app->user->id) );
} }
/** @noinspection PhpUnused */ /** @noinspection PhpUnused */
@ -42,7 +42,7 @@ class EventRegistrationController extends CustomerApiController
{ {
$registrationManager = new EventRegistrationManager(); $registrationManager = new EventRegistrationManager();
return $this->asJson( return $this->asJson(
$registrationManager->findRegistration($id_registration) $registrationManager->findRegistration($id_registration,\Yii::$app->user->id)
); );
} }

View File

@ -2,9 +2,11 @@
namespace customerapi\manager; namespace customerapi\manager;
use common\models\EventRegistration; use common\models\EventRegistration;
use common\modules\event\manager\EventManager;
use customerapi\models\available\EventInterval; use customerapi\models\available\EventInterval;
use customerapi\models\registrations\EventRegistrationAvailable; use customerapi\models\dto\EventDTO;
use yii\db\ActiveQuery; use customerapi\models\dto\EventRegistrationDTO;
use yii\web\NotFoundHttpException;
class EventRegistrationManager class EventRegistrationManager
{ {
@ -12,44 +14,55 @@ class EventRegistrationManager
/** Get Customer registrations /** Get Customer registrations
* @throws \Exception * @throws \Exception
*/ */
public function findCustomerRegistrationsWithEvent() public function findCustomerRegistrationsWithEvent($idCustomer)
{
return $this->prepareQueryFindRegistrationsForCustomer()->all();
}
public function findCustomerRegistrations($clazz= EventRegistration::class )
{ {
$interval = EventInterval::createInterval(); $interval = EventInterval::createInterval();
return EventRegistration::find() $now = new \DateTime();
->innerJoinWith('event') $eventRegistrations = EventRegistration::find()
->andWhere(['and', ->andWhere(['id_customer' => $idCustomer])
['>=', 'event.start', $interval->firstActiveDate->getTimestamp()], // ->andWhere(['>=', 'event.start', $now->getTimestamp()])
['id_customer' => \Yii::$app->user->getId()] ->all();
])->all();
}
public function findRegistration($id_registration) $result = [];
{ $eventManager = new EventManager();
return $this->prepareQueryFindRegistrationsForCustomer() foreach ($eventRegistrations as $registration ){
->andWhere(['event_registration.id' => $id_registration]) $dto = EventRegistrationDTO::fromEventRegistration($registration);
->one();
$event = $eventManager->findActiveEvent($registration->id_event, $interval,true);
if ( isset($event)){
$dto->event = EventDTO::fromEventWithRelatedObjects($event);
$result[] = $dto;
}
}
return $result;
} }
/** /**
* Prepare a query to get registrations for customer * @throws NotFoundHttpException
* @return ActiveQuery query
* @throws \Exception
*/ */
private function prepareQueryFindRegistrationsForCustomer(){ public function findRegistration($id_registration, $id_customer)
{
$interval = EventInterval::createInterval(); $interval = EventInterval::createInterval();
return EventRegistrationAvailable::find()
->innerJoinWith('event') $registration = EventRegistration::findOne(['id' => $id_registration, 'id_customer' => $id_customer]);
->andWhere(['and',
['>=', 'event.start', $interval->firstActiveDate->getTimestamp()], if ( !isset($registration)){
['id_customer' => \Yii::$app->user->getId()] throw new NotFoundHttpException();
]); }
$eventManager = new EventManager();
$event = $eventManager->findActiveEvent($registration->id_event,$interval,true);
if ( !isset($event)){
throw new NotFoundHttpException();
}
return EventRegistrationDTO::fromEventRegistrationWithEvent($registration,$event);
} }
} }

View File

@ -5,54 +5,72 @@ namespace customerapi\models\available;
use common\models\Event; use common\models\Event;
use common\models\EventRegistration;
use common\models\EventType;
use common\models\Room;
use common\models\Trainer;
use yii\base\Model;
class EventAvailable extends Event class EventAvailable extends Model
{ {
public $reservationCount; public $id;
public $start;
public $end;
public $seat_count;
public $created_at;
public $updated_at;
public $deleted_at;
public $active;
public $eventType;
public $trainer;
public $room;
public $eventRegistrations;
public $registrationCount;
public $hasFreeSeats; public $hasFreeSeats;
protected function getTrainerClass() /**
* @param $event /common/models/Event
*/
public static function fromEvent($event)
{ {
// override trainer class to have more control $available = new EventAvailable();
// about json fields $available->id = $event->id;
return TrainerAvailable::class; $available->start = $event->start;
} $available->end = $event->end;
$available->seat_count = $event->seat_count;
$available->created_at = $event->created_at;
$available->updated_at = $event->updated_at;
$available->deleted_at = $event->deleted_at;
$available->active = $event->active;
protected function getEventTypeClass() return $available;
{
return EventTypeAvailable::class;
} }
protected function getRoomClass()
{
return RoomAvailable::class;
}
function fields() function fields()
{ {
$fields = [ $fields = [
"id" => "id", "id" => "id",
"start" => "start", "start" => "start",
"end" => "end", "end" => "end",
"seat_count" => "seat_count", "seat_count" => "seat_count",
"active" => "active", "active" => "active",
"reservationCount" => "reservationCount", "reservationCount" => "registrationCount",
"hasFreeSeats" => "hasFreeSeats", "hasFreeSeats" => "hasFreeSeats",
]; ];
$fields['trainer'] = 'trainer'; $fields['trainer'] = 'trainer';
$fields['eventType'] = 'eventType'; $fields['eventType'] = 'eventType';
$fields['room'] = 'room'; $fields['room'] = 'room';
$fields['registrations'] = 'activeEventRegistrationsForCustomer'; $fields['registrations'] = 'eventRegistrations';
return $fields; return $fields;
} }
function extraFields() function extraFields()
{ {
$extra= parent::extraFields(); $extra = parent::extraFields();
$extra[] = 'trainer'; $extra[] = 'trainer';
return $extra; return $extra;
} }

View File

@ -13,7 +13,8 @@ class EventTypeAvailable extends EventType
{ {
return [ return [
'id' => 'id', 'id' => 'id',
'name' => 'name' 'name' => 'name',
'theme' => 'theme'
]; ];
} }

View File

@ -0,0 +1,70 @@
<?php
namespace customerapi\models\dto;
use customerapi\models\available\EventAvailable;
class EventDTO extends \yii\base\Model
{
public $id;
public $start;
public $end;
public $seat_count;
public $created_at;
public $updated_at;
public $deleted_at;
public $active;
public $eventType;
public $trainer;
public $room;
public $eventRegistrations;
public $registrationCount;
public $hasFreeSeats;
function fields()
{
$fields = [
"id" => "id",
"start" => "start",
"end" => "end",
"seat_count" => "seat_count",
"active" => "active",
"reservationCount" => "registrationCount",
"hasFreeSeats" => "hasFreeSeats",
"registrations" => "eventRegistrations",
];
$fields['trainer'] = 'trainer';
$fields['eventType'] = 'eventType';
$fields['room'] = 'room';
// $fields['registrations'] = 'eventRegistrations';
return $fields;
}
/**
* @param $event /common/models/Event
*/
public static function fromEvent($event)
{
$dto = new EventDTO();
$dto->id = $event->id;
$dto->start = $event->start;
$dto->end = $event->end;
$dto->seat_count = $event->seat_count;
$dto->created_at = $event->created_at;
$dto->updated_at = $event->updated_at;
$dto->deleted_at = $event->deleted_at;
$dto->active = $event->active;
return $dto;
}
public static function fromEventWithRelatedObjects($event){
$eventDto = EventDTO::fromEvent($event);
$eventDto->trainer = TrainerDTO::fromTrainer($event->trainer);
$eventDto->room = RoomDTO::fromRoom($event->room);
$eventDto->eventType = EventTypeDTO::fromEventType($event->eventType);
return $eventDto;
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace customerapi\models\dto;
use common\helpers\AppDateTimeHelper;
use yii\base\Model;
class EventRegistrationDTO extends Model
{
public $id;
public $id_event;
public $id_customer;
public $id_card;
public $id_ticket;
public $created_at;
public $updated_at;
public $canceled_at;
public $deleted_at;
public $event;
function fields()
{
$fields = [
'id' => 'id',
'id_event' => 'id_event',
'id_customer' => 'id_customer',
'id_card' => 'id_card',
'id_ticket' => 'id_ticket',
'created_at' => 'created_at',
'updated_at' => 'updated_at',
'canceled_at' => 'canceled_at',
'deleted_at' => 'deleted_at',
];
$fields['event'] = 'event';
return $fields;
}
public static function fromEventRegistration($registration){
$dto = new EventRegistrationDTO();
$dto->id = $registration->id;
$dto->id_event = $registration->id_event;
$dto->id_customer = $registration->id_customer;
$dto->id_card = $registration->id_card;
$dto->id_ticket = $registration->id_ticket;
$dto->created_at = AppDateTimeHelper::convertMySqlDatetimeToPhpInteger( $registration->created_at);
$dto->updated_at = AppDateTimeHelper::convertMySqlDatetimeToPhpInteger($registration->updated_at);
$dto->canceled_at =AppDateTimeHelper::convertMySqlDatetimeToPhpInteger( $registration->canceled_at);
$dto->deleted_at = AppDateTimeHelper::convertMySqlDatetimeToPhpInteger($registration->deleted_at);
return $dto;
}
public static function fromEventRegistrationWithEvent($registration,$event){
$registrationDto = EventRegistrationDTO::fromEventRegistration($registration);
$registrationDto->event = EventDTO::fromEventWithRelatedObjects($event);
return $registrationDto;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace customerapi\models\dto;
use yii\base\Model;
class EventTypeDTO extends Model
{
public $id;
public $name;
public $theme;
public $created_at;
public $updated_at;
public static function fromEventType($eventType){
$dto = new EventTypeDTO();
$dto->id = $eventType->id;
$dto->name = $eventType->name;
$dto->theme = $eventType->theme;
$dto->created_at = $eventType->created_at;
$dto->updated_at = $eventType->updated_at;
return $dto;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace customerapi\models\dto;
use yii\base\Model;
class RoomDTO extends Model
{
public $id;
public $name;
public $seat_count;
public $created_at;
public $updated_at;
public static function fromRoom($room)
{
$dto = new RoomDTO();
$dto->id = $room->id;
$dto->name = $room->name;
$dto->seat_count = $room->seat_count;
$dto->created_at = $room->created_at;
$dto->updated_at = $room->updated_at;
return $dto;
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace customerapi\models\dto;
use yii\base\Model;
class TrainerDTO extends Model
{
public $id;
public $name;
public $phone;
public $email;
public $password;
public $active;
public $created_at;
public $updated_at;
public static function fromTrainer($trainer){
$dto = new TrainerDTO();
$dto->id = $trainer->id;
$dto->name = $trainer->name;
$dto->phone = $trainer->phone;
$dto->email = $trainer->email;
$dto->password = $trainer->password;
$dto->active = $trainer->active;
$dto->created_at = $trainer->created_at;
$dto->updated_at = $trainer->updated_at;
return $dto;
}
}

View File

@ -242,6 +242,7 @@ class CustomerController extends Controller
$model->customer = $customer; $model->customer = $customer;
$model->email = $customer->email; $model->email = $customer->email;
$model->companyName = Helper::getCompanyName(); $model->companyName = Helper::getCompanyName();
$model->groupTrainingUrl = Helper::getGroupTrainingUrl();
if ( \Yii::$app->request->isPost ){ if ( \Yii::$app->request->isPost ){
$model->load(\Yii::$app->request->post()); $model->load(\Yii::$app->request->post());

View File

@ -19,6 +19,7 @@ class PasswordChangeModel extends Model
public $card; public $card;
public $companyName; public $companyName;
public $plainPassword; public $plainPassword;
public $groupTrainingUrl;
/** /**
* @inheritdoc * @inheritdoc