/// <summary>
        /// Method to determine wheater a student can change his/her current room
        /// </summary>
        /// <param name="bid">the BID of the student</param>
        /// <param name="error">out, an error message</param>
        /// <returns>true, if the student can change room, false, otherwise</returns>
        public bool CanChangeRoom(string bid, out string error)
        {
            error = "";
            TransactionHelper helper = new TransactionHelper();
            // get the student from the database
            Student student = GetStudent(bid);

            // if the student exists
            if (student != null)
            {
                // find the student his/her allotment and dues
                Allotment alllotment          = student.Allotments.Where(x => x.dateOfLeave == null).First();
                int       currentAcademicYear = helper.GetAcademicYear(DateTime.Now);

                if (currentAcademicYear == alllotment.year)
                {
                    error = "Can not update allotment more than once per academic year";
                    return(false);
                }

                return(true);
            }
            error = "Student not found!";
            return(false);
        }
        /// <summary>
        /// Method to get all the rooms that a student can stay in including his current room
        /// </summary>
        /// <param name="bid">the BID of the student</param>
        /// <returns>a list of rooms</returns>
        public List <Room> GetRoomsIncludingCurrent(string bid)
        {
            List <Room> roomList = new List <Room>();

            // get the student
            Student student = GetStudent(bid);

            // if the student exists
            if (student != null)
            {
                // get the student current room
                Allotment allotment = student.Allotments.OrderByDescending(x => x.year).First();

                // get all rooms in the current block where the student is staying
                var rooms = db.Rooms.Where(x => x.hostelBlockNumber == allotment.hostelBlock);

                // for each room in the current block, add it to the list if it is vacant
                foreach (Room room in rooms)
                {
                    if (room.roomNumber == allotment.roomNum || room.currentOccupancy < room.maxOccupancy)
                    {
                        roomList.Add(room);
                    }
                }

                return(roomList);
            }

            // if the student does not exsist
            return(null);
        }
        /// <summary>
        /// Method to remove a student from the hostel
        /// </summary>
        /// <param name="userInput">the form filled by the user</param>
        /// <returns>error message</returns>
        public string PerformRemoveStudent(RemoveStudentViewModel userInput)
        {
            TransactionHelper helper = new TransactionHelper();

            // get the student
            Student student = GetStudent(userInput.bid);

            // get the current room that the student is staying in
            Allotment allotment = student.Allotments.Where(x => x.dateOfLeave == null).First();

            // get all the transactions that were perfromed by the student
            List <TransactionsViewModel> transactions = helper.GetAllTransactionsForStudent(userInput.bid);

            // get the amount of rent and fixed deposit that were payed
            decimal rentPaid = transactions.Where(x => x.accountHead == "Rent" && x.transaction == "Debit").Sum(x => x.amount);
            decimal fixPaid  = transactions.Where(x => x.accountHead == "Fixed Charges" && x.transaction == "Debit").Sum(x => x.amount);

            // get the amount refund requested by the user
            userInput.depRefund = GetDepositRefund(userInput.bid);

            // if user wants to refund more rent than the student has payed
            if (userInput.rentRefund > rentPaid)
            {
                return("Can not refund more rent than paid");
            }

            // if user wants to refund more fixed deposit than the student has payed
            if (userInput.fixRefund > fixPaid)
            {
                return("Can not refund more fixed changes than paid");
            }

            // if the user has not entered the a reference number for the rent refund
            if (userInput.rentRefund > 0 && string.IsNullOrWhiteSpace(userInput.rentRefundRef))
            {
                return("Reference number needed to refund rent");
            }

            // if the user has not entered the a reference number for the fixed deposit refund
            if (userInput.fixRefund > 0 && string.IsNullOrWhiteSpace(userInput.fixRefundRef))
            {
                return("Reference number needed to refund fixed charges");
            }

            // if the user has not entered the a reference number for the deposit refund
            if (userInput.depRefund > 0 && string.IsNullOrWhiteSpace(userInput.depRefundRef))
            {
                return("Reference number needed to refund deposit");
            }

            // begin a transaction
            using (var tran = db.Database.BeginTransaction())
            {
                try
                {
                    // if the user would like to refund rent add the appropriate transaction
                    if (userInput.rentRefund > 0)
                    {
                        db.HostelTransactions.Add(new HostelTransaction
                        {
                            receipt       = userInput.rentRefundRef,
                            bankName      = "Canara Bank",
                            bid           = userInput.bid,
                            amount        = -userInput.rentRefund,
                            dateOfPay     = DateTime.Now,
                            head          = 5,
                            year          = helper.GetAcademicYear(DateTime.Now),
                            paymentTypeId = 5
                        });
                        db.SaveChanges();
                    }

                    // if the user would like to refund fixed deposit add the appropriate transaction
                    if (userInput.fixRefund > 0)
                    {
                        db.HostelTransactions.Add(new HostelTransaction
                        {
                            receipt       = userInput.fixRefundRef,
                            bankName      = "Canara Bank",
                            bid           = userInput.bid,
                            amount        = -userInput.fixRefund,
                            dateOfPay     = DateTime.Now,
                            head          = 5,
                            year          = helper.GetAcademicYear(DateTime.Now),
                            paymentTypeId = 5
                        });
                        db.SaveChanges();
                    }

                    // if the user would like to refund deposit add the appropriate transaction
                    if (userInput.depRefund > 0)
                    {
                        db.HostelTransactions.Add(new HostelTransaction
                        {
                            receipt       = userInput.depRefundRef,
                            bankName      = "Canara Bank",
                            bid           = userInput.bid,
                            amount        = -userInput.depRefund,
                            dateOfPay     = DateTime.Now,
                            head          = 5,
                            year          = helper.GetAcademicYear(DateTime.Now),
                            paymentTypeId = 5
                        });
                        db.SaveChanges();
                    }

                    // update the allotment of the student
                    allotment.dateOfLeave            = DateTime.Now;
                    allotment.Room.currentOccupancy -= 1;
                    db.Allotments.Attach(allotment);
                    db.Entry(allotment).State = EntityState.Modified;
                    db.SaveChanges();

                    // commit the transaction
                    tran.Commit();
                }
                catch (Exception e)
                {
                    // if an error has occured rollback all changes
                    tran.Rollback();
                    return("An error occurred: " + e.Message + "(" + e.InnerException.Message + ")");
                }
            }

            return("Success!");
        }
        /// <summary>
        /// Method to change the allotment for a student
        /// </summary>
        /// <param name="userInput">the form that the user has filled</param>
        /// <param name="bid">the bid of the student</param>
        /// <returns>the result to be displayed to the user</returns>
        public string PerformRoomChange(ChangeRoomViewModel userInput, string bid)
        {
            TransactionHelper helper    = new TransactionHelper();
            Student           student   = GetStudent(bid);
            Allotment         allotment = student.Allotments.OrderByDescending(x => x.year).First();
            Room currentRoom            = db.Rooms.Where(x => x.hostelBlockNumber == allotment.hostelBlock && x.roomNumber == allotment.roomNum).First();

            userInput.year = helper.GetAcademicYear(DateTime.Now);

            // if the user did not make any changes
            if (allotment.hostelBlock == userInput.hostelBlock && allotment.roomNum == userInput.roomNumber)
            {
                return("No change detected!");
            }

            if (student.HostelTransactions.Where(x => x.year == userInput.year).ToList().Count > 0)
            {
                return("Hostel Transactions for the year have been performed, can not change room");
            }

            // initiate a transaction
            using (var transaction = db.Database.BeginTransaction())
            {
                try
                {
                    // reduce the occupancy in the current room
                    currentRoom.currentOccupancy = currentRoom.currentOccupancy - 1;
                    db.Rooms.Attach(currentRoom);
                    db.Entry(currentRoom).State = EntityState.Modified;
                    db.SaveChanges();

                    // add the date of leave
                    allotment.dateOfLeave = DateTime.Now;
                    db.Allotments.Attach(allotment);
                    db.Entry(allotment).State = EntityState.Modified;
                    db.SaveChanges();

                    // add the new allotment
                    db.Allotments.Add(new Allotment()
                    {
                        bid         = student.bid,
                        dateOfJoin  = DateTime.Now,
                        year        = userInput.year,
                        hostelBlock = userInput.hostelBlock,
                        roomNum     = userInput.roomNumber,
                    });
                    db.SaveChanges();

                    // change the current occupancy in the new room
                    Room newRoom = db.Rooms.Where(x => x.hostelBlockNumber == userInput.hostelBlock && x.roomNumber == userInput.roomNumber).First();
                    newRoom.currentOccupancy = newRoom.currentOccupancy + 1;
                    db.Rooms.Attach(newRoom);
                    db.Entry(newRoom).State = EntityState.Modified;
                    db.SaveChanges();

                    // commit the transaction
                    transaction.Commit();
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    return("An error occured! Please try again later!");
                }
            }
            return("Success!");
        }