Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="value"></param>
        /// <param name="isNew"></param>
        /// <param name="dbFactory"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        internal static async Task <SubmitResult <EventEntry> > SaveEvent(EventEntry value, bool isNew, Func <IMissionLineDbContext> dbFactory, IConfigSource config)
        {
            var result = new SubmitResult <EventEntry>();

            if (string.IsNullOrWhiteSpace(value.Name))
            {
                result.Errors.Add(new SubmitError("name", "Required"));
            }
            DateTimeOffset localOpened = value.Opened.ToOrgTime(config);

            if (localOpened < minDate || localOpened > maxDate)
            {
                result.Errors.Add(new SubmitError("opened", "Date invalid or out of range"));
            }
            DateTimeOffset?localClosed = value.Closed == null ? (DateTimeOffset?)null : value.Closed.Value.ToOrgTime(config);

            if (localClosed.HasValue)
            {
                if (localClosed < minDate || localClosed > maxDate)
                {
                    result.Errors.Add(new SubmitError("closed", "Date invalid or out of range"));
                }
                else if (localClosed < localOpened)
                {
                    result.Errors.Add(new SubmitError("closed", "Must be after open time"));
                }
            }

            if (result.Errors.Count == 0)
            {
                using (var db = dbFactory())
                {
                    SarEvent evt;
                    if (isNew)
                    {
                        evt = new SarEvent
                        {
                            Name   = value.Name,
                            Opened = localOpened,
                            Closed = localClosed
                        };
                        db.Events.Add(evt);
                    }
                    else
                    {
                        evt = db.Events.Single(f => f.Id == value.Id);
                    }

                    if (value.Name != evt.Name)
                    {
                        evt.Name = value.Name;
                    }
                    if (localOpened != evt.Opened)
                    {
                        evt.Opened = localOpened;
                    }
                    if (localClosed != evt.Closed)
                    {
                        evt.Closed = localClosed;
                    }

                    await db.SaveChangesAsync();

                    result.Data = new[] { evt }.AsQueryable().Select(proj).Single();
                    config.GetPushHub <CallsHub>().updatedEvent(result.Data);
                }
            }
            return(result);
        }
Пример #2
0
        internal static async Task <SubmitResult> AssignInternal(MemberSignIn signin, int?eventId, IMissionLineDbContext db, IConfigSource config)
        {
            var result        = new SubmitResult();
            var notifications = new List <Action>();
            var hub           = config.GetPushHub <CallsHub>();

            var exposedSignin = await db.SignIns
                                .Where(f => f.MemberId == signin.MemberId && f.EventId == signin.EventId && f.Id != signin.Id)
                                .OrderByDescending(f => f.TimeIn)
                                .FirstOrDefaultAsync();

            if (exposedSignin != null)
            {
                notifications.Add(() => hub.updatedRoster(compiledProj(exposedSignin), true));
            }

            var            others           = db.SignIns.Where(f => f.EventId == eventId && f.MemberId == signin.MemberId && f.Id != signin.Id).OrderBy(f => f.TimeIn).ToList();
            DateTimeOffset effectiveTimeOut = signin.TimeOut ?? DateTimeOffset.MaxValue;
            bool           rosterisLatest   = true;

            foreach (var other in others)
            {
                var otherTimeOut = other.TimeOut ?? DateTimeOffset.MaxValue;
                // R: [---------->
                // O:      [----------]

                // R: [---------->
                // O:       [-------->

                // R: [----------]
                // O:         [----->

                // R: [--------------------]
                // O:       [-------]

                // R: [---------]
                // O:     [--->

                // R: [------]
                // O:    [------]

                // R: [---]
                // O:       [----]

                // R:      [-----]
                // O:   [-----]

                // R:        [---]
                // O: [---]



                // Trim signins that overlap our time in.
                if (signin.TimeIn <= other.TimeIn)
                {
                    if (effectiveTimeOut >= other.TimeIn && effectiveTimeOut <= otherTimeOut)
                    {
                        // roster is before the other one. It is not the latest
                        rosterisLatest = false;
                        notifications.Add(() => hub.updatedRoster(compiledProj(other), true));
                        signin.TimeOut = other.TimeIn;
                    }
                    else if (effectiveTimeOut > otherTimeOut)
                    {
                        // split roster around other.
                        // roster is the most recent, other and front are not.
                        var front = SplitSignin(eventId, signin, other, db, config);
                        notifications.Add(() => hub.updatedRoster(compiledProj(front), false));
                        notifications.Add(() => hub.updatedRoster(compiledProj(other), false));
                    }
                }
                else
                {
                    if (otherTimeOut > signin.TimeIn && otherTimeOut <= effectiveTimeOut)
                    {
                        // other overlaps on the early side
                        other.TimeOut = signin.TimeIn;
                        notifications.Add(() => hub.updatedRoster(compiledProj(other), false));
                    }
                    else if (otherTimeOut > effectiveTimeOut)
                    {
                        //split other around roster
                        var front = SplitSignin(eventId, other, signin, db, config);
                        notifications.Add(() => hub.updatedRoster(compiledProj(front), false));
                        notifications.Add(() => hub.updatedRoster(compiledProj(other), true));
                        rosterisLatest = false;
                    }
                    else if (otherTimeOut < signin.TimeIn)
                    {
                        // other notification is not the latest.
                        notifications.Add(() => hub.updatedRoster(compiledProj(other), false));
                    }
                }
            }

            signin.EventId = eventId;
            notifications.Add(() => hub.updatedRoster(compiledProj(signin), rosterisLatest));
            db.SaveChanges();
            foreach (var notify in notifications)
            {
                notify();
            }

            return(result);
        }