public static ReservationStateArgs Create(IReservationItem rsv, ReservationClient client, DateTime now) { var isAuthorized = client.IsAuthorized(rsv); var args = new ReservationStateArgs(rsv.ReservationID, client.InLab, client.IsReserver, client.IsInvited, isAuthorized, !rsv.Editable, rsv.IsFacilityDownTime, rsv.MinCancelTime, rsv.MinReservTime, rsv.BeginDateTime, rsv.EndDateTime, rsv.ActualBeginDateTime, rsv.ActualEndDateTime, client.UserAuth); return(args); }
public bool HandlePracticeReservation(IReservationItem rsv, IEnumerable <Invitee> invitees, int modifiedByClientId) { // 2009-09-16 Practice reservation : we must also check if tool engineers want to receive the notify email if (IsPracticeActivity(rsv.ActivityID)) { Invitee invitee = null; if (invitees != null) { invitee = invitees.FirstOrDefault(); } if (invitee == null) { throw new InvalidOperationException("A practice reservation must have at least one invitee."); } Provider.Scheduler.Email.EmailOnPracticeRes(rsv.ReservationID, invitee.DisplayName, modifiedByClientId); return(true); } else { return(false); } }
public ReservationClient GetReservationClient(IReservationItem rsv, IClient client, IEnumerable <IResourceClient> resourceClients, IEnumerable <IReservationInviteeItem> invitees) { var physicalAccessUtil = GetPhysicalAccessUtility(); var inlab = physicalAccessUtil.ClientInLab(client.ClientID, rsv.LabID); return(ReservationClient.Create(rsv, client, resourceClients, invitees, inlab)); }
public bool HandleFacilityDowntimeReservation(IReservationItem rsv, int modifiedByClientId) { // 2009-06-21 If it's Facility downtime, we must delete the reservations that has been made during that period if (IsFacilityDownTimeActivity(rsv.ActivityID)) { // Find and Remove any un-started reservations made during time of repair var query = Provider.Scheduler.Reservation.SelectByResource(rsv.ResourceID, rsv.BeginDateTime, rsv.EndDateTime, false); foreach (var existing in query) { // Only if the reservation has not begun if (existing.ActualBeginDateTime == null) { Provider.Scheduler.Reservation.CancelAndForgive(existing.ReservationID, "Cancelled and forgiven for facility down time.", modifiedByClientId); Provider.Scheduler.Email.EmailOnCanceledByRepair(existing.ReservationID, true, $"{SendEmail.CompanyName} Facility Down", "Facility is down, thus we have to disable the tool.", rsv.EndDateTime, modifiedByClientId); } else { // We have to disable all those reservations that have been activated by setting IsActive to 0. // The catch here is that we must compare the "Actual" usage time with the repair time because if the user ends the reservation before the repair starts, we still // have to charge the user for that reservation } } return(true); } else { return(false); } }
public ReservationModel(SchedulerContextHelper helper, DateTime now) { Helper = helper; Now = now; int reservationId = helper.GetReservationID(); if (reservationId > 0) { IReservationItem rsv = helper.Provider.Scheduler.Reservation.GetReservation(reservationId); var res = helper.Provider.Scheduler.Resource.GetResource(rsv.ResourceID); Reservation = rsv; ActivityID = rsv.ActivityID; AccountID = rsv.AccountID; RecurrenceID = rsv.RecurrenceID; Notes = rsv.Notes; AutoEnd = rsv.ReservationAutoEnd; KeepAlive = rsv.KeepAlive; Resource = res; } if (Resource == null) { var resourceId = helper.Context.Request.SelectedPath().ResourceID; Resource = helper.Provider.Scheduler.Resource.GetResource(resourceId); } }
public bool IsBeforeForgiveCutoff(IReservationItem rsv, DateTime now, int maxForgivenDay, IEnumerable <IHoliday> holidays) { // Normal lab users cannot forgive reservations // Staff can forgive a reservation on the same day it ended, and during the following 3 three business days // Admins can always forgive reservations DateTime maxDay = rsv.ActualBeginDateTime.GetValueOrDefault(rsv.EndDateTime); return(IsBeforeForgiveCutoff(now, maxDay, maxForgivenDay, rsv.Editable, holidays)); }
public bool ReservationNotesCanBeChanged(IClient client, IReservationItem rsv) { // staff can always change notes if (client.HasPriv(ClientPrivilege.Staff | ClientPrivilege.Administrator | ClientPrivilege.Developer)) { return(true); } // otherwise notes can be changed by the reserver return(client.ClientID == rsv.ClientID); }
public static bool CreateForModification(IReservationItem rsv, ReservationDuration rd) { // if Time And Duration modified create new reservation else change existing if (rsv.BeginDateTime != rd.BeginDateTime || rsv.Duration != rd.Duration.TotalMinutes) { return(true); } else { return(false); } }
public void End(IReservationItem rsv, DateTime actualEndDateTime, int?endedByClientId) { if (rsv == null) { throw new ArgumentNullException($"The argument rsv cannot be null."); } // Make sure this reservation hasn't already been ended some how // [2016-01-21 jg] Allow FacilityDownTime because they already have ActualEndDateTime set if (rsv.ActualEndDateTime != null && !rsv.IsFacilityDownTime) { return; } // must set these for future use rsv.ActualEndDateTime = actualEndDateTime; rsv.ClientIDEnd = endedByClientId.GetValueOrDefault(-1); // End reservation Provider.Scheduler.Reservation.EndReservation(new EndReservationArgs { ReservationID = rsv.ReservationID, ActualEndDateTime = actualEndDateTime, EndedByClientID = endedByClientId.GetValueOrDefault(-1) }); // Turn Interlock Off if (CacheManager.Current.WagoEnabled) { WagoInterlock.ToggleInterlock(rsv.ResourceID, false, 0); } // Check for other open reservation slots between now and the reservation fence DateTime?nextBeginDateTime = OpenResSlot(rsv.ResourceID, TimeSpan.FromMinutes(rsv.ReservFence), TimeSpan.FromMinutes(rsv.MinReservTime), rsv.EndDateTime); if (nextBeginDateTime == null) { return; } // Get the next reservation start time DateTime currentEndDateTime = rsv.GetNextGranularity(actualEndDateTime, GranularityDirection.Previous); // Send email notifications to all clients who want to be notified of open reservation slots Provider.Scheduler.Email.EmailOnOpenSlot(rsv.ReservationID, currentEndDateTime, nextBeginDateTime.Value, EmailNotify.Always, endedByClientId.GetValueOrDefault(-1)); if (nextBeginDateTime.Value.Subtract(currentEndDateTime).TotalMinutes >= rsv.MinReservTime) { Provider.Scheduler.Email.EmailOnOpenSlot(rsv.ReservationID, currentEndDateTime, nextBeginDateTime.Value, EmailNotify.OnOpening, endedByClientId.GetValueOrDefault(-1)); } }
private ReservationStateArgs GetReservationStateArgs(IReservationItem rsv, int currentUserClientId, int inviteeClientId, bool inlab, DateTime now) { IClient client = Provider.Data.Client.GetClient(currentUserClientId); IEnumerable <IResourceClient> resourceClients = Provider.Scheduler.Resource.GetResourceClients(rsv.ResourceID); IEnumerable <IReservationInviteeItem> invitees = new[] { GetMockReservationInvitee(inviteeClientId, rsv.ReservationID) }; ReservationClient rc = Helper.GetReservationClient(rsv, client, resourceClients, invitees); rc.InLab = inlab; ReservationStateArgs result = ReservationStateArgs.Create(rsv, rc, now); return(result); }
public bool IsBeforeChangeAccountCutoff(IReservationItem rsv, DateTime now, IEnumerable <IHoliday> holidays) { // Normal lab users can modify their own reservation's account on the same day it ended through 3 business days after the 1st of the following month // Staff can modify any reservation's account on the same day it ended through 3 business days after the 1st of the following month // Admins can always modify a reservation's account DateTime maxDay = rsv.ActualBeginDateTime.GetValueOrDefault(rsv.EndDateTime); // need to see if current date is between maxDay and next period business day cutoff var d = maxDay.AddMonths(1).FirstOfMonth(); DateTime cutoff = Utility.NextBusinessDay(d, holidays); return(now >= maxDay && now < cutoff && rsv.Editable); }
public bool ReservationCanBeForgiven(IClient client, IReservationItem rsv, DateTime now, int maxForgivenDay, IEnumerable <IHoliday> holidays) { // first, only admins and staff can possibly forgive if (!client.HasPriv(ClientPrivilege.Administrator | ClientPrivilege.Staff | ClientPrivilege.Developer)) { return(false); } // always let admins forgive even after business day cutoff if (client.HasPriv(ClientPrivilege.Administrator | ClientPrivilege.Developer)) { return(true); } return(IsBeforeForgiveCutoff(rsv, now, maxForgivenDay, holidays)); }
public bool ReservationAccountCanBeChanged(IClient client, IReservationItem rsv, DateTime now, IEnumerable <IHoliday> holidays) { // admins can always change the account if (client.HasPriv(ClientPrivilege.Administrator | ClientPrivilege.Developer)) { return(true); } // reserver and staff can before 3rd business day of next period if (client.HasPriv(ClientPrivilege.Staff) || client.ClientID == rsv.ClientID) { return(IsBeforeChangeAccountCutoff(rsv, now, holidays)); } return(false); }
public IReservationItem ModifyReservation(IReservationItem rsv, ReservationData data) { IReservationItem result; bool insert = false; if (IsFacilityDownTimeActivity(rsv.ActivityID)) { result = Provider.Scheduler.Reservation.UpdateFacilityDownTime(rsv.ReservationID, data.Duration.BeginDateTime, data.Duration.EndDateTime, data.ClientID); HandleFacilityDowntimeReservation(result, data.ClientID); } else { if (CreateForModification(rsv, data.Duration)) { var args = GetInsertReservationArgs(data, rsv.ReservationID); Provider.Scheduler.Reservation.CancelReservation(rsv.ReservationID, string.Empty, args.ModifiedByClientID); result = Provider.Scheduler.Reservation.InsertForModification(args); Provider.Scheduler.Reservation.AppendNotes(rsv.ReservationID, $"Cancelled for modification. New ReservationID: {result.ReservationID}"); insert = true; } else { // at this point data does not Contain var args = GetUpdateReservationArgs(data, rsv.ReservationID); result = Provider.Scheduler.Reservation.UpdateReservation(args); } HandlePracticeReservation(result, data.Invitees, data.ClientID); } if (insert) { InsertReservationInvitees(result.ReservationID, data.Invitees); InsertReservationProcessInfos(result.ReservationID, data.ProcessInfos); } else { UpdateReservationInvitees(data.Invitees); UpdateReservationProcessInfos(data.ProcessInfos); } Provider.Scheduler.Email.EmailOnUserUpdate(result.ReservationID, data.ClientID); Provider.Scheduler.Email.EmailOnInvited(result.ReservationID, data.Invitees, data.ClientID, ReservationModificationType.Modified); Provider.Scheduler.Email.EmailOnUninvited(rsv.ReservationID, data.Invitees, data.ClientID); return(result); }
public ReservationClient GetReservationClient(IReservationItem rsv, IEnumerable <IReservationInviteeItem> invitees, IClient client) { var resourceClients = Provider.Scheduler.Reservation.GetResourceClients(rsv.ResourceID); var userAuth = Reservations.GetAuthLevel(resourceClients, client); var result = new ReservationClient { ClientID = client.ClientID, ReservationID = rsv.ReservationID, ResourceID = rsv.ResourceID, IsReserver = rsv.ClientID == client.ClientID, IsInvited = invitees.Any(x => x.InviteeID == client.ClientID), InLab = ClientInLab(rsv.LabID), UserAuth = userAuth }; return(result); }
public static ReservationClient Create(IReservationItem rsv, IClient client, IEnumerable <IResourceClient> resourceClients, IEnumerable <IReservationInviteeItem> invitees, bool inlab) { var userAuth = Reservations.GetAuthLevel(resourceClients, client); var isReserver = rsv.ClientID == client.ClientID; var isInvited = invitees.Any(x => x.InviteeID == client.ClientID); var result = new ReservationClient { ClientID = client.ClientID, ReservationID = rsv.ReservationID, ResourceID = rsv.ResourceID, IsReserver = isReserver, IsInvited = isInvited, InLab = inlab, UserAuth = userAuth }; return(result); }
private void ReservationStateTester(int resourceId, int reserverClientId, int currentClientId, int inviteeClientId, int activityId, DateTime beginDateTime, int duration, bool inlab, bool canDelete, bool canModify) { var now = DateTime.Now; DateTime endDateTime = beginDateTime.AddMinutes(duration); IReservationItem rsv = GetMockReservation(123456, resourceId, reserverClientId, activityId, beginDateTime, endDateTime, null, null); ReservationStateArgs args = GetReservationStateArgs(rsv, currentClientId, inviteeClientId, inlab, now); ReservationState state = ReservationStateUtility.Create(now).GetReservationState(args); bool actual; actual = SchedulerUtility.CanDeleteReservation(state, args, now); Assert.AreEqual(canDelete, actual); actual = SchedulerUtility.CanModifyReservation(state, args, now); Assert.AreEqual(canModify, actual); }
private static ReservationDateRangeItem CreateReservation(IReservationItem rsv, IEnumerable <ICost> costs) { var filtered = costs.Where(c => (c.RecordID == rsv.ResourceID || c.RecordID == 0) && c.ChargeTypeID == rsv.ChargeTypeID).ToList(); IResourceCost rc = ResourceCost.CreateResourceCosts(filtered).FirstOrDefault(); if (rc == null) { throw new Exception($"Cannot determine cost for Resource: [{rsv.ResourceID}] {rsv.ResourceName}"); } return(new ReservationDateRangeItem() { ReservationID = rsv.ReservationID, ResourceID = rsv.ResourceID, ResourceName = rsv.ResourceName, ProcessTechID = rsv.ProcessTechID, ProcessTechName = rsv.ProcessTechName, ClientID = rsv.ClientID, UserName = rsv.UserName, LName = rsv.LName, FName = rsv.FName, ActivityID = rsv.ActivityID, ActivityName = rsv.ActivityName, AccountID = rsv.AccountID, AccountName = rsv.AccountName, ShortCode = rsv.ShortCode, ChargeTypeID = rsv.ChargeTypeID, IsActive = rsv.IsActive, IsStarted = rsv.IsStarted, BeginDateTime = rsv.BeginDateTime, EndDateTime = rsv.EndDateTime, ActualBeginDateTime = rsv.ActualBeginDateTime, ActualEndDateTime = rsv.ActualEndDateTime, ChargeBeginDateTime = rsv.ChargeBeginDateTime, ChargeEndDateTime = rsv.ChargeEndDateTime, LastModifiedOn = rsv.LastModifiedOn, IsCancelledBeforeCutoff = rsv.IsCancelledBeforeCutoff, ChargeMultiplier = rsv.ChargeMultiplier, Cost = rc }); }
public void Delete(IReservationItem rsv, int?modifiedByClientId) { Provider.Scheduler.Reservation.CancelReservation(rsv.ReservationID, string.Empty, modifiedByClientId); // Send email to reserver and invitees var invitees = ReservationInvitees.Create(Provider).SelectInvitees(rsv.ReservationID); Provider.Scheduler.Email.EmailOnUserDelete(rsv.ReservationID, modifiedByClientId.GetValueOrDefault()); Provider.Scheduler.Email.EmailOnUninvited(rsv.ReservationID, invitees, modifiedByClientId.GetValueOrDefault()); // Send email notifications to all clients want to be notified of open reservation slots Provider.Scheduler.Email.EmailOnOpenSlot(rsv.ReservationID, rsv.BeginDateTime, rsv.EndDateTime, EmailNotify.Always, modifiedByClientId.GetValueOrDefault()); // Check for other open reservation slots between now and the reservation fence and Get the next reservation start time DateTime?nextBeginDateTime = OpenResSlot(rsv.ResourceID, TimeSpan.FromMinutes(rsv.ReservFence), TimeSpan.FromMinutes(rsv.MinReservTime), rsv.EndDateTime); if (nextBeginDateTime.HasValue) { Provider.Scheduler.Email.EmailOnOpenSlot(rsv.ReservationID, rsv.BeginDateTime, nextBeginDateTime.Value, EmailNotify.OnOpening, modifiedByClientId.GetValueOrDefault()); } }
/// <summary> /// Checks for all reservations affected by the repair and either cancels or deletes them (depending of if they are started or not), and then forgives them. /// </summary> /// <param name="repair">The repair reservation.</param> private bool UpdateAffectedReservations(IReservationItem repair) { // Might be null when resource state is Limited if (repair == null) { return(false); } // Find and end reservations that are in progress (Endable) for this resource var endableReservations = Provider.Scheduler.Reservation.SelectEndableReservations(repair.ResourceID); foreach (var endable in endableReservations.Where(x => x.ReservationID != repair.ReservationID)) { Provider.Scheduler.Reservation.EndAndForgiveForRepair(endable.ReservationID, "Ended and forgiven for repair.", CurrentUser.ClientID, CurrentUser.ClientID); Provider.Scheduler.Email.EmailOnCanceledByRepair(endable.ReservationID, false, "Offline", repair.Notes, repair.EndDateTime, CurrentUser.ClientID); Provider.Scheduler.Email.EmailOnForgiveCharge(endable.ReservationID, 100, true, CurrentUser.ClientID); } // Find and remove any unstarted reservations made during time of repair var unstartedReservations = Provider.Scheduler.Reservation.SelectUnstarted(repair.ResourceID, repair.BeginDateTime, repair.EndDateTime); foreach (var unstarted in unstartedReservations) { Provider.Scheduler.Reservation.CancelReservation(unstarted.ReservationID, "Cancelled and forgiven for repair.", CurrentUser.ClientID); Provider.Scheduler.Email.EmailOnCanceledByRepair(unstarted.ReservationID, true, "Offline", repair.Notes, repair.EndDateTime, CurrentUser.ClientID); // Don't send forgiveness email yet, this will happen below... } // 2009-05-21 Make the old reservations that were covered by the repair to be forgiven // Get all the past active reservations that were covered by this specific repair period // [2013-05-20 jg] We also need cancelled reservations so booking fee is forgiven // [2017-08-24 jg] Changing to beginDateTime and endDateTime so that any existing reservations in the entire repair range are forgiven. // The previous date range only covered reservations scheduled to start between the actualBeginDateTime (the time the repair began // without going to the previous granularity) and the current time. The range is now between the repair begin (to previous granularity) // to repair end (to next granularity). // [2018-08-31 jg] This is now just a catch all. Nothing will happen if the reservation is already 100% forgiven. // Overlapping reservations (started and unstarted) are forgiven above and an email is sent. This will catch // unstarted overlapping reservations where IsActive == true and ActualBeginDateTime.HasValue == true, or // IsActive == false since these are skipped above. var query = Provider.Scheduler.Reservation.SelectHistoryToForgiveForRepair(repair.ResourceID, repair.BeginDateTime, repair.EndDateTime); var result = false; foreach (var rsv in query) { // Avoid resending the email if the reservation was already forgiven if (rsv.ChargeMultiplier > 0) { // Set charge multiplier to zero, notes have already been appended Provider.Scheduler.Reservation.UpdateCharges(rsv.ReservationID, string.Empty, 0, true, CurrentUser.ClientID); // Email User after everything is done. Provider.Scheduler.Email.EmailOnForgiveCharge(rsv.ReservationID, 100, true, CurrentUser.ClientID); // The session variable is set now and then checked for on the next page load. result = true; } } // Update forgiven charge on FinOps. Enqueue an UpdateBilling request. This will // return immediately and the update will process in the background using OnlineServicesWorker. DateTime sd = repair.BeginDateTime.FirstOfMonth(); Provider.Worker.Execute(new UpdateBillingWorkerRequest(sd, 0, new[] { "tool", "room" })); return(result); }
public ReservationClient GetReservationClient(IReservationItem rsv, IClient client, IEnumerable <IResourceClient> resourceClients) { var invitees = Provider.Scheduler.Reservation.GetInvitees(rsv.ReservationID); return(GetReservationClient(rsv, client, resourceClients, invitees)); }
public ReservationClient GetReservationClient(IReservationItem rsv, IClient client) { var resourceClients = Provider.Scheduler.Reservation.GetResourceClients(rsv.ResourceID); return(GetReservationClient(rsv, client, resourceClients)); }
public ReservationClient GetReservationClient(IReservationItem rsv) => GetReservationClient(rsv, CurrentUser());
public bool IsAuthorized(IReservationItem rsv) => (UserAuth & rsv.StartEndAuth) > 0;
public ReservationClient GetReservationClient(IReservationItem rsv, IEnumerable <IReservationInviteeItem> invitees) => GetReservationClient(rsv, CurrentUser());
public SaveReservationHistoryResult SaveReservationHistory(IReservationItem rsv, int accountId, double?forgivenPct, string notes, bool emailClient, int modifiedByClientId) { throw new NotImplementedException(); }
public static bool IsRunning(this IReservationItem item) { return(item.ActualBeginDateTime != null && item.ActualEndDateTime == null); }
public IEnumerable <IClientAccount> AvailableAccounts(IReservationItem rsv) { throw new NotImplementedException(); }
public IAutoEndLog AddAutoEndLog(IReservationItem rsv, string action) { throw new NotImplementedException(); }
public static StartReservationItem CreateStartReservationItem(HttpContextBase context, IProvider provider, IReservationItem rsv) { var now = DateTime.Now; var item = new StartReservationItem { ReservationID = rsv.ReservationID, ResourceID = rsv.ResourceID, ResourceName = rsv.ResourceName, ReservedByClientID = rsv.ClientID, ReservedByClientName = string.Format("{0} {1}", rsv.FName, rsv.LName) }; var currentUser = context.CurrentUser(provider); if (rsv.ClientIDBegin.HasValue) { if (rsv.ClientIDBegin.Value > 0) { IClient startedBy = provider.Data.Client.GetClient(rsv.ClientIDBegin.Value); item.StartedByClientID = startedBy.ClientID; item.StartedByClientName = string.Format("{0} {1}", startedBy.FName, startedBy.LName); } else { item.StartedByClientID = 0; item.StartedByClientName = string.Empty; } } else { item.StartedByClientID = currentUser.ClientID; item.StartedByClientName = string.Format("{0} {1}", currentUser.FName, currentUser.LName); } var reservationItem = provider.Scheduler.Reservation.GetReservationWithInvitees(rsv.ReservationID); var helper = new SchedulerContextHelper(context, provider); var args = ReservationStateArgs.Create(reservationItem, helper.GetReservationClient(reservationItem), now); var stateUtil = ReservationStateUtility.Create(now); ReservationState state = stateUtil.GetReservationState(args); item.Startable = stateUtil.IsStartable(state); item.NotStartableMessage = GetNotStartableMessage(state); var inst = ActionInstances.Find(ActionType.Interlock, rsv.ResourceID); item.HasInterlock = inst != null; var res = provider.Scheduler.Resource.GetResource(rsv.ResourceID); item.ReturnUrl = GetResourceUrl(context, res); return(item); }