Exemple #1
0
        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 ReservationState GetUnstartedReservationState(ReservationStateArgs args)
        {
            bool isInLab               = false;
            bool isReserver            = false;
            bool isInvited             = false;
            bool isAuthorized          = false;
            bool isBeforeMinCancelTime = args.IsBeforeMinCancelTime(Now);
            bool isStartable           = args.IsStartable(Now);

            if (!args.IsToolEngineer)
            {
                isInLab      = args.IsInLab;
                isReserver   = args.IsReserver;
                isInvited    = args.IsInvited;
                isAuthorized = args.IsAuthorized;
            }

            var subStateValue = GetSubStateVal(isInLab, isReserver, isInvited, isAuthorized, isBeforeMinCancelTime, isStartable);

            var result = (args.IsToolEngineer)
                ? TruthTableTE[subStateValue]
                : TruthTable[subStateValue];

            bool throwErrorOnUndefined = false;

            if (throwErrorOnUndefined && result == ReservationState.Undefined)
            {
                var errmsg = "Unstarted reservation state is undefined."
                             + " ReservationID: {0}, IsToolEngineer: {1}, IsInLab: {2}, IsReserver: {3}, IsInvited: {4}, IsAuthorized: {5}, IsBeforeMinCancelTime: {6}, IsStartable: {7}, SubStateValue: {8}";

                throw new Exception(string.Format(errmsg,
                                                  args.ReservationID,
                                                  args.IsToolEngineer ? "Yes" : "No",
                                                  isInLab ? "Yes" : "No",
                                                  isReserver ? "Yes" : "No",
                                                  isInvited ? "Yes" : "No",
                                                  isAuthorized ? "Yes" : "No",
                                                  isBeforeMinCancelTime ? "Yes" : "No",
                                                  isStartable ? "Yes" : "No",
                                                  subStateValue));
            }

            return(result);
        }
        // This is the truth table for non tool engineer
        // note that having both R and I true is meaningless
        // L - IsInLab
        // R - IsReserver
        // I - IsInvited
        // A - IsAuth
        // M - Before MCT
        // S - In Start Per

        // L  R  I  A  M  S
        // 0  0  0  0  0  0  ReservationState.Other         [00]
        // 0  0  0  0  0  1  ReservationState.Other         [01]
        // 0  0  0  0  1  0  ReservationState.Other         [02]
        // 0  0  0  0  1  1  ReservationState.Other         [03]
        // 0  0  0  1  0  0  ReservationState.Other         [04]
        // 0  0  0  1  0  1  ReservationState.Other         [05]
        // 0  0  0  1  1  0  ReservationState.Other         [06]
        // 0  0  0  1  1  1  ReservationState.Other         [07]
        // 0  0  1  0  0  0  ReservationState.Invited       [08]
        // 0  0  1  0  0  1  ReservationState.Invited       [09]
        // 0  0  1  0  1  0  ReservationState.Invited       [10]
        // 0  0  1  0  1  1  ReservationState.Invited       [11]
        // 0  0  1  1  0  0  ReservationState.Invited       [12]
        // 0  0  1  1  0  1  ReservationState.NotInLab      [13]
        // 0  0  1  1  1  0  ReservationState.Invited       [14]
        // 0  0  1  1  1  1  ReservationState.NotInLab      [15]
        // 0  1  0  0  0  0  ReservationState.Undefined     [16]
        // 0  1  0  0  0  1  ReservationState.UnAuthToStart [17]
        // 0  1  0  0  1  0  ReservationState.Editable      [18]
        // 0  1  0  0  1  1  ReservationState.Editable      [19]
        // 0  1  0  1  0  0  ReservationState.Undefined     [20]
        // 0  1  0  1  0  1  ReservationState.NotInLab      [21]
        // 0  1  0  1  1  0  ReservationState.Editable      [22]
        // 0  1  0  1  1  1  ReservationState.Editable      [23]
        // 0  1  1  0  0  0  ReservationState.Undefined     [24]
        // 0  1  1  0  0  1  ReservationState.Undefined     [25]
        // 0  1  1  0  1  0  ReservationState.Undefined     [26]
        // 0  1  1  0  1  1  ReservationState.Undefined     [27]
        // 0  1  1  1  0  0  ReservationState.Undefined     [28]
        // 0  1  1  1  0  1  ReservationState.Undefined     [29]
        // 0  1  1  1  1  0  ReservationState.Undefined     [30]
        // 0  1  1  1  1  1  ReservationState.Undefined     [31]
        // 1  0  0  0  0  0  ReservationState.Other         [32]
        // 1  0  0  0  0  1  ReservationState.Other         [33]
        // 1  0  0  0  1  0  ReservationState.Other         [34]
        // 1  0  0  0  1  1  ReservationState.Other         [35]
        // 1  0  0  1  0  0  ReservationState.Other         [36]
        // 1  0  0  1  0  1  ReservationState.Other         [37]
        // 1  0  0  1  1  0  ReservationState.Other         [38]
        // 1  0  0  1  1  1  ReservationState.Other         [39]
        // 1  0  1  0  0  0  ReservationState.Invited       [40]
        // 1  0  1  0  0  1  ReservationState.Invited       [41]
        // 1  0  1  0  1  0  ReservationState.Invited       [42]
        // 1  0  1  0  1  1  ReservationState.Invited       [43]
        // 1  0  1  1  0  0  ReservationState.Invited       [44]
        // 1  0  1  1  0  1  ReservationState.StartOnly     [45]
        // 1  0  1  1  1  0  ReservationState.Invited       [46]
        // 1  0  1  1  1  1  ReservationState.StartOrDelete [47] [2020-10-08 jg] changed from StartOnly to StartOrDelete so invitee can cancel reservation
        // 1  1  0  0  0  0  ReservationState.Undefined     [48]
        // 1  1  0  0  0  1  ReservationState.UnAuthToStart [49]
        // 1  1  0  0  1  0  ReservationState.Editable      [50]
        // 1  1  0  0  1  1  ReservationState.Editable      [51]
        // 1  1  0  1  0  0  ReservationState.Undefined     [52]
        // 1  1  0  1  0  1  ReservationState.StartOnly     [53]
        // 1  1  0  1  1  0  ReservationState.Editable      [54]
        // 1  1  0  1  1  1  ReservationState.StartOrDelete [55]
        // 1  1  1  0  0  0  ReservationState.Undefined     [56]
        // 1  1  1  0  0  1  ReservationState.Undefined     [57]
        // 1  1  1  0  1  0  ReservationState.Undefined     [58]
        // 1  1  1  0  1  1  ReservationState.Undefined     [59]
        // 1  1  1  1  0  0  ReservationState.Undefined     [60]
        // 1  1  1  1  0  1  ReservationState.Undefined     [61]
        // 1  1  1  1  1  0  ReservationState.Undefined     [62]
        // 1  1  1  1  1  1  ReservationState.Undefined     [63]
        // L  R  I  A  M  S

        // The truth table for tool engineers is simply this
        // for TE, MCT=0, so both M and S cannot both be false
        // L  R  I  A  M  S
        // x  x  x  x  0  0  ReservationState.Undefined
        // x  x  x  x  0  1  ReservationState.StartOnly
        // x  x  x  x  1  0  ReservationState.Editable
        // x  x  x  x  1  1  ReservationState.StartOrDelete

        // Note that the four cases in which the res can be started are modified by IsInLab.
        // if this is false, the state changes as shown above
        #endregion

        public ReservationState GetReservationState(ReservationStateArgs args)
        {
            // Repair Reservations, returns immediately
            // 2008-08-15 temp (return Meeting if ReservationID is -1)
            if (args.IsRepair)
            {
                return(args.ReservationID == -1
                    ? ReservationState.Meeting
                    : ReservationState.Repair);
            }

            if (args.ActualBeginDateTime == null && args.ActualEndDateTime == null)
            {
                // reservations that have not yet been started
                if (args.EndDateTime <= Now) // should never occur - if in the past, the actuals should exist
                {
                    if (args.IsReserver)
                    {
                        return(ReservationState.PastSelf);
                    }
                    else
                    {
                        return(ReservationState.PastOther);
                    }
                }

                // redefine min cancel time (MCT) for tool engineers - can edit up until scheduled start time
                return(GetUnstartedReservationState(args));
            }
            else if (args.ActualBeginDateTime != null && args.ActualEndDateTime == null)
            {
                // reservations that have been started
                if (args.IsReserver || args.IsToolEngineer)
                {
                    return(ReservationState.Endable);
                }
                else if (args.IsInvited)
                {
                    if (args.UserAuth != ClientAuthLevel.UnauthorizedUser && args.UserAuth != ClientAuthLevel.RemoteUser)
                    {
                        //2008-06-26 Sandrine requested that invitee should be able to end the reservation
                        return(ReservationState.Endable);
                    }
                    else
                    {
                        return(ReservationState.Invited);
                    }
                }
                else
                {
                    return(ReservationState.ActiveNotEndable);
                }
            }
            else if (args.ActualBeginDateTime != null && args.ActualEndDateTime != null)
            {
                // at this point actualEndDateTime must not be null, and
                // we don't care if actualBeginDateTime is null or not

                // reservations in the past OR it's Facility Down Time reservation
                if (args.IsFacilityDownTime)
                {
                    // Facility Down Time, it must be editable if it's not started yet
                    if (args.ActualEndDateTime.HasValue && args.ActualEndDateTime.Value < Now && args.IsToolEngineer)
                    {
                        return(ReservationState.PastSelf); // FDT reservation that has already ended
                    }
                    else if (args.BeginDateTime > Now && args.IsToolEngineer)
                    {
                        return(ReservationState.Editable); // FDT reservation that has not started yet
                    }
                    else if (args.EndDateTime > Now && args.IsToolEngineer)
                    {
                        return(ReservationState.Endable); //it's endable only if it's not ended yet
                    }
                    else
                    {
                        return(ReservationState.Other);
                    }
                }

                if (args.IsReserver)
                {
                    return(ReservationState.PastSelf);
                }
                else
                {
                    return(ReservationState.PastOther);
                }
            }
            else //if (actualBeginDateTime == null && actualEndDateTime != null)
            {
                // a reservation cannot have ended if it never began
                throw new InvalidOperationException("ActualBeginDateTime cannot be null if ActualEndDateTime is not null.");
            }
        }
