Files
ophelias-oasis/OpheliasOasis/Models/Reservation.cs

304 lines
14 KiB
C#

using Ophelias.Managers;
using System.Data.SQLite;
namespace Ophelias.Models
{
internal class Reservation
{
/*
* The reservation class is comprised of many pieces of information. For details on the
* Guest and Transaction components, see Guest and Transaction classes.
*
* Reservations are comprised of the following:
*
* ID
* Identifies the reservation
*
* RoomNum
* Indicates what room the guest is staying/ stayed in
*
* Guest
* See Guest.cs model class
*
* Transaction
* See Transaction.cs model class
*
* IsNoShow
* Boolean to indicate if someone is a no-show/ does not show up to their
* scheduled reservation
*
* Type
* The type of reservation made (Conventional, Prepaid, Incentive, 60-day/ Advance)
*
* Status
* Indicates if the reservation is active, changed, cancelled, or ended
*
* CreationDate
* The date the reservation was created
*
* StartDate
* The date the reservation is scheduled to being
*
* EndDate
* The date the reservation is scheduled to end
*
* CheckIn
* Reflects when the guest checked in, currently mirrors StartDate when set
*
* CheckOut
* Reflects when the guest checked out, currently mirrors EndDate when set
*
* DateChanged
* The date the reservation was updated/ changed
*/
internal int Id;
internal int? RoomNum;
internal Guest Guest;
internal Transaction Transaction;
internal bool IsNoShow;
internal ReservationType Type;
internal ReservationStatus Status;
internal DateTime CreationDate;
internal DateTime StartDate;
internal DateTime EndDate;
internal DateTime? CheckIn;
internal DateTime? CheckOut;
internal DateTime? DateChanged;
internal Reservation(Guest Guest, ReservationType Type,
DateTime CreationDate, DateTime StartDate, DateTime EndDate, ReservationStatus Status = ReservationStatus.Active,
bool IsNoShow = false, DateTime? CheckIn = null, DateTime? CheckOut = null, DateTime? DateChanged = null, int? RoomNum = null)
{
/*
* Creates a new reservation assuming it never existed in the first place.
*
* Upon creating a reservation, this function will set the appropriate fees
* based on the type of reservation. See TxFunctions in the transaction class
* for the specific fee multiplier values. The base rate is then retrieved for
* the current date if a new one was set for that date, otherwise the base rate
* used is whatever the default last was. We do not tether the rate to an ID
* since the rate only changes when the reservation is tweaked. This information
* is then passed off to create a new Transaction. See the Transaction class for
* more information.
*
* Once a new transaction has been created, a database connection is opened to create
* a new reservation and the ID generated is returned back. This value is then set
* to the reservation and a new instance is returned.
*/
int Id; double Multiplier;
switch (Type) // Determines the appropriate fee multiplier to set
{
case ReservationType.Conventional: Multiplier = TxFunctions.ConventionalFee; break;
case ReservationType.Prepaid: Multiplier = TxFunctions.PrepaidFee; break;
case ReservationType.Incentive: Multiplier = TxFunctions.IncentiveFee(StartDate, EndDate); break;
case ReservationType.SixtyDayAdvance: Multiplier = TxFunctions.SixtyDayFee; break;
default: throw new NotImplementedException();
}
double? BaseRate = Hotel.GetBaseRate(); // Checks to see if there is a new base rate and uses the rate returned, old default or new default
if (BaseRate == null) // Exists for the unlikely situation a reservation is made on a null rate
{
throw new NotImplementedException();
}
Transaction Transaction = new( // Creates a new transaction, see the Transaction class for more details on TxFunctions or trnsaction itself
Rate: (double)BaseRate,
Owed: TxFunctions.CalculateOwed((double)BaseRate, (int)(EndDate.Date - StartDate.Date).TotalDays, Multiplier),
Multiplier: Multiplier,
PayBy: TxFunctions.GetPayByDate(Type, StartDate, EndDate)
);
using (Database Manager = new()) // Creates a new database connection
{
using (SQLiteCommand cmd = Manager.con.CreateCommand()) // Creates a new command that will be executed in the database
{
if (RoomNum != null)
{
this.RoomNum = RoomNum;
}
/*
* The folowing is a query with parameters that are set based off certain conditions,
* such as if the value exists.
*/
cmd.CommandText =
"INSERT INTO reservations (RoomNum, GuestID, TransactionID, IsNoShow, Type, Status, CreationDate, StartDate, EndDate, CheckIn, CheckOut, DateChanged) " +
"VALUES (@RoomNum, @GuestID, @TransactionID, @IsNoShow, @Type, @Status, @CreationDate, @StartDate, @EndDate, @CheckIn, @CheckOut, @DateChanged);";
cmd.Parameters.AddWithValue("@RoomNum", RoomNum);
cmd.Parameters.AddWithValue("@GuestID", Guest.Id);
cmd.Parameters.AddWithValue("@TransactionID", Transaction.Id);
cmd.Parameters.AddWithValue("@IsNoShow", Convert.ToInt32(IsNoShow));
cmd.Parameters.AddWithValue("@Type", (int)Type);
cmd.Parameters.AddWithValue("@Status", (int)Status);
cmd.Parameters.AddWithValue("@CreationDate", CreationDate.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@StartDate", StartDate.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@EndDate", EndDate.ToString("yyyy-MM-dd"));
if (CheckIn.HasValue)
{
cmd.Parameters.AddWithValue("@CheckIn", CheckIn.Value.ToString("yyyy-MM-dd"));
}
else
{
cmd.Parameters.AddWithValue("@CheckIn", CheckIn);
}
if (CheckOut.HasValue)
{
cmd.Parameters.AddWithValue("@CheckOut", CheckOut.Value.ToString("yyyy-MM-dd"));
}
else
{
cmd.Parameters.AddWithValue("@CheckOut", CheckOut);
}
if (DateChanged.HasValue)
{
cmd.Parameters.AddWithValue("@DateChanged", DateChanged.Value.ToString("yyyy-MM-dd"));
}
else
{
cmd.Parameters.AddWithValue("@DateChanged", DateChanged);
}
cmd.ExecuteNonQuery();
}
Id = (int)Manager.con.LastInsertRowId; // Sets the ID returned by the query
}
this.Id = Id;
this.RoomNum = RoomNum;
this.Guest = Guest;
this.Transaction = Transaction;
this.IsNoShow = IsNoShow;
this.Type = Type;
this.Status = Status;
this.CreationDate = CreationDate;
this.StartDate = StartDate;
this.EndDate = EndDate;
this.CheckIn = CheckIn;
this.CheckOut = CheckOut;
this.DateChanged = DateChanged;
}
internal Reservation(int Id, Guest Guest, Transaction Transaction, ReservationType Type, ReservationStatus Status,
DateTime CreationDate, DateTime StartDate, DateTime EndDate, bool IsNoShow = false, DateTime? CheckIn = null, DateTime? CheckOut = null, DateTime? DateChanged = null, int? RoomNum = null)
{
/*
* This creates and returns a reservation assuming it already existed
* as an ID is required if the reservation exists in the system.
*/
this.Id = Id;
this.RoomNum = RoomNum;
this.Guest = Guest;
this.Transaction = Transaction;
this.IsNoShow = IsNoShow;
this.Type = Type;
this.Status = Status;
this.CreationDate = CreationDate;
this.StartDate = StartDate;
this.EndDate = EndDate;
this.CheckIn = CheckIn;
this.CheckOut = CheckOut;
this.DateChanged = DateChanged;
}
internal void ChangeReservationDates(DateTime StartDate, DateTime EndDate)
{
/*
* Change Reservation Dates allows for the manipulation of start and end dates.
* These changes saved to the reservation and reflected in the database.
* It also makes a call to update the transaction fees. See Transaction class for
* details on this. A new rate and multiplier are set also since reservation changes
* come at the cost of paying based on the most recent base rate and 110% multipler.
*/
this.StartDate = StartDate;
this.EndDate = EndDate;
DateChanged = DateTime.Now.Date;
using (Database Manager = new()) // Creates a new database connection
{
using (SQLiteCommand cmd = Manager.con.CreateCommand()) // Creates a new command that will be executed in the database
{
string? query = QueryBuilder.UpdateReservation(Id: Id, Status: ReservationStatus.Changed, StartDate: this.StartDate, EndDate: this.EndDate, DateChanged: DateChanged); // Builds a new query string with parameters
if (query == null)
{
throw new Exception();
}
cmd.CommandText = query;
cmd.Parameters.AddWithValue("@ID", Id);
cmd.Parameters.AddWithValue("@Status", Status);
cmd.Parameters.AddWithValue("@StartDate", StartDate.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@EndDate", EndDate.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@DateChanged", DateChanged.Value.ToString("yyyy-MM-dd"));
cmd.ExecuteNonQuery();
}
}
double? BaseRate = Hotel.GetBaseRate(); // Checks for the most recent rate to replace the old rate
if (BaseRate == null)
{
throw new ArgumentNullException(nameof(BaseRate));
}
Transaction.UpdateTransactionFees((double)BaseRate, TxFunctions.Changed, TxFunctions.GetPayByDate(Type, this.StartDate, this.EndDate)); // Creates a new transaction
}
internal void CancelReservation()
{
/*
* Cancel Reservation will cancel the existing reservation and issue penalties
* if they apply. Specifically if the reservation type is conventional, incentive,
* or the reservation is past due and the right criteria are met, the transaction
* class calls the pay function and the accounts are charged. See Transaction.Pay()
* for more details. The reservation is also set to cancelled in the database.
*/
DateTime _DateChanged = DateTime.Now.Date;
using (Database Manager = new()) // Creates a new database connection
{
using (SQLiteCommand cmd = Manager.con.CreateCommand()) // Creates a new command that will be executed in the database
{
string? query = QueryBuilder.UpdateReservation(Id: Id, Status: ReservationStatus.Cancelled, DateChanged: _DateChanged); // Builds a new query string with parameters
if (query == null)
{
throw new Exception();
}
Status = ReservationStatus.Cancelled;
DateChanged = _DateChanged;
cmd.CommandText = query;
cmd.Parameters.AddWithValue("@ID", Id);
cmd.Parameters.AddWithValue("@Status", Status);
cmd.Parameters.AddWithValue("@DateChanged", DateChanged.Value.ToString("yyyy-MM-dd"));
cmd.ExecuteNonQuery();
}
}
if (Type == ReservationType.Conventional && _DateChanged.Date >= StartDate.AddDays(-3).Date) // Charge conventional reservations cancelled three or less days of stay
{
Transaction.Pay(Transaction.Owed, Guest.CreditCard);
}
else if (Type == ReservationType.Incentive && _DateChanged.Date >= StartDate.AddDays(-3).Date) // Charge incentive based on the same policy as conventional
{
Transaction.Pay(Transaction.Owed, Guest.CreditCard);
}
else if (_DateChanged.Date > StartDate.Date) // Charge based on no-show
{
Transaction.Pay(Transaction.Owed, Guest.CreditCard);
}
}
}
internal enum ReservationStatus // Represets numerical values as words
{
Active,
Changed,
Cancelled,
Ended,
}
internal enum ReservationType // Represents numerical values as words
{
Conventional,
Prepaid,
SixtyDayAdvance,
Incentive,
}
}