353 lines
13 KiB
PHP
353 lines
13 KiB
PHP
<?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');
|
||
}
|
||
|
||
}
|