Exemple #4
0
        /// <summary>
        /// Starts a reservation, and turns on Interlock.
        /// </summary>
        /// <param name="item">The reservation to start</param>
        /// <param name="client">The current user starting the reservation</param>
        public void Start(IReservationItem item, ReservationClient client, int?modifiedByClientId)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item", "A null ReservationItem object is not allowed.");
            }

            if (item.IsStarted)
            {
                return;
            }

            var args = ReservationStateArgs.Create(item, client, Now);
            ReservationState state = ReservationStateUtility.Create(Now).GetReservationState(args);

            if (state != ReservationState.StartOnly && state != ReservationState.StartOrDelete)
            {
                if (!args.IsInLab)
                {
                    throw new Exception($"Reservation #{item.ReservationID} is not startable at this time. You must be inside the lab to start reservations.");
                }
                else if (!args.IsAuthorized)
                {
                    throw new Exception($"Reservation #{item.ReservationID} is not startable at this time. You are not authorized to start reservations on this tool.");
                }
                else
                {
                    throw new Exception($"Reservation #{item.ReservationID} is not startable at this time. State: {state}.");
                }
            }

            // End Previous un-ended reservations
            var endableQuery = Provider.Scheduler.Reservation.SelectEndableReservations(item.ResourceID);

            foreach (var endable in endableQuery)
            {
                // no need to disable interlock or send open slot notifications for each of these
                // so calling IReservationManager.EndReservation directly instead of ReservationUtility.End
                Provider.Scheduler.Reservation.EndReservation(new EndReservationArgs
                {
                    ReservationID     = endable.ReservationID,
                    ActualEndDateTime = Now,
                    EndedByClientID   = modifiedByClientId.GetValueOrDefault(-1)
                });
            }

            // Start Reservation
            Provider.Scheduler.Reservation.StartReservation(item.ReservationID, modifiedByClientId);

            // If Resource authorization type is rolling and the reserver is a regular user for the resource then reset reserver's expiration date
            int authLevel = 0, resourceClientId = 0;

            var resourceClients = Provider.Scheduler.Resource.GetResourceClients(item.ResourceID, clientId: client.ClientID);

            if (resourceClients.Any())
            {
                var rc = resourceClients.First();
                authLevel        = Convert.ToInt32(rc.AuthLevel);
                resourceClientId = rc.ResourceClientID;
            }

            if (item.AuthState && (authLevel == (int)ClientAuthLevel.AuthorizedUser))
            {
                DateTime expiration = Now.AddMonths(item.AuthDuration);
                Provider.Scheduler.Resource.UpdateExpiration(resourceClientId, expiration);
            }

            // Turn Interlock On
            if (CacheManager.Current.WagoEnabled)
            {
                uint duration     = OnTheFlyUtility.GetStateDuration(item.ResourceID);
                bool hasInterlock = WagoInterlock.ToggleInterlock(item.ResourceID, true, duration);
                if (hasInterlock)
                {
                    bool interlockState = WagoInterlock.GetPointState(item.ResourceID);
                    if (!interlockState)
                    {
                        throw new InvalidOperationException($"Failed to start interlock for ResourceID {item.ResourceID}.");
                    }
                }
            }
        }