From 28890a2b6a667b2e947aa29e2958d0859bcda1e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B2=E8=8F=AF?= <42814579+yunwah@users.noreply.github.com> Date: Sun, 17 Apr 2022 00:44:54 -0400 Subject: [PATCH] Adds documentation to the main program.cs --- OpheliasOasis/Managers/Hotel.cs | 5 +- OpheliasOasis/Program.cs | 488 +++++++++++++++++++++++++------- 2 files changed, 396 insertions(+), 97 deletions(-) diff --git a/OpheliasOasis/Managers/Hotel.cs b/OpheliasOasis/Managers/Hotel.cs index 281b0d0..795420c 100644 --- a/OpheliasOasis/Managers/Hotel.cs +++ b/OpheliasOasis/Managers/Hotel.cs @@ -37,7 +37,8 @@ namespace Ophelias.Managers 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) AND CheckIn IS NOT NULL;"; + "WHERE (DATE(@Date) BETWEEN StartDate AND EndDate) AND Status IN (@Status1,@Status2) AND CheckIn IS NOT NULL " + + "ORDER BY RoomNum 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); @@ -54,7 +55,7 @@ namespace Ophelias.Managers 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);"; + "WHERE DATE (DATE(@Date) BETWEEN StartDate AND 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()) diff --git a/OpheliasOasis/Program.cs b/OpheliasOasis/Program.cs index 4075007..5638d08 100644 --- a/OpheliasOasis/Program.cs +++ b/OpheliasOasis/Program.cs @@ -8,6 +8,12 @@ internal class Program { private static string GetGuestEmail() { + /* + * This is a function that previously resided + * within the GuestMode(), however this functionality + * has been moved out as the AdminMode() relies on it + * since this essentially is a email validation prompt. + */ Console.Write("Specify email: "); string Email = ""; while (!Validation.ValidateEmail(Email)) @@ -23,10 +29,21 @@ internal class Program private static void GuestMode() { - Reservation? activeReservation = null; - Guest? activeGuest = null; + /* + * Guest mode is meant for guests to create an account and make a reservation. + * Specifically this mode allows for guests to create an account containing their + * personal and payment information, create a reservation, manage that reservation, and/ or + * pay for that reservation. + */ + Reservation? activeReservation = null; // Holds the current reservation if one is loaded + Guest? activeGuest = null; // Holds the active guest if one logs in void help() { + /* + * Used to inform users on what the commands do. See + * the main while loop in GuestMode() for more details + * on what these mean. + */ Console.WriteLine( "Reservation Commands:\n" + "\treservation create - Create a new reservation.\n" + @@ -41,9 +58,15 @@ internal class Program ); return; } - (string?, string?, string?) GetCreditCardInformation() { + /* + * This function attempts to gather creditcard information. + * Since we need all three pieces, card number, expiration, and CCV + * we provide options to quit for which the information is discarded + * and null values are returned. If valid inputs are input and all + * three pieces are collected, they are returned. + */ Console.Write("What is your credit card number: "); string CreditCard = ""; while (!Validation.ValidateCreditCard(CreditCard)) @@ -93,6 +116,11 @@ internal class Program } (string, string) GetGuestName() { + /* + * This function is a series of while loops that will attempt + * to collect a users first and last name, these are then returned + * to the call location. + */ Console.Write("What is your first name: "); string FirstName = ""; while (FirstName.Length == 0) @@ -117,10 +145,21 @@ internal class Program } void GuestLogin() { + /* + * This function will attempt to login using an email specified by + * the guest. We use email because they are designated as unique + * identifiers and no two users can have the same email. For that reason + * we use emails to login rather than collecting multiple pieces of + * information or returning a list of accounts to scroll through. + */ Console.Write("\nEnter your email address: "); string email = ""; while (!Validation.ValidateEmail(email)) { + /* + * This loop attepts to get a valid email. If there is no valid + * formatted email it will keep trying. + */ email = Console.ReadLine(); if (!Validation.ValidateEmail(email)) { @@ -138,6 +177,11 @@ internal class Program } void CreateNewGuestPrompt() { + /* + * This prompt allows guest to create a new account using functionality that + * has been split into other functions. See those functions for details on how + * they work. + */ (string FirstName, string LastName) = GetGuestName(); string Email = GetGuestEmail(); Console.Write("Would you like to enter your credit card details? (Y/n): "); @@ -167,6 +211,12 @@ internal class Program } void UpdateGuestInformation() { + /* + * This function allows a guest, if logged in, to update any piece of their + * personal information. This includes name, email, and creditcard information. + * For more information on how this gets set on the backend, see UpdateGuest() + * in the Guest model. + */ if (activeGuest == null) { Console.WriteLine("No guest is currently logged in, please login."); @@ -177,6 +227,11 @@ internal class Program void SavePrompt() { + /* + * This save prompt is just to inform users of their changes and show them + * what information gets updated. Also calls the UpdateGuest() function to + * update the database. + */ if (NewFname == null && NewLname == null && NewEmail == null && NewCard == null && NewExpiry == null && NewCCV == null) { Console.WriteLine("No changes have been made."); @@ -231,12 +286,18 @@ internal class Program do { + /* + * This loop traps users until the enter one of the cases which results + * in updating a piece of information, saving their changes, or discarding + * them. + */ 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 "Q": return; case "1": (NewFname, NewLname) = GetGuestName(); break; case "2": NewEmail = GetGuestEmail(); break; @@ -248,6 +309,12 @@ internal class Program } ReservationType SelectReservation() { + /* + * This function was broken out to allow it to be reused in multiple sections. + * It prompts a user for their selection of reservation type and that type + * is then returned. We subtract 1 from the type since we start our input + * options at 1 instead of 0 (Enums start at 0). + */ string input = ""; Console.Write("What kind of reservation would you like to make?\n" + "1. Conventional\n" + @@ -269,6 +336,12 @@ internal class Program } bool CheckReservationRestrictions(DateTime Date, ReservationType Type) { + /* + * This function checks to see if there are reservation restrictions. + * Prepaid reservations must be made 90 days ahead of the start date + * and 60-day 60 days. This function informs the user if their reservation + * does not adhere to these constraints. + */ if (Type == ReservationType.Prepaid) { if ((int)(Date - DateTime.Now).TotalDays < 90) @@ -384,49 +457,17 @@ internal class Program 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() { + /* + * Allows users with no existing reservation to make a new reservation. + * If a user is not logged in, they will not be able to register either. + * The reservation will collect all the necessary information depending + * on requirements set by the reservation. Specifically if the reservation + * is anything but 60-day-in-advance, the creditcard is required. If users + * do not want to proceed, the are free to cancel and abort the creation + * of their reservation. + */ if (activeGuest == null) { Console.WriteLine("No guest is currently logged in, please login."); @@ -490,12 +531,12 @@ internal class Program input = Console.ReadLine(); } } - if (Type == ReservationType.Prepaid) + if (Type == ReservationType.Prepaid) // Creates a new reservation and set it as the active. Also pays for the reservation if the reservation type was prepaid. { activeReservation = new(activeGuest, Type, DateTime.Now.Date, StartDate.Value, EndDate.Value); activeReservation.Transaction.Pay(activeReservation.Transaction.Owed, activeGuest.CreditCard); } - else + else // Creates a new reservation and set it as the active. { activeReservation = new(activeGuest, Type, DateTime.Now.Date, StartDate.Value, EndDate.Value); } @@ -503,6 +544,16 @@ internal class Program } void UpdateReservation() { + /* + * Update reservation allows guests to change their reservation at the + * cost of having to pay a new amount based on the current base rate + * with a multiplier of 110% or 1.1. If a user opts to not update + * their reservation the changes will be discarded. Furthermore the + * system prevents people from registering when the hotel is at max + * capacity for a certain date. For more details, see the SelectDate() + * function. If a user is not logged in, they will not be able to update + * their reservation. + */ string input = "NO"; if (activeGuest == null) { @@ -556,6 +607,13 @@ internal class Program } void CancelReservation() { + /* + * This function will provide guests with the option to cancel their reservation + * or abort if they decide they do not want to cancel. If the reservation is cancelled, + * the reservation cancellation function CancelReservation() is called on the reservation + * and the database is updated accordingly. See CancelReservation() for more details. + * If a user is not logged in, they will not be able to cancel either. + */ if (activeGuest == null) { Console.WriteLine("No guest is currently logged in, please login."); @@ -590,6 +648,17 @@ internal class Program } void PayForReservation() { + /* + * This function allows for guests to pay for their 60-day-in-advance if they + * meet the 30-45 day before start date window. All other reservations are denied + * the ability to pay since they have specific points at which they are charged. + * If there is no creditcard information, this function will attempt to collect it + * and then update the guests information before paying for the transaction. Depending + * on various factors, the transaction may be completed or invalid. However + * since the current design is to have members pay in full, most of these cases + * should be impossible to trigger. Currently they are implemented for future changes + * or if they do trigger. + */ if (activeGuest == null) { Console.WriteLine("No guest is currently logged in, please login."); @@ -617,6 +686,11 @@ internal class Program return; } else if (ReservationType.SixtyDayAdvance == activeReservation.Type) { + /* + * Checks to see if the reservation has been paid for are is past the latest possible + * payment date. If it has been payed, the user will be informed, if it is past the + * payment collection date, the reservation is cancelled and user is notified. + */ if(activeReservation.StartDate.AddDays(-30).Date < DateTime.Now.Date) { if (activeReservation.Transaction.Owed <= activeReservation.Transaction.AmountPaid) @@ -636,10 +710,18 @@ internal class Program ccv = activeGuest.CCV; while (true) { - if (cc == null || exp == null || ccv == null) - (cc, exp, ccv) = GetCreditCardInformation(); + /* + * This loop traps the user until they either choose to pay or not. + * If the card details they specify are invalid at any point within the latest + * date of the payment, we choose to reject that as it theoretically could cause + * problems. In this hypothetical situation is would not but in the real world it + * might depending on the card vendor. If a user choses to abort payment, the function + * will discard any changes to that guests payment information if changes were made. + * In the case where a customers payment information is already valid, they will pay for + * the reservation in full without any prompts. + */ - if (cc == null || exp == null || ccv == null) + if (cc == null || exp == null || ccv == null) // Trigger to get new card information { Console.Write("Would you like to try again and enter your payment information? (Your reservation will not be canceled)\n" + "YES or NO: "); @@ -659,8 +741,31 @@ internal class Program Console.WriteLine("Input must be YES or NO."); } } + (cc, exp, ccv) = GetCreditCardInformation(); // See for more information on how input is collected. + } else if (cc != null && exp != null && ccv != null) { + /* + * If the creditcard is not null, this section checks to see if payment can be made. + * If payment can be made the guest information is updated and an attempt to pay is made. + * The payment can result in any of the following: + * + * Successful + * Payment was made and recorded + * + * Failed + * An error occurred and the staff should be notified + * + * Attempt to pay $0 or less + * Self explanatory + * + * Missing card information + * If the card is missing payments cannot be made + * + * Already Paid + * The payment has already been paid at an earlier date + * or due to some other factor, therefore there was no need to charge. + */ if (ReservationType.SixtyDayAdvance == activeReservation.Type && ((DateTime.Parse(exp).Date < activeReservation.StartDate.AddDays(-30).Date) && (DateTime.Parse(exp).Date < activeReservation.StartDate.AddDays(-45).Date))) { Console.WriteLine("Your card expires too soon. Please enter the correct expiration date if incorrect or a new card."); @@ -707,20 +812,57 @@ internal class Program ); while (true) { - + /* + * This is the main administrator loop. + * The following are valid operations: + * + * reservation create: + * Creates a new reservation with the information specified by the guest. + * For more information see the CreateNewReservation() function. + * + * reservation update: + * Updates an existing reservation if there is one. If there is no existing + * reservation the function will immediately return. To get more information + * see the UpdateReservation() function. + * + * reservation cancel: + * Cancels a reservation. If the reservation is subject to penalties, the + * guest will be charged. For more infromation, see CancelReservation(). + * + * reservation pay: + * Enables 60-day-in-advance reservees to pay for their reservations if + * they are within the valid payment window. Other reservation types will + * be blocked. For more details, see PayForReservation(). + * + * account create: + * Enables guests to create a new account. See CreateNewGuestPrompt for + * more details on account creation. + * + * account update: + * Update an existing guests information, such as name, email, and + * creditcard information. For more details on how this is handled, + * see UpdateGuestInformation(). + * + * account login: + * Logs into an account using a guests email if they have an account. + * For more details see GuestLogin(). + * + * Q and q: + * Returns to the main loop for choosing either the Guest or Admin flow. + */ 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 "reservation pay": PayForReservation(); break; - case "account create": CreateNewGuestPrompt(); break; - case "account update": UpdateGuestInformation(); break; - case "account login": GuestLogin(); break; - case "q": return; - case "Q": return; + case "help": help(); break; // Gets help text + case "reservation create": CreateNewReservation(); break; // Allows guests to create a reservation + case "reservation update": UpdateReservation(); break; // Allows guests to update a reservation if they have one + case "reservation cancel": CancelReservation(); break; // Allows guests to cancel a reservation if they have one + case "reservation pay": PayForReservation(); break; // Allows guests with 60-day reservations to pay for it + case "account create": CreateNewGuestPrompt(); break; // Creates a new guest + case "account update": UpdateGuestInformation(); break; // Updates a guests personal and/ or payment information + case "account login": GuestLogin(); break; // Logs a guest in + case "q": return; // Quit to mode loop + case "Q": return; // Quit to mode loop default: Console.WriteLine("Unknown command, enter help for more inforamtion."); break; } Console.Write("\nCommand: "); @@ -728,29 +870,55 @@ internal class Program } private static void AdminMode() { + /* + * Admin mode is meant for employees. There is no authetication or security measures + * for this class as the design specification did not include that and for the goals + * of this project, security was not to be a concern. Realistically this would be + * handled differently and securely. + * + * The pupose of this class is to provide employees with the ability to perform + * specific operations such as checking/ checking out a guest, generating + * reports that management needs to understand how the hotel is operating, + * a system to set the hotels rates, and the ability to issue penalties and/ or + * notify outstanding payments. For more details on how each of these components work, + * see the documentation within their functions. + */ void help() { + /* + * Help text to understand commands. + */ 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." + + "\nManagement Commands:\n" + + "\tnotify pending payments - Generates and emails 60 day advance reservations that they must pay for their reservation or it will be cancelled.\n" + + "\tissue penalties - Issues penalties for guests that are no shows.\n" + "\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 or q to quit.\n" + "\nEnter Q or q to quit.\n" ); return; } - void SetFutureBaseRate() { + /* + * Allows employees to configure a future base rate. See SetRatePrompt() for the + * details as it was broken out into a nested function. + */ bool SetRatePrompt(DateTime? FixedDate = null) { + /* + * This function promopts an employee with a base rate configuration prompt. + * If this is the first time configuring the base rate, in cases where one is not set, + * the default rate will be set effective immediately, otherwise the base rate prompt + * will require the employee to set the base rate sometime in the future. The accepted inputs + * are checked against the function ValidateMoney() which basically checks for how money is typically + * represented in the United States. + */ string input; string amount; amount = Console.ReadLine(); @@ -783,13 +951,13 @@ internal class Program ": "); if (Console.ReadLine() == "YES") { - Hotel.UpdateBaseRate(Convert.ToDouble(amount), FixedDate.Value.Date, DefaultRate: true); + Hotel.UpdateBaseRate(Convert.ToDouble(amount), FixedDate.Value.Date, DefaultRate: true); // Replaces the existing base rate with a new value if the date matches. Also marks as default. return true; } } else { - Hotel.SetBaseRate(Convert.ToDouble(amount), (DateTime)FixedDate, true); + Hotel.SetBaseRate(Convert.ToDouble(amount), (DateTime)FixedDate, true); // Sets the base rate as the default. } Console.WriteLine($"A base rate of {amount} has been set and will take effect immediately."); @@ -816,7 +984,7 @@ internal class Program ": "); if (Console.ReadLine() == "YES") { - Hotel.UpdateBaseRate(Convert.ToDouble(amount), StartDate.Date); + Hotel.UpdateBaseRate(Convert.ToDouble(amount), StartDate.Date); // Replaces the existing base rate with a new value if the date matches. return true; } } @@ -828,7 +996,7 @@ internal class Program Console.Write("Please enter a valid date (2021-12-31): "); } - Hotel.SetBaseRate(Convert.ToDouble(amount), StartDate); + Hotel.SetBaseRate(Convert.ToDouble(amount), StartDate); // Sets the base rate as a future base rate. Console.WriteLine($"A base rate of {amount} has been set and will take effect on {DateTime.Now.Date.ToString("yyyy-MM-dd")}."); } return true; @@ -844,20 +1012,29 @@ internal class Program if (Hotel.GetBaseRate() == null) { + // This is for the specific case where there is no configured/ default rate. 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)) { } + while (!SetRatePrompt(DateTime.Now.Date)) { } // Continues to loop until a base rate is successfully configured. } else { Console.Write("What is the value of the rate you would like to set.\n" + "Enter new rate: "); - while (!SetRatePrompt()) { } + while (!SetRatePrompt()) { } // Continues to loop until a base rate is successfully configured. } } void CheckIn() { + /* + * Checks in a guest if they have an existing reservation that can be checked in. + * If not the function informs the employee that no reservation exists or no guest + * guest account could be found. This function will also assign the guest their room + * number or cancel their reservation if they attempt to check in after their start date + * as the policy calls for "no-shows" to be charged and therefore are canceled due to a + * no refund policy. Guests also cannot check in ahead of time, only on the day of. + */ string Email = GetGuestEmail(); TimeRefs? status = Hotel.CanBeCheckedIn(Email); Guest? g = Hotel.GetGuestByEmail(Email); @@ -901,6 +1078,12 @@ internal class Program } void CheckOut() { + /* + * Checks out a guest and charges them if they have an incentive or conventional reservation. + * For more details on how the data is manipulated, see Pay() and CheckOutGuest(). While + * there are null refs warnings here, they should never reach this point + * so we choose not to handle them. + */ string Email = GetGuestEmail(); if (Hotel.GuestCurrentlyCheckedIn(Email)) { @@ -921,6 +1104,12 @@ internal class Program } void NotifyOutstandingPayments() { + /* + * This function is used to notify any 60-day-in-advance reservation that they have a payment + * due. If the payment is past the number of days then the reservation is canceled. If the + * reservation is within the 30-45 day window then an email is sent out for a customer to + * pay through the payment system. For more details on how the email works, see the Email class. + */ List activeSixtyRes = Hotel.GetActiveSixtyDayRes(); foreach (Reservation r in activeSixtyRes) { @@ -935,14 +1124,35 @@ internal class Program e.Send(); } } - if (File.Exists("Emails.txt")) + if (File.Exists("Emails.txt") && activeSixtyRes.Count != 0) { FileInfo f = new("Emails.txt"); Console.WriteLine($"Emails have been written and appended to {f.FullName}"); + } else + { + Console.WriteLine("There are no emails to send."); } } void GenerateManagementReports() { + /* + * GenerateManagementReports is used to generate the following reports: + * + * - Expected Occupancy + * Reports the expected hotel occupancy and relies on GetExpectedOccupancyCount() + * for the data used in reporting. See CalculateExpectedOccupancy() for more details + * on the output. + * + * - Expected Income + * Reports the expected income for the hotel and relies on GetExpectedIncomeCount() + * for the data used in reporting. See CalculateExpectedIncome() for more details + * on the output. + * + * - Incentive Losses + * Reports the revenue lost as a result of providing incentives and relies on + * GetIncentiveTransactions() for the data used in reporting. See CalculateIncentiveLosses() + * for more details on the output. + */ var w = Hotel.GetExpectedOccupancyCount(); Management.CalculateExpectedOccupancy(w.Item2, w.Item1); if (File.Exists("ExpectedOccupancy.txt")) @@ -967,7 +1177,19 @@ internal class Program } void GenerateAccommodationBills() { + /* + * This generates a single report called accommodation bills. If there + * are no reservations there will be no accomodation bills to generate. + * The reservations are returned by GetDailyArrivals(). + */ List reservations = Hotel.GetDailyArrivals(); + + if (reservations.Count == 0) + { + Console.WriteLine($"No accommodation bills to generate."); + return; + } + Accommodation.GenerateAccommodationBills(reservations); if (File.Exists("AccommodationBills.txt")) @@ -978,23 +1200,53 @@ internal class Program } void GenerateOperationalReports() { + /* + * This generates two operational reports. The daily arrivals and the daily occupancy. + * The daily arrival report is generated based off list of reservations returned by + * GetDailyArrivals(). This is then passed off to the Operational reporting class + * where it writes out to DailyArrivals.txt. THe same applies to the daily occupancy + * however the GetDailyOccupancy() function is a litte more complex returning two lists, + * one with the occupancy for that day and one with rooms occupied the night before. + * If the file(s) are successfully written, the output is printed to the console for + * staff to find them. + */ List reservations = Hotel.GetDailyArrivals(); - Operational.FetchDailyArriavals(reservations); - if (File.Exists("DailyArrivals.txt")) + + if (reservations.Count == 0) { - FileInfo f = new("DailyArrivals.txt"); - Console.WriteLine($"Daily arrivals have been written and appended to {f.FullName}"); + Console.WriteLine($"No daily arrivals to report."); + } else + { + 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")) + + var x = Hotel.GetDailyOccupancy(); // Using var instead of explicity breaking out the tuple since it's simpler + if (x.Item1.Count == 0) { - FileInfo f = new("DailyOccupancy.txt"); - Console.WriteLine($"Daily occupancy has been written and appended to {f.FullName}"); + Console.WriteLine($"No daily occupancies to report."); + } else + { + 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}"); + } } } void IssuePenalties() { + /* + * Iterates over a list of reservations returned by GetPastDueReservations(), + * a function of the Hotel class. Since all the reservations returned are known + * to be past due, the cancellation function is called and the reservation is + * canceled and charged if applicable. + */ List reservations = Hotel.GetPastDueReservations(); foreach (Reservation reservation in reservations) { @@ -1009,28 +1261,74 @@ internal class Program "Command: "); while (true) { - + /* + * This is the main administrator loop. + * The following are valid operations: + * + * generate management report: + * Generates a series of report detailing the expected occupancy, expected room income, + * and the losses incurred due to incentive reservations. For more information see the + * GenerateManagementReport() function. + * + * generate operational report: + * Generates a series of reports detailing the daily arrivals and daily occupancy. + * For more information see the GenerateOperationalReports() function. + * + * generate accommodation bills: + * Generates the accommodation bills for reservations arriving that day. These will + * be handed out upon checkout (No process for this since there is no printer + * connected to this application). For more information see the GenerateAccommodationBills() + * function. + * + * notify pending payments: + * Generates an email for any outstanding payments within the payment window for + * 60-day-in-advance reservations. For more information see the NotifyOutstandingPayments() + * function. + * + * issue penalties: + * Issues penalties to reservations that end up as "no-show". Furthermore, it will + * also charge them if applicable. This is mostly just to pick up any reservations + * that are not canceled by users or canceled as a result of attempting to checkin + * or pay for a reservation that would be market as "no-show". For more information + * see the IssuePenalties() function. + * + * checkin guest: + * Checks in the guest and assigns them a room number. For more information see the + * CheckIn() function. + * + * checkout guest: + * Checks a guest out and marks their reservation as ended. The room number is + * not removed for historical purposes. For more information see the CheckOut() + * function. + * + * set rate: + * Set rate allows employees to set a specific rate for a specific day. This + * rate takes effect on the date set. For more information see the SetFutureBaseRate() + * function. + * + * Q or Q: + * Returns to the main loop for choosing either the Guest or Admin flow. + */ 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": IssuePenalties(); break; - case "checkin guest": CheckIn(); break; - case "checkout guest": CheckOut(); break; - case "set rate": SetFutureBaseRate(); break; - case "Q": return; - case "q": return; + case "help": help(); break; // Gets help text + case "generate management report": GenerateManagementReports(); break; // Generates management reports and outputs to text files + case "generate operational report": GenerateOperationalReports(); break; // Generates operational reports and outputs to text files + case "generate accommodation bills": GenerateAccommodationBills(); break; // Generates accommodation bills and outputs to a text file + case "notify pending payments": NotifyOutstandingPayments(); break; // Generates an email and outputs to a text file + case "issue penalties": IssuePenalties(); break; // Cancels "no-show" reservations and charges their accounts + case "checkin guest": CheckIn(); break; // Checks a guest in and assigns a room + case "checkout guest": CheckOut(); break; // Checks out a guest and marks their reservation as ended + case "set rate": SetFutureBaseRate(); break; // Allows employees to configure base rates + case "Q": return; // Quit to mode loop + case "q": return; // Quit to mode loop 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)