public void Split_SevenAmAndFivePm_Successful()
        {
            var db          = new SqlContext();
            var currentUser = db.Users.Find(1);

            var service = new PunchService();
            var inAt    = new DateTime(2020, 1, 1);
            var outAt   = new DateTime(2020, 1, 31);

            var originalPunches = GetPunches()
                                  .OrderBy(p => p.UserId)
                                  .ThenBy(p => p.InAt)
                                  .ToList();

            // Assert original count
            Assert.AreEqual(19, originalPunches.Count);

            // Split at midnight, must always do this first
            var splitMidnight = service.SplitAtMidnight(originalPunches, currentUser);

            // Assert that there are more punches now
            Assert.AreEqual(21, splitMidnight.Count);

            // Split again at 7am and assert that there are yet more punches
            var splitSevenAm = service.SplitAtMinute(splitMidnight, currentUser, minuteOfDay: 420); // Split at 7am = 420 minutes

            // Assert that there are more punches now
            Assert.AreEqual(22, splitSevenAm.Count);

            // Finally split at 5pm and assert that there are even more punches
            var splitFivePm = service.SplitAtMinute(splitSevenAm, currentUser, minuteOfDay: 1020); // Split at 5pm = 1020 minutes

            // Assert that there are more punches now
            Assert.AreEqual(34, splitFivePm.Count);
        }
        public void Split_Midnight_Successful()
        {
            var db          = new SqlContext();
            var currentUser = db.Users.Find(1);

            var service = new PunchService();

            var originalPunches = GetPunches()
                                  .OrderBy(p => p.UserId)
                                  .ThenBy(p => p.InAt)
                                  .ToList();

            // Assert original count
            Assert.AreEqual(19, originalPunches.Count);

            // Split at midnight
            var splitMidnight = service.SplitAtMidnight(originalPunches, currentUser);

            // Assert that there are more punches now
            Assert.AreEqual(21, splitMidnight.Count);
        }
        // POST: odata/Commits
        public IHttpActionResult Post(Commit commit)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var currentUser = CurrentUser();

            // Ensure that user is authorized.
            if (!currentUser.CanCreateLocks)
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            using (var transaction = db.Database.BeginTransaction())
            {
                try
                {
                    var inAt  = new DateTime(commit.InAt.Year, commit.InAt.Month, commit.InAt.Day, 0, 0, 0, DateTimeKind.Unspecified);
                    var outAt = new DateTime(commit.OutAt.Year, commit.OutAt.Month, commit.OutAt.Day, 23, 59, 59, DateTimeKind.Unspecified);

                    // Ensure that no two commits overlap
                    var overlap = db.Commits
                                  .Where(c => c.OrganizationId == commit.OrganizationId)
                                  .Where(c => (inAt < c.OutAt) && (c.InAt < outAt))
                                  .FirstOrDefault();
                    if (overlap != null)
                    {
                        return(BadRequest(string.Format(
                                              "The commit overlaps another commit: {0} thru {1}",
                                              overlap.InAt.ToString("yyyy-MM-dd"),
                                              overlap.OutAt.ToString("yyyy-MM-dd")
                                              )));
                    }

                    // Auto-generated
                    commit.CreatedAt      = DateTime.UtcNow;
                    commit.Guid           = Guid.NewGuid();
                    commit.OrganizationId = currentUser.OrganizationId;
                    commit.UserId         = currentUser.Id;
                    commit.InAt           = inAt;
                    commit.OutAt          = outAt;

                    db.Commits.Add(commit);

                    db.SaveChanges();

                    // Split the punches at midnight.
                    var   service = new PunchService();
                    int[] userIds = db.Users
                                    .Where(u => u.OrganizationId == currentUser.OrganizationId)
                                    .Select(u => u.Id)
                                    .ToArray();
                    var originalPunchesTracked = db.Punches
                                                 .Where(p => userIds.Contains(p.UserId))
                                                 .Where(p => p.InAt >= inAt && p.OutAt.HasValue && p.OutAt.Value <= outAt)
                                                 .Where(p => !p.CommitId.HasValue); // Only uncommited punches
                    var originalPunchesNotTracked = originalPunchesTracked
                                                    .AsNoTracking()                 // Will be manipulated in memory
                                                    .ToList();
                    var splitPunches = service.SplitAtMidnight(originalPunchesNotTracked, currentUser);

                    // Delete the old punches and save the new ones.
                    db.Punches.RemoveRange(originalPunchesTracked);
                    db.SaveChanges();

                    // Save the commit id with the new punches.
                    foreach (var punch in splitPunches)
                    {
                        punch.CommitId = commit.Id;
                    }
                    commit.PunchCount = splitPunches.Count();

                    db.Punches.AddRange(splitPunches);
                    db.SaveChanges();

                    transaction.Commit();

                    return(Created(commit));
                }
                catch (Exception ex)
                {
                    transaction.Rollback();

                    return(BadRequest(ex.ToString()));
                }
            }
        }