door manager

This commit is contained in:
Schneider Roland 2022-05-04 19:41:18 +02:00
parent fb39d6599e
commit 946799a598
20 changed files with 8872 additions and 220 deletions

View File

@ -8,7 +8,6 @@ use backend\models\CitySearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\base\Object;
use yii\db\Query;
use yii\helpers\Json;
@ -36,5 +35,5 @@ class BackendController extends Controller
];
}
}

View File

@ -8,7 +8,6 @@ use backend\models\CitySearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\base\Object;
use yii\db\Query;
use yii\helpers\Json;
@ -34,7 +33,7 @@ class CityController extends \backend\controllers\BackendController
],
];
}
/**
* Lists all City models.
@ -128,14 +127,14 @@ class CityController extends \backend\controllers\BackendController
throw new NotFoundHttpException('The requested page does not exist.');
}
}
/**
* Your controller action to fetch the list
*/
public function actionNameList($search = null) {
$query = new Query();
$query->select ( [
'name',
'min(zip) as zip',
@ -158,7 +157,7 @@ class CityController extends \backend\controllers\BackendController
*/
public function actionZipList($search = null) {
$query = new Query();
$query->select ( [
'name',
'min(zip) as zip',

View File

@ -12,7 +12,6 @@ use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\base\Object;
use backend\models\CustomerUpdate;
use backend\models\CustomerNewsLetterModel;
use yii\db\Query;
@ -24,7 +23,7 @@ use yii\data\ActiveDataProvider;
class CustomerController extends \backend\controllers\BackendController
{
public function behaviors()
{
@ -130,10 +129,10 @@ class CustomerController extends \backend\controllers\BackendController
public function actionCreate()
{
$model = new CustomerCreate();
$model->country = "Magyarország";
$model->id_user = Yii::$app->user->id;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_customer]);
@ -157,9 +156,9 @@ class CustomerController extends \backend\controllers\BackendController
if (($model = CustomerUpdate::findOne($id)) == null) {
throw new NotFoundHttpException('The requested page does not exist.');
}
$model->birthdate= isset($model->birthdate ) ? Yii::$app->formatter->asDate($model->birthdate) :'';
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_customer]);
@ -198,24 +197,24 @@ class CustomerController extends \backend\controllers\BackendController
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionMail(){
$model = new CustomerNewsLetterModel();
$query = new Query();
$query->distinct();
$query->select([ 'email']);
$query->from("customer");
$query->andWhere(['newsletter' => 1]);
$query->andWhere(['status' => Customer::STATUS_ACTIVE]);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$message = \Yii::$app->mailer->compose ( );
$message
->setFrom ( "noreply@fitnessadmin.hu" )
->setBcc(['rocho02@gmail.com',"rocho02@freemail.hu"])
@ -225,9 +224,9 @@ class CustomerController extends \backend\controllers\BackendController
->send ();
return $this->redirect(['customer/mail']);
}
return $this->render('mail', [ 'model' => $model ]);
}
}

View File

@ -9,7 +9,6 @@ use backend\models\UserCreate;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\base\Object;
use backend\models\UserUpdate;
use common\models\Account;
use common\models\UserAccountAssignment;
@ -20,7 +19,7 @@ use common\components\RoleDefinition;
*/
class UserController extends \backend\controllers\BackendController
{
public function behaviors()
{
@ -45,8 +44,8 @@ class UserController extends \backend\controllers\BackendController
],
];
}
/**
* Lists all User models.
* @return mixed
@ -55,8 +54,8 @@ class UserController extends \backend\controllers\BackendController
{
$searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
@ -84,25 +83,25 @@ class UserController extends \backend\controllers\BackendController
public function actionCreate()
{
$model = new UserCreate();
$accounts = Account::readAccounts();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$this->updateAccountAssignments($model);
return $this->redirect(['index' ]);
}
}
return $this->render('create', [
'model' => $model,
'accounts' => $accounts,
]);
}
public function updateAccountAssignments($model){
echo "saving accounts";
UserAccountAssignment::deleteAll(['id_user' => $model->id]);
foreach ( $model->selected_accounts as $id_account ){
@ -112,7 +111,7 @@ class UserController extends \backend\controllers\BackendController
$uaa->id_account = $id_account;
$uaa->save();
}
}
/**
@ -124,7 +123,7 @@ class UserController extends \backend\controllers\BackendController
public function actionUpdate($id)
{
$model = UserUpdate::findOne(['id' => $id]);
if ( Yii::$app->authManager->checkAccess($model->id, 'admin')){
$model->role = 'admin';
} else if ( Yii::$app->authManager->checkAccess($model->id, 'employee')){
@ -132,16 +131,16 @@ class UserController extends \backend\controllers\BackendController
}else if ( Yii::$app->authManager->checkAccess($model->id, 'reception')){
$model->role = 'reception';
}
if ( $model == null ){
throw new NotFoundHttpException('The requested page does not exist.');
}
$accounts = Account::readAccounts();
$this->applyAccounts($model);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$this->updateAccountAssignments($model);
@ -153,7 +152,7 @@ class UserController extends \backend\controllers\BackendController
'accounts' => $accounts,
]);
}
private function applyAccounts($model ){
$assignedAccounts = $model->userAccountAssignments;
foreach ($assignedAccounts as $acc ){
@ -171,12 +170,12 @@ class UserController extends \backend\controllers\BackendController
{
$user = $this->findModel($id);
$user->updateAttributes(['status' => User::STATUS_DELETED]);
return $this->redirect(['index']);
}
/**
* Creates a new User model.
* If creation is successful, the browser will be redirected to the 'view' page.
@ -185,17 +184,17 @@ class UserController extends \backend\controllers\BackendController
public function actionRole()
{
$model = new \backend\models\RoleForm();
$model->availablePermissions = [
[
'name' => "reception.transfers",
'description' => 'Tranzakciók'
]
];
if ($model->load(Yii::$app->request->post()) ) {
if ( $model->validate() && $model->save()){
Yii::$app->session->setFlash('success', 'Jogosultságok elmentve');
@ -209,7 +208,7 @@ class UserController extends \backend\controllers\BackendController
$model->permissions[] = $child->name;
}
}
return $this->render('role', [
'model' => $model,
]);

View File

@ -18,6 +18,12 @@ use yii\i18n\Formatter;
class DateUtil
{
public static function fromUnixTimeStamp($timestamp){
$dt = DateUtil::utcDate();
$dt->setTimestamp($timestamp);
return $dt;
}
/**
* Get UTC today @00:00:00 .
* Helper method to generate date for mysql
@ -25,13 +31,49 @@ class DateUtil
* @return DateTime
* @throws Exception
*/
public static function todayStart( ){
$d2 = new DateTime();
public static function todayStart(){
$d2 = new DateTime();
return DateUtil::utcDate($d2);
}
/**
* @param $date \DateTime optional. The date to set as utc date. If not set, new DateTime() will be used
* @return DateTime the datetime object with time reset and utc timezone
*/
public static function utcDate($date = null){
$d2 = isset($date ) ? $date : new DateTime();
$d2 = DateUtil::withTimeZoneUTC($d2);
return DateUtil::resetTime($d2);
}
/**
* @param $date \DateTime optional. If not set,defaults to : new DateTime() .
* @return DateTime
*/
public static function utcDateTime($date = null){
$d2 = isset($date ) ? $date : new DateTime();
return DateUtil::withTimeZoneUTC($d2);
}
/**
* @param $date \DateTime
* @return DateTime
*/
public static function withTimeZoneUTC( $date = null){
$d2 = isset($date ) ? $date : new DateTime();
$d2->setTimezone( new DateTimeZone('UTC') );
$d2->setTime(0, 0);
return $d2;
}
/**
* @param $dateTime \DateTime
* @return \DateTime
*/
public static function resetTime($dateTime){
$dateTime->setTime(0, 0);
return $dateTime;
}
/**
* Get UTC t @00:00:00 .
* Helper method to generate date for mysql
@ -39,16 +81,12 @@ class DateUtil
* @return DateTime
* @throws Exception
*/
public static function tomorrowStart( ){
$d2 = new DateTime();
public static function tomorrowStart( $date = null){
$d2 = isset($date) ? $date : new DateTime();
$d2->add(new DateInterval('P1D'));
$d2->setTimezone( new DateTimeZone('UTC') );
$d2->setTime(0, 0);
return $d2;
return DateUtil::utcDate($d2);
}
public static function addMonth($timestamp, $monthCount = 1)
{
@ -99,7 +137,7 @@ class DateUtil
* @return string
* @throws InvalidConfigException
*/
public static function formatUtc($dateTimeObject)
public static function formatDateTimeUtc($dateTimeObject)
{
$formatter = new Formatter;
$formatter->datetimeFormat = 'php:Y-m-d H:i:s';
@ -127,6 +165,10 @@ class DateUtil
return $date;
}
public static function parseDateTime($dateTimeString){
return DateTime::createFromFormat('Y-m-d H:i:s', $dateTimeString, new DateTimeZone( 'UTC'));
}
/**
* @param integer $weekDay Numeric representation of the day of the week. @See https://www.php.net/manual/en/function.date.php
* @return string

View File

@ -0,0 +1,352 @@
<?php
namespace common\manager;
use common\components\DateUtil;
use common\components\Helper;
use common\models\Card;
use common\models\CardEventRegistrationForm;
use common\models\Customer;
use common\models\DoorLog;
use common\models\DoorLogForTest;
use common\models\Event;
use common\models\EventRegistration;
use common\models\Log;
use common\models\MobileDevice;
use common\models\Ticket;
use customerapi\models\available\EventInterval;
use customerapi\models\registrations\EventRegistrationAvailable;
use customerapi\models\details\EventRegistrationView;
use Exception;
use Yii;
use yii\base\BaseObject;
use yii\db\ActiveRecord;
use yii\db\Query;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException;
/**
* Created by IntelliJ IDEA.
* User: rocho
* Date: 2018.12.17.
* Time: 6:12
*/
class DoorManager extends BaseObject
{
/**
* @param $cardNumber
* @param $device
* @param $direction
* @param $createdAt number unix timestamp , override createdAt for doorLogs
* @param $date number unix timestamp, override date for validation check 'now'
* @return void
* @throws BadRequestHttpException
* @throws \yii\base\InvalidConfigException
*/
public function move($cardNumber, $device, $direction, $createdAt = null, $date = null )
{
if ( isset($createdAt)){
$createdAt = DateUtil::parseDateTime($createdAt);
}else{
$createdAt = DateUtil::utcDateTime();
}
$createdAtStr = DateUtil::formatDateTimeUtc($createdAt);
if ( isset($date)){
$date = DateUtil::parseDateTime($date);
}else{
$date = DateUtil::utcDate();
}
$dateStr = DateUtil::formatDateUtc($date);
$doorLog = new DoorLog();
$doorLog->direction = $direction;
$doorLog->source_app = $device;
$doorLog->created_at = $createdAtStr;
/**
* emergency- no card needed
*/
if ($direction == DoorLog::$DIRECTION_ALL_EMERGENCY) {
$doorLog->save(false);
Log::log(
[
'type' => Log::$TYPE_INFO,
'message' => 'Ajtó nyitás: vészhelyzet',
'id_door_log' => $doorLog->id_door_log
]
);
\Yii::$app->response->statusCode = 204;
return;
}
$card = Card::readCard(Helper::fixAsciiChars($cardNumber));
/*
* in any other cases, the door needs a card
*/
if (!isset($card)) {
throw new BadRequestHttpException('Card not found with number: ' . $cardNumber);
}
$doorLog->id_card = $card->id_card;
$doorLog->card_flag = $card->flag;
/**
* if the card type is employee, neither customer nor ticket is needed.
* Free to enter/leave
*/
if ($card->type == Card::TYPE_EMPLOYEE) {
$doorLog->save(false);
\Yii::$app->response->statusCode = 204;
return;
}
//otherwise ticket is required
$activeTickets = Ticket::readActive($card, clone $date);
\Yii::error('active ticket count:' . count($activeTickets));
$ticket = null;
if (isset($activeTickets) && count($activeTickets) > 0) {
$ticket = $activeTickets[0];
}
$doorLog->id_ticket_current = $ticket->id_ticket;
if (!isset($ticket)) {
throw new BadRequestHttpException("No active ticket found for:" . $card->number);
}
\Yii::error("active ticket: " . $ticket->id_ticket);
// customer is also required
$customer = $card->customer;
if (!isset($customer)) {
throw new BadRequestHttpException("Customer not found for:" . $card->number);
}
$doorLog->id_customer = $customer->id_customer;
// save the door log
$doorLog->save(false);
// if direction is in
if ($direction == DoorLog::$DIRECTION_IN || $direction == DoorLog::$DIRECTION_IN_WITHOUT_MOVE) {
$countDoorLogsForTicketSince = $this->getCountDoorLogsForTicketSince($ticket->id_ticket, DateUtil::utcDate( clone $date));
// if the current event is the first door log today
if ($countDoorLogsForTicketSince == 1) {
// increase the ticket usage count with 1
$usageCount = $ticket->usage_count;
$ticket->usage_count += 1;
$ticket->save(false);
Log::log(
[
'type' => Log::$TYPE_TICKET_USAGE_FIRST,
'message' => 'Bérlet használat(előtte: ' . $usageCount . ' -> utána: ' . $ticket->usage_count,
'id_ticket' => $ticket->id_ticket,
'id_door_log' => $doorLog->id_door_log
]
);
} else {
// we have already a door log for today, other than this
// Now we split the day into 3hour intervalls, starting with the createdAt value of the first event.
// If the actual event happens in an interval, in which still now doorlog event happend, we increase
// the usage count with 1
// 3 óránként 1-et levonunk
$startOfDay = DateUtil::utcDate(clone $date);
$startOfTomorrow = DateUtil::tomorrowStart(clone $date);
$allDoorLogToday = DoorLog::find()
->andWhere(['>=', 'door_log.created_at', DateUtil::formatDateUtc($startOfDay)])
->andWhere(['<', 'door_log.created_at', DateUtil::formatDateUtc($startOfTomorrow)])
->andWhere(['id_ticket_current' => $ticket->id_ticket])
->andWhere(['in', 'direction', [DoorLog::$DIRECTION_IN_WITHOUT_MOVE, DoorLog::$DIRECTION_IN]])
->orderBy(['door_log.created_at' => SORT_ASC])
->all();
\Yii::error("new door log: ".$doorLog->id_door_log.";".$doorLog->created_at.";".$doorLog->type);
foreach ($allDoorLogToday as $log){
\Yii::error("all log: ".$log->id_door_log.";".$log->created_at.";".$log->type);
}
$firstInToday = $allDoorLogToday[0];
if (isset($firstInToday)) {
$firstEntryDateTimeToday = DateUtil::parseDateTime($firstInToday->created_at);
$interval = \DateInterval::createFromDateString('3 hours');
$daterange = new \DatePeriod($firstEntryDateTimeToday, $interval ,$startOfTomorrow);
$intervals = [];
$intervalStart = null;
foreach($daterange as $intervalEnd){
if ( isset($intervalStart)){
$intervals[] = $this->createTicketUsageInterval($intervalStart,$intervalEnd,$allDoorLogToday,$doorLog);
}
$intervalStart = clone $intervalEnd;
}
if ( $intervalStart < $startOfTomorrow ){
$intervals[] = $this->createTicketUsageInterval($intervalStart,$startOfTomorrow,$allDoorLogToday,$doorLog);
}
$activeInterval = $this->getActiveInterval($intervals,$createdAt);
if ( !isset($activeInterval)){
throw new ServerErrorHttpException("Active Interval not found");
}
$logCountInActiveInterval = count($activeInterval['logs']);
if ( $logCountInActiveInterval == 1){
$ticket->usage_count = $ticket->usage_count+1;
$ticket->save(false);
}
}
// select min(created_at) + INTERVAL (3 * FLOOR( ( ( HOUR( TIMEDIFF( min(created_at) , now() ) ) /3 ) ) ) ) hour as last_date
// into @p_from
// from door_log
// where created_at > CURDATE() and id_customer is not null and id_ticket_current = NEW.id_ticket_current and ( direction = 7 or direction = 3);
// select count(*) into @p_count_all_2 from door_log where created_at >= @p_from and id_ticket_current = New.id_ticket_current and ( direction = 7 or direction = 3);
// INSERT INTO devlog ( msg) values(CONCAT( 'Bel<65>p<EFBFBD>sek sz<73>ma az aktu<74>lis 3 <20>r<EFBFBD>s intervalumban: ', @p_count_all_2) );
// IF @p_count_all_2 = 1
// THEN
// INSERT INTO devlog ( msg) values( 'Az aktu<74>lis intervallumban ez az els? bel<65>p<EFBFBD>s, usage_count n<>vel<65>se' );
//
// select usage_count, max_usage_count into @p_usage_count ,@p_max_usage_count from ticket where id_ticket = NEW.id_ticket_current;
//
// update ticket set usage_count = usage_count +1 where id_ticket = New.id_ticket_current;
//
// INSERT INTO log (type,message, app, id_ticket, id_door_log,created_at, updated_at)
// values(
// 40, concat('B<>rlet haszn<7A>lat/egy nap tobbszori (elotte: ',@p_usage_count, ' > utana: ' , @p_usage_count +1 , ' max: ', @p_max_usage_count, ')' ), ' trigger_inc_ticket',New.id_ticket_current, New.id_door_log,now(),now());
// END IF;
}
//
//
//
\Yii::error("finished");
}
}
function getActiveInterval($intervals,$date){
foreach ($intervals as $interval ){
$start = $interval['start'];
$end = $interval['end'];
if ( $start <= $date && $date < $end ){
return $interval;
}
}
return null;
}
function createTicketUsageInterval($start,$end, $allLogs, $actualDoorLog){
$result = ['start' => $start, 'end' => $end , 'logs' =>[] ];
foreach ($allLogs as $log){
$createdAt = DateUtil::parseDateTime($log->created_at);
if ( $createdAt >= $start && $createdAt < $end){
$result['logs'][] = $log;
}
}
return $result;
}
function getCountDoorLogsForTicketSince($idTicket, $since)
{
\Yii::error("getting door log count for today");
return DoorLog::find()
->innerJoinWith('card')
->andWhere(['card.id_ticket_current' => $idTicket])
->andWhere(['in', 'door_log.direction', [DoorLog::$DIRECTION_IN, DoorLog::$DIRECTION_IN_WITHOUT_MOVE]])
->andWhere(['>=', 'door_log.created_at', DateUtil::formatDateUtc($since)])
->count();
}
public function readActive($cardNumber)
{
$card = Card::readCard($cardNumber);
return Ticket::readActive($card);
}
public function resetLogs($cardNumber)
{
$card = Card::readCard($cardNumber);
DoorLog::deleteAll(
['id_card' => $card->id_card]
);
}
public function getLogs($cardNumber)
{
return DoorLog::findAll(
['id_card' => $cardNumber]
);
}
public function getInfo($cardNumber)
{
$card = Card::readCard($cardNumber);
return [
'card' => $card,
'customer' => $card->customer,
'tickets' => Ticket::readActive($card),
'doorLogs' => DoorLog::findAll(
['id_card' => $card->id_card]
),
'lastDoorLog' => DoorLog::find()->orderBy(['id_door_log' => SORT_DESC])->limit(1)->one(),
'doorLogCount' => DoorLog::find()->count()
];
}
//
// public function createDoorLog($direction, $idCard, $idTicket, $createdAt)
// {
// $doorLog = new DoorLog();
// $doorLog->id_card = $idCard;
// $doorLog->direction = $direction;
// $doorLog->id_ticket_current = $idTicket;
//
// $doorLog->save(false);
// // update the created at flag
// \Yii::$app->db->createCommand('update door_log set created_at = :created_at where id_door_log = :id ')
// ->bindValue("created_at", $createdAt)
// ->bindValue("id", $doorLog->id_door_log)
// ->execute();
// }
public function createLog()
{
\Yii::error("Post create log:". \Yii::$app->request->method);
if (\Yii::$app->request->isPost) {
$log = new DoorLogForTest();
if ($log->load(\Yii::$app->request->post(), "")) {
if ($log->validate()) {
\Yii::error("Door log saving:".$log->created_at);
$log->save(false);
return $log;
}else{
throw new BadRequestHttpException(print_r($log->getErrors(),true));
}
} else {
\Yii::error("validated" . print_r($log->errors, true));
throw new BadRequestHttpException();
}
}
throw new BadRequestHttpException('Not a Post');
}
}

View File

@ -25,9 +25,25 @@ use yii\helpers\ArrayHelper;
*/
class DoorLog extends \yii\db\ActiveRecord
{
public static $SOURCE_APP_FORGO_VILLA = "forgo_villa";
public static $SOURCE_APP_FITNESS_ADMIN = "fitness_admin";
public static $SOURCE_APP_FORGO_VILLA = "forgo_villa";
public static $SOURCE_APP_FITNESS_ADMIN = "fitness_admin";
public static $DIRECTION_OUT_MANUAL_READ_KEY_ASSIGNED = -2; // "Kézi olvasás/Kulcs ki",
public static $DIRECTION_IN_MANUAL_READ_KEY_UNASSIGNED = -1; // "Kézi olvasás/Kulcs vissza",
public static $DIRECTION_ALL_MANUAL_READ = 0; // "Kézi olvasás",
public static $DIRECTION_OUT_WITHOUT_MOVE = 1; // "KI olvastatás mozgás nélkül",
public static $DIRECTION_IN_WITHOUT_MOVE = 3; // "BE olvastatás mozgás nélkül",
public static $DIRECTION_OUT_ = 5; // "KI mozgás",
public static $DIRECTION_IN = 7; // "BE mozgás",
public static $DIRECTION_OUT_ERROR_KEY_ASSIGNED = 9; // "KI olvastatás, van érvényes öltöző kulcs (nem enged)",
public static $DIRECTION_IN_ERROR_KEY_MISSING = 11; // "BE olvastatás, nincs érvényes öltöző kulcs (nem enged)",
public static $DIRECTION_OUT_NO_TICKET = 17; // "Bérlet érvényességi időn kívüli KI olvastatás (nem enged)",
public static $DIRECTION_IN_NO_TICKET = 19; // "Bérlet érvényességi időn kívüli BE olvastatás (nem enged)",
public static $DIRECTION_ALL_EMERGENCY = 128; // "Vésznyitás",
public static $DIRECTION_ALL_CARD_BLOCKED = 256; // "Kártya tiltva -> információ mező",
/**
* @inheritdoc
*/
@ -35,16 +51,21 @@ class DoorLog extends \yii\db\ActiveRecord
{
return 'door_log';
}
public function behaviors()
{
return ArrayHelper::merge( [
[
'class' => TimestampBehavior::className(),
'value' => function(){ return date('Y-m-d H:i:s' ); },
'updatedAtAttribute' => false,
]
], parent::behaviors());
return ArrayHelper::merge([
[
'class' => TimestampBehavior::className(),
'value' => function ($event) {
if ( isset($event->sender->created_at) ){
return $event->sender->created_at;
}
return date('Y-m-d H:i:s');
},
'updatedAtAttribute' => false,
]
], parent::behaviors());
}
/**
@ -75,133 +96,147 @@ class DoorLog extends \yii\db\ActiveRecord
'source_app' => Yii::t('common/door_log', 'Eszköz'),
];
}
public function getCustomer(){
return $this->hasOne( Customer::className(), ["id_customer" =>"id_customer" ] );
}
public function getCustomerName(){
$result = "";
if (isset($this->customer)){
$result = $this->customer->name;
}
return $result;
}
public function getCard(){
return $this->hasOne( Card::className(), ["id_card" =>"id_card" ] );
}
public function getCardNumber(){
$result = "";
if (isset($this->card)){
$result = $this->card->number;
}
return $result;
}
public function getKey(){
return $this->hasOne( Key::className(), ["id_key" =>"id_key" ] );
}
public function getKeyNumber(){
$result = "";
if (isset($this->key)){
$result = $this->key->number;
}
return $result;
}
public function getDirectionName(){
$result = "";
if ( $this->source_app == 'forgo_villa'){
if (isset($this->direction)){
$result = Helper::getArrayValue(self::getDirectionTypes() , $this->direction, "-");
}
}else{
$result = "Kézi olvasás";
}
return $result;
}
public static function getSourceAppName($source_app){
$result = "";
switch ($source_app){
case self::$SOURCE_APP_FITNESS_ADMIN :
$result = "Recepciós alkalmazás";
break;
case self::$SOURCE_APP_FORGO_VILLA:
$result = "Forgó villa";
break;
}
return $result;
}
public static function getDirectionTypes( ){
return [
-2 => "Kézi olvasás/Kulcs ki",
-1 => "Kézi olvasás/Kulcs vissza",
0 => "Kézi olvasás",
1 => "KI olvastatás mozgás nélkül",
3 => "BE olvastatás mozgás nélkül",
5 => "KI mozgás",
7 => "BE mozgás",
9 => "KI olvastatás, van érvényes öltöző kulcs (nem enged)",
11 => "BE olvastatás, nincs érvényes öltöző kulcs (nem enged)",
17 => "Bérlet érvényességi időn kívüli KI olvastatás (nem enged)",
19 => "Bérlet érvényességi időn kívüli BE olvastatás (nem enged)",
128 => "Vésznyitás",
256 => "Kártya tiltva -> információ mező",
];
}
public static function getCardFlagTexts( ){
return [
0 => "Kártya érvényes bérlettel",
1 => "Nincs érvényes bérlet",
2 => "Kártya inaktív/Érvényes bérlet",
3 => "Kártya inaktív/Nincs érvényes bérlet"
];
}
public function getCustomer()
{
return $this->hasOne(Customer::className(), ["id_customer" => "id_customer"]);
}
public static function mkDoorLog($direction,$card,$customer = null,$key = null){
public function getCustomerName()
{
$result = "";
if (isset($this->customer)) {
$result = $this->customer->name;
}
return $result;
}
if ( !Helper::isKeyToggleDoorLogEnabled() ){
return;
public function getCard()
{
return $this->hasOne(Card::className(), ["id_card" => "id_card"]);
}
public function getCardNumber()
{
$result = "";
if (isset($this->card)) {
$result = $this->card->number;
}
return $result;
}
public function getKey()
{
return $this->hasOne(Key::className(), ["id_key" => "id_key"]);
}
public function getKeyNumber()
{
$result = "";
if (isset($this->key)) {
$result = $this->key->number;
}
return $result;
}
public function getDirectionName()
{
$result = "";
if ($this->source_app == 'forgo_villa') {
if (isset($this->direction)) {
$result = Helper::getArrayValue(self::getDirectionTypes(), $this->direction, "-");
}
} else {
$result = "Kézi olvasás";
}
return $result;
}
public static function getSourceAppName($source_app)
{
$result = "";
switch ($source_app) {
case self::$SOURCE_APP_FITNESS_ADMIN :
$result = "Recepciós alkalmazás";
break;
case self::$SOURCE_APP_FORGO_VILLA:
$result = "Forgó villa";
break;
}
return $result;
}
public static function getDirectionTypes()
{
return [
-2 => "Kézi olvasás/Kulcs ki",
-1 => "Kézi olvasás/Kulcs vissza",
0 => "Kézi olvasás",
1 => "KI olvastatás mozgás nélkül",
3 => "BE olvastatás mozgás nélkül",
5 => "KI mozgás",
7 => "BE mozgás",
9 => "KI olvastatás, van érvényes öltöző kulcs (nem enged)",
11 => "BE olvastatás, nincs érvényes öltöző kulcs (nem enged)",
17 => "Bérlet érvényességi időn kívüli KI olvastatás (nem enged)",
19 => "Bérlet érvényességi időn kívüli BE olvastatás (nem enged)",
128 => "Vésznyitás",
256 => "Kártya tiltva -> információ mező",
];
}
public static function getCardFlagTexts()
{
return [
0 => "Kártya érvényes bérlettel",
1 => "Nincs érvényes bérlet",
2 => "Kártya inaktív/Érvényes bérlet",
3 => "Kártya inaktív/Nincs érvényes bérlet"
];
}
public static function mkDoorLog($direction, $card, $customer = null, $key = null)
{
if (!Helper::isKeyToggleDoorLogEnabled()) {
return;
}
$dlog = new DoorLog();
$dlog->id_card = $card->id_card;
$dlog = new DoorLog();
$dlog->id_card = $card->id_card;
if ( isset($customer)){
$dlog->id_customer = $customer->id_customer;
}
if (isset($customer)) {
$dlog->id_customer = $customer->id_customer;
}
if ( isset($key)){
$dlog->id_key = $key->id_key;
}
$dlog->direction = $direction;
$dlog->type = $card->type;
$dlog->source_app = DoorLog::$SOURCE_APP_FITNESS_ADMIN;
if (isset($key)) {
$dlog->id_key = $key->id_key;
}
$dlog->direction = $direction;
$dlog->type = $card->type;
$dlog->source_app = DoorLog::$SOURCE_APP_FITNESS_ADMIN;
$dlog->id_account = Account::readDefault();
$dlog->id_account = Account::readDefault();
if ( $dlog->direction == 0){
$dlog->card_flag = $card->validity;
}else{
$dlog->card_flag = -1;
}
if ($dlog->direction == 0) {
$dlog->card_flag = $card->validity;
} else {
$dlog->card_flag = -1;
}
$dlog->created_at = date('Y-m-d H:i:s');
$dlog->save(false);
}
$dlog->created_at = date('Y-m-d H:i:s');
$dlog->save(false);
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace common\models;
use Yii;
use common\components\Helper;
use yii\behaviors\TimestampBehavior;
use yii\helpers\ArrayHelper;
/**
* This is the model class for table "door_log".
*
* @property integer $id_door_log
* @property integer $id_card
* @property integer $id_customer
* @property integer $id_key
* @property integer $direction
* @property integer $type
* @property integer $id_account
* @property string $created_at
* @property string $source_app
* @property integer id_ticket_current
* @property integer card_flag
* @property integer flag_out
*/
class DoorLogForTest extends DoorLog
{
public function behaviors()
{
return [];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[
['id_card', 'id_customer', 'id_key', 'direction', 'type', 'id_ticket_current'], 'integer'
],
[['created_at'], 'string'],
[['created_at'], 'required'],
];
}
}

View File

@ -26,7 +26,7 @@ class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
const ROLE_RECEPTION = 'receptionist';
/**
@ -192,18 +192,18 @@ class User extends ActiveRecord implements IdentityInterface
{
$this->password_reset_token = null;
}
public function getUserAccountAssignments(){
return $this->hasMany(UserAccountAssignment::className(), ['id_user' =>'id']);
}
static function statuses() {
return [
self::STATUS_ACTIVE => Yii::t('app', 'Aktív'),
self::STATUS_DELETED => Yii::t('app', 'Inaktív'),
] ;
}
public function getStatusHuman(){
$result = null;
$s = self::statuses($this->status);
@ -212,8 +212,8 @@ class User extends ActiveRecord implements IdentityInterface
}
return $result;
}
public function attributeLabels(){
return [
'status' => 'Státusz',
@ -224,14 +224,14 @@ class User extends ActiveRecord implements IdentityInterface
'statusHuman' => Yii::t('backend/user', 'Status'),
];
}
/**
*
*
*
*
* @return \yii\rbac\Role[]*/
public function getRoles(){
$roles = \Yii::$app->authManager->getRolesByUser($this->id );
return $roles;
return $roles;
}
/**
@ -239,28 +239,28 @@ class User extends ActiveRecord implements IdentityInterface
* */
public function getRoleString(){
$roles = \Yii::$app->authManager->getRolesByUser($this->id );
return implode(', ', array_map(function ($role) { return sprintf("%s", RoleDefinition::getRoleLabel($role->name)); }, $roles ));
}
/**
* $param int $forceIncludeAccount id warehouse, that should be included in list, even if it is inactive
* */
public static function read($forceIncludeObjectWithId = null){
$users = null;
$query = User::find();
if ( RoleDefinition::isReception()){
$query->andWhere(['id' => Yii::$app->user->id ]);
}
if ( $forceIncludeObjectWithId == null){
$users = $query->andWhere(['status' => User::STATUS_ACTIVE])->all();
}else{
$users = $query->andWhere( ['or', ['status' => User::STATUS_ACTIVE], ['id' => $forceIncludeObjectWithId ] ])->all();
}
return $users;
}
}

138
doc/trigger.sql Normal file
View File

@ -0,0 +1,138 @@
CREATE TRIGGER trigger_inc_ticket_usage_count AFTER INSERT ON `door_log` FOR EACH ROW
begin
DECLARE p_count_all Integer;
DECLARE p_count_all_2 Integer;
DECLARE p_from DATETIME;
DECLARE p_usage_count Integer;
DECLARE p_max_usage_count Integer;
DECLARE p_mo_ticket_id Integer;
DECLARE p_mo_ticket_max_usage_count Integer;
DECLARE p_allow_multiple_enter boolean;
DECLARE p_allow_enter boolean;
delete from devlog;
IF NEW.id_customer is not null and NEW.id_card is not null
THEN
IF (NEW.direction = 7 or New.direction = 3 ) and NEW.id_ticket_current is not null
then
INSERT INTO devlog ( msg) values('belepes feldoglozas indit');
select count(*) into @p_count_all from door_log where created_at >= CURDATE() and id_ticket_current = New.id_ticket_current and ( direction = 7 or direction = 3);
INSERT INTO devlog ( msg) values( concat( 'count all' ,@p_count_all ) );
IF @p_count_all = 1
THEN
select usage_count, max_usage_count into @p_usage_count ,@p_max_usage_count from ticket where id_ticket = NEW.id_ticket_current;
update ticket set usage_count = usage_count +1 where id_ticket = NEW.id_ticket_current;
INSERT INTO log (type,message, app, id_ticket, id_door_log,created_at, updated_at)
values(
30, concat('B<EFBFBD>rlet haszn<7A>lat (elotte: ',@p_usage_count, ' > utana: ' , @p_usage_count +1 , ' max: ', @p_max_usage_count, ')' ), ' trigger_inc_ticket',New.id_ticket_current, New.id_door_log,now(),now());
else
-- deltaElsoBelépés a napi első door log és 'most' között eltelt órák
-- HOUR( TIMEDIFF( min(created_at) , now() ) )
-- hány darab 3 órás intervallum telt el
-- floor : 2.75 -> 2
-- FLOOR( ( ( HOUR( TIMEDIFF( min(created_at) , now() ) ) /3 ) ) )
-- a napi első belépés után kiszámoljuk az aktuális n-edik 3órás intervallum kezdetét
select min(created_at) + INTERVAL (3 * FLOOR( ( ( HOUR( TIMEDIFF( min(created_at) , now() ) ) /3 ) ) ) ) hour as last_date
into @p_from
from door_log
where created_at > CURDATE() and id_customer is not null and id_ticket_current = NEW.id_ticket_current and ( direction = 7 or direction = 3);
select count(*) into @p_count_all_2 from door_log where created_at >= @p_from and id_ticket_current = New.id_ticket_current and ( direction = 7 or direction = 3);
INSERT INTO devlog ( msg) values(CONCAT( 'Bel<EFBFBD>p<EFBFBD>sek sz<73>ma az aktu<74>lis 3 <20>r<EFBFBD>s intervalumban: ', @p_count_all_2) );
IF @p_count_all_2 = 1
THEN
INSERT INTO devlog ( msg) values( 'Az aktu<74>lis intervallumban ez az els? bel<65>p<EFBFBD>s, usage_count n<>vel<65>se' );
select usage_count, max_usage_count into @p_usage_count ,@p_max_usage_count from ticket where id_ticket = NEW.id_ticket_current;
update ticket set usage_count = usage_count +1 where id_ticket = New.id_ticket_current;
INSERT INTO log (type,message, app, id_ticket, id_door_log,created_at, updated_at)
values(
40, concat('B<EFBFBD>rlet haszn<7A>lat/egy nap tobbszori (elotte: ',@p_usage_count, ' > utana: ' , @p_usage_count +1 , ' max: ', @p_max_usage_count, ')' ), ' trigger_inc_ticket',New.id_ticket_current, New.id_door_log,now(),now());
END IF;
END IF;
End IF;
IF NEW.direction = 5 or New.direction = 1
then
INSERT INTO devlog ( msg) values('Kil<EFBFBD>p<EFBFBD>s van folyamatban, kil<69>p<EFBFBD>sek sz<73>m<EFBFBD>nak be<62>ll<6C>t<EFBFBD>sa');
update ticket set count_move_out = usage_count where id_ticket = NEW.id_ticket_current;
END IF;
INSERT INTO devlog ( msg) values( 'K<EFBFBD>rtya valid<69>ci<63> m<>dos<6F>t<EFBFBD>sa' );
UPDATE card as c1
left JOIN ( select ticket.id_card as id_card , max(ticket.id_ticket) as id_ticket
from ticket
where ticket.start <= CURDATE()
and ticket.end >= curdate()
and ticket.status = 10
and ticket.count_move_out < ticket.max_usage_count
and ticket.id_card = New.id_card
group by id_card
order by id_card desc ) as t
on t.id_card = c1.id_card
SET c1.validity = case when t.id_card is null then ( c1.validity | 1 << 0 ) else ( c1.validity & ~(1 << 0) ) end
, c1.flag = case when t.id_card is null then ( c1.flag | 1 << 0 ) else ( c1.flag & ~(1 << 0) ) end
, c1.id_ticket_current = case when t.id_ticket is null then null else t.id_ticket end
WHERE c1.type <> 50 and c1.id_card = New.id_card;
IF NEW.direction = 5 or New.direction = 1
then
select max(ticket.id_ticket) into @p_mo_ticket_id
from ticket
where ticket.start <= CURDATE()
and ticket.end >= curdate()
and ticket.status = 10
and ticket.count_move_out < ticket.max_usage_count
and ticket.id_card = New.id_card
group by id_card
order by id_card desc;
set @p_allow_enter = true;
update card set
flag_out = ( flag_out | 1 << 1 ) ,
flag = case when @p_allow_enter then ( flag & ~(1 << 1) ) else ( flag | 1 << 1 ) end
WHERE type <> 50 and id_card = New.id_card;
END IF;
IF (NEW.direction = 7 or New.direction = 3 ) and NEW.id_ticket_current is not null
THEN
update card set
flag_out = ( flag_out & ~(1 << 1 ) ) ,
flag = ( flag | 1 << 1 )
WHERE type <> 50 and id_card = New.id_card;
END IF;
END IF;
END

20
docker/start2.sh Normal file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
PROJECT_DIR=$(pwd)/..
PORT=86
HOST=localhost
docker container stop fitness-web || true
docker run \
-v ${PROJECT_DIR}:/var/www/html/fitness_web \
--rm \
-d \
-p ${PORT}:80 \
--name fitness-web \
--hostname test.fintess_web.hu \
--link mariadb1:mariadb1 \
-e XDEBUG_CONFIG="idekey=PHPSTORM" \
rocho02.ddns.net/admin/cutlergyor
echo "started http://"${HOST}:${PORT}

View File

@ -9,7 +9,6 @@ use frontend\models\AccountSelect;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\base\Object;
use common\models\Log;
use common\models\User;
@ -30,7 +29,7 @@ class AccountController extends Controller
];
}
/**
* Lists all Account models.
* @return mixed
@ -40,12 +39,12 @@ class AccountController extends Controller
$model = new AccountSelect();
$model->id_account = Account::readDefault();
$accounts = Account::read();
if ($model->load(Yii::$app->request->post()) && $model->writeToSession()) {
Yii::$app->session->setFlash('success', Yii::t('frontend/ticket', 'Default account is set!') );
$user = User::findOne(\Yii::$app->user->id);
Log::log([ 'type' => Log::$TYPE_DEFAULT_ACCOUNT,
'message' => "Alapértelmezett kassza - Felhasználó: " . $user->username . " - Kassza: " . Account::readDefaultObject()->name,
@ -58,7 +57,7 @@ class AccountController extends Controller
'accounts' => $accounts
]);
}
/**
* Lists all Account models.
* @return mixed

View File

@ -13,7 +13,7 @@ use yii\helpers\Url;
<?php
/** @var \common\models\Ticket $ticket */
$ticket = null;
if (count($model->tickets) > 0) {
if ( isset($model->tickets) && count($model->tickets) > 0) {
$ticket = $model->tickets[0];
}

View File

@ -24,7 +24,7 @@ $this->params['breadcrumbs'][] = $this->title;
$dt->sub( new DateInterval( 'P2D') );
echo \common\components\DateUtil::formatUtc($dt);
echo \common\components\DateUtil::formatDateTimeUtc($dt);
echo " - ";
@ -33,7 +33,7 @@ $this->params['breadcrumbs'][] = $this->title;
$ticketType->time_unit_count = 3;
$dt2 = \common\components\Helper::getTicketExpirationDate($dt, $ticketType);
echo \common\components\DateUtil::formatUtc($dt2);
echo \common\components\DateUtil::formatDateTimeUtc($dt2);
// $dt2 = \common\components\Helper::getTicketExpirationDate($dt, $ticketType);
// echo \common\components\DateUtil::formatUtc($dt2);

View File

@ -48,6 +48,7 @@ class LoginController extends RestController
->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + $validFor)// Configures the expiration time of the token (exp claim)
->withClaim('uid', $form->getMobileDevice()->getId())// Configures a new claim, called "uid"
->withClaim('cardId', $form->getMobileDevice()->card->number)// Configures a new claim, called "uid"
->getToken($signer, $key); // Retrieves the generated token
return $this->asJson([

View File

@ -0,0 +1,49 @@
<?php /** @noinspection PhpUnused */
namespace rest\controllers;
use common\manager\DoorManager;
use rest\models\DoorMoveForm;
use Yii;
use yii\web\BadRequestHttpException;
class DoorController extends RestController
{
public function actionMove()
{
$formModel = new DoorMoveForm();
if ($formModel->load(Yii::$app->request->post(),"") ) {
if ( !$formModel->validate()){
$keys = array_keys($formModel->getFirstErrors());
throw new BadRequestHttpException("Invalid move request:". $formModel->getFirstErrors()[$keys[0]]);
}
$doorManager = new DoorManager();
$doorManager->move($formModel->cardNumber,$formModel->device,$formModel->direction, $formModel->createdAt, $formModel->date);
}
return $formModel;
}
public function actionReset($cardNumber){
$doorManager = new DoorManager();
$doorManager->resetLogs($cardNumber);
}
public function actionInfo($cardNumber){
$doorManager = new DoorManager();
return $doorManager->getInfo($cardNumber);
}
public function actionCreateDoorLog(){
$doorManager = new DoorManager();
return $doorManager->createLog();
}
public function actionPing(){
\Yii::$app->response->statusCode = 204;
echo "hello";
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace rest\models;
use yii\base\Model;
class DoorMoveForm extends Model
{
public $cardNumber;
public $device;
public $direction;
public $test;
public $createdAt;
public $date;
public function rules( ) {
return [
[ ['cardNumber', 'device', 'direction' ], 'required'],
[ ['createdAt', 'date' ], 'string']
];
}
}

7715
test/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
test/package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "rest-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest",
"test:watch": "jest --watch"
},
"author": "",
"license": "ISC",
"devDependencies": {
"jest": "^27.5.1",
"supertest": "^6.2.2"
},
"dependencies": {
"axios": "^0.27.0",
"node-fetch": "^3.2.3"
}
}

212
test/src/rest/move.test.js Normal file
View File

@ -0,0 +1,212 @@
// const fetch = require('node-fetch');
// const {test, expect} = require('jest')
const axios = require('axios');
const url = 'http://localhost:86/fitness_web/rest/web/index.php?r=';
const auth = "Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE=";
const TEST_CARD_NUMBER = "10WMVXMZ";
const TEST_AUTH_HEADER = {
'Authorization': auth
};
function fail(reason = "fail was called in a test.") {
throw new Error(reason);
}
function secondsSinceEpoch(d){
return Math.floor( d.getTime() / 1000 );
}
global.fail = fail;
function formatDateTime(date){
let s = date.getFullYear()
+ "-"
+ (date.getMonth() + 1+"").padStart(2,"0")
+ "-"
+ (date.getDate() +"").padStart(2,"0")
+ " "
+ (date.getHours()+"").padStart(2,"0")
+ ":"
+ (date.getMinutes()+"").padStart(2,"0")
+ ":"
+ "00";
console.info(s);
return s;
}
// This test fails because 1 !== 2
test('Testing to see if Jest works', () => {
expect(1).toBe(1)
})
class Client {
async reset($cardNumber) {
return await axios.get(url + 'door/reset&cardNumber=' + $cardNumber, {
headers: {...TEST_AUTH_HEADER}
});
}
async getInfo($cardNumber) {
return await axios.get(url + 'door/info&cardNumber=' + $cardNumber, {
headers: {...TEST_AUTH_HEADER}
});
}
async createDoorLog(doorlog) {
return await axios.post(url + 'door/create-door-log', doorlog,{
headers: {...TEST_AUTH_HEADER},
});
}
async move(data, headers) {
return await axios.get(url + 'door/move', {
headers: {
...TEST_AUTH_HEADER,
...headers
},
data: {
direction: 3,
device: 'QRCODE',
cardNumber: '10WMVXMZ',
...data
}
});
}
async moveWithInfo(data, headers) {
const before = await this.getInfo(data.cardNumber);
const response = await this.move(data, headers);
const after = await this.getInfo(data.cardNumber);
return {
before,
response,
after
}
}
}
test('Emergency open', async () => {
try {
const client = new Client();
await client.reset(TEST_CARD_NUMBER)
let before = await client.getInfo(TEST_CARD_NUMBER);
let response = await client.move({direction: 128})
expect(response.status).toBe(204);
let after = await client.getInfo(TEST_CARD_NUMBER);
// console.info("before:after", before.data.doorLogCount, after.data.doorLogCount);
expect(after.data.doorLogs.length).toBe(0);
expect(after.data.doorLogCount).toBe("" + (parseInt(before.data.doorLogCount) + 1));
expect(after.data.lastDoorLog?.direction).toBe(128);
} catch (e) {
throw e;
}
})
test('Error if card not exists', async () => {
const client = new Client();
try {
await client.move({cardNumber: 'notexists', direction: 3});
} catch (e) {
expect(e?.response?.status).toBe(400);
}
expect.assertions(1);
})
test('Allow card type employee', async () => {
const client = new Client();
let createdAt = new Date();
createdAt.setHours(18);
const info = await client.moveWithInfo({cardNumber: 'employee', direction: 3, createdAt: secondsSinceEpoch(createdAt)});
// console.info("employee ready");
const lastLog = info.after.data.lastDoorLog;
expect(lastLog.id_card).not.toBeNull();
expect(lastLog.direction).toBe(3);
})
test('Normal Ticket: usage count will be increased on entry', async () => {
const client = new Client();
client.reset(TEST_CARD_NUMBER);
const info = await client.moveWithInfo({cardNumber: TEST_CARD_NUMBER, direction: 3});
expect(info?.response?.status).toBe(200);
const ticketBefore = info?.before.data?.tickets[0];
const ticketAfter = info?.after.data?.tickets[0];
expect(ticketBefore.usage_count + 1).toBe(ticketAfter.usage_count);
const info2 = await client.moveWithInfo({cardNumber: TEST_CARD_NUMBER, direction: 3});
expect(info?.response?.status).toBe(200);
const ticketAfter2 = info2?.after.data?.tickets[0];
expect(ticketAfter.usage_count).toBe(ticketAfter2.usage_count);
})
test('Normal Ticket: increase door log after 3 hours', async () => {
const client = new Client();
client.reset(TEST_CARD_NUMBER);
let info = await client.getInfo(TEST_CARD_NUMBER);
// First log on this day
let date = new Date();
date.setHours(1);
date.setMinutes(0,0,0);
await client.createDoorLog({
'created_at' : formatDateTime( date ),
'id_card': info.data.card.id_card,
'id_customer': info.data.customer.id_customer,
'id_ticket_current' : info.data.tickets[0].id_ticket,
'direction' : 3
});
// second door in @ 2:00 am. Less then 3 hours since first door log, so no
// usage_count must be consumed
let createdAt = new Date();
createdAt.setHours(2);
createdAt.setMinutes(0,0,0);
info = await client.moveWithInfo({
cardNumber: TEST_CARD_NUMBER,
direction: 3,
createdAt: formatDateTime(createdAt)
});
let ticketBefore = info?.before.data?.tickets[0];
let ticketAfter = info?.after.data?.tickets[0];
expect(ticketBefore.usage_count).toBe(ticketAfter.usage_count);
// @4:00 3 hours already passed, we need consume usage count
createdAt = new Date();
createdAt.setHours(4);
createdAt.setMinutes(0,0,0);
info = await client.moveWithInfo({
cardNumber: TEST_CARD_NUMBER,
direction: 3,
createdAt: formatDateTime(createdAt)
});
ticketBefore = info?.before.data?.tickets[0];
ticketAfter = info?.after.data?.tickets[0];
expect(ticketBefore.usage_count+1).toBe(ticketAfter.usage_count);
// @6:00 2 hours passed since 4, we don't need consume usage count
createdAt = new Date();
createdAt.setHours(5);
createdAt.setMinutes(0,0,0);
info = await client.moveWithInfo({
cardNumber: TEST_CARD_NUMBER,
direction: 3,
createdAt: formatDateTime(createdAt)
});
ticketBefore = info?.before.data?.tickets[0];
ticketAfter = info?.after.data?.tickets[0];
expect(ticketBefore.usage_count).toBe(ticketAfter.usage_count);
// @20:15 Need to consume usage count
createdAt = new Date();
createdAt.setHours(20);
createdAt.setMinutes(15,0,0);
info = await client.moveWithInfo({
cardNumber: TEST_CARD_NUMBER,
direction: 3,
createdAt: formatDateTime(createdAt)
});
ticketBefore = info?.before.data?.tickets[0];
ticketAfter = info?.after.data?.tickets[0];
expect(ticketBefore.usage_count+1).toBe(ticketAfter.usage_count);
},10000)