/// <summary> /// Update earned gratuities for users to ensure that the expiration dates, etc., are correct. /// </summary> /// <param name="szUser">The user for whom gratuities should be updated; null or empty for all users</param> /// <param name="fResetReminders">True to reset reminders to 0 (i.e., no reminders sent)</param> public static void UpdateEarnedGratuities(string szUser, bool fResetReminders) { if (String.IsNullOrEmpty(szUser)) { return; } Dictionary <string, Collection <Payment> > dictPayments = PaymentListsForUser(szUser); ReadOnlyCollection <Gratuity> lstKnownGratuities = Gratuity.KnownGratuities; List <EarnedGrauity> lstUpdatedGratuityList = new List <EarnedGrauity>(); ResetSessionForGratuities(szUser); // Go through each user's payment history (could be just the one user) and determine their gratuities. foreach (string szKey in dictPayments.Keys) { List <Payment> lstPayments = new List <Payment>(dictPayments[szKey]); CompressPaymentsForUser(lstPayments); // OK, payments should be compacted - go through them and apply the gratuities foreach (Payment p in lstPayments) { // Now process the payment: // Enumerate each known gratuity and, if this qualifies for the gratuity, create/extend the gratuity. foreach (Gratuity g in lstKnownGratuities) { // see if this payment + priors qualifies if (Payment.PaymentsInDateRange(p.Timestamp.Subtract(g.Window).Date, p.Timestamp.Date, lstPayments) >= g.Threshold) { // Find the existing gratuity, if any, for the user // Add it to the list to update if we either have a new one, or if we have extended the epxiration EarnedGrauity eg = lstUpdatedGratuityList.Find(eg2 => (eg2.GratuityType == g.GratuityType && eg2.Username == p.Username)); if (eg == null) { eg = new EarnedGrauity(g, p); lstUpdatedGratuityList.Add(eg); } else { eg.ExtendExpiration(p, fResetReminders); // don't extend expiration for new earned gratuities; correct date is already set above. } eg.EarnedDate = p.Timestamp.LaterDate(eg.EarnedDate); g.GratuityWasEarned(eg); // take any action that is appropriate for the gratuity now that it is earned. } } } } // We now have a list of gratuities that should be correct List <EarnedGrauity> lstExistingEarnedGratuities = EarnedGrauity.GratuitiesForUser(szUser, Gratuity.GratuityTypes.Unknown); foreach (EarnedGrauity eg in lstUpdatedGratuityList) { // if this exists as an existing earned gratuity, update the expiration date on that one and save it OR if reseting EarnedGrauity egExisting = lstExistingEarnedGratuities.Find(eg2 => (eg2.GratuityType == eg.GratuityType && eg2.Username == eg.Username)); if (egExisting == null) // not found - this one is new { eg.Commit(); } else { int prevReminderCount = egExisting.ReminderCount; if (fResetReminders) { egExisting.ReminderCount = 0; } egExisting.ExpirationDate = eg.ExpirationDate; // Only save to database if expiration date or reminders changed if (eg.ReminderCount != egExisting.ReminderCount || egExisting.ReminderCount != prevReminderCount || eg.ExpirationDate.CompareTo(egExisting.ExpirationDate) != 0 || eg.EarnedDate.CompareTo(egExisting.EarnedDate) != 0) { egExisting.Commit(); } lstExistingEarnedGratuities.Remove(egExisting); } } // Anything that is left is no longer found (e.g., if a payment was deleted) // Shouldn't happen, but clean up just in case foreach (EarnedGrauity eg in lstExistingEarnedGratuities) { eg.Delete(); } }