public async Task <ActionResult <TimesheetDTO> > PostTimesheet(TimesheetDTO timesheet)
        {
            var user = await _userManager.FindByNameAsync(User?.Identity?.Name);

            if (user != null)
            {
                timesheet.UserId = user.Id;
            }

            var isTimesheetForValidMonth = !_context.Timesheet.Any(t => t.Date.Year.Equals(timesheet.Date.Year) && t.Date.Month.Equals(timesheet.Date.Month) && t.UserId.Equals(user.Id));

            if (!isTimesheetForValidMonth)
            {
                return(BadRequest(new { Message = "Timesheet for selected month already exists!" }));
            }

            var timesheetObj = DtoToModel.DtoToTimesheet(timesheet);

            var validStates = States.GetStatesValues();

            if (!validStates.Contains(timesheet.State))
            {
                return(BadRequest("Provided status does not exist!"));
            }

            await _context.Timesheet.AddAsync(timesheetObj);

            await _context.SaveChangesAsync();

            var dto = ModelToDto.TimesheetToDto(timesheetObj);

            return(CreatedAtAction("GetTimesheet", new { id = timesheet.Id }, dto));
        }
        public void DtoToTimesheet_Should_ReturnValidTimesheetObject()
        {
            var timesheetDto = CreateMockTimesheetDTO();

            var sut = DtoToModel.DtoToTimesheet(timesheetDto);

            Assert.AreEqual(1, sut.Id);
            Assert.AreEqual(_sampleDate, sut.Date);
            Assert.AreEqual(_sampleUserId, sut.UserId);
            Assert.AreEqual(States.Open, sut.State);
            Assert.AreEqual(1, sut.Rows.ElementAt(0).Id);
            Assert.AreEqual(1, sut.Rows.ElementAt(0).RateTypeId);
            Assert.AreEqual(1, sut.Rows.ElementAt(0).TimesheetId);
            Assert.AreEqual(1, sut.Rows.ElementAt(1).Id);
            Assert.AreEqual(2, sut.Rows.ElementAt(1).RateTypeId);
            Assert.AreEqual(1, sut.Rows.ElementAt(1).TimesheetId);
            Assert.AreEqual(sut.Rows.ElementAt(0).Days, "[{\"Date\":\"2020-05-15T00:00:00\",\"ReportedHours\":8},{\"Date\":\"2020-05-15T00:00:00\",\"ReportedHours\":7}]");
        }
        public async Task <IActionResult> PutTimesheet(int id, TimesheetDTO timesheet)
        {
            if (id != timesheet.Id)
            {
                return(BadRequest());
            }

            var currentUser = await _userManager.FindByNameAsync(User?.Identity?.Name);

            var isCorrectUser = _context.Timesheet.AsNoTracking().Any(t => t.Id == id && t.UserId == currentUser.Id);

            if (!isCorrectUser)
            {
                return(Forbid());
            }

            var timesheetObj = DtoToModel.DtoToTimesheet(timesheet);

            var validStates = States.GetStatesValues();

            if (!validStates.Contains(timesheet.State))
            {
                return(BadRequest());
            }

            var isModificationAllowed = _context.Timesheet.AsNoTracking().First(t => t.Id.Equals(id)).State != States.Closed;

            if (!isModificationAllowed)
            {
                return(BadRequest());
            }

            // new Rows
            var newRows = timesheetObj.Rows.Where(row => row.Id.Equals(0));

            foreach (var newRow in newRows)
            {
                await _context.Row.AddAsync(newRow);
            }

            // edited Rows
            var oldRows = timesheetObj.Rows.Where(row => row.Id > 0);

            foreach (var oldRow in oldRows)
            {
                _context.Entry(oldRow).State = EntityState.Modified;
            }


            // main entity
            _context.Entry(timesheetObj).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!TimesheetExists(id))
                {
                    return(NotFound());
                }
                else
                {
                    throw;
                }
            }

            return(NoContent());
        }