fitness-web/common/manager/DoorManager.php
2023-02-11 14:32:17 +01:00

746 lines
30 KiB
PHP

<?php
namespace common\manager;
use common\components\DateUtil;
use common\components\DoorMoveContext;
use common\components\FitnessException;
use common\components\Helper;
use common\components\StopWatch;
use common\models\Card;
use common\models\CardKeyAssignment;
use common\models\DoorLog;
use common\models\DoorLogForTest;
use common\models\Key;
use common\models\Log;
use common\models\Ticket;
use common\models\VirtualKey;
use frontend\models\KeyToggleForm;
use yii\base\BaseObject;
use yii\base\InvalidConfigException;
use yii\db\Exception;
use yii\web\BadRequestHttpException;
use yii\web\ServerErrorHttpException;
/**
* Created by IntelliJ IDEA.
* User: rocho
* Date: 2018.12.17.
* Time: 6:12
*/
class DoorManager extends BaseObject
{
/**
* @param $identifier 00000000: nyomogombos nyitás
* @param $device string B(gomb)|Q(qrcode)|C(nfc),E(emergency)
* @param $direction string IN|OUT
* @param $verifyOnly boolean true: akkor csak lekerdezés, false: megtörtént a mozgás (ilyenkor vonunk le egy alkalmat)
* @param $createdAt number unix timestamp , override createdAt for doorLogs
* @param $date number unix timestamp, override date for validation check 'now'
* @return void
*/
public function move($identifier, $device, $direction, $verifyOnly, $createdAt = null, $date = null)
{
$requestId = uniqid("", false);
$context = new DoorMoveContext([
'id' => $requestId,
'$identifier' => $identifier,
'device' => $device,
'direction' => $direction,
'originalDirection' => $direction,
'verifyOnly' => $verifyOnly
]);
try {
$stopWatch = new StopWatch();
// for testing purposes
if (Helper::isRestAllowVerifyOnly() === false) {
\Yii::info("$requestId: verifyonly not allowed");
$verifyOnly = false;
}
\Yii::info("$requestId: move with next parameers:" . ";identifier" . $identifier . ";device" . $device . ";direction" . $direction . ";verifyOnly" . $verifyOnly . ";createdAt" . print_r($createdAt, true) . ";date" . print_r($date, true));
\Yii::info("$requestId: move get request: " . print_r($_GET, true));
\Yii::info("$requestId: move post request: " . print_r($_GET, true));
if (isset($createdAt)) {
$createdAt = DateUtil::parseDateTime($createdAt);
} else {
$createdAt = DateUtil::utcDateTime();
}
$context->created_at = $createdAt;
if (isset($date)) {
$date = DateUtil::parseDateTime($date);
} else {
$date = DateUtil::utcDate();
}
$context->date = $date;
if ($device === 'E') {
$this->moveEmergency($context/*;$requestId,$identifier, $device, $direction, $verifyOnly, $createdAt, $date*/);
return;
}
$cardNumber = $identifier;
$virtualKey = null;
switch ($direction) {
case 'IN':
$direction = DoorLog::$DIRECTION_IN;
break;
case 'OUT':
$direction = DoorLog::$DIRECTION_OUT;
break;
default:
throw new BadRequestHttpException("$requestId: Direction not supported: " . $direction);
}
$context->direction = $direction;
// if device is qr code
if ($device == 'Q') {
// allow only virtual key
$virtualKey = VirtualKey::findOne(['number' => $identifier]);
if (!isset($virtualKey)) {
$context->error = true;
$context->errorCode = "VIRTUAL_KEY_NOT_FOUND";
throw new BadRequestHttpException("$requestId: Virtual key not found: " . $identifier);
}
$card = Card::findOne($virtualKey->id_card);
if ($card != null) {
$card = Card::readCard($card->number);
}
if ($card == null) {
$context->error = true;
$context->errorCode = "CARD_NOT_FOUND";
throw new BadRequestHttpException("$requestId: Card not found by virtual key: " . $identifier . '/' . $virtualKey->id_card);
}
$cardNumber = $card->number;
\Yii::info("$requestId: virtual key and card loaded in sec " . $stopWatch->split());
} else {
// load by rfid or card number
$card = Card::readCard(Helper::fixAsciiChars($identifier));
\Yii::info("$requestId: Card loaded in sec " . $stopWatch->split());
if (!isset($card)) {
$context->error = true;
$context->errorCode = "CARD_NOT_FOUND";
throw new BadRequestHttpException("$requestId: Card not found with number: " . $identifier);
}
\Yii::info("$requestId: card loaded in sec " . $stopWatch->split());
$virtualKey = VirtualKey::findOne(['id_card' => $card->id_card]);
\Yii::info("$requestId: virtual key for card loaded in sec " . $stopWatch->split());
}
$context->virtualKey = $virtualKey;
$context->card = $card;
$context->cardNumber = $cardNumber;
\Yii::info("$requestId: Card number " . $card->number);
if ($card->type == Card::TYPE_EMPLOYEE) {
$this->moveEmployee($context /*$identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey*/);
return;
}
$this->moveCustomer($context /* $requestId, $identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey*/);
} catch (FitnessException $e) {
$context->error = true;
$context->exception = $e->originalException;
$context->errorCode = $e->errorCode;
} catch (\Exception $e) {
$context->error = true;
$context->exception = $e;
$context->errorCode = "UNKNOWN";
} finally {
// do logging
$this->logContext($context);
}
}
/**
* @param $ctx DoorMoveContext
* @return void
*/
function logContext($ctx){
try{
$result = [
'requestId' => $ctx->id,
'identifier' => $ctx->identifier,
'verifyOnly' => $ctx->verifyOnly,
'device' => $ctx->device,
'direction' => $ctx->direction,
'originalDirection' => $ctx->originalDirection,
'idCard' => isset($ctx->card)? $ctx->card->id_card : null,
'cardNumber' => isset($ctx->card) ? $ctx->card->number : null,
'idTicket' => isset($ctx->ticket) ? $ctx->ticket->id_ticket : null,
'ticketType' => isset($ctx->ticket) ? $ctx->ticket->ticketType->name : null,
'ticketUsageCount' => isset($ctx->ticket) ? $ctx->ticket->usage_count : null,
'idCustomer' => isset($ctx->customer) ? $ctx->customer->id_customer : null,
'customerName' => isset($ctx->customer) ? $ctx->customer->name : null,
'customerEmail' => isset($ctx->customer) ? $ctx->customer->email : null,
'key' => isset($ctx->key) ? $ctx->key->name : null,
'idVirtualKey' => isset($ctx->virtualKey) ? $ctx->virtualKey->idVirtualKey : null,
'kind' => $ctx->kind,
'actions' => implode(",",$ctx->actions),
'error' => $ctx->error,
'errorCode' => $ctx->errorCode,
'ticketUsage' => 1,
];
if ( $ctx->error === true ){
if ( isset($ctx->exception )){
$result['errorMessage'] = substr( $ctx->exception->message,0,100);
}
}
\Yii::info("door log: " . implode(";", $result));
}catch (\Exception $e){
\Yii::error("Failed to log door context");
}
}
function moveEmergency($ctx)
{
$ctx->kind = "EMERGENCY";
\Yii::info("$ctx->requestId: emergency move");
try {
$createdAtStr = DateUtil::formatDateTimeUtc($ctx->createdAt);
\Yii::$app->db->beginTransaction();
$doorLog = new DoorLog();
$doorLog->version = 2;
$doorLog->direction = DoorLog::$DIRECTION_ALL_EMERGENCY;
$doorLog->source_app = $ctx->device;
$doorLog->created_at = $createdAtStr;
$doorLog->save(false);
Log::log(
[
'type' => Log::$TYPE_INFO,
'message' => 'Ajtó nyitás: vészhelyzet',
'id_door_log' => $doorLog->id_door_log
]
);
$ctx->actions[] = "EMERGENCY_MOVE";
\Yii::$app->db->transaction->commit();
} catch (\Exception $e) {
\Yii::$app->db->transaction->rollBack();
throw new FitnessException(
"unknowon error",
FitnessException::UNKNOWN_ERROR,
"EMERGENCY_OPEN_FAILED",
$ctx,
$e
);
}
}
function moveEmployee($ctx /*$identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey*/)
{
$ctx->kind = "EMPLOYEE";
/**
* if the card type is employee, neither customer nor ticket is needed.
* Free to enter/leave
*/
\Yii::info("employee move");
try {
$createdAtStr = DateUtil::formatDateTimeUtc($ctx->createdAt);
\Yii::$app->db->beginTransaction();
$doorLog = new DoorLog();
$doorLog->version = 2;
$doorLog->direction = $ctx->direction;
$doorLog->source_app = $ctx->device;
$doorLog->created_at = $createdAtStr;
$doorLog->id_card = $ctx->card->id_card;
$doorLog->card_flag = $ctx->card->flag;
if (!$ctx->verifyOnly) {
$doorLog->save(false);
Log::log(
[
'type' => Log::$TYPE_INFO,
'message' => 'Ajtó nyitás: munkatárs',
'id_door_log' => $doorLog->id_door_log
]
);
}
$ctx->actions[] = "EMPLOYEE_" . $ctx->originalDirection;
\Yii::$app->db->transaction->commit();
} catch (\Exception $e) {
\Yii::$app->db->transaction->rollBack();
throw new FitnessException(
"unknowon error",
FitnessException::UNKNOWN_ERROR,
"EMPLOYEE_FAILED",
$ctx,
$e
);
}
}
/**
* @param $ctx
*
* @return void
* @throws BadRequestHttpException
* @throws ServerErrorHttpException
* @throws InvalidConfigException
* @throws Exception
*/
function moveCustomer($ctx/* $requestId, $identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey*/)
{
$ctx->kind = "CUSTOMER";
\Yii::info("$ctx->requestId: move customer");
$stopWatch = new StopWatch();
try {
$createdAtStr = DateUtil::formatDateTimeUtc($ctx->createdAt);
\Yii::info("$ctx->requestId: crated at str: " . $createdAtStr);
\Yii::$app->db->beginTransaction();
$doorLog = new DoorLog();
$doorLog->version = 2;
$doorLog->direction = $ctx->direction;
$doorLog->source_app = $ctx->device;
$doorLog->created_at = $createdAtStr;
$doorLog->id_card = $ctx->card->id_card;
$doorLog->card_flag = $ctx->card->flag;
$activeTickets = Ticket::readActive($ctx->card, clone $ctx->date);
\Yii::info("$ctx->requestId: active ticket count:" . count($activeTickets));
/** @var Ticket $ticket */
$ticket = null;
if (isset($activeTickets) && count($activeTickets) > 0) {
$ticket = $activeTickets[0];
}
if (!isset($ticket)) {
throw new FitnessException(
"$ctx->requestId: No active ticket found for:" . $ctx->card->number,
FitnessException::TYPE_BAD_REQUEST,
"NOT_FOUND_ACTIVE_TICKET",
$ctx
);
}
$ctx->ticket = $ticket;
\Yii::info("$ctx->requestId: ticket {$ticket->id_ticket} loaded in sec " . $stopWatch->split());
$doorLog->id_ticket_current = $ticket->id_ticket;
// customer is also required
$customer = $ctx->card->customer;
if (!isset($customer)) {
throw new FitnessException(
"$ctx->requestId: Customer not found for:" . $ctx->card->number,
FitnessException::TYPE_BAD_REQUEST,
"NOT_FOUND_CUSTOMER",
$ctx
);
}
$ctx->customer = $customer;
$doorLog->id_customer = $customer->id_customer;
\Yii::info("$ctx->requestId: customer {$customer->id_customer} loaded in sec " . $stopWatch->split());
if (!$ctx->verifyOnly) {
// save the door log
$doorLog->save(false);
}
\Yii::info("$ctx->requestId: door log {$doorLog->id_door_log} saved in sec " . $stopWatch->split());
// if direction is in, check if usage count must be increased
if ($ctx->direction == DoorLog::$DIRECTION_IN) {
if ($ctx->card->isFlagDoor()) {
throw new FitnessException(
"$ctx->requestId: Card already 'IN': " . $ctx->card->id_card,
FitnessException::TYPE_BAD_REQUEST,
"ALREADY_IN",
$ctx
);
}
if ($ctx->card->isFlagKey()) {
throw new FitnessException(
"$ctx->requestId: Key required: " . $ctx->card->id_card,
FitnessException::TYPE_BAD_REQUEST,
"REQUIRED_KEY",
$ctx
);
}
if ($ctx->card->isFlagStatus()) {
throw new FitnessException(
"$ctx->requestId: Card has no active status: " . $ctx->card->id_card,
FitnessException::TYPE_BAD_REQUEST,
"CARD_STATUS_NOT_ACTIVE",
$ctx
);
}
if (isset($ctx->virtualKey)) {
if (isset($ctx->virtualKey->direction_in_at)) {
throw new FitnessException(
"$ctx->requestId: Virtual key - already moved in: " . $ctx->identifier . '/' . $ctx->virtualKey->id_card,
FitnessException::TYPE_BAD_REQUEST,
"VIRTUAL_KEY_ALREADY_IN",
$ctx
);
}
$ctx->virtualKey->direction_in_at = Helper::getDateTimeString();
\Yii::info("$ctx->requestId: Setting virtual key direction_in_at");
$ctx->actions[] = "VIRTUAL_KEY_MOVE_IN";
if (!$ctx->verifyOnly) {
\Yii::info("$ctx->requestId: Updating virtual key");
$ctx->virtualKey->save(false);
}
}
// detect if need to increase usage count for ticket
if (!$ctx->verifyOnly) {
// if not verifyonly, check, if ticket usage count must be increased
$countDoorLogsForTicketSince = $this->getCountDoorLogsForTicketSince($ticket->id_ticket, DateUtil::utcDate(clone $ctx->date));
\Yii::info("$ctx->requestId: getCountDoorLogsForTicketSince: " . $countDoorLogsForTicketSince);
if (!isset($countDoorLogsForTicketSince)) {
$countDoorLogsForTicketSince = 0;
}
\Yii::info("$ctx->requestId: count of door logs '{$countDoorLogsForTicketSince}' loaded in sec " . $stopWatch->split());
// 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);
\Yii::info("$ctx->requestId: First ticket usage today, increasing usage count for card: " . $ctx->card->id_card);
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
]
);
\Yii::info("$ctx->requestId: Ticket usage count increased after first doorlog of day in sec " . $stopWatch->split());
$ctx->actions[] = "TICKET_FIRST_USAGE_TODAY";
} else {
\Yii::info("$ctx->requestId: more then one door log today for card: " . $ctx->card->id_card);
// 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 $ctx->date);
$startOfTomorrow = DateUtil::tomorrowStart(clone $ctx->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::info("$ctx->requestId: All door logs for today loaded in sec " . $stopWatch->split());
\Yii::info("$ctx->requestId: allDoorLogToday", print_r($allDoorLogToday, true));
if (isset($allDoorLogToday) && count($allDoorLogToday) > 0) {
$firstInToday = $allDoorLogToday[0];
}
if (isset($firstInToday)) {
\Yii::info("$ctx->requestId: first in today for card: " . $ctx->card->id_card . " was at " . $firstInToday->created_at);
$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, $ctx->createdAt);
if (!isset($activeInterval)) {
throw new ServerErrorHttpException("$ctx->requestId: Active Interval not found");
}
$logCountInActiveInterval = count($activeInterval['logs']);
if ($logCountInActiveInterval == 1) {
$ticket->usage_count = $ticket->usage_count + 1;
$ticket->save(false);
\Yii::info("$ctx->requestId: Ticket usage count increased after first IN after first door_log in interval in sec " . $stopWatch->split());
$ctx->actions[] = "TICKET_INCREASE_USAGE";
}
}
}
}
$ctx->actions[] = "MOVE_IN";
}
if ($ctx->direction == DoorLog::$DIRECTION_OUT || $ctx->direction == DoorLog::$DIRECTION_OUT_WITHOUT_MOVE) {
if ($ctx->card->isFlagOutKey()) {
throw new FitnessException(
"$ctx->requestId: Can't exit with card has a key assigned",
FitnessException::TYPE_BAD_REQUEST,
"CARD_LOCKER_KEY_ASSIGNED_FLAG",
$ctx
);
}
if ($ctx->card->isFlagStatus()) {
throw new FitnessException(
"$ctx->requestId: Can't exit with card has inactive status",
FitnessException::TYPE_BAD_REQUEST,
"CARD_STATUS_INACTIVE",
$ctx
);
}
$keyAssigned = CardKeyAssignment::findOne(['id_card' => $ctx->card->id_card]);
if (isset($keyAssigned)) {
throw new FitnessException(
"$ctx->requestId: Can't exit with card has a key assigned",
FitnessException::TYPE_BAD_REQUEST,
"CARD_LOCKER_KEY_ASSIGNED_KEY",
$ctx
);
}
if (isset($virtualKey)) {
if (!isset($virtualKey->direction_in_at)) {
throw new FitnessException(
"$ctx->requestId: Virtual key: move out without move in",
FitnessException::TYPE_BAD_REQUEST,
"VIRTUAL_KEY_MOVE_OUT_WITHOUT_MOVE_IN",
$ctx
);
}
if (isset($virtualKey->direction_out_at)) {
throw new FitnessException(
"$ctx->requestId: Virtual key: already move out",
FitnessException::TYPE_BAD_REQUEST,
"VIRTUAL_KEY_ALREADY_OUT",
$ctx
);
}
$virtualKey->direction_out_at = Helper::getDateTimeString();
if (!$ctx->verifyOnly) {
$virtualKey->save(false);
}
}
$ticket->count_move_out = $ticket->usage_count;
if (!$ctx->verifyOnly) {
$ticket->save(false);
}
$ctx->actions[] = "MOVE_OUT";
\Yii::info("$ctx->requestId: direction_out: ticket count_move_out set after direction_out in sec " . $stopWatch->split());
}
if (!$ctx->verifyOnly) {
Card::updateCardFlagTicket($ticket->id_ticket);
\Yii::info("$ctx->requestId: updateCardFlagTicket: card flag updated in sec " . $stopWatch->split());
// reload card after flag is set
$ctx->card = Card::readCard($ctx->cardNumber);
if ($ctx->direction == DoorLog::$DIRECTION_OUT_WITHOUT_MOVE || $ctx->direction == DoorLog::$DIRECTION_OUT) {
$ctx->card->flag_out = Helper::setBit($ctx->card->flag_out, Card::$FLAG_DOOR, true);
$ctx->card->flag = Helper::setBit($ctx->card->flag, Card::$FLAG_DOOR, false);
$ctx->card->save(false);
\Yii::info("$ctx->requestId: direction_out: Door flag updated in sec " . $stopWatch->split());
} else if ($ctx->direction == DoorLog::$DIRECTION_IN || $ctx->direction == DoorLog::$DIRECTION_IN_WITHOUT_MOVE) {
$ctx->card->flag_out = Helper::setBit($ctx->card->flag_out, Card::$FLAG_DOOR, false);
$ctx->card->flag = Helper::setBit($ctx->card->flag, Card::$FLAG_DOOR, true);
$ctx->card->save(false);
\Yii::info("$ctx->requestId: direction_in: Card flag updated in sec " . $stopWatch->split());
}
}
$stopWatch->stop();
\Yii::info("$ctx->requestId: finished in sec " . $stopWatch->getTotal());
\Yii::$app->db->transaction->commit();
\Yii::info("$ctx->requestId: Commited");
} catch (FitnessException $fe) {
\Yii::$app->db->transaction->rollBack();
\Yii::info("$ctx->requestId: rollbacked");
throw $fe;
} catch (\Exception $e) {
\Yii::$app->db->transaction->rollBack();
\Yii::info("$ctx->requestId: rollbacked");
throw new FitnessException(
"UNKNOWN_ERROR",
FitnessException::UNKNOWN_ERROR,
"CUSTOMER_UNKNOWN_ERROR",
$ctx,
$e
);
}
}
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::info("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);
$card->flag = 0;
$card->flag_out = 0;
$card->save(false);
Card::updateCardFlagTicket($card->id_card);
DoorLog::deleteAll(
['id_card' => $card->id_card]
);
// todo: revoke all assigned key
$this->revokeKey($cardNumber, "f100");
}
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 createLog()
{
\Yii::info("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::info("Door log saving:" . $log->created_at);
$log->save(false);
return $log;
} else {
throw new BadRequestHttpException(print_r($log->getErrors(), true));
}
} else {
\Yii::info("validated" . print_r($log->errors, true));
throw new BadRequestHttpException();
}
}
throw new BadRequestHttpException('Not a Post');
}
function checkoutKey($cardNumber, $keyNumber)
{
$model = new KeyToggleForm();
$model->card = Card::readCard($cardNumber);
$model->customer = $model->card->customer;
$model->keyCard = $model->card;
$model->keyModel = $model->readKey($keyNumber);
$model->assign();
}
function revokeKey($cardNumber, $keyNumber)
{
$model = new KeyToggleForm();
$model->card = Card::readCard($cardNumber);
$model->customer = $model->card->customer;
$model->keyCard = $model->card;
$model->keyModel = $model->readKey($keyNumber);
$model->revoke();
}
}