From 821d852d5b037e34b3e8da63ceff023500abc52c Mon Sep 17 00:00:00 2001 From: Schneider Roland Date: Wed, 26 Oct 2022 18:55:27 +0200 Subject: [PATCH] desta fix for invalid bankaccount numbers; add virtual key object --- .../TicketInstallmentRequestController.php | 18 +- .../TicketInstallmentMarkForSendForm.php | 38 +- common/manager/DoorManager.php | 499 +++++++++++------- common/models/HuBankAccountValidator.php | 36 ++ common/models/VirtualKey.php | 13 +- ...er_table_virtual_key_add_column_number.php | 42 ++ ...irtual_key_add_column_direction_out_at.php | 27 + frontend/models/KeyToggleForm.php | 12 + mobileapi/manager/ApiManager.php | 18 +- rest.http | 65 ++- rest/config/main.php | 7 +- 11 files changed, 542 insertions(+), 233 deletions(-) create mode 100644 common/models/HuBankAccountValidator.php create mode 100644 console/migrations/m221024_203742_alter_table_virtual_key_add_column_number.php create mode 100644 console/migrations/m221026_111439_alter_table_virtual_key_add_column_direction_out_at.php diff --git a/backend/controllers/TicketInstallmentRequestController.php b/backend/controllers/TicketInstallmentRequestController.php index 1821ee3..a8d02c3 100644 --- a/backend/controllers/TicketInstallmentRequestController.php +++ b/backend/controllers/TicketInstallmentRequestController.php @@ -17,7 +17,7 @@ use backend\models\GiroKotegForm; /** * TicketInstallmentRequestController implements the CRUD actions for TicketInstallmentRequest model. - * + * * TODO: FIX ACCESS */ class TicketInstallmentRequestController extends Controller @@ -47,7 +47,6 @@ class TicketInstallmentRequestController extends Controller ] ] // everything else is denied - ] ]; } @@ -66,18 +65,19 @@ class TicketInstallmentRequestController extends Controller 'dataProvider' => $dataProvider, ]); } - + /** * Lists pending TicketInstallmentRequest models. * @return mixed */ public function actionPending() { + \Yii::info("Showing pending"); $model = new TicketInstallmentMarkForSendForm(); if ($model->load(Yii::$app->request->post()) ) { $model->markForSend(); } - + $searchModel = new TicketInstallmentRequestSearchPending(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); @@ -102,7 +102,7 @@ class TicketInstallmentRequestController extends Controller \Yii::$app->session->setFlash('success',"Megbízás teljesítve"); } - return $this->redirect(['ticket-installment-request/view', + return $this->redirect(['ticket-installment-request/view', 'id' => $model->id_ticket_installment_request, ]); } @@ -115,15 +115,15 @@ class TicketInstallmentRequestController extends Controller public function actionDownloadGiro() { $model = new GiroKotegForm(); - + if ($model->load(Yii::$app->request->post()) && $model->validate() ) { $model->createKoteg(); return $this->redirect(['ugiro/view', 'id' => $model->koteg->id_ugiro]); } - + $searchModel = new TicketInstallmentRequestSearchDownloadGiro(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); - + $model->action = "create"; return $this->render('index_download_giro', [ 'searchModel' => $searchModel, @@ -197,7 +197,7 @@ class TicketInstallmentRequestController extends Controller return $this->redirect(['index']); } - + public function actionTest( ) { return $this->render('test'); diff --git a/backend/models/TicketInstallmentMarkForSendForm.php b/backend/models/TicketInstallmentMarkForSendForm.php index 94fa3b6..f6fdf36 100644 --- a/backend/models/TicketInstallmentMarkForSendForm.php +++ b/backend/models/TicketInstallmentMarkForSendForm.php @@ -2,6 +2,7 @@ namespace backend\models; +use common\models\HuBankAccountValidator; use Yii; use yii\base\Model; use common\models\Card; @@ -16,25 +17,48 @@ use common\models\TicketInstallmentRequest; * @property \Yii\web\UploadedFile $file */ class TicketInstallmentMarkForSendForm extends Model{ - + public $items; - + public function rules(){ return [ ['items', 'each', 'rule' => ['integer']], + ['items', 'validateBankAccount'], ]; } - - - + + public function validateBankAccount($attribute, $params){ + $items = TicketInstallmentRequest::find()->andWhere([ + 'in', 'id_ticket_installment_request' , $this->items + ])->all(); + \Yii::info("validateBankAccount:". count($items)); + $validator = new HuBankAccountValidator(); + foreach($items as $item){ + \Yii::info("validateBankAccount2:". $item->id_ticket_installment_request); + /** @var Customer $customer */ + $customer = $item->customer; + \Yii::info("validateBankAccount3:". $customer->username); + $isBankAccountValid = $validator->validate($customer->bank_account); + if (!$isBankAccountValid){ + $errorMessage = ""; + $errorMessage .= "Vendég=".$customer->name; + $errorMessage .= "; Kártya=".$customer->card->number; + $errorMessage .= "; Megbízás=".$item->id_ticket_installment_request; + $this->addError('items', "Hibás bankszámlaszám:" .$errorMessage ); + } + } + } + + public function markForSend(){ + \Yii::info("mark for send"); if ( $this->validate() && isset($this->items ) && is_array($this->items ) ){ $updated = 0; $updated = TicketInstallmentRequest::updateAll(['status' => TicketInstallmentRequest::$STATUS_MARKED_TO_SEND ],['in', 'id_ticket_installment_request' , $this->items]); \Yii::$app->session->setFlash('success', $updated . " megbízás küldésre jelölve " ); }else{ - \Yii::$app->session->setFlash('success', " Nem történt küldésre jelölés! " ); + \Yii::$app->session->setFlash('error', " Nem történt küldésre jelölés! " . $this->getFirstError('items') ); } } - + } \ No newline at end of file diff --git a/common/manager/DoorManager.php b/common/manager/DoorManager.php index aaea916..ea9e4d1 100644 --- a/common/manager/DoorManager.php +++ b/common/manager/DoorManager.php @@ -12,6 +12,7 @@ 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\web\BadRequestHttpException; @@ -26,9 +27,8 @@ use yii\web\ServerErrorHttpException; class DoorManager extends BaseObject { - /** - * @param $cardNumber 00000000: nyomogombos nyitás + * @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) @@ -40,131 +40,205 @@ class DoorManager extends BaseObject * @throws \yii\base\InvalidConfigException * @throws \yii\db\Exception */ - public function move($cardNumber, $device, $direction, $verifyOnly, $createdAt = null, $date = null) + public function move($identifier, $device, $direction, $verifyOnly, $createdAt = null, $date = null) { + $stopWatch = new StopWatch(); + + \Yii::info("move with next parameers:" . ";identifier" . $identifier . ";device" . $device . ";direction" . $direction . ";verifyOnly" . $verifyOnly . ";createdAt" . print_r($createdAt,true) . ";date" . print_r($date,true)); + \Yii::info("move get request: " . print_r($_GET, true)); + \Yii::info("move post request: " . print_r($_GET, true)); + + if (isset($createdAt)) { + $createdAt = DateUtil::parseDateTime($createdAt); + } else { + $createdAt = DateUtil::utcDateTime(); + } + + if (isset($date)) { + $date = DateUtil::parseDateTime($date); + } else { + $date = DateUtil::utcDate(); + } + + if ($device === 'E') { + $this->moveEmergency($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("Direction not supported: " . $direction); + } + + // if device is qr code + if ($device == 'Q') { + // allow only virtual key + $virtualKey = VirtualKey::findOne(['number' => $identifier]); + if (!isset($virtualKey)) { + throw new BadRequestHttpException("Virtual key not found: " . $identifier); + } + $card = Card::findOne($virtualKey->id_card); + if ($card != null) { + $card = Card::readCard($card->number); + } + if ($card == null) { + throw new BadRequestHttpException("Card not found by virtual key: " . $identifier . '/' . $virtualKey->id_card); + } + $cardNumber = $card->number; + \Yii::info("virtual key and card loaded in sec " . $stopWatch->split()); + } else { + // load by rfid or card number + $card = Card::readCard(Helper::fixAsciiChars($identifier)); + \Yii::info("Card loaded in sec " . $stopWatch->split()); + if (!isset($card)) { + throw new BadRequestHttpException('Card not found with number: ' . $identifier); + } + \Yii::info("card loaded in sec " . $stopWatch->split()); + $virtualKey = VirtualKey::findOne(['id_card' => $card->id_card]); + \Yii::info("virtual key for card loaded in sec " . $stopWatch->split()); + + } + + if ($card->type == Card::TYPE_EMPLOYEE) { + $this->moveEmployee($identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey); + return; + } + + $this->moveCustomer($identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey); + + } + + function moveEmergency($identifier, $device, $direction, $verifyOnly, $createdAt, $date) + { + \Yii::info("emergency move"); try { - \Yii::$app->db->beginTransaction(); - - $stopWatch = new StopWatch(); - \Yii::error("Started"); - 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); + \Yii::$app->db->beginTransaction(); $doorLog = new DoorLog(); $doorLog->version = 2; - if ( $device == 'E'){ - $direction = DoorLog::$DIRECTION_ALL_EMERGENCY; - }else{ - switch ($direction) { - case 'IN': - $direction = DoorLog::$DIRECTION_IN ; - break; - case 'OUT': - $direction = DoorLog::$DIRECTION_OUT; - break; - default: - throw new BadRequestHttpException("Direction not supported: ".$direction); - } - - } - $doorLog->direction = $direction; + $doorLog->direction = DoorLog::$DIRECTION_ALL_EMERGENCY; $doorLog->source_app = $device; $doorLog->created_at = $createdAtStr; - /** - * emergency- no card needed - */ - if ($device == 'E' ) { - if (!$verifyOnly) { - $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; - \Yii::error("emergency event in sec " . $stopWatch->split()); - } - \Yii::$app->db->transaction->commit(); - return; - } + $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; - /* - * in any other cases, the door needs a card - */ - - - // if device is qr code - if ( $device == 'Q'){ - - // allow only virtual key - $keyAssignment = CardKeyAssignment::findOne(['virtual_key' => $cardNumber]); - if (!isset($keyAssignment)){ - throw new BadRequestHttpException("Virtual key not found: ". $cardNumber); - } - $card = Card::findOne($keyAssignment->id_card); - if ( $card != null ){ - $card = Card::readCard($card->number); - } - if ( $card == null ){ - throw new BadRequestHttpException("Card not found by virtual key: ". $cardNumber.'/'.$keyAssignment->id_card); - } - \Yii::error("virtual key loaded in sec " . $stopWatch->split()); - } else{ - $card = Card::readCard(Helper::fixAsciiChars($cardNumber)); - \Yii::error("Card loaded in sec " . $stopWatch->split()); - if (!isset($card)) { - throw new BadRequestHttpException('Card not found with number: ' . $cardNumber); - } - } + \Yii::$app->db->transaction->commit(); + } catch (\Exception $e) { + \Yii::$app->db->transaction->rollBack(); + throw $e; + } + } + function moveEmployee($identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey) + { + /** + * if the card type is employee, neither customer nor ticket is needed. + * Free to enter/leave + */ + \Yii::info("employee move"); + try { + $createdAtStr = DateUtil::formatDateTimeUtc($createdAt); + \Yii::$app->db->beginTransaction(); + $doorLog = new DoorLog(); + $doorLog->version = 2; + $doorLog->direction = $direction; + $doorLog->source_app = $device; + $doorLog->created_at = $createdAtStr; $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) { - if (!$verifyOnly) { - $doorLog->save(false); - \Yii::$app->response->statusCode = 204; - \Yii::error("employee card {$card->id_card} event finished in sec " . $stopWatch->split()); - } - \Yii::$app->db->transaction->commit(); - return; - } - //otherwise ticket is required + if (!$verifyOnly) { + + $doorLog->save(false); + Log::log( + [ + 'type' => Log::$TYPE_INFO, + 'message' => 'Ajtó nyitás: munkatárs', + 'id_door_log' => $doorLog->id_door_log + ] + ); + } + \Yii::$app->response->statusCode = 204; + + \Yii::$app->db->transaction->commit(); + } catch (\Exception $e) { + \Yii::$app->db->transaction->rollBack(); + throw $e; + } + + } + + /** + * @param $identifier string virtual key id, card rfid or card number + * @param $device string device + * @param $direction number direction + * @param $verifyOnly boolean only check or real move + * @param $createdAt + * @param $date + * @param $card + * @param $cardNumber + * @param $virtualKey + * @return void + * @throws BadRequestHttpException + * @throws ServerErrorHttpException + * @throws \Throwable + * @throws \yii\base\InvalidConfigException + * @throws \yii\db\Exception + * @throws \yii\db\StaleObjectException + */ + function moveCustomer($identifier, $device, $direction, $verifyOnly, $createdAt, $date, $card, $cardNumber, $virtualKey) + { + \Yii::info("move customer"); + $stopWatch = new StopWatch(); + + try { + $createdAtStr = DateUtil::formatDateTimeUtc($createdAt); + \Yii::info("crated at str: ". $createdAtStr); + \Yii::$app->db->beginTransaction(); + + $doorLog = new DoorLog(); + $doorLog->version = 2; + $doorLog->direction = $direction; + $doorLog->source_app = $device; + $doorLog->created_at = $createdAtStr; + $doorLog->id_card = $card->id_card; + $doorLog->card_flag = $card->flag; + + $activeTickets = Ticket::readActive($card, clone $date); - \Yii::error('active ticket count:' . count($activeTickets)); + \Yii::info('active ticket count:' . count($activeTickets)); /** @var Ticket $ticket */ $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("ticket {$ticket->id_ticket} loaded in sec " . $stopWatch->split()); + + \Yii::info("ticket {$ticket->id_ticket} loaded in sec " . $stopWatch->split()); + + $doorLog->id_ticket_current = $ticket->id_ticket; // customer is also required $customer = $card->customer; @@ -173,16 +247,16 @@ class DoorManager extends BaseObject } $doorLog->id_customer = $customer->id_customer; - \Yii::error("customer {$customer->id_customer} loaded in sec " . $stopWatch->split()); + \Yii::info("customer {$customer->id_customer} loaded in sec " . $stopWatch->split()); if (!$verifyOnly) { // save the door log $doorLog->save(false); } - \Yii::error("door log {$doorLog->id_door_log} saved in sec " . $stopWatch->split()); + \Yii::info("door log {$doorLog->id_door_log} saved in sec " . $stopWatch->split()); // if direction is in - if ($direction == DoorLog::$DIRECTION_IN || $direction == DoorLog::$DIRECTION_IN_WITHOUT_MOVE) { + if ($direction == DoorLog::$DIRECTION_IN) { if ($card->isFlagDoor()) { throw new BadRequestHttpException("Card already 'IN': " . $card->id_card); @@ -196,20 +270,40 @@ class DoorManager extends BaseObject throw new BadRequestHttpException("Card has no active status: " . $card->id_card); } - $countDoorLogsForTicketSince = $this->getCountDoorLogsForTicketSince($ticket->id_ticket, DateUtil::utcDate(clone $date)); - if (!$verifyOnly) { - // if verifyOnly, the actual doorLog is not saved, so we hate to increase the count artificially - $countDoorLogsForTicketSince = $countDoorLogsForTicketSince + 1; - } - \Yii::error("count of door logs '{$countDoorLogsForTicketSince}' loaded in sec " . $stopWatch->split()); + if (isset($virtualKey)) { + + if (isset($virtualKey->direction_in_at)) { + throw new BadRequestHttpException("Virtual key - already moved in: " . $identifier . '/' . $virtualKey->id_card); + } + + $virtualKey->direction_in_at = Helper::getDateTimeString(); + \Yii::info("Setting virtual key direction_in_at"); - // 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; if (!$verifyOnly) { + \Yii::info("Updating virtual key"); + $virtualKey->save(false); + } + } + + // detect if need to increase usage count for ticket + if (!$verifyOnly) { + // if not verifyonly, check, if ticket usage count must be increased + $countDoorLogsForTicketSince = $this->getCountDoorLogsForTicketSince($ticket->id_ticket, DateUtil::utcDate(clone $date)); + \Yii::info("getCountDoorLogsForTicketSince: " . $countDoorLogsForTicketSince); + + if (!isset($countDoorLogsForTicketSince)) { + $countDoorLogsForTicketSince = 0; + } + + \Yii::info("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("First ticket usage today, increasing usage count for card: " . $card->id_card); Log::log( [ 'type' => Log::$TYPE_TICKET_USAGE_FIRST, @@ -218,68 +312,73 @@ class DoorManager extends BaseObject 'id_door_log' => $doorLog->id_door_log ] ); - } - \Yii::error("Ticket usage count increased after first doorlog of day in sec " . $stopWatch->split()); + \Yii::info("Ticket usage count increased after first doorlog of day in sec " . $stopWatch->split()); - } else { + } else { + \Yii::info("more then one door log today for card: " . $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 - // 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); - $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::info("All door logs for today loaded in sec " . $stopWatch->split()); - $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("All door logs for today loaded in sec " . $stopWatch->split()); + \Yii::info("allDoorLogToday", print_r($allDoorLogToday, true)); - $firstInToday = $allDoorLogToday[0]; - if (isset($firstInToday)) { + if (isset($allDoorLogToday) && count($allDoorLogToday) > 0) { + $firstInToday = $allDoorLogToday[0]; + } - $firstEntryDateTimeToday = DateUtil::parseDateTime($firstInToday->created_at); + if (isset($firstInToday)) { - $interval = \DateInterval::createFromDateString('3 hours'); - $daterange = new \DatePeriod($firstEntryDateTimeToday, $interval, $startOfTomorrow); + \Yii::info("first in today for card: " . $card->id_card . " was at " . $firstInToday->created_at); - $intervals = []; - $intervalStart = null; - foreach ($daterange as $intervalEnd) { - if (isset($intervalStart)) { - $intervals[] = $this->createTicketUsageInterval($intervalStart, $intervalEnd, $allDoorLogToday, $doorLog); + $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; } - $intervalStart = clone $intervalEnd; - } - if ($intervalStart < $startOfTomorrow) { - $intervals[] = $this->createTicketUsageInterval($intervalStart, $startOfTomorrow, $allDoorLogToday, $doorLog); - } + 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"); - } + $activeInterval = $this->getActiveInterval($intervals, $createdAt); + if (!isset($activeInterval)) { + throw new ServerErrorHttpException("Active Interval not found"); + } - $logCountInActiveInterval = count($activeInterval['logs']); + $logCountInActiveInterval = count($activeInterval['logs']); - if ($logCountInActiveInterval == 1) { - $ticket->usage_count = $ticket->usage_count + 1; - if (!$verifyOnly) { + if ($logCountInActiveInterval == 1) { + $ticket->usage_count = $ticket->usage_count + 1; $ticket->save(false); + \Yii::info("Ticket usage count increased after first IN after first door_log in interval in sec " . $stopWatch->split()); + } - \Yii::error("Ticket usage count increased after first IN after first door_log in interval in sec " . $stopWatch->split()); - } - } + } } } @@ -293,41 +392,62 @@ class DoorManager extends BaseObject throw new BadRequestHttpException("Can't exit with card has inactive status"); } + $keyAssigned = CardKeyAssignment::findOne(['id_card' => $card->id_card]); + + if (isset($keyAssigned)) { + throw new BadRequestHttpException("Can't exit with card has a key assigned"); + } + + if (isset($virtualKey)) { + + if (!isset($virtualKey->direction_in_at)) { + throw new BadRequestHttpException("Virtual key: move out without move in"); + } + + if (isset($virtualKey->direction_out_at)) { + throw new BadRequestHttpException("Virtual key: already move out"); + } + + $virtualKey->direction_out_at = Helper::getDateTimeString(); + + if (!$verifyOnly) { + $virtualKey->save(false); + } + } + $ticket->count_move_out = $ticket->usage_count; if (!$verifyOnly) { $ticket->save(false); } - \Yii::error("direction_out: ticket count_move_out set after direction_out in sec " . $stopWatch->split()); + \Yii::info("direction_out: ticket count_move_out set after direction_out in sec " . $stopWatch->split()); } if (!$verifyOnly) { Card::updateCardFlagTicket($ticket->id_ticket); - \Yii::error("updateCardFlagTicket: card flag updated in sec " . $stopWatch->split()); + \Yii::info("updateCardFlagTicket: card flag updated in sec " . $stopWatch->split()); // reload card after flag is set $card = Card::readCard($cardNumber); - if ($card->type != Card::TYPE_EMPLOYEE) { - if ($direction == DoorLog::$DIRECTION_OUT_WITHOUT_MOVE || $direction == DoorLog::$DIRECTION_OUT) { - $card->flag_out = Helper::setBit($card->flag_out, Card::$FLAG_DOOR, true); - $card->flag = Helper::setBit($card->flag, Card::$FLAG_DOOR, false); - $card->save(false); - \Yii::error("direction_out: Door flag updated in sec " . $stopWatch->split()); + if ($direction == DoorLog::$DIRECTION_OUT_WITHOUT_MOVE || $direction == DoorLog::$DIRECTION_OUT) { + $card->flag_out = Helper::setBit($card->flag_out, Card::$FLAG_DOOR, true); + $card->flag = Helper::setBit($card->flag, Card::$FLAG_DOOR, false); + $card->save(false); + \Yii::info("direction_out: Door flag updated in sec " . $stopWatch->split()); - } else if ($direction == DoorLog::$DIRECTION_IN || $direction == DoorLog::$DIRECTION_IN_WITHOUT_MOVE) { - $card->flag_out = Helper::setBit($card->flag_out, Card::$FLAG_DOOR, false); - $card->flag = Helper::setBit($card->flag, Card::$FLAG_DOOR, true); - $card->save(false); - \Yii::error("direction_in: Card flag updated in sec " . $stopWatch->split()); - } + } else if ($direction == DoorLog::$DIRECTION_IN || $direction == DoorLog::$DIRECTION_IN_WITHOUT_MOVE) { + $card->flag_out = Helper::setBit($card->flag_out, Card::$FLAG_DOOR, false); + $card->flag = Helper::setBit($card->flag, Card::$FLAG_DOOR, true); + $card->save(false); + \Yii::info("direction_in: Card flag updated in sec " . $stopWatch->split()); } } - - $stopWatch->stop(); - \Yii::error("finished in sec " . $stopWatch->getTotal()); + \Yii::info("finished in sec " . $stopWatch->getTotal()); \Yii::$app->db->transaction->commit(); - } catch (Exception $e) { + \Yii::info("Commited"); + } catch (\Exception $e) { \Yii::$app->db->transaction->rollBack(); + \Yii::info("rollbacked"); throw $e; } } @@ -358,7 +478,7 @@ class DoorManager extends BaseObject function getCountDoorLogsForTicketSince($idTicket, $since) { - \Yii::error("getting door log count for today"); + \Yii::info("getting door log count for today"); return DoorLog::find() ->innerJoinWith('card') ->andWhere(['card.id_ticket_current' => $idTicket]) @@ -409,37 +529,22 @@ class DoorManager extends BaseObject ]; } -// -// 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); + \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::error("Door log saving:" . $log->created_at); + \Yii::info("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)); + \Yii::info("validated" . print_r($log->errors, true)); throw new BadRequestHttpException(); } } diff --git a/common/models/HuBankAccountValidator.php b/common/models/HuBankAccountValidator.php new file mode 100644 index 0000000..e93cf4c --- /dev/null +++ b/common/models/HuBankAccountValidator.php @@ -0,0 +1,36 @@ + 0 ){ + return false; + } + } + + return true; + } + +} \ No newline at end of file diff --git a/common/models/VirtualKey.php b/common/models/VirtualKey.php index 60ae769..46dcc7e 100644 --- a/common/models/VirtualKey.php +++ b/common/models/VirtualKey.php @@ -12,7 +12,7 @@ use yii\helpers\ArrayHelper; * @property integer $id * @property integer $id_card * @property integer $id_key - * @property string $valid_until + * @property integer $number * @property string $direction_in_at * @property string $direction_out_at * @property string $created_at @@ -35,8 +35,8 @@ class VirtualKey extends \yii\db\ActiveRecord { return [ [['id_card', 'id_key'], 'integer'], - [['valid_until', 'created_at', 'updated_at'], 'required'], - [['valid_until', 'direction_in_at', 'direction_out_at', 'created_at', 'updated_at'], 'safe'] + [[ 'created_at', 'updated_at'], 'required'], + [[ 'direction_in_at', 'created_at', 'updated_at'], 'safe'] ]; } @@ -49,7 +49,6 @@ class VirtualKey extends \yii\db\ActiveRecord 'id' => Yii::t('common/virtualkey', 'ID'), 'id_card' => Yii::t('common/virtualkey', 'Id Card'), 'id_key' => Yii::t('common/virtualkey', 'Id Key'), - 'valid_until' => Yii::t('common/virtualkey', 'Valid Until'), 'direction_in_at' => Yii::t('common/virtualkey', 'Direction In At'), 'direction_out_at' => Yii::t('common/virtualkey', 'Direction Out At'), 'created_at' => Yii::t('common/virtualkey', 'Created At'), @@ -59,10 +58,12 @@ class VirtualKey extends \yii\db\ActiveRecord public function behaviors() { - return ArrayHelper::merge( [ + return ArrayHelper::merge([ [ '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()); diff --git a/console/migrations/m221024_203742_alter_table_virtual_key_add_column_number.php b/console/migrations/m221024_203742_alter_table_virtual_key_add_column_number.php new file mode 100644 index 0000000..5666be9 --- /dev/null +++ b/console/migrations/m221024_203742_alter_table_virtual_key_add_column_number.php @@ -0,0 +1,42 @@ +addColumn("virtual_key","number", $this->string(23)); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + echo "m221024_203742_alter_table_virtual_key_add_column_number cannot be reverted.\n"; + + return false; + } + + /* + // Use up()/down() to run migration code without a transaction. + public function up() + { + + } + + public function down() + { + echo "m221024_203742_alter_table_virtual_key_add_column_number cannot be reverted.\n"; + + return false; + } + */ +} diff --git a/console/migrations/m221026_111439_alter_table_virtual_key_add_column_direction_out_at.php b/console/migrations/m221026_111439_alter_table_virtual_key_add_column_direction_out_at.php new file mode 100644 index 0000000..b2f9011 --- /dev/null +++ b/console/migrations/m221026_111439_alter_table_virtual_key_add_column_direction_out_at.php @@ -0,0 +1,27 @@ +addColumn("virtual_key", "direction_out_at", $this->dateTime() ); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + echo "m221026_111439_alter_table_virtual_key_add_column_direction_out_at cannot be reverted.\n"; + return false; + } + +} diff --git a/frontend/models/KeyToggleForm.php b/frontend/models/KeyToggleForm.php index 7255376..fda830c 100644 --- a/frontend/models/KeyToggleForm.php +++ b/frontend/models/KeyToggleForm.php @@ -4,6 +4,7 @@ namespace frontend\models; use common\models\DoorLog; use common\models\Log; +use common\models\VirtualKey; use /** @noinspection PhpUndefinedClassInspection */ yii\base\Model; use common\models\CardKeyAssignment; @@ -138,6 +139,17 @@ class KeyToggleForm extends Model ]); DoorLog::mkDoorLog(-2,$this->card,$this->customer,$this->keyModel ); + + // delete all virtual key for this card + VirtualKey::deleteAll(['id_card' => $this->card->id_card]); + + // create a new virtual key + $virtualKey = new VirtualKey(); + $virtualKey->id_card = $this->card->id_card; + $virtualKey->id_key = $this->keyModel->id_key; + $virtualKey->number = uniqid(null,true); + + $virtualKey->save(false); } }else{ /** @noinspection PhpUndefinedClassInspection */ diff --git a/mobileapi/manager/ApiManager.php b/mobileapi/manager/ApiManager.php index acfd18e..05f5de3 100644 --- a/mobileapi/manager/ApiManager.php +++ b/mobileapi/manager/ApiManager.php @@ -4,6 +4,7 @@ namespace mobileapi\manager; use common\components\DateUtil; use common\components\Helper; +use common\models\VirtualKey; use Exception; use Yii; use common\models\Card; @@ -72,8 +73,8 @@ class ApiManager 'name' => $ticket->ticketType->name, ], 'usageCount' => $ticket->usage_count, - 'start' => DateUtil::parseDateTime( $ticket->start)->getTimestamp(), - 'end' => DateUtil::parseDateTime( $ticket->end)->getTimestamp() + 'start' => DateUtil::parseDateTime($ticket->start)->getTimestamp(), + 'end' => DateUtil::parseDateTime($ticket->end)->getTimestamp() ]; } return [ @@ -96,19 +97,19 @@ class ApiManager $keyObject = null; try { - $keyAssignment = CardKeyAssignment::findOne(['id_card' => $card->id_card]); - if (!isset($keyAssignment)) { + $virtualKey = VirtualKey::findOne(['id_card' => $card->id_card]); + + if (!isset($virtualKey)) { throw new NotFoundHttpException(); } - $key = Key::findOne(['id_key' => $keyAssignment->id_key]); - + $key = Key::findOne(['id_key' => $virtualKey->id_key]); if (!isset($key)) { throw new NotFoundHttpException(); } - $qrCode = new QrCode($keyAssignment->virtual_key); + $qrCode = new QrCode($virtualKey->number); $keyObject = [ 'qrcode' => $qrCode->writeDataUri(), @@ -127,7 +128,8 @@ class ApiManager } - public function getDashboardPage(){ + public function getDashboardPage() + { return [ 'virtual-key' => $this->getVirtualKeyPage(), 'card' => $this->getCardPage(), diff --git a/rest.http b/rest.http index a1dbf8f..2953ed3 100644 --- a/rest.http +++ b/rest.http @@ -15,22 +15,79 @@ Content-Type: application/json Authorization: Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE= { - "cardNumber": "10WMVXMZ", + "cardNumber": "63592ca5ee39a6.42682526", + "direction": "IN", + "device": "Q", + "validateOnly": false +} + +### + +## enter with qr code +POST {{restapi-url}}door/move +Accept: application/json +Content-Type: application/json +Authorization: Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE= + +{ + "cardNumber": "63595944529997.36018993", + "direction": "IN", + "device": "Q", + "validateOnly": false +} + +### + +POST {{restapi-url}}door/move +Accept: application/json +Content-Type: application/json +Authorization: Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE= + +{ + "cardNumber": "63595944529997.36018993", "direction": "OUT", + "device": "Q", + "validateOnly": false +} + +### + +POST {{restapi-url}}door/move +Accept: application/json +Content-Type: application/json +Authorization: Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE= + +{ + "cardNumber": "123456", + "direction": "IN", "device": "C", "validateOnly": false } ### -GET {{restapi-url}}door/info?cardNumber=10WMVXMZ +POST {{restapi-url}}door/move Accept: application/json Content-Type: application/json Authorization: Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE= { - "cardNumber": "10WMVXMZ", - "direction": "IN", + "cardNumber": "123456", + "direction": "OUT", "device": "C", "validateOnly": false } + +### +# +#GET {{restapi-url}}door/info?cardNumber=10WMVXMZ +#Accept: application/json +#Content-Type: application/json +#Authorization: Basic ZG9vcl9zeXN0ZW06ZG9vcnN5c3RlbTE= +# +#{ +# "cardNumber": "10WMVXMZ", +# "direction": "IN", +# "device": "C", +# "validateOnly": false +#} diff --git a/rest/config/main.php b/rest/config/main.php index 4b48aad..0cdfca7 100644 --- a/rest/config/main.php +++ b/rest/config/main.php @@ -31,8 +31,11 @@ return [ 'targets' => [ [ 'class' => 'yii\log\FileTarget', - 'levels' => ['error', 'warning'], - ] + 'levels' => ['info', 'error', 'warning'], + 'except' => [ + 'yii\db\Command*', + ], + ], ], ], 'errorHandler' => [