/// <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); }
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); }