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 PaymentStatus Pay(double Amount, string cc) { if (string.IsNullOrEmpty(cc)) { return PaymentStatus.MissingCreditCard; } if (Amount >= Owed) { return PaymentStatus.AlreadyPaid; } if (Amount <= 0) { return PaymentStatus.AmountCannotZero; } 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(); return PaymentStatus.SuccessfulPayment; } 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 enum PaymentStatus { SuccessfulPayment, AlreadyPaid, FailedPayment, AmountCannotZero, MissingCreditCard } }