diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f36235 --- /dev/null +++ b/.gitignore @@ -0,0 +1,137 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.svclog +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Visual Studio cache files +*.vs + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.azurePubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +packages/ +## TODO: If the tool you use requires repositories.config, also uncomment the next line +!packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +![Ss]tyle[Cc]op.targets +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml + +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +_NCrunch* + diff --git a/OpheliasOasis.sln b/OpheliasOasis.sln new file mode 100644 index 0000000..e96a389 --- /dev/null +++ b/OpheliasOasis.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32328.378 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpheliasOasis", "OpheliasOasis\OpheliasOasis.csproj", "{69288F69-68F7-4A9E-A740-507AE1CBF6CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {69288F69-68F7-4A9E-A740-507AE1CBF6CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69288F69-68F7-4A9E-A740-507AE1CBF6CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69288F69-68F7-4A9E-A740-507AE1CBF6CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69288F69-68F7-4A9E-A740-507AE1CBF6CF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A72041BE-1FE9-4C15-AED6-91C0217466EA} + EndGlobalSection +EndGlobal diff --git a/OpheliasOasis/Managers/Database.cs b/OpheliasOasis/Managers/Database.cs new file mode 100644 index 0000000..e043114 --- /dev/null +++ b/OpheliasOasis/Managers/Database.cs @@ -0,0 +1,293 @@ +using Ophelias.Models; +using System.Data.SQLite; + +namespace Ophelias.Managers +{ + internal class Database : IDisposable + { + internal SQLiteConnection con = new("DataSource=database.sqlite3;Version=3;"); + + internal Database() + { + Connect(); + } + internal void Connect() + { + con.Open(); + } + internal void Close() + { + con.Close(); + con.Dispose(); + } + internal void InitializeTables() + { + string tableCommands = + @"CREATE TABLE IF NOT EXISTS [transactions] ( + [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + [Rate] INTEGER NOT NULL, + [Owed] INTEGER NOT NULL, + [Penalty] INTEGER NOT NULL, + [Multiplier] INTEGER NOT NULL, + [RefundAmount] INTEGER NOT NULL, + [AmountPaid] INTEGER NOT NULL, + [PayBy] TEXT NOT NULL, + [LastPaid] TEXT NULL, + [PaidOn] TEXT NULL); + + CREATE TABLE IF NOT EXISTS [reservations] ( + [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + [RoomNum] INTEGER NULL, + [GuestID] INTEGER NOT NULL, + [TransactionID] INTEGER NOT NULL UNIQUE, + [IsNoShow] BOOLEAN NOT NULL CHECK ([IsNoShow] IN (0,1)), + [Type] INTEGER NOT NULL CHECK ([Type] IN (0,1,2,3)), + [Status] INTEGER NOT NULL CHECK ([Status] IN (0,1,2,3)), + [CreationDate] TEXT NOT NULL, + [StartDate] TEXT NOT NULL, + [EndDate] TEXT NOT NULL, + [CheckIn] TEXT NULL, + [CheckOut] TEXT NULL, + [DateChanged] TEXT NULL, + FOREIGN KEY ([RoomNum]) REFERENCES rooms(ID), + FOREIGN KEY ([GuestID]) REFERENCES guests(ID), + FOREIGN KEY ([TransactionID]) REFERENCES transactions(ID)); + + CREATE TABLE IF NOT EXISTS [guests] ( + [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + [Fname] TEXT NOT NULL, + [Lname] TEXT NOT NULL, + [Email] TEXT NOT NULL UNIQUE, + [CreditCard] TEXT NULL UNIQUE, + [Expiration] TEXT NULL, + [CCV] TEXT NULL); + + CREATE TABLE IF NOT EXISTS [rooms] ( + [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + [Occupied] BOOLEAN NOT NULL CHECK ([Occupied] IN (0,1))); + + CREATE TABLE IF NOT EXISTS [rates] ( + [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + [Rate] INTEGER NOT NULL, + [DateSet] TEXT NOT NULL UNIQUE, + [DefaultRate] INTEGER NULL UNIQUE CHECK ([DefaultRate] IN (1)));"; + + using SQLiteCommand cmd = con.CreateCommand(); + cmd.CommandText = tableCommands; + cmd.ExecuteNonQuery(); + } + + internal void InitializeRoomsTable() + { + using SQLiteCommand cmd = con.CreateCommand(); + for (int i = 1; i < 46; i++) + { + cmd.CommandText = $"INSERT INTO ROOMS (Occupied) VALUES (0);"; + cmd.ExecuteNonQuery(); + } + + // Initialize Rooms + + } + public void Dispose() + { + Close(); + } + } + + internal static class QueryBuilder + { + + internal static string? UpdateTransaction(int Id, + double? Rate = null, double? Owed = null, double? Penalty = null, + double? Multiplier = null, double? Refund = null, + DateTime? PayBy = null, DateTime? LastPaid = null, DateTime? PaidOn = null, double? AmountPaid = null) + { + List queryComponents = new(); + string query = "UPDATE transactions SET"; + + if (Rate.HasValue) + { + queryComponents.Add($"Rate = @Rate"); + } + + if (Owed.HasValue) + { + queryComponents.Add($"Owed = @Owed"); + } + + if (Penalty.HasValue) + { + queryComponents.Add($"Penalty = @Penalty"); + } + + if (Multiplier.HasValue) + { + queryComponents.Add($"Multiplier = @Multiplier"); + } + + if (Refund.HasValue) + { + queryComponents.Add($"RefundAmount = @RefundAmount"); + } + + if (AmountPaid.HasValue) + { + queryComponents.Add($"AmountPaid = @AmountPaid"); + } + + if (PayBy.HasValue) + { + queryComponents.Add($"PayBy = @PayBy"); + } + + if (LastPaid.HasValue) + { + queryComponents.Add($"LastPaid = @LastPaid"); + } + + if (PaidOn.HasValue) + { + queryComponents.Add($"PaidOn = @PaidOn"); + } + + if (queryComponents.Count > 0) + { + query += " " + string.Join(", ", queryComponents) + " " + $"WHERE ID = @ID;"; + } + else + { + return null; + } + + return query; + } + + internal static string? UpdateReservation(int Id, + int? RoomID = null, int? GuestID = null, int? TransactionID = null, bool? IsNoShow = null, ReservationType? Type = null, + ReservationStatus? Status = null, DateTime? CreationDate = null, DateTime? StartDate = null, DateTime? EndDate = null, + DateTime? CheckIn = null, DateTime? CheckOut = null, DateTime? DateChanged = null) + { + List QueryParts = new(); + string query = "UPDATE reservations SET"; + + if (RoomID.HasValue) + { + QueryParts.Add($"RoomID = @RID"); + } + + if (GuestID.HasValue) + { + QueryParts.Add($"GuestID = @GID"); + } + + if (TransactionID.HasValue) + { + QueryParts.Add($"TransactionID = @TID"); + } + + if (IsNoShow.HasValue) + { + QueryParts.Add($"IsNoShow = @IsNoShow"); + } + + if (Type.HasValue) + { + QueryParts.Add($"Type = @Type"); + } + + if (Status.HasValue) + { + QueryParts.Add($"Status = @Status"); + } + + if (CreationDate.HasValue) + { + QueryParts.Add($"CreationDate = @CreationDate"); + } + + if (StartDate.HasValue) + { + QueryParts.Add($"StartDate = @StartDate"); + } + + if (EndDate.HasValue) + { + QueryParts.Add($"EndDate = @EndDate"); + } + + if (CheckIn.HasValue) + { + QueryParts.Add($"CheckIn = @CheckIn"); + } + + if (CheckOut.HasValue) + { + QueryParts.Add($"CheckOut = @CheckOut"); + } + + if (DateChanged.HasValue) + { + QueryParts.Add($"DateChanged = @DateChanged"); + } + + if (QueryParts.Count > 0) + { + query += " " + string.Join(", ", QueryParts) + " " + $"WHERE ID = @ID;"; + } + else + { + return null; + } + + return query; + } + + internal static string? UpdateGuest(int Id, string? FirstName = null, string? LastName = null, string? Email = null, string? CreditCard = null, string? Expiration = null, string? CCV = null) + { + List QueryParts = new(); + string query = "UPDATE guests SET"; + + if (!string.IsNullOrEmpty(FirstName)) + { + QueryParts.Add($"Fname = @Fname"); + } + + if (!string.IsNullOrEmpty(LastName)) + { + QueryParts.Add($"Lname = @Lname"); + } + + if (!string.IsNullOrEmpty(LastName)) + { + QueryParts.Add($"Email = @Email"); + } + + if (!string.IsNullOrEmpty(CreditCard)) + { + QueryParts.Add($"CreditCard = @CC"); + } + + if (!string.IsNullOrEmpty(Expiration)) + { + QueryParts.Add($"Expiration = @Expiry"); + } + + if (!string.IsNullOrEmpty(CCV)) + { + QueryParts.Add($"CCV = @CCV"); + } + + if (QueryParts.Count > 0) + { + query += " " + string.Join(", ", QueryParts) + " " + $"WHERE ID = @ID;"; + } + else + { + return null; + } + + return query; + } + } +} diff --git a/OpheliasOasis/Managers/Hotel.cs b/OpheliasOasis/Managers/Hotel.cs new file mode 100644 index 0000000..f40e18e --- /dev/null +++ b/OpheliasOasis/Managers/Hotel.cs @@ -0,0 +1,949 @@ +using Ophelias.Models; +using System.Data.SQLite; + +namespace Ophelias.Managers +{ + internal static class Hotel + { + internal static int GetLastId(string tableName) + { + int LastId = 0; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = $"SELECT SEQ FROM sqlite_sequence WHERE name=@Table;"; + cmd.ExecuteNonQuery(); + cmd.Parameters.AddWithValue("@Table", tableName); + using SQLiteDataReader reader = cmd.ExecuteReader(); + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + LastId = reader.GetInt32(0); + } + } + } + return LastId; + } + internal static (List<(DateTime, int, string, string)>, List) GetDailyOccupancy() + { + List previousOccupancies = new(); + List<(DateTime, int, string, string)> currentOccupancies = new(); + using (Database Manager = new()) + { + using SQLiteTransaction Transaction = Manager.con.BeginTransaction(); + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT RoomNum, Lname, Fname, EndDate FROM reservations " + + "INNER JOIN guests ON reservations.GuestID = guests.ID " + + "INNER JOIN rooms ON reservations.RoomNum = rooms.ID " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status IN (@Status1,@Status2);"; + cmd.Parameters.AddWithValue("@Date", DateTime.Now.Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + currentOccupancies.Add((reader.GetDateTime(3), reader.GetInt32(0), reader.GetString(1), reader.GetString(2))); + } + } + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT RoomNum FROM reservations " + + "INNER JOIN guests ON reservations.GuestID = guests.ID " + + "INNER JOIN rooms ON reservations.RoomNum = rooms.ID " + + "WHERE DATE (@Date) = EndDate AND Status IN (@Status1);"; + cmd.Parameters.AddWithValue("@Date", DateTime.Now.AddDays(-1).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Ended); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + foreach (int item in reader.GetValues()) + { + previousOccupancies.Add(item); + } + } + } + } + Transaction.Commit(); + } + return (currentOccupancies, previousOccupancies); + } + internal static List GetDailyArrivals() + { + List reservations = new(); + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT * FROM reservations " + + "INNER JOIN transactions ON reservations.TransactionID = transactions.ID " + + "INNER JOIN guests ON reservations.GuestID = guests.ID " + + "WHERE DATE (@Date) = StartDate AND Status IN (@Status1,@Status2)" + + "ORDER BY Lname ASC;"; + cmd.Parameters.AddWithValue("@Date", DateTime.Now.Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + Reservation? r; + Transaction? t; + Guest g; + int? RoomNumber = null; + DateTime? CheckIn = null, CheckOut = null, DateChanged = null, LastPaid = null, PaidOn = null; + + if (reader.HasRows && !reader.IsDBNull(0)) + { + if (reader[21].GetType() != typeof(DBNull)) + { + LastPaid = reader.GetDateTime(21); + } + + if (reader[22].GetType() != typeof(DBNull)) + { + PaidOn = reader.GetDateTime(22); + } + + t = new(reader.GetInt32(13), reader.GetDouble(14), reader.GetDouble(15), reader.GetDouble(17), reader.GetDateTime(20), + LastPaid: LastPaid, PaidOn: PaidOn, RefundAmount: reader.GetDouble(18), Penalty: reader.GetDouble(16), AmountPaid: reader.GetDouble(19)); + + g = new(reader.GetInt32(23), reader.GetString(24), reader.GetString(25), reader.GetString(26), reader.GetString(27), reader.GetString(28), reader.GetString(29)); + + if (reader[1].GetType() != typeof(DBNull)) + { + RoomNumber = reader.GetInt32(1); + } + + if (reader[10].GetType() != typeof(DBNull)) + { + CheckIn = reader.GetDateTime(10); + } + + if (reader[11].GetType() != typeof(DBNull)) + { + CheckOut = reader.GetDateTime(11); + } + + if (reader[12].GetType() != typeof(DBNull)) + { + DateChanged = reader.GetDateTime(12); + } + + r = new(reader.GetInt32(0), g, t, (ReservationType)reader.GetInt32(5), (ReservationStatus)reader.GetInt32(6), + reader.GetDateTime(7), reader.GetDateTime(8), reader.GetDateTime(9), RoomNum: RoomNumber, IsNoShow: reader.GetBoolean(4), + CheckIn: CheckIn, CheckOut: CheckOut, DateChanged: DateChanged); + reservations.Add(r); + } + } + } + } + } + return reservations; + } + internal static (double, double, List<(DateTime, double)>) GetIncentiveTransactions() + { + double losses; + double totalLosses = 0; + int days = 30; + DateTime dt = DateTime.Now; + List<(DateTime, double)> dailyLosses = new(); + using (Database Manager = new()) + { + for (int i = 0; i < days; i++) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT sum(((julianday(EndDate) - julianday(StartDate)) * transactions.Rate) - transactions.Owed) AS Loss " + + "FROM reservations " + + "INNER JOIN transactions ON reservations.TransactionID = transactions.ID " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND STATUS IN (@Status1,@Status2) AND Type = @Type"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + cmd.Parameters.AddWithValue("@Type", (int)ReservationType.Incentive); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + totalLosses += reader.GetDouble(0); + losses = reader.GetDouble(0); + } + else + { + losses = 0; + } + } + } + dailyLosses.Add((dt.AddDays(i), losses)); + } + } + return (totalLosses, totalLosses / 30, dailyLosses); + } + internal static (List<(DateTime, double)>, double, double) GetExpectedIncomeCount() + { + double totalIncome = 0; + double income; + int days = 30; + DateTime dt = DateTime.Now; + List<(DateTime, double)> dailyIncomes = new(); + using (Database Manager = new()) + { + for (int i = 0; i < days; i++) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT sum(transactions.Owed) FROM reservations " + + "INNER JOIN transactions ON reservations.TransactionID = transactions.ID " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status IN (@Status1,@Status2);"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + totalIncome += reader.GetDouble(0); + income = reader.GetDouble(0); + } + else + { + income = 0; + } + } + } + dailyIncomes.Add((dt.AddDays(i), income)); + } + } + return (dailyIncomes, totalIncome, totalIncome / 30); + } + internal static (double, List<(DateTime, int, int, int, int, int)>) GetExpectedOccupancyCount() + { + double thirtyDayOcc = 0; + int days = 30; + DateTime dt = DateTime.Now; + List<(DateTime, int, int, int, int, int)> occData = new(); + using (Database Manager = new()) + { + for (int i = 0; i < days; i++) + { + int rooms, conventional, prepaid, sixty, incentive; + using (SQLiteTransaction Transaction = Manager.con.BeginTransaction()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT COUNT(*) " + + "FROM reservations " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status in (@Status1,@Status2);"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + thirtyDayOcc += reader.GetInt32(0); + rooms = reader.GetInt32(0); + } + else + { + rooms = 0; + } + } + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT COUNT(*) " + + "FROM reservations " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status in (@Status1,@Status2) AND Type = 0;"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + conventional = reader.GetInt32(0); + } + else + { + conventional = 0; + } + } + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT COUNT(*) " + + "FROM reservations " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status in (@Status1,@Status2) AND Type = 1;"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + prepaid = reader.GetInt32(0); + } + else + { + prepaid = 0; + } + } + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT COUNT(*) " + + "FROM reservations " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status in (@Status1,@Status2) AND Type = 2;"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + sixty = reader.GetInt32(0); + } + else + { + sixty = 0; + } + } + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT COUNT(*) " + + "FROM reservations " + + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status in (@Status1,@Status2) AND Type = 3;"; + cmd.Parameters.AddWithValue("@Date", dt.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + incentive = reader.GetInt32(0); + } + else + { + incentive = 0; + } + } + } + Transaction.Commit(); + } + occData.Add((dt.AddDays(i), rooms, conventional, prepaid, sixty, incentive)); + } + } + return (thirtyDayOcc / days, occData); + } + internal static (int, bool) AvgOccupancySpan(DateTime Start, DateTime End) + { + int thirtyDayOcc = 0; + bool maxCapacityInRange = false; + int days = (int)(End.Date - Start.Date).TotalDays; + using (Database Manager = new()) + { + for (int i = 0; i < days; i++) + { + using SQLiteCommand cmd = Manager.con.CreateCommand(); + cmd.CommandText = $@"SELECT COUNT(*) + FROM reservations + WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status in (@Status1,@Status2);"; + cmd.Parameters.AddWithValue("@Date", Start.AddDays(i).Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + + using SQLiteDataReader reader = cmd.ExecuteReader(); + reader.Read(); + if (reader.HasRows && !reader.IsDBNull(0)) + { + thirtyDayOcc += reader.GetInt32(0); + if (reader.GetInt32(0) == 45) + { + maxCapacityInRange = true; + } + } + } + } + return (thirtyDayOcc / days, maxCapacityInRange); + } + internal static Guest? GetGuestByEmail(string Email) + { + Guest? g = null; + using (Database Manager = new()) + { + using SQLiteCommand cmd = Manager.con.CreateCommand(); + cmd.CommandText = $"SELECT * FROM guests WHERE Email = @Email"; + cmd.Parameters.AddWithValue("@Email", Email); + using SQLiteDataReader reader = cmd.ExecuteReader(); + reader.Read(); + if (reader.HasRows) + { + string? CreditCard = null, Expiration = null, CCV = null; + if (reader[4].GetType() != typeof(DBNull)) + { + CreditCard = reader[4].ToString(); + } + + if (reader[5].GetType() != typeof(DBNull)) + { + Expiration = reader[5].ToString(); + } + + if (reader[6].GetType() != typeof(DBNull)) + { + CCV = reader[6].ToString(); + } + + g = new(reader.GetInt32(0), reader.GetString(1), reader.GetString(2), reader.GetString(3), CreditCard, Expiration, CCV); + } + } + return g; + } + internal static Reservation? GetResByGuest(Guest g) + { + Reservation? r = null; + Transaction? t; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + int? RoomNumber = null; + DateTime? CheckIn = null, CheckOut = null, DateChanged = null, LastPaid = null, PaidOn = null; + + cmd.CommandText = @"SELECT * FROM reservations + INNER JOIN transactions ON reservations.TransactionID = transactions.ID + WHERE GuestID = @GuestID AND Status = @Status;"; + cmd.Parameters.AddWithValue("@GuestID", g.Id); + cmd.Parameters.AddWithValue("@Status", (int)ReservationStatus.Active); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + if (reader[21].GetType() != typeof(DBNull)) + { + LastPaid = reader.GetDateTime(21); + } + + if (reader[22].GetType() != typeof(DBNull)) + { + PaidOn = reader.GetDateTime(22); + } + + t = new(reader.GetInt32(13), reader.GetDouble(14), reader.GetDouble(15), reader.GetDouble(17), reader.GetDateTime(20), + LastPaid: LastPaid, PaidOn: PaidOn, RefundAmount: reader.GetDouble(18), Penalty: reader.GetDouble(16), AmountPaid: reader.GetDouble(19)); + + if (reader[1].GetType() != typeof(DBNull)) + { + RoomNumber = reader.GetInt32(1); + } + + if (reader[10].GetType() != typeof(DBNull)) + { + CheckIn = reader.GetDateTime(10); + } + + if (reader[11].GetType() != typeof(DBNull)) + { + CheckOut = reader.GetDateTime(11); + } + + if (reader[12].GetType() != typeof(DBNull)) + { + DateChanged = reader.GetDateTime(12); + } + + r = new(reader.GetInt32(0), g, t, (ReservationType)reader.GetInt32(5), (ReservationStatus)reader.GetInt32(6), + reader.GetDateTime(7), reader.GetDateTime(8), reader.GetDateTime(9), RoomNum: RoomNumber, IsNoShow: reader.GetBoolean(4), + CheckIn: CheckIn, CheckOut: CheckOut, DateChanged: DateChanged); + } + } + } + } + return r; + } + internal static TimeRefs? CanBeCheckedIn(string Email) + { + TimeRefs? status = null; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = $"SELECT * FROM reservation WHERE Email = @Email AND Status IN (0,1)"; + cmd.Parameters.AddWithValue("@Email", Email); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + DateTime dt = reader.GetDateTime(8); + if (dt.Date == DateTime.Now.Date) + { + status = TimeRefs.OnTime; + } + else if (dt.Date > DateTime.Now.Date) + { + status = TimeRefs.Late; + } + else if (dt.Date < DateTime.Now.Date) + { + status = TimeRefs.Early; + } + } + else + { + status = null; + } + } + } + } + return status; + } + internal static double? GetBaseRate() + { + double? rate; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string query = "SELECT Rate FROM rates WHERE DefaultRate = 1;"; + cmd.CommandText = query; + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + rate = reader.GetDouble(0); + } + else + { + rate = null; + } + } + } + } + return rate; + } + internal static bool GetBaseRateByDate(DateTime dt) + { + bool configured; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string query = "SELECT Rate FROM rates WHERE DateSet = @Date;"; + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@Date", dt.ToString("yyyy-MM-dd")); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + configured = true; + } + else + { + configured = false; + } + } + } + } + return configured; + } + internal static void SetBaseRate(double Rate, DateTime DateSet, bool? DefaultRate = null) + { + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string query = $"INSERT INTO rates (Rate, DateSet, DefaultRate) VALUES (@Rate, @DateSet, @DefaultRate);"; + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@Rate", Rate); + cmd.Parameters.AddWithValue("@DateSet", DateSet.ToString("yyyy-MM-dd")); + if (DefaultRate != null) + { + if (DefaultRate.Value == true) + { + cmd.Parameters.AddWithValue("@DefaultRate", Convert.ToInt32(DefaultRate)); + } + else + { + cmd.Parameters.AddWithValue("@DefaultRate", null); + } + } + else + { + cmd.Parameters.AddWithValue("@DefaultRate", null); + } + + cmd.ExecuteNonQuery(); + } + } + } + internal static void UpdateBaseRate(double Rate, DateTime DateSet, bool? DefaultRate = null) + { + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + if (DefaultRate != null) + { + if (DefaultRate.Value == true) + { + cmd.CommandText = $"UPDATE rates SET rate = @Rate, defaultrate = @DefaultRate WHERE DateSet = @Date;"; + cmd.Parameters.AddWithValue("@DefaultRate", Convert.ToInt32(DefaultRate)); + } + else + { + cmd.CommandText = $"UPDATE rates SET rate = @Rate WHERE DateSet = @Date;"; + } + } + else + { + cmd.CommandText = $"UPDATE rates SET rate = @Rate WHERE DateSet = @Date;"; + } + cmd.Parameters.AddWithValue("@Rate", Rate); + cmd.Parameters.AddWithValue("@Date", DateSet.ToString("yyyy-MM-dd")); + cmd.ExecuteNonQuery(); + } + } + } + internal static bool CheckBaseRate() + { + int? OldId = null; + bool Success = true; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string query = "SELECT Id FROM rates WHERE DefaultRate = 1;"; + cmd.CommandText = query; + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + OldId = reader.GetInt32(0); + } + } + } + int? Id; + if (OldId != null) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string query = "SELECT Id FROM rates WHERE DateSet = @Date;"; + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@Date", DateTime.Now.Date.ToString("yyyy-MM-dd")); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + Id = reader.GetInt32(0); + } + else + { + Id = null; + } + } + } + if (Id != null) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = @"UPDATE rates SET DefaultRate = NULL WHERE Id = @OldID; + UPDATE rates SET DefaultRate = 1 WHERE Id = @ID"; + cmd.Parameters.AddWithValue("@OldID", OldId); + cmd.Parameters.AddWithValue("@ID", Id); + cmd.ExecuteNonQuery(); + } + } + } + else + { + Success = false; + } + } + return Success; + } + internal static int? CheckInGuest(string Email, DateTime CheckIn) + { + int? RoomID = null; + using (Database Manager = new()) + { + using (SQLiteTransaction Transaction = Manager.con.BeginTransaction()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "UPDATE reservations SET RoomNum = (SELECT ID FROM rooms WHERE Occupied = 0 LIMIT 1), CheckIn = @Date " + + "WHERE GuestID = (SELECT ID FROM guests WHERE Email = @Email) AND RoomNum IS NULL AND Status in (@SActive,@SChanged);"; + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@SActive", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@SChanged", (int)ReservationStatus.Changed); + cmd.Parameters.AddWithValue("@Date", CheckIn.ToString("yyyy-MM-dd")); + cmd.ExecuteNonQuery(); + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "UPDATE rooms SET Occupied = 1 " + + "WHERE ID = (SELECT RoomNum FROM reservations WHERE GuestID = (SELECT ID FROM guests WHERE Email = @Email AND Status in (@SActive,@SChanged))));"; + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@SActive", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@SChanged", (int)ReservationStatus.Changed); + cmd.ExecuteNonQuery(); + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT RoomNum FROM reservations WHERE GuestID = (SELECT ID FROM guests WHERE Email = @Email AND Status in (@SActive,@SChanged))"; + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@SActive", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@SChanged", (int)ReservationStatus.Changed); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + RoomID = (int)reader.GetValue(0); + } + } + } + Transaction.Commit(); + } + } + return RoomID; + } + internal static bool GuestCurrentlyCheckedIn(string Email) + { + bool EntryFound; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT * FROM reservations " + + "WHERE GuestID = (SELECT ID FROM guests WHERE Email = @Email AND Status in (@SActive,@SChanged)) AND CheckIn IS NOT NULL"; + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@SActive", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@SChanged", (int)ReservationStatus.Changed); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + if (reader.HasRows) + { + EntryFound = true; + } + else + { + EntryFound = false; + } + } + } + } + return EntryFound; + } + internal static void CheckOutGuest(string Email, DateTime CheckOut) + { + using (Database Manager = new()) + { + using (SQLiteTransaction Transaction = Manager.con.BeginTransaction()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "UPDATE rooms SET Occupied = 0 " + + "WHERE ID = (SELECT RoomNum FROM reservations WHERE GuestID = (SELECT ID FROM guests WHERE Email = @Email AND Status in (@SActive,@SChanged)));"; + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@SActive", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@SChanged", (int)ReservationStatus.Ended); + cmd.ExecuteNonQuery(); + } + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "UPDATE reservations SET CheckOut = @Date, Status = @Status " + + "WHERE GuestID = (SELECT ID FROM guests WHERE Email = @Email) AND RoomNum IS NOT NULL AND Status in (@SActive,@SChanged);"; + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@Status", (int)ReservationStatus.Ended); + cmd.Parameters.AddWithValue("@SActive", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@SChanged", (int)ReservationStatus.Changed); + cmd.Parameters.AddWithValue("@Date", CheckOut.ToString("yyyy-MM-dd")); + cmd.ExecuteNonQuery(); + } + Transaction.Commit(); + } + } + return; + } + internal static List GetActiveSixtyDayRes() + { + List list = new(); + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT * FROM reservations " + + "INNER JOIN transactions ON reservations.TransactionID = transactions.ID " + + "INNER JOIN guests ON reservations.GuestID = guests.ID " + + "WHERE Type = @Type AND Status IN (@Status1,@Status2);"; + cmd.Parameters.AddWithValue("@Type", (int)ReservationType.SixtyDayAdvance); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + cmd.ExecuteNonQuery(); + + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + Reservation? r; + Transaction? t; + Guest g; + int? RoomNumber = null; + DateTime? CheckIn = null, CheckOut = null, DateChanged = null, LastPaid = null, PaidOn = null; + + if (reader.HasRows) + { + if (reader[21].GetType() != typeof(DBNull)) + { + LastPaid = reader.GetDateTime(21); + } + + if (reader[22].GetType() != typeof(DBNull)) + { + PaidOn = reader.GetDateTime(22); + } + + t = new(reader.GetInt32(13), reader.GetDouble(14), reader.GetDouble(15), reader.GetDouble(17), reader.GetDateTime(20), + LastPaid: LastPaid, PaidOn: PaidOn, RefundAmount: reader.GetDouble(18), Penalty: reader.GetDouble(16), AmountPaid: reader.GetDouble(19)); + + g = new(reader.GetInt32(23), reader.GetString(24), reader.GetString(25), reader.GetString(26), reader.GetString(27), reader.GetString(28), reader.GetString(29)); + + if (reader[1].GetType() != typeof(DBNull)) + { + RoomNumber = reader.GetInt32(1); + } + + if (reader[10].GetType() != typeof(DBNull)) + { + CheckIn = reader.GetDateTime(10); + } + + if (reader[11].GetType() != typeof(DBNull)) + { + CheckOut = reader.GetDateTime(11); + } + + if (reader[12].GetType() != typeof(DBNull)) + { + DateChanged = reader.GetDateTime(12); + } + + r = new(reader.GetInt32(0), g, t, (ReservationType)reader.GetInt32(5), (ReservationStatus)reader.GetInt32(6), + reader.GetDateTime(7), reader.GetDateTime(8), reader.GetDateTime(9), RoomNum: RoomNumber, IsNoShow: reader.GetBoolean(4), + CheckIn: CheckIn, CheckOut: CheckOut, DateChanged: DateChanged); + list.Add(r); + } + } + } + } + } + return list; + } + internal static List GetPastDueReservations() + { + List list = new(); + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "SELECT * FROM reservations " + + "INNER JOIN transactions ON reservations.TransactionID = transactions.ID " + + "INNER JOIN guests ON reservations.GuestID = guests.ID " + + "WHERE DATE(@Date) > StartDate AND Status IN (@Status1,@Status2) AND CheckIn IS NULL;"; + cmd.Parameters.AddWithValue("@Date", DateTime.Now.Date.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@Status1", (int)ReservationStatus.Active); + cmd.Parameters.AddWithValue("@Status2", (int)ReservationStatus.Changed); + using (SQLiteDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + Reservation? r; + Transaction? t; + Guest g; + int? RoomNumber = null; + DateTime? CheckIn = null, CheckOut = null, DateChanged = null, LastPaid = null, PaidOn = null; + + if (reader.HasRows) + { + if (reader[21].GetType() != typeof(DBNull)) + { + LastPaid = reader.GetDateTime(21); + } + + if (reader[22].GetType() != typeof(DBNull)) + { + PaidOn = reader.GetDateTime(22); + } + + t = new(reader.GetInt32(13), reader.GetDouble(14), reader.GetDouble(15), reader.GetDouble(17), reader.GetDateTime(20), + LastPaid: LastPaid, PaidOn: PaidOn, RefundAmount: reader.GetDouble(18), Penalty: reader.GetDouble(16), AmountPaid: reader.GetDouble(19)); + + g = new(reader.GetInt32(23), reader.GetString(24), reader.GetString(25), reader.GetString(26), reader.GetString(27), reader.GetString(28), reader.GetString(29)); + + if (reader[1].GetType() != typeof(DBNull)) + { + RoomNumber = reader.GetInt32(1); + } + + if (reader[10].GetType() != typeof(DBNull)) + { + CheckIn = reader.GetDateTime(10); + } + + if (reader[11].GetType() != typeof(DBNull)) + { + CheckOut = reader.GetDateTime(11); + } + + if (reader[12].GetType() != typeof(DBNull)) + { + DateChanged = reader.GetDateTime(12); + } + + r = new(reader.GetInt32(0), g, t, (ReservationType)reader.GetInt32(5), (ReservationStatus)reader.GetInt32(6), + reader.GetDateTime(7), reader.GetDateTime(8), reader.GetDateTime(9), RoomNum: RoomNumber, IsNoShow: reader.GetBoolean(4), + CheckIn: CheckIn, CheckOut: CheckOut, DateChanged: DateChanged); + list.Add(r); + } + } + } + } + } + return list; + } + } + internal enum TimeRefs + { + OnTime, + Early, + Late + } +} diff --git a/OpheliasOasis/Models/Guest.cs b/OpheliasOasis/Models/Guest.cs new file mode 100644 index 0000000..15e86e0 --- /dev/null +++ b/OpheliasOasis/Models/Guest.cs @@ -0,0 +1,117 @@ +using Ophelias.Managers; +using System.Data.SQLite; + +namespace Ophelias.Models +{ + internal class Guest + { + internal int Id; + internal string FirstName; + internal string LastName; + internal string Email; + internal string? CreditCard; + internal string? CCV; + internal string? Expiration; + + internal Guest(string FirstName, string LastName, string Email, string? CreditCard = null, string? Expiration = null, string? CCV = null) + { + int Id; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "INSERT INTO guests (Fname, Lname, Email, CreditCard, Expiration, CCV) " + + "VALUES (@Fname, @Lname, @Email, @CreditCard, @Expiry, @CCV);"; + cmd.Parameters.AddWithValue("@Fname", FirstName); + cmd.Parameters.AddWithValue("@Lname", LastName); + cmd.Parameters.AddWithValue("@Email", Email); + cmd.Parameters.AddWithValue("@CreditCard", CreditCard); + cmd.Parameters.AddWithValue("@Expiry", Expiration); + cmd.Parameters.AddWithValue("@CCV", CCV); + cmd.ExecuteNonQuery(); + } + Id = (int)Manager.con.LastInsertRowId; + } + + if (CreditCard != null && Expiration != null && CCV != null) + { + this.Id = Id; + this.FirstName = FirstName; + this.LastName = LastName; + this.Email = Email; + this.CreditCard = CreditCard; + this.Expiration = Expiration; + this.CCV = CCV; + } + else + { + this.Id = Id; + this.FirstName = FirstName; + this.LastName = LastName; + this.Email = Email; + } + } + internal Guest(int Id, string FirstName, string LastName, string Email, string? CreditCard = null, string? Expiration = null, string? CCV = null) + { + this.Id = Id; + this.FirstName = FirstName; + this.LastName = LastName; + this.Email = Email; + this.CreditCard = CreditCard; + this.Expiration = Expiration; + this.CCV = CCV; + } + internal void UpdateGuest(int Id, string? FirstName = null, string? LastName = null, string? Email = null, string? CreditCard = null, string? Expiration = null, string? CCV = null) + { + using (Database Manager = new()) + { + using SQLiteCommand cmd = Manager.con.CreateCommand(); + cmd.CommandText = QueryBuilder.UpdateGuest(Id, FirstName, LastName, Email, CreditCard, Expiration, CCV); + cmd.ExecuteNonQuery(); + } + if (FirstName != null) + { + this.FirstName = FirstName; + } + + if (LastName != null) + { + this.LastName = LastName; + } + + if (Email != null) + { + this.Email = Email; + } + + if (CreditCard != null) + { + this.CreditCard = CreditCard; + } + if (Expiration != null) + { + this.Expiration = Expiration; + } + + if (CCV != null) + { + this.CCV = CCV; + } + } + internal void SetCreditCardInformation(string CreditCard, string Expiration, string CCV) + { + this.CreditCard = CreditCard; + this.Expiration = Expiration; + this.CCV = CCV; + } + } + internal class GuestList + { + internal List Guests; + + internal GuestList() + { + Guests = new(); + } + } +} diff --git a/OpheliasOasis/Models/Rate.cs b/OpheliasOasis/Models/Rate.cs new file mode 100644 index 0000000..ef12544 --- /dev/null +++ b/OpheliasOasis/Models/Rate.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Ophelias.Models; + +namespace Ophelias.Models +{ + internal class BaseRate + { + internal int Id; + internal double Rate; + internal DateTime DateSet; + + internal BaseRate(int id, double rate) + { + Id = id; + Rate = rate; + DateSet = DateTime.Now; + } + } + + internal class Rates + { + internal List BaseRates; + + internal Rates() + { + BaseRates = new(); + } + } +} diff --git a/OpheliasOasis/Models/Reservation.cs b/OpheliasOasis/Models/Reservation.cs new file mode 100644 index 0000000..a099661 --- /dev/null +++ b/OpheliasOasis/Models/Reservation.cs @@ -0,0 +1,207 @@ +using Ophelias.Managers; +using System.Data.SQLite; + +namespace Ophelias.Models +{ + internal class Reservation + { + 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) + { + int Id; double Multiplier; + switch (Type) + { + 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(); + if (BaseRate == null) + { + throw new NotImplementedException(); + } + + Transaction Transaction = new( + 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()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + if (RoomNum != null) + { + this.RoomNum = RoomNum; + } + + 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; + } + 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.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) + { + this.StartDate = StartDate; + this.EndDate = EndDate; + DateChanged = DateTime.Now.Date; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string? query = QueryBuilder.UpdateReservation(Id: Id, Status: ReservationStatus.Changed, StartDate: this.StartDate, EndDate: this.EndDate, DateChanged: DateChanged); + + 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(); + if (BaseRate == null) + { + throw new ArgumentNullException(nameof(BaseRate)); + } + + Transaction.UpdateTransactionFees((double)BaseRate, TxFunctions.Changed, TxFunctions.GetPayByDate(Type, this.StartDate, this.EndDate)); + } + internal void CancelReservation() + { + DateTime _DateChanged = DateTime.Now.Date; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + string? query = QueryBuilder.UpdateReservation(Id: Id, Status: ReservationStatus.Cancelled, DateChanged: _DateChanged); + + 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(); + } + } + } + } + internal enum ReservationStatus + { + Active, + Changed, + Cancelled, + Ended, + } + internal enum ReservationType + { + Conventional, + Prepaid, + SixtyDayAdvance, + Incentive, + } +} diff --git a/OpheliasOasis/Models/Transaction.cs b/OpheliasOasis/Models/Transaction.cs new file mode 100644 index 0000000..8d7be35 --- /dev/null +++ b/OpheliasOasis/Models/Transaction.cs @@ -0,0 +1,212 @@ +using Ophelias.Managers; +using System.Data.SQLite; + +namespace Ophelias.Models +{ + internal class Transaction + { + internal int Id; + internal double Rate; + internal double Owed; + internal double Penalty; + internal double Multiplier; + internal double RefundAmount; + internal double AmountPaid; + internal DateTime PayBy; + internal DateTime? LastPaid = null; + internal DateTime? PaidOn = null; + + internal Transaction(double Rate, double Owed, + double Multiplier, DateTime PayBy, DateTime? LastPaid = null, + DateTime? PaidOn = null, double RefundAmount = 0, double Penalty = 0, double AmountPaid = 0) + { + int Id; + using (Database Manager = new()) + { + using (SQLiteCommand cmd = Manager.con.CreateCommand()) + { + cmd.CommandText = "INSERT INTO transactions (Rate, Owed, Penalty, Multiplier, RefundAmount, AmountPaid, PayBy, LastPaid, PaidOn) " + + "VALUES (@Rate, @Owed, @Penalty, @Multiplier, @RefundAmount, @AmountPaid, @PayBy, @LastPaid, @PaidOn)"; + cmd.Parameters.AddWithValue("@Rate", Rate); + cmd.Parameters.AddWithValue("@Owed", Owed); + cmd.Parameters.AddWithValue("@Multiplier", Multiplier); + cmd.Parameters.AddWithValue("@RefundAmount", RefundAmount); + cmd.Parameters.AddWithValue("@AmountPaid", AmountPaid); + cmd.Parameters.AddWithValue("@Penalty", Penalty); + cmd.Parameters.AddWithValue("@PayBy", PayBy.ToString("yyyy-MM-dd")); + cmd.Parameters.AddWithValue("@LastPaid", LastPaid); + cmd.Parameters.AddWithValue("@PaidOn", PaidOn); + if (LastPaid != null) + { + cmd.Parameters.AddWithValue("@LastPaid", LastPaid.Value.ToString("yyyy-MM-dd")); + } + else + { + cmd.Parameters.AddWithValue("@LastPaid", LastPaid); + } + + if (PaidOn != null) + { + cmd.Parameters.AddWithValue("@PaidOn", PaidOn.Value.ToString("yyyy-MM-dd")); + } + else + { + cmd.Parameters.AddWithValue("@PaidOn", PaidOn); + } + + //cmd.CommandText = QueryBuilder.CreateTransaction(Rate, Owed, Multiplier, PayBy, Refund: RefundAmount, Penalty: Penalty, LastPaid: LastPaid, PaidOn: PaidOn); + cmd.ExecuteNonQuery(); + } + Id = (int)Manager.con.LastInsertRowId; + } + this.Id = Id; + this.Rate = Rate; + this.Owed = Owed; + this.Penalty = Penalty; + this.Multiplier = Multiplier; + this.RefundAmount = RefundAmount; + this.AmountPaid = AmountPaid; + this.PayBy = PayBy; + this.LastPaid = LastPaid; + this.PaidOn = PaidOn; + } + internal Transaction(int Id, double Rate, double Owed, + double Multiplier, DateTime PayBy, DateTime? LastPaid = null, + DateTime? PaidOn = null, double RefundAmount = 0, double Penalty = 0, double AmountPaid = 0) + { + this.Id = Id; + this.Rate = Rate; + this.Owed = Owed; + this.Penalty = Penalty; + this.Multiplier = Multiplier; + this.RefundAmount = RefundAmount; + this.AmountPaid = AmountPaid; + this.PayBy = PayBy; + this.LastPaid = LastPaid; + this.PaidOn = PaidOn; + } + + internal void UpdateTransactionFees(double Rate, double Multiplier, DateTime PayBy) + { + this.Rate = Rate; + this.Multiplier = Multiplier; + this.PayBy = PayBy; + using Database Manager = new(); + using SQLiteCommand cmd = Manager.con.CreateCommand(); + string? query = QueryBuilder.UpdateTransaction(Id: Id, Rate: this.Rate, Multiplier: this.Multiplier, PayBy: this.PayBy); + + if (query == null) + { + throw new Exception(); + } + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@ID", Id); + cmd.Parameters.AddWithValue("@Rate", this.Rate); + cmd.Parameters.AddWithValue("@Multiplier", this.Multiplier); + cmd.Parameters.AddWithValue("@PayBy", this.PayBy.ToString("yyyy-MM-dd")); + cmd.ExecuteNonQuery(); + } + internal void Pay(double Amount) + { + if (Amount <= 0) + { + return; + } + + LastPaid = DateTime.Now; + AmountPaid += Amount; + if (Owed - AmountPaid < 0) + { + RefundAmount = Math.Abs(Owed - Amount); + } + + if (Owed - AmountPaid <= 0) + { + PaidOn = DateTime.Now; + } + + using Database Manager = new(); + using SQLiteCommand cmd = Manager.con.CreateCommand(); + string? query = QueryBuilder.UpdateTransaction(Id: Id, Refund: RefundAmount, AmountPaid: AmountPaid, LastPaid: LastPaid, PaidOn: PaidOn); + + if (query == null) + { + throw new Exception(); + } + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@ID", Id); + cmd.Parameters.AddWithValue("@RefundAmount", RefundAmount); + cmd.Parameters.AddWithValue("@AmountPaid", AmountPaid); + cmd.Parameters.AddWithValue("@LastPaid", LastPaid.Value.ToString("yyyy-MM-dd")); + if(!PaidOn.HasValue) + throw new Exception(); + cmd.Parameters.AddWithValue("@PaidOn", PaidOn.Value.ToString("yyyy-MM-dd")); + cmd.ExecuteNonQuery(); + } + internal void Refund() + { + AmountPaid -= RefundAmount; + RefundAmount = 0; + using Database Manager = new(); + using SQLiteCommand cmd = Manager.con.CreateCommand(); + string? query = QueryBuilder.UpdateTransaction(Id: Id, Refund: RefundAmount); + + if (query == null) + { + throw new Exception(); + } + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@ID", Id); + cmd.Parameters.AddWithValue("@RefundAmount", RefundAmount); + cmd.ExecuteNonQuery(); + } + } + + internal static class TxFunctions + { + internal static double ConventionalFee = 1.0; + internal static double PrepaidFee = 0.75; + internal static double SixtyDayFee = 0.85; + internal static double Changed = 1.1; + internal static double IncentiveFee(DateTime Start, DateTime End) + { + int thirtyDayOcc; + (thirtyDayOcc, _) = Hotel.AvgOccupancySpan(Start, End); + if ((double)(thirtyDayOcc / 45.0) <= 0.6) + { + return 0.80; + } + + return 1.0; + } + internal static DateTime GetPayByDate(ReservationType Type, DateTime StartDate, DateTime EndDate) + { + switch (Type) + { + case ReservationType.Conventional: return EndDate; + case ReservationType.Prepaid: return StartDate; + case ReservationType.Incentive: return EndDate; + case ReservationType.SixtyDayAdvance: return StartDate.AddDays(-30); + default: throw new NotImplementedException(); + } + } + internal static double CalculateOwed(double Rate, int Days, double Multiplier) + { + return Math.Round(Rate * Days * Multiplier); + } + + + } + internal class TransactionList + { + internal List Transactions; + + internal TransactionList() + { + Transactions = new(); + } + } +} diff --git a/OpheliasOasis/OpheliasOasis.csproj b/OpheliasOasis/OpheliasOasis.csproj new file mode 100644 index 0000000..beb2f6a --- /dev/null +++ b/OpheliasOasis/OpheliasOasis.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/OpheliasOasis/Program.cs b/OpheliasOasis/Program.cs new file mode 100644 index 0000000..e08749a --- /dev/null +++ b/OpheliasOasis/Program.cs @@ -0,0 +1,942 @@ +using Ophelias.Expressions; +using Ophelias.Managers; +using Ophelias.Models; +using Ophelias.Reporting; +using System.Data.SQLite; + +internal class Program +{ + private static string GetGuestEmail() + { + Console.Write("Specify email: "); + string Email = ""; + while (!Validation.ValidateEmail(Email)) + { + Email = Console.ReadLine(); + if (!Validation.ValidateEmail(Email)) + { + Console.Write("Please enter a valid email: "); + } + } + return Email; + } + + private static void GuestMode() + { + Reservation? activeReservation = null; + Guest? activeGuest = null; + void help() + { + Console.WriteLine( + "Reservation Commands:\n" + + "\treservation create - Create a new reservation.\n" + + "\treservation update - Update your active reservation.\n" + + "\treservation cancel - Cancel a reservation.\n" + + "Account Commands:\n" + + "\taccount create - Create a new guest account.\n" + + "\taccount update - Update your account information.\n" + + "\taccount login - Log into your guest account." + + "Enter Q to quit.\n" + ); + return; + } + + (string?, string?, string?) GetCreditCardInformation() + { + Console.Write("What is your credit card number: "); + string CreditCard = ""; + while (!Validation.ValidateCreditCard(CreditCard)) + { + CreditCard = Console.ReadLine().Trim().Replace("\t", ""); + if (CreditCard == "q" || CreditCard == "Q") + { + return (null, null, null); + } + + if (!Validation.ValidateCreditCard(CreditCard)) + { + Console.Write("Please enter a valid credit card. If your card is expired, enter Q to cancel: "); + } + } + Console.Write("What is your credit card expiration date (MM/yy): "); + string CardExpiration = ""; + while (!Validation.ValidateExpirationDate(CardExpiration)) + { + CardExpiration = Console.ReadLine().Trim().Replace("\t", ""); + if (CardExpiration == "q" || CardExpiration == "Q") + { + return (null, null, null); + } + + if (!Validation.ValidateExpirationDate(CardExpiration)) + { + Console.Write("Please enter a valid expiration date. If your card is expired, enter Q to cancel: "); + } + } + Console.Write("What is your credit card CCV: "); + string CCV = ""; + while (!Validation.ValidateCCV(CCV)) + { + CCV = Console.ReadLine().Trim().Replace("\t", ""); + if (CCV == "q" || CCV == "Q") + { + return (null, null, null); + } + + if (!Validation.ValidateCCV(CCV)) + { + Console.Write("Please enter a valid credit card CCV. If your card is expired, enter Q to cancel: "); + } + } + return (CreditCard, CardExpiration, CCV); + } + (string, string) GetGuestName() + { + Console.Write("What is your first name: "); + string FirstName = ""; + while (FirstName.Length == 0) + { + FirstName = Console.ReadLine(); + if (FirstName == "") + { + Console.Write("What is your first name: "); + } + } + Console.Write("What is your last name: "); + string LastName = ""; + while (LastName.Length == 0) + { + LastName = Console.ReadLine(); + if (LastName == "") + { + Console.Write("What is your last name: "); + } + } + return (FirstName, LastName); + } + void GuestLogin() + { + Console.Write("\nEnter your email address: "); + string email = ""; + while (!Validation.ValidateEmail(email)) + { + email = Console.ReadLine(); + if (!Validation.ValidateEmail(email)) + { + Console.Write("Please enter a valid email: "); + } + } + activeGuest = Hotel.GetGuestByEmail(email); + if (activeGuest == null) + { + Console.WriteLine($"\nNo account was found with the email {email}."); + return; + } + Console.WriteLine($"\nYou have logged into {activeGuest.FirstName} {activeGuest.LastName} ({email})."); + activeReservation = Hotel.GetResByGuest(activeGuest); + } + void CreateNewGuestPrompt() + { + (string FirstName, string LastName) = GetGuestName(); + string Email = GetGuestEmail(); + Console.Write("Would you like to enter your credit card details? (Y/n): "); + string? CreditCard = null; + string? CardExpiration = null; + string? CCV = null; + while (true) + { + string input = Console.ReadLine(); + if (input.Equals("y") || input.Equals("Y")) + { + (CreditCard, CardExpiration, CCV) = GetCreditCardInformation(); + break; + } + else if (input.Equals("n") || input.Equals("N")) + { + break; + } + else + { + Console.Write("Input must be Y, y or N, n: "); + } + } + + activeGuest = new(FirstName, LastName, Email, CreditCard: CreditCard, Expiration: CardExpiration, CCV: CCV); + Console.Write($"You are now logged in as {FirstName} {LastName} ({Email})"); + } + void UpdateGuestInformation() + { + if (activeGuest == null) + { + Console.WriteLine("No guest is currently logged in, please login."); + return; + } + + string? NewFname = null, NewLname = null, NewEmail = null, NewCard = null, NewExpiry = null, NewCCV = null; + + void SavePrompt() + { + if (NewFname == null && NewLname == null && NewEmail == null && NewCard == null && NewExpiry == null && NewCCV == null) + { + Console.WriteLine("No changes have been made."); + return; + } + string changes = ""; + List NewDetails = new(); + if (!string.IsNullOrEmpty(NewFname)) + { + NewDetails.Add($"\tFirst Name: {activeGuest.FirstName} -> {NewFname}"); + activeGuest.FirstName = NewFname; + } + if (!string.IsNullOrEmpty(NewLname)) + { + NewDetails.Add($"\tLast Name: {activeGuest.LastName} -> {NewLname}"); + activeGuest.LastName = NewLname; + } + if (!string.IsNullOrEmpty(NewEmail)) + { + NewDetails.Add($"\tEmail: {activeGuest.Email} -> {NewEmail}"); + activeGuest.Email = NewEmail; + } + if (!string.IsNullOrEmpty(NewCard)) + { + NewDetails.Add($"\tCredit Card: {activeGuest.CreditCard} -> {NewCard}"); + activeGuest.CreditCard = NewCard; + } + if (!string.IsNullOrEmpty(NewExpiry)) + { + NewDetails.Add($"\tCard Expiration Date: {activeGuest.Expiration} -> {NewExpiry}"); + activeGuest.Expiration = NewExpiry; + } + if (!string.IsNullOrEmpty(NewCCV)) + { + NewDetails.Add($"\tCard CCV: {activeGuest.CCV} -> {NewCCV}"); + activeGuest.CCV = NewCCV; + } + if (NewDetails.Count > 0) + { + changes += string.Join("\n", NewDetails); + } + + Console.WriteLine($"The following changes have been made:\n {changes}"); + activeGuest.UpdateGuest(activeGuest.Id, NewFname, NewLname, NewEmail, NewCard, NewExpiry, NewCCV); + return; + } + + Console.WriteLine($"You are currently logged in as {activeGuest.FirstName} {activeGuest.LastName} ({activeGuest.Email}).\n" + + $"If this is not your account, please (Q)uit and log into your account. Changes will be recorded, but not saved\n" + + $"until you enter S.\n"); + + do + { + Console.Write("Please select the option you would like to change or enter S to save:\n" + + "1. First Name and Last Name\n" + + "2. Email Address\n" + + "3. Credit Card Information\n"); + switch (Console.ReadLine()) + { + case "Q": return; + case "1": (NewFname, NewLname) = GetGuestName(); break; + case "2": NewEmail = GetGuestEmail(); break; + case "3": (NewCard, NewExpiry, NewCCV) = GetCreditCardInformation(); break; + case "S": SavePrompt(); return; + default: break; + } + } while (true); + } + ReservationType SelectReservation() + { + string input = ""; + Console.Write("What kind of reservation would you like to make?\n" + + "1. Conventional\n" + + "2. Prepaid\n" + + "3. 60 Day Advance\n" + + "4. Incentive\n" + + "Input a number: "); + while (true) + { + input = Console.ReadLine(); + if (input == "1" || input == "2" || input == "3" || input == "4") + { + break; + } + + Console.Write("Please enter either 1, 2, 3, or 4: "); + } + return (ReservationType)(Convert.ToInt32(input) - 1); + } + bool CheckReservationRestrictions(DateTime Date, ReservationType Type) + { + if (Type == ReservationType.Prepaid) + { + if ((int)(Date - DateTime.Now).TotalDays < 90) + { + Console.WriteLine("Prepaid reservations must be made 90 days in advance."); + } + else + { + return true; + } + } + else if (Type == ReservationType.SixtyDayAdvance) + { + if ((int)(Date - DateTime.Now).TotalDays < 60) + { + Console.WriteLine("Sixty-days-in-advance reservations must be made 60 days in advance."); + } + else + { + return true; + } + } + return false; + } + (DateTime?, DateTime?) SelectDate(ReservationType Type) + { + + (DateTime, DateTime) Dates() + { + string input = ""; + DateTime _StartDate; + DateTime _EndDate; + Console.Write("When would you like to begin your stay.\n" + + "Your date input should be in in the following format - yyyy-MM-dd. Example: (2021-12-31)?\n" + + "Input a date (2021-12-31): "); + while (true) + { + input = Console.ReadLine(); + if (DateTime.TryParse(input, out _StartDate) && _StartDate >= DateTime.Now) + { + break; + } + + if (_StartDate <= DateTime.Now) + { + Console.Write("Start date cannot be before current date. Please enter a valid date (2021-12-31): "); + } + else + { + Console.Write("Please enter a valid date (2021-12-31): "); + } + } + Console.Write("When would you like to end your stay.\n" + + "Your date input should be in in the following format - yyyy-MM-dd. Example: (2021-12-31)?\n" + + "Input a date (2021-12-31): "); + while (true) + { + input = Console.ReadLine(); + if (DateTime.TryParse(input, out _EndDate) && _EndDate > _StartDate) + { + break; + } + + if (_EndDate < _StartDate) + { + Console.Write("End date must be after start date. Please enter a valid date (2021-12-31): "); + } + else + { + Console.Write("Please enter a valid date (2021-12-31): "); + } + } + return (_StartDate.Date, _EndDate.Date); + } + + DateTime StartDate; + DateTime EndDate; + string input; + + while (true) + { + bool maxCapacity = false; + (StartDate, EndDate) = Dates(); + if (StartDate == null || EndDate == null) + { + (_, maxCapacity) = Hotel.AvgOccupancySpan(StartDate, EndDate); + } + + if (!maxCapacity) + { + if (!CheckReservationRestrictions(StartDate, Type)) + { + Console.Write("Do you want to quit? Type YES to quit and discard, enter anything or nothing to select another date range.\n" + + ": "); + input = Console.ReadLine(); + if (input == "YES") + { + Console.WriteLine("Aborting reservation changes."); + return (null, null); + } + } + else + { + break; + } + } + else + { + Console.WriteLine("Your reservation covers a range where we are already at max capacity, please change your reservation dates."); + } + + } + return (StartDate, EndDate); + + } + void EditReservationPrompt() + { + string input; + DateTime? NewStartDate = activeReservation.StartDate, NewEndDate = activeReservation.EndDate; + ReservationType NewType = activeReservation.Type; + + bool completed = false; + do + { + Console.Write("What information would you like to edit?\n" + + "If not and you wish to cancel, enter Q to exit. If you want to save and complete your changes, enter S.\n" + + "1. Reservation type\n" + + "2. Reservation dates\n" + + "Enter 1 or 2: "); + input = Console.ReadLine(); + switch (input) + { + case "Q": Console.WriteLine("Changes have has been deleted."); return; + case "1": NewType = SelectReservation(); break; + case "2": (NewStartDate, NewEndDate) = SelectDate(NewType); break; + case "S": + if (NewStartDate == null || NewEndDate == null) + { + return; + } + + while (CheckReservationRestrictions((DateTime)NewStartDate, NewType)) + { + (NewStartDate, NewEndDate) = SelectDate(NewType); + if (NewStartDate == null || NewEndDate == null) + { + return; + } + } + completed = true; + (activeReservation.Type, activeReservation.StartDate, activeReservation.EndDate) = (NewType, (DateTime)NewStartDate, (DateTime)NewEndDate); + break; + default: break; + } + } while (!completed); + } + void CreateNewReservation() + { + if (activeGuest == null) + { + Console.WriteLine("No guest is currently logged in, please login."); + return; + } + if (activeReservation != null) + { + Console.WriteLine("You currently have an active registration."); + return; + } + if (Hotel.GetBaseRate() == null) + { + Console.WriteLine("Unable to proceed with reservation due to no base rate being set. Please inform an employee."); + return; + } + + string input; + + ReservationType Type; + DateTime? StartDate; + DateTime? EndDate; + + Type = SelectReservation(); + (StartDate, EndDate) = SelectDate(Type); + if (StartDate == null || EndDate == null) + { + Console.WriteLine("Aborting reservation creation."); + return; + } + + while ((Type != ReservationType.SixtyDayAdvance && + (activeGuest.CreditCard == null || activeGuest.Expiration == null || activeGuest.CCV == null))) + { + Console.Write("The reservation type you chose requires you to specify your credit card.\n" + + "If you are unable to provide one, enter Q to quit or hit enter to continue.\n" + + ": "); + input = Console.ReadLine(); + if (input == "Q") + { + return; + } + + GetCreditCardInformation(); + } + + Console.Write($"Thank you for filling out your reservation details. Currently you have made a {Type} " + + $"reservation and are scheduled to stay from {StartDate.Value.ToString("yyyy-MM-dd")} to {EndDate.Value.ToString("yyyy-MM-dd")}." + + $"If these details are correct, enter YES to complete. To cancel your reservation enter Q.\n" + + $": "); + input = Console.ReadLine(); + while (input != "YES") + { + if (input == "Q") + { + Console.WriteLine("Reservation has been deleted."); + return; + } + else + { + Console.Write("Input must be YES or Q.\n: "); + input = Console.ReadLine(); + } + } + if (Type == ReservationType.Prepaid) + { + activeReservation = new(activeGuest, Type, DateTime.Now.Date, StartDate.Value, EndDate.Value); + activeReservation.Transaction.Pay(activeReservation.Transaction.Owed); + } + else + { + activeReservation = new(activeGuest, Type, DateTime.Now.Date, StartDate.Value, EndDate.Value); + } + Console.WriteLine("Your reservation has been made."); + } + void UpdateReservation() + { + string input = "NO"; + if (activeGuest == null) + { + Console.WriteLine("No guest is currently logged in, please login."); + return; + } + if (activeReservation == null) + { + Console.WriteLine("You currently do not have an active registration."); + return; + } + + Console.Write("Your current reservation details are:\n" + + $"\tStarts on: {activeReservation.StartDate.ToString("yyyy-MM-dd")}\n" + + $"\tEnds on: {activeReservation.EndDate.ToString("yyyy-MM-dd")}\n"); + DateTime? _StartDate = null, _EndDate = null; + do + { + if (input == "NO") + { + (_StartDate, _EndDate) = SelectDate(activeReservation.Type); + if (_StartDate.HasValue && _EndDate.HasValue) + { + Console.Write("Your new reservation details are:\n" + + $"\tStarts on: {activeReservation.StartDate.ToString("yyyy-MM-dd")} -> {_StartDate.Value.ToString("yyyy-MM-dd")}\n" + + $"\tEnds on: {activeReservation.EndDate.ToString("yyyy-MM-dd")} -> {_EndDate.Value.ToString("yyyy-MM-dd")}\n"); + } + + Console.Write("Are you done with your changes?\n" + + "Enter YES to finish and save, NO to continue editing.\n" + + ": "); + } + else if (input == "Q") + { + Console.WriteLine("Your changes have been discarded."); + return; + } + else + { + Console.WriteLine("Input must be YES, NO, or Q."); + Console.Write(": "); + } + input = Console.ReadLine(); + } while (input != "YES"); + if (_StartDate != null && _EndDate != null) + { + activeReservation.ChangeReservationDates((DateTime)_StartDate, (DateTime)_EndDate); + Console.WriteLine("Your changes have been saved."); + } + return; + } + void CancelReservation() + { + if (activeGuest == null) + { + Console.WriteLine("No guest is currently logged in, please login."); + return; + } + if (activeReservation == null) + { + Console.WriteLine("You currently do not have an active registration."); + return; + } + string input; + Console.Write("Would you like to cancel your reservation?\n" + + "You may be charged depending on your reservation.\n" + + "Enter YES to confirm or NO to exit: "); + input = Console.ReadLine(); + while (input != "YES") + { + if (input == "NO") + { + Console.Write("Reservation has not been cancelled."); + return; + } + else + { + Console.Write("Your input must be YES or NO: "); + Console.ReadLine(); + } + } + activeReservation.CancelReservation(); + activeReservation = null; + Console.Write("Reservation has been cancelled, you may be charged based on your reservation."); + } + Console.Write( + "\nWelcome to the Ophelias Oasis Hotel Registration System!\n" + + "Type help to get a full list of commands or enter a command.\n" + + "Command: " + ); + while (true) + { + + string? input = Console.ReadLine(); + switch (input) + { + case "help": help(); break; + case "reservation create": CreateNewReservation(); break; + case "reservation update": UpdateReservation(); break; + case "reservation cancel": CancelReservation(); break; + case "account create": CreateNewGuestPrompt(); break; + case "account update": UpdateGuestInformation(); break; + case "account login": GuestLogin(); break; + case "q": return; + default: Console.WriteLine("Unknown command, enter help for more inforamtion."); break; + } + Console.Write("\nCommand: "); + } + } + private static void AdminMode() + { + void help() + { + Console.WriteLine( + "Report Commands:\n" + + "\tgenerate management report - Generates a daily management report on expected occupancy, room income, and incentive losses.\n" + + "\tgenerate operational report - Generates a report of daily arrivals and occupancy.\n" + + "\tgenerate accommodation bills - Generates an accommodation bill that will be handed to guests upon checkout.\n" + + "\treservation cancel\n" + + "Management Commands:" + + "\nnotify pending payments - Generates and emails 60 day advance reservations that they must pay for their reservation or it will be cancelled." + + "\nissue penalties - Issues penalties for guests that are no shows." + + "\tcheckin guest - Checks in a guest and assigns them a room.\n" + + "\tcheckout guest - Checks out a guest and removes their room assignment.\n" + + "\tset rate - Sets a new base rate to begin after a specified date.\n" + + "Enter Q to quit.\n" + ); + return; + } + + void SetFutureBaseRate() + { + bool SetRatePrompt(DateTime? FixedDate = null) + { + string input; + string amount; + amount = Console.ReadLine(); + if (Validation.ValidateMoney(amount)) + { + Console.Write($"Is this the correct base rate {amount}?\n" + + $"Enter YES or NO: "); + input = Console.ReadLine(); + while (input != "YES") + { + if (input == "NO") + { + break; + } + else + { + Console.Write("Input must be YES or NO: "); + } + input = Console.ReadLine(); + } + if (input == "YES") + { + if (FixedDate != null) + { + if (Hotel.GetBaseRateByDate((DateTime)FixedDate)) + { + Console.Write("There is already a base rate configured for this date.\n" + + "If you are entering a new rate because one was not configured and got this error, type YES.\n" + + "Would you like to overwrite it (YES)? If not enter anything to continue.\n" + + ": "); + if (Console.ReadLine() == "YES") + { + Hotel.UpdateBaseRate(Convert.ToDouble(amount), FixedDate.Value.Date, DefaultRate: true); + return true; + } + } + else + { + Hotel.SetBaseRate(Convert.ToDouble(amount), (DateTime)FixedDate, true); + } + + Console.WriteLine($"A base rate of {amount} has been set and will take effect immediately."); + } + else + { + DateTime StartDate; + Console.Write("When would you like the new rate to take effect.\n" + + "Your date input should be in in the following format - yyyy-MM-dd. Example: (2021-12-31)?\n" + + "Input a date (2021-12-31): "); + while (true) + { + input = Console.ReadLine(); + if (DateTime.TryParse(input, out StartDate)) + { + if (StartDate.Date <= DateTime.Now.Date) + { + Console.WriteLine("Base rate must be configured for a future night. Not the same day or past."); + } + else if (Hotel.GetBaseRateByDate(StartDate)) + { + Console.Write("There is already a base rate configured for this date.\n" + + "Would you like to overwrite it (YES)? If not enter anything to continue." + + ": "); + if (Console.ReadLine() == "YES") + { + Hotel.UpdateBaseRate(Convert.ToDouble(amount), StartDate.Date); + return true; + } + } + else + { + break; + } + } + + Console.Write("Please enter a valid date (2021-12-31): "); + } + Hotel.SetBaseRate(Convert.ToDouble(amount), StartDate); + Console.WriteLine($"A base rate of {amount} has been set and will take effect on {DateTime.Now.Date.ToString("yyyy-MM-dd")}."); + } + return true; + } + } + else + { + Console.WriteLine("Your input was not a valid input, an example of a valid input would be 100 or 100.00."); + } + Console.Write("Enter new rate: "); + return false; + } + + if (Hotel.GetBaseRate() == null) + { + Console.Write("No base rate has been configured. " + + "You must set one for the current date.\n" + + "Enter new rate: "); + while (!SetRatePrompt(DateTime.Now.Date)) { } + } + else + { + Console.Write("What is the value of the rate you would like to set.\n" + + "Enter new rate: "); + while (!SetRatePrompt()) { } + } + } + void CheckIn() + { + string Email = GetGuestEmail(); + TimeRefs? status = Hotel.CanBeCheckedIn(Email); + Guest? g = Hotel.GetGuestByEmail(Email); + if (g == null) + { + Console.WriteLine("No guest with that email exists."); + return; + } + if (!status.HasValue) + { + Console.WriteLine("No reservation exists for this email."); + return; + } + + if (status.Value == TimeRefs.OnTime) + { + int? RoomID = Hotel.CheckInGuest(Email, DateTime.Now.Date); + if (RoomID != null) + { + Console.WriteLine($"Guest has been checked in, their room number is {RoomID}."); + } + } + else if (status.Value == TimeRefs.Late) + { + Console.WriteLine("Since the reservation was not checked in on the date scheduled, it has been cancelled. The guest will be charged the \"no show\" penalty."); + Reservation? r = Hotel.GetResByGuest(g); + + if (r == null) + { + throw new Exception(); + } + + r.CancelReservation(); + + } + else if (status.Value == TimeRefs.Early) + { + Console.WriteLine("Since the reservation was not checked in on the date scheduled, it has been cancelled. The guest will be charged the \"no show\" penalty."); + } + return; + } + void CheckOut() + { + string Email = GetGuestEmail(); + if (Hotel.GuestCurrentlyCheckedIn(Email)) + { + Reservation r = Hotel.GetResByGuest(Hotel.GetGuestByEmail(Email)); + if (r.Type == ReservationType.Incentive || r.Type == ReservationType.Conventional) + { + r.Transaction.Pay(r.Transaction.Owed); + } + + Hotel.CheckOutGuest(Email, DateTime.Now.Date); + Console.WriteLine($"Guest has been checked out."); + } + else + { + Console.WriteLine($"Can't checkout a guest that hasn't been checked in."); + } + return; + } + void NotifyOutstandingPayments() + { + List activeSixtyRes = Hotel.GetActiveSixtyDayRes(); + foreach (Reservation r in activeSixtyRes) + { + int days = (int)(r.StartDate.Date - DateTime.Now.Date).TotalDays - 30; + if (days < 0) + { + r.CancelReservation(); + } + else if (days <= 15) + { + Email e = new(r.Guest.Email); + e.Send(); + } + } + if (File.Exists("Emails.txt")) + { + FileInfo f = new("Emails.txt"); + Console.WriteLine($"Emails have been written and appended to {f.FullName}"); + } + } + void GenerateManagementReports() + { + var w = Hotel.GetExpectedOccupancyCount(); + Management.CalculateExpectedOccupancy(w.Item2, w.Item1); + if (File.Exists("ExpectedOccupancy.txt")) + { + FileInfo f = new("ExpectedOccupancy.txt"); + Console.WriteLine($"Expected occupancy has been written and appended to {f.FullName}"); + } + var x = Hotel.GetExpectedIncomeCount(); + Management.CalculateExpectedIncome(x.Item1, x.Item2, x.Item3); + if (File.Exists("ExpectedIncome.txt")) + { + FileInfo f = new("ExpectedIncome.txt"); + Console.WriteLine($"Expected income has been written and appended to {f.FullName}"); + } + var y = Hotel.GetIncentiveTransactions(); + Management.CalculateIncentiveLosses(y.Item3, y.Item1, y.Item2); + if (File.Exists("IncentiveLosses.txt")) + { + FileInfo f = new("IncentiveLosses.txt"); + Console.WriteLine($"Incentive losses have been written and appended to {f.FullName}"); + } + } + void GenerateAccommodationBills() + { + List reservations = Hotel.GetDailyArrivals(); + Accommodation.GenerateAccommodationBills(reservations); + + if (File.Exists("AccommodationBills.txt")) + { + FileInfo f = new("AccommodationBills.txt"); + Console.WriteLine($"Accommodation bills have been written and appended to {f.FullName}"); + } + } + void GenerateOperationalReports() + { + List reservations = Hotel.GetDailyArrivals(); + Operational.FetchDailyArriavals(reservations); + if (File.Exists("DailyArrivals.txt")) + { + FileInfo f = new("DailyArrivals.txt"); + Console.WriteLine($"Daily arrivals have been written and appended to {f.FullName}"); + } + var x = Hotel.GetDailyOccupancy(); + Operational.FetchDailyOccupancy(x.Item1, x.Item2); + if (File.Exists("DailyOccupancy.txt")) + { + FileInfo f = new("DailyOccupancy.txt"); + Console.WriteLine($"Daily occupancy has been written and appended to {f.FullName}"); + } + } + + Console.Write( + "\nWelcome to the Ophelias Oasis Hotel Management System!\n" + + "Type help to get a full list of commands or enter a command.\n" + + "Command: "); + while (true) + { + + string? input = Console.ReadLine(); + switch (input) + { + case "help": help(); break; + case "generate management report": GenerateManagementReports(); break; + case "generate operational report": GenerateOperationalReports(); break; + case "generate accommodation bills": GenerateAccommodationBills(); break; + case "notify pending payments": NotifyOutstandingPayments(); break; + case "issue penalties": break; + case "checkin guest": CheckIn(); break; + case "checkout guest": CheckOut(); break; + case "set rate": SetFutureBaseRate(); break; + case "Q": return; + default: Console.WriteLine("Unknown command, enter help for more inforamtion."); break; + } + Console.Write("\nCommand: "); + } + + } + + private static void Main() + { + if (!File.Exists("database.sqlite3") || new FileInfo("database.sqlite3").Length == 0) + { + SQLiteConnection.CreateFile("database.sqlite3"); + using (Database Manager = new()) + { + Manager.InitializeTables(); + Manager.InitializeRoomsTable(); + } + } + if (!Hotel.CheckBaseRate()) + { + Console.WriteLine("No base rate is configured. As a result reservations cannot be made until one is configured."); + } + + bool run = true; + while (run) + { + Console.Write( + "Are you an employee or customer?\n" + + "1. Employee\n" + + "2. Customer/ Guest\n" + + ": " + ); + switch (Console.ReadLine().ToUpper()) + { + case "1": AdminMode(); break; + case "2": GuestMode(); break; + case "Q": run = false; break; + default: Console.WriteLine("You must either specify 1 for Employee, 2 for Customer/ Guest, or Q to quit.\n\n"); break; + } + } + } +} \ No newline at end of file diff --git a/OpheliasOasis/Reporting/Accommodation.cs b/OpheliasOasis/Reporting/Accommodation.cs new file mode 100644 index 0000000..1041454 --- /dev/null +++ b/OpheliasOasis/Reporting/Accommodation.cs @@ -0,0 +1,20 @@ +using Ophelias.Models; +namespace Ophelias.Reporting +{ + internal static class Accommodation + { + internal static void GenerateAccommodationBills(List reservations) + { + foreach (Reservation? r in reservations) + { + string report = $"ACCOMMODATION BILL - GENERATED ON {DateTime.Now.Date.ToString("yyyy-MM-dd")}\n" + + $"Name: {r.Guest.LastName}, {r.Guest.FirstName}\n" + + $"Arrival Date: {r.StartDate}\n" + + $"Departure Date: {r.EndDate}\n" + + $"Length of Stay: {(int)(r.EndDate.Date - r.StartDate.Date).TotalDays} days\n" + + $"Charged: ${r.Transaction.Owed}\n\n"; + File.AppendAllText(Path.GetFullPath("AccommodationBills.txt"), report); + } + } + } +} diff --git a/OpheliasOasis/Reporting/Email.cs b/OpheliasOasis/Reporting/Email.cs new file mode 100644 index 0000000..8392100 --- /dev/null +++ b/OpheliasOasis/Reporting/Email.cs @@ -0,0 +1,24 @@ +namespace Ophelias.Reporting +{ + internal class Email + { + private readonly string to; + private readonly string subject = "Your payment is due soon!"; + private readonly string body = "Hello valued customer, this is a reminder that your payment for your reservation is due soon, please login to the system and pay for your reservation. If you do not it will be canceled."; + private readonly string from = "no-reply@ophelias.oasis"; + + internal Email(string to) + { + this.to = to; + } + internal void Send() + { + File.AppendAllText(Path.GetFullPath("Emails.txt"), + $"TO: {to}\n" + + $"FROM: {from}\n" + + $"SUBJECT: {subject}\n" + + $"MESSAGE: {body}\n" + + $"\n"); + } + } +} diff --git a/OpheliasOasis/Reporting/Management.cs b/OpheliasOasis/Reporting/Management.cs new file mode 100644 index 0000000..98a9b10 --- /dev/null +++ b/OpheliasOasis/Reporting/Management.cs @@ -0,0 +1,54 @@ +using Ophelias.Models; +using Ophelias.Managers; + + +namespace Ophelias.Reporting +{ + internal static class Management + { + internal static void CalculateExpectedOccupancy(List<(DateTime, int, int, int, int, int)> items, double average) + { + List entries = new(); + foreach (var x in items) + { + entries.Add($"{x.Item1.Date.ToString("yyyy-MM-dd")}\t{x.Item2}\t{x.Item3}\t{x.Item4}\t{x.Item5}\t{x.Item6}"); + } + string report = $"EXPECTED 30 DAY OCCUPANCY REPORT - GENERATED ON {DateTime.Now.Date.ToString("yyyy-MM-dd")}\n" + + $"Date\tRooms Filled\tConventional\tPrepaid\t60-Day\tIncentive\n" + + $"{string.Join("\n", entries)}\n" + + $"Average Occupancy Rate: {average}\n\n"; + + File.AppendAllText(Path.GetFullPath("ExpectedOccupancy.txt"), report); + } + internal static void CalculateExpectedIncome(List<(DateTime, double)> items, double totalIncome, double average) + { + List entries = new(); + foreach (var x in items) + { + entries.Add($"{x.Item1.Date.ToString("yyyy-MM-dd")}\t{x.Item2}"); + } + string report = $"EXPECTED 30 DAY INCOME REPORT - GENERATED ON {DateTime.Now.Date.ToString("yyyy-MM-dd")}\n" + + $"Date\tIncome\n" + + $"{string.Join("\n", entries)}\n" + + $"Average Income: {average}\n" + + $"Total Income: {totalIncome}\n\n"; + + File.AppendAllText(Path.GetFullPath("ExpectedIncome.txt"), report); + } + internal static void CalculateIncentiveLosses(List<(DateTime, double)> items, double totalLosses, double average) + { + List entries = new(); + foreach (var x in items) + { + entries.Add($"{x.Item1.Date.ToString("yyyy-MM-dd")}\t{x.Item2}"); + } + string report = $"EXPECTED 30 DAY LOSSES (TO INCENTIVE) REPORT - GENERATED ON {DateTime.Now.Date.ToString("yyyy-MM-dd")}\n" + + $"Date\tLosses\n" + + $"{string.Join("\n", entries)}\n" + + $"Average Losses (Due to incentive): {average}\n" + + $"Total Losses (Due to incentive): {totalLosses}\n\n"; + + File.AppendAllText(Path.GetFullPath("IncentiveLosses.txt"), report); + } + } +} diff --git a/OpheliasOasis/Reporting/Operational.cs b/OpheliasOasis/Reporting/Operational.cs new file mode 100644 index 0000000..c675f4e --- /dev/null +++ b/OpheliasOasis/Reporting/Operational.cs @@ -0,0 +1,62 @@ +using Ophelias.Models; + + +namespace Ophelias.Reporting +{ + internal static class Operational + { + internal static void FetchDailyArriavals(List reservations) + { + List entries = new(); + foreach (Reservation r in reservations) + { + string roominfo; + if (!r.RoomNum.HasValue) + { + roominfo = "N/A"; + } + else + { + + roominfo = r.RoomNum.Value.ToString(); + } + + entries.Add($"{r.Guest.LastName}, {r.Guest.FirstName}\t{r.Type}\t{roominfo}\t{r.EndDate}"); + } + string report = $"DAILY ARRIVAL REPORT - GENERATED ON {DateTime.Now.Date.ToString("yyyy-MM-dd")}\n" + + $"Last, First\tType\tRoom\tDeparture" + + $"{string.Join("\n", entries)}\n\n"; + + File.AppendAllText(Path.GetFullPath("DailyArrivals.txt"), report); + } + internal static void FetchDailyOccupancy(List<(DateTime, int, string, string)> cop, List pop) + { + List entries = new(); + foreach (var c in cop) + { + string lastOccupied; + string sameDayLeave = ""; + if (pop.Contains(c.Item2)) + { + lastOccupied = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"); + } else + { + lastOccupied = "N/A"; + } + + if(DateTime.Now.Date == c.Item1.Date) + { + sameDayLeave = "*"; + } + entries.Add($"{c.Item2}\t{lastOccupied}\t{sameDayLeave}{c.Item3}, {c.Item4}"); + } + string report = $"DAILY OCCUPANCY REPORT - GENERATED ON {DateTime.Now.Date.ToString("yyyy-MM-dd")}\n" + + $"An * means that the guest is leaving the same day.\n" + + $"Room #\tPrev. Occupied\tCurrent Occupant\n" + + $"{string.Join("\n", entries)}\n\n"; + + File.AppendAllText(Path.GetFullPath("DailyOccupancy.txt"), report); + } + + } +} diff --git a/OpheliasOasis/Validation.cs b/OpheliasOasis/Validation.cs new file mode 100644 index 0000000..6f9c8da --- /dev/null +++ b/OpheliasOasis/Validation.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Text.RegularExpressions; +using System.ComponentModel.DataAnnotations; +using System.Globalization; + +namespace Ophelias.Expressions +{ + internal static class Expressions + { + internal static Regex CardRx = new(@"^[0-9]{16}$", RegexOptions.Compiled); + internal static Regex ExpriationRx = new(@"^(0?[1-9]|1[012])/2[0-9]{1}$", RegexOptions.Compiled); + internal static Regex CCVRx = new(@"^[0-9]{3}$", RegexOptions.Compiled); + internal static Regex MoneyRx = new(@"^(\d+\.\d{2}|\d+)$", RegexOptions.Compiled); + } + internal static class Validation + { + internal static bool ValidateCreditCard(string CreditCard) + { + return Expressions.CardRx.IsMatch(CreditCard); + } + internal static bool ValidateExpirationDate(string Expiration) + { + if (Expressions.ExpriationRx.IsMatch(Expiration)) + { + DateTime dt = DateTime.ParseExact(Expiration, "MM/yy", CultureInfo.InvariantCulture); + if (dt.Date >= DateTime.Now.Date) + return true; + } + return false; + } + internal static bool ValidateExpirationNotBeforeReservation(string Expiration, DateTime CollectionDate) + { + DateTime dt = DateTime.ParseExact(Expiration, "MM/yy", CultureInfo.InvariantCulture); + if (dt.Date > CollectionDate.Date) + return true; + return false; + } + internal static bool ValidateEmail(string email) + { + EmailAddressAttribute EmailChecker = new(); + return EmailChecker.IsValid(email); + } + internal static bool ValidateCCV(string CCV) + { + if (Expressions.CCVRx.IsMatch(CCV)) + return true; + return false; + } + internal static bool ValidateMoney(string Money) + { + return Expressions.MoneyRx.IsMatch(Money); + } + + } +}