AppStateESS/homestead

View on GitHub
class/Command/CheckoutFormSubmitCommand.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php

namespace Homestead\Command;

use \Homestead\StudentFactory;
use \Homestead\CheckinFactory;
use \Homestead\HMS_Activity_Log;
use \Homestead\Room;
use \Homestead\RoomDamage;
use \Homestead\RoomDamageFactory;
use \Homestead\RoomDamageResponsibility;
use \Homestead\RoomDamageResponsibilityFactory;
use \Homestead\BedFactory;
use \Homestead\Term;
use \Homestead\UserStatus;
use \Homestead\InfoCard;
use \Homestead\HMS_Email;
use \Homestead\RoomChangeRequestFactory;
use \Homestead\RoomChangeParticipantFactory;
use \Homestead\RoomChangeStateComplete;
use \Homestead\NotificationView;
use \Homestead\ParticipantStateCheckedOut;
//use \Homestead\InfoCardPdfView;
use \Homestead\Exception\PermissionException;


class CheckoutFormSubmitCommand extends Command {

    private $term;

    public function getRequestVars()
    {
        // Handeled by Angular, so we don't need anything here
        return array ();
    }

    public function execute(CommandContext $context)
    {
        // Check permissions
        if (!\Current_User::allow('hms', 'checkin')) {
            throw new PermissionException('You do not have permission to checkin students.');
        }

        // Grab data from JSON source
        $bannerId = filter_input(INPUT_POST, 'bannerId', FILTER_VALIDATE_INT);
        $checkinId = filter_input(INPUT_POST, 'checkinId', FILTER_VALIDATE_INT);

        if (empty($bannerId)) {
            throw new \InvalidArgumentException('Missing banner id.');
        }

        if (empty($checkinId)) {
            throw new \InvalidArgumentException('Missing checkin id.');
        }

        // Check for key code
        //$keyCode = filter_input(INPUT_POST, 'keyCode',FILTER_SANITIZE_SPECIAL_CHARS);
        $keyCode = filter_input(INPUT_POST, 'keyCode',FILTER_VALIDATE_REGEXP, array('options'=>array('regexp'=>'/[^\W]/')));
        $keyReturned = filter_input(INPUT_POST, 'keyReturned', FILTER_VALIDATE_BOOLEAN);

        if (!isset($keyReturned) || !isset($keyCode)) {
            throw new \InvalidArgumentException('Missing key return information.');
        }

        if ($keyReturned == "1" && empty($keyCode)) {
            throw new \InvalidArgumentException('Missing key code.');
        }

        $properCheckout = filter_input(INPUT_POST, 'properCheckout', FILTER_VALIDATE_BOOLEAN);

        $term = Term::getSelectedTerm();
        $this->term = $term;

        // Lookup the student
        $student = StudentFactory::getStudentByBannerId($bannerId, $term);

        // Get the existing check-in
        $checkin = CheckinFactory::getCheckinById($checkinId);

        // Make sure we found a check-in
        if (is_null($checkin)) {
            /*
            \NQ::simple('hms', NotificationView::ERROR, "Sorry, we couldn't find a corresponding check-in for this check-out.");
            $errorCmd = CommandFactory::getCommand('ShowCheckoutForm');
            $errorCmd->setBannerId($bannerId);
            $errorCmd->setHallId($hallId);
            $errorCmd->redirect();
            */

            throw new \Exception('Could not find a corresponding checkin.');
        }

        // Create the bed
        $bed = BedFactory::getBedByPersistentId($checkin->getBedPersistentId(), $term);

        // Get the room
        $room = $bed->get_parent();


        /*****
         * Add new damages
         */
        $newDamages = filter_input(INPUT_POST, 'newDamage', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY);

        if (!empty($newDamages)) {
            foreach ($newDamages as $dmg) {
                $this->addDamage($dmg, $room);
            }
        }

        /******
         * Complete the Checkout
         */

        // Set checkout date and user
        $checkin->setCheckoutDate(time());
        $checkin->setCheckoutBy(\Current_User::getUsername());

        // Set the checkout code code, if any
        $checkin->setCheckoutKeyCode($keyCode);

        // Improper checkout handling
        if ($properCheckout == "1") {
            $checkin->setImproperCheckout(false);
        } else {
            $checkin->setImproperCheckout(true);

            $improperNote = filter_input(INPUT_POST, 'improperNote', FILTER_SANITIZE_SPECIAL_CHARS);
            // Add damage for improper checkout
            // TODO: Find a better way to handle the magic number for dmg type
            $dmg = array('damage_type'=>105, 'side'=>'both', 'note'=>$improperNote, 'residents' => array(array('studentId'=> $student->getBannerId(), 'selected'=>true)));
            $this->addDamage($dmg, $room);

            // Add the improper checkout note
            $checkin->setImproperCheckoutNote($improperNote);
        }

        if ($keyReturned == "1") {
            $checkin->setKeyNotReturned(false);
        } else {
            $checkin->setKeyNotReturned(true);

            // Add a damage record for key not returned
            // TODO: Find a better way to handle the magic number for dmg type
            $dmg = array('damage_type'=>79, 'side'=>'both', 'note'=>'Key not returned.', 'residents' => array(array('studentId'=> $student->getBannerId(), 'selected'=>true)));
            $this->addDamage($dmg, $room);
        }

        // Save the check-in
        $checkin->save();

        // Add this to the activity log
        HMS_Activity_Log::log_activity($student->getUsername(), ACTIVITY_CHECK_OUT, UserStatus::getUsername(), $bed->where_am_i());

        // Generate the RIC
        $infoCard = new InfoCard($checkin);

        /*
         * Info card removed per #869
        $infoCardView = new InfoCardPdfView();
        $infoCardView->addInfoCard($infoCard);
        */

        // Send confirmation Email with the RIC form to the student
        HMS_Email::sendCheckoutConfirmation($student, $infoCard);

        /***** Room Change Request Handling *******/

        // Check if this checkout was part of a room change request
        $request = RoomChangeRequestFactory::getRequestPendingCheckout($student, $term);

        if (!is_null($request)) {
            $participant = RoomChangeParticipantFactory::getParticipantByRequestStudent($request, $student);

            // Transition to StudentApproved state
            $participant->transitionTo(new ParticipantStateCheckedOut($participant, time(), null, UserStatus::getUsername()));

            // If all the participants are in CheckedOut state, then this room change is complete, so transition it
            if($request->allParticipantsInState('CheckedOut')) {
                $request->transitionTo(new RoomChangeStateComplete($request, time(), null, UserStatus::getUsername()));
            }
        }

        // Cleanup and redirect
        \NQ::simple('hms', NotificationView::SUCCESS, 'Checkout successful.');
        \NQ::close();
        exit;
    }

    private function addDamage(Array $dmg, Room $room)
    {
        $damage = new RoomDamage($room, $this->term, $dmg['damage_type'], $dmg['side'], $dmg['note']);

        // Save the damage
        RoomDamageFactory::save($damage);

        // Determine the residents which were responsible
        // For each resident submitted
        foreach ($dmg['residents'] as $resident) {

            // If the resident was selected as being responsible for this damage
            if(isset($resident['selected']) && $resident['selected']){
                // Create the student
                $student = StudentFactory::getStudentByBannerId($resident['studentId'], $this->term);

                // Create the responsibility
                $resp = new RoomDamageResponsibility($student, $damage);
                RoomDamageResponsibilityFactory::save($resp);
            }
        }
    }
}