private async Task <TimeEntryResult> DeleteTimeEntry(TimeEntry entry)
        {
            _logger.LogInformation(GetLogMessage("Deleting time entry: {0}"), entry.Id);

            var retVal = new TimeEntryResult
            {
                TimeEntryId = entry.Id
            };

            if (entry.Status == TimeStatus.Logged)
            {
                entry.IsDeleted   = true;
                entry.UpdatedById = _userInfo.UserId;
                entry.Updated     = DateTimeOffset.UtcNow;

                var result = await Repository.UpdateAsync(entry, true);

                _logger.LogDebug(GetLogMessage("{0} results updated"), result);
                if (result > 0)
                {
                    retVal.Succeeded = true;
                }
            }
            else
            {
                retVal.ErrorMessage = "You cannot delete a time entry that has been approved or invoiced";
            }


            return(retVal);
        }
        public async Task <TimeEntryResult> UpdateTimeEntry(IOrganizationProjectManager co, Guid entryId, TimeEntryInput input)
        {
            _logger.LogInformation(GetLogMessage("Entry: {0}"), entryId);
            var retVal = new TimeEntryResult()
            {
                TimeEntryId = entryId
            };

            var entry = await Repository.FirstOrDefaultAsync(x => x.Id == entryId);

            if (entry.Status == TimeStatus.Logged)
            {
                if (input.MinutesDuration.HasValue && input.MinutesDuration.Value > 0)
                {
                    input.EndDate = input.StartDate.AddMinutes(input.MinutesDuration.Value);
                }

                entry.InjectFrom(input);

                retVal = await UpdateTimeEntry(entry);
            }
            else
            {
                retVal.ErrorMessage = "You can only update time entry in the logged state";
            }

            return(retVal);
        }
        public Task <TimeEntryResult> Reject(List <TimeEntry> entries)
        {
            var retVal = new TimeEntryResult
            {
                TimeEntryIds = entries.Select(x => x.Id).ToArray()
            };

            foreach (var e in entries)
            {
                _logger.LogDebug(GetLogMessage("rejecting entry: {0}"), e.Id);

                e.Status      = TimeStatus.Rejected;
                e.Updated     = DateTimeOffset.UtcNow;
                e.UpdatedById = _userInfo.UserId;

                e.StatusTransitions.Add(new TimeEntryStatusTransition()
                {
                    Status      = TimeStatus.Rejected,
                    ObjectState = ObjectState.Added
                });

                Repository.Update(e);
            }

            var result = Repository.Commit();

            _logger.LogDebug(GetLogMessage("{0} records updated in db"), result);

            if (result > 0)
            {
                retVal.Succeeded = true;
            }

            return(Task.FromResult(retVal));
        }
        private async Task <TimeEntryResult> Approve(List <TimeEntry> timeEntries)
        {
            _logger.LogInformation(GetLogMessage("Approving {0} entries"), timeEntries.Count);

            var retVal = new TimeEntryResult();

            foreach (var e in timeEntries)
            {
                e.Status      = TimeStatus.Approved;
                e.Updated     = DateTimeOffset.UtcNow;
                e.UpdatedById = _userInfo.UserId;
                e.ObjectState = ObjectState.Modified;
                e.StatusTransitions.Add(new TimeEntryStatusTransition()
                {
                    Status      = TimeStatus.Approved,
                    ObjectState = ObjectState.Added
                });

                Repository.Update(e);
            }

            var result = Repository.Commit();

            _logger.LogDebug(GetLogMessage("{0} records updated"), result);

            if (result > 0)
            {
                retVal.Succeeded    = true;
                retVal.TimeEntryIds = timeEntries.Select(x => x.Id).ToArray();

                foreach (var e in timeEntries)
                {
                    await Task.Run(() =>
                    {
                        RaiseEvent(new TimeEntryApprovedEvent()
                        {
                            TimeEntryId = e.Id
                        });
                    });
                }
            }

            return(retVal);
        }
        private async Task <TimeEntryResult> UpdateTimeEntry(TimeEntry entry)
        {
            _logger.LogInformation(GetLogMessage("Entry: {0}"), entry.Id);

            var retVal = new TimeEntryResult();

            entry.Updated     = DateTimeOffset.UtcNow;
            entry.UpdatedById = _userInfo.UserId;

            var result = await Repository.UpdateAsync(entry, true);

            _logger.LogDebug(GetLogMessage("{0} results updated"), result);

            if (result > 0)
            {
                retVal.Succeeded   = true;
                retVal.TimeEntryId = entry.Id;
            }

            return(retVal);
        }
        public async Task <TimeEntryResult> UpdateTimeEntry(IOrganizationContractor co, Guid entryId, TimeEntryInput input)
        {
            _logger.LogInformation(GetLogMessage("Entry: {0}"), entryId);

            var entry = await Repository
                        .FirstOrDefaultAsync(x => x.Id == entryId);

            var retVal = new TimeEntryResult {
                TimeEntryId = entryId
            };

            if (entry.Status == TimeStatus.Logged || entry.Status == TimeStatus.Rejected)
            {
                if (input.MinutesDuration.HasValue && input.MinutesDuration.Value > 0)
                {
                    input.EndDate = input.StartDate.AddMinutes(input.MinutesDuration.Value);
                }

                if (entry.Status == TimeStatus.Rejected)
                {
                    entry.Status = TimeStatus.Logged;
                    entry.StatusTransitions.Add(new TimeEntryStatusTransition()
                    {
                        Status      = TimeStatus.Logged,
                        ObjectState = ObjectState.Added
                    });
                }


                entry.InjectFrom(input);

                entry.ObjectState = ObjectState.Modified;
                entry.Updated     = DateTimeOffset.UtcNow;

                var storyId         = input.StoryId;
                var isStoryComplete = input.CompleteStory;

                if (!input.StoryId.HasValue)
                {
                    return(await UpdateTimeEntry(entry));
                }

                var story = await _storyService.Repository
                            .Queryable()
                            .FirstOrDefaultAsync(x => x.Id == storyId.Value);

                if (isStoryComplete.HasValue && isStoryComplete is true)
                {
                    story.Status = StoryStatus.Completed;
                    story.StatusTransitions.Add(new StoryStatusTransition()
                    {
                        Status = StoryStatus.Completed
                    });
                    //else if (isStoryComplete is false) story.Status = StoryStatus.InProgress;
                }

                story.ObjectState = ObjectState.Modified;
                story.Updated     = DateTimeOffset.UtcNow;

                var result = await _storyService.Repository.UpdateAsync(story, true);

                return(await UpdateTimeEntry(entry));
            }

            return(retVal);
        }
        private async Task <TimeEntryResult> TrackTime(TimeEntry entry, Guid?storyId, bool?isStoryComplete)
        {
            _logger.LogInformation(GetLogMessage("Tracking time entry..."));

            var retVal = new TimeEntryResult();

            var contract = await _contractService.Repository.Queryable()
                           .Include(x => x.Project)
                           .ThenInclude(x => x.CustomerAccount)
                           .Include(x => x.Project)
                           .ThenInclude(x => x.Proposal)
                           .Include(x => x.ProviderOrganization)
                           .ThenInclude(x => x.Organization)
                           .Include(x => x.MarketerOrganization)
                           .ThenInclude(x => x.Organization)
                           .Include(x => x.RecruiterOrganization)
                           .ThenInclude(x => x.Organization)
                           .Include(x => x.OrganizationContractor)
                           .Where(x => x.Id == entry.ContractId)
                           .FirstOrDefaultAsync();

            if (contract.Status == ContractStatus.Paused || contract.Status == ContractStatus.Inactive)
            {
                retVal.ErrorMessage = "You cannot log time if contract is paused or ended";
                _logger.LogInformation(GetLogMessage(retVal.ErrorMessage));
                return(retVal);
            }

            if (contract.Project.Proposal == null)
            {
                retVal.ErrorMessage = "Proposal not found for the project";
                _logger.LogInformation(GetLogMessage(retVal.ErrorMessage));
                return(retVal);
            }

            if (contract.Project.Proposal.Status != ProposalStatus.Accepted)
            {
                retVal.ErrorMessage = "Proposal not accepted for the project";
                _logger.LogInformation(GetLogMessage(retVal.ErrorMessage));
                return(retVal);
            }

            var autoApproveProject    = contract.Project.AutoApproveTimeEntries;
            var autoApproveContractor = contract.OrganizationContractor.AutoApproveTimeEntries;
            var autoApprove           = autoApproveProject || autoApproveContractor;

            entry.ProviderAgencyOwnerId   = contract.ProviderOrganization.Organization.CustomerId;
            entry.MarketingAgencyOwnerId  = contract.MarketerOrganization.Organization.CustomerId;
            entry.RecruitingAgencyOwnerId = contract.RecruiterOrganization.Organization.CustomerId;

            entry.ProviderOrganizationId   = contract.ContractorOrganizationId;
            entry.MarketingOrganizationId  = contract.MarketerOrganizationId;
            entry.RecruitingOrganizationId = contract.RecruiterOrganizationId;

            entry.ContractorId           = contract.ContractorId;
            entry.MarketerId             = contract.MarketerId;
            entry.RecruiterId            = contract.RecruiterId;
            entry.ProjectManagerId       = contract.ProjectManagerId;
            entry.AccountManagerId       = contract.AccountManagerId;
            entry.ProjectId              = contract.ProjectId;
            entry.CustomerId             = contract.Project.CustomerId;
            entry.CustomerOrganizationId = contract.Project.CustomerOrganizationId;
            entry.Status  = autoApprove ? TimeStatus.Approved : TimeStatus.Logged;
            entry.StoryId = storyId;
            entry.InstantAccountManagerStream   = contract.AccountManagerStream;
            entry.InstantProjectManagerStream   = contract.ProjectManagerStream;
            entry.InstantRecruiterStream        = contract.RecruiterStream;
            entry.InstantMarketerStream         = contract.MarketerStream;
            entry.InstantContractorStream       = contract.ContractorStream;
            entry.InstantSystemStream           = contract.SystemStream;
            entry.InstantAgencyStream           = contract.AgencyStream;
            entry.InstantRecruitingAgencyStream = contract.RecruitingAgencyStream;
            entry.InstantMarketingAgencyStream  = contract.MarketingAgencyStream;

            entry.UpdatedById = _userInfo.UserId;
            entry.CreatedById = _userInfo.UserId;

            if (autoApprove)
            {
                entry.StatusTransitions.Add(new TimeEntryStatusTransition()
                {
                    Status      = TimeStatus.Approved,
                    ObjectState = ObjectState.Added
                });
            }
            else
            {
                entry.StatusTransitions.Add(new TimeEntryStatusTransition()
                {
                    Status      = TimeStatus.Logged,
                    ObjectState = ObjectState.Added
                });
            }


            var records = await Repository.InsertAsync(entry, true);


            _logger.LogDebug(GetLogMessage("{0} records updated"), records);


            if (records > 0)
            {
                bool isStoryCompleted = false;

                if (storyId.HasValue)
                {
                    _logger.LogDebug(GetLogMessage("Time entry has story: {0}"), storyId.Value);

                    var story = await _storyService.Repository
                                .Queryable()
                                .FirstOrDefaultAsync(x => x.Id == storyId.Value);

                    if (isStoryComplete.HasValue)
                    {
                        if (isStoryComplete.Value && story.Status != StoryStatus.Completed)
                        {
                            _logger.LogDebug(GetLogMessage("Story was completed"));

                            story.Status = StoryStatus.Completed;
                            story.StatusTransitions.Add(new StoryStatusTransition()
                            {
                                Status      = StoryStatus.Completed,
                                ObjectState = ObjectState.Added
                            });

                            isStoryCompleted = true;
                        }
                    }
                    else
                    {
                        _logger.LogDebug(GetLogMessage("Story was not completed"));
                        if (story.Status != StoryStatus.InProgress)
                        {
                            story.Status = StoryStatus.InProgress;
                            story.StatusTransitions.Add(new StoryStatusTransition()
                            {
                                Status      = StoryStatus.InProgress,
                                ObjectState = ObjectState.Added
                            });
                        }
                    }

                    story.TotalHoursLogged += entry.TotalHours;
                    story.ObjectState       = ObjectState.Modified;
                    story.Updated           = DateTimeOffset.UtcNow;

                    var result = _storyService.Repository.InsertOrUpdateGraph(story, true);

                    _logger.LogDebug(GetLogMessage("{0} records updated in db"), result);

                    if (result > 0)
                    {
                        retVal.Succeeded   = true;
                        retVal.TimeEntryId = entry.Id;

                        await Task.Run(() =>
                        {
                            RaiseEvent(new TimeEntryLoggedEvent()
                            {
                                TimeEntryId = entry.Id
                            });
                        });

                        if (isStoryCompleted)
                        {
                            await Task.Run(() => RaiseEvent(new StoryCompletedEvent()
                            {
                                StoryId = storyId.Value
                            }));
                        }
                    }
                }
                else
                {
                    retVal.Succeeded   = true;
                    retVal.TimeEntryId = entry.Id;
                }
            }

            return(retVal);
        }