예제 #1
0
        public void TrackTime(int projectId, int userId, DateTime at, decimal hours)
        {
            var command = new TrackTimeCommand
            {
                At        = at,
                Hours     = hours,
                ProjectId = projectId,
                ForUserId = userId,
                ByUserId  = _currentUser.Id
            };

            _cqrs.Execute(command);
        }
예제 #2
0
        public IEnumerable <IEvent <ProjectTimeAggregateRoot, int> > Execute(TrackTimeCommand command)
        {
            var project = _projectService.GetById(command.ProjectId);

            if (project == null || project.Status != ProjectStatus.Active)
            {
                throw new ProjectNotReportableException();
            }

            var targetUserProjectData = _projectService.GetProjectUserInfo(command.ForUserId, command.ProjectId);

            if (targetUserProjectData == null)
            {
                throw new ProjectAuthorizationException("User is not assigned to the project.");
            }

            var trackingPermissions = command.ForUserId == command.ByUserId ? ProjectPermissions.TrackSelf : ProjectPermissions.TrackAsOtherUser;
            var trackerUserData     = _projectService.GetProjectUserInfo(command.ByUserId, project.Id);

            if (trackerUserData == null ||
                (trackerUserData.UserPermissions & trackingPermissions) == 0)
            {
                throw new ProjectAuthorizationException();
            }

            if (project.StartDate.Date > command.At.Date)
            {
                throw new ProjectNotReportableException();
            }
            if (project.EndDate != null && project.EndDate < command.At.Date)
            {
                throw new ProjectNotReportableException();
            }

            var trackedTime = State.DailyTime.SingleOrDefault(t => t.Date == command.At.Date && t.UserId == command.ForUserId);

            if (trackedTime != null && command.Hours < trackedTime.TotalHours)
            {
                if (command.Hours < trackedTime.PaidHours)
                {
                    throw new IncorrectHoursException(String.Format("{0} hours already paid for this day.", trackedTime.BilledHours));
                }

                // By decreasing time you will decrease number of billing hours available
                // (because already billed hours will distribute on further time).
                // So you couldn't decrease billing hours down zero.
                var billingHoursAvailable = State.MaxBillableHours(command.ForUserId);
                if (command.Hours - trackedTime.TotalHours + billingHoursAvailable < 0)
                {
                    throw new IncorrectHoursException("The hours already billed.");
                }
            }

            var maxDailyHours = targetUserProjectData.MaxDailyHours ?? 24;

            if (command.Hours > maxDailyHours)
            {
                throw new IncorrectHoursException(String.Format("Max daily hours value {0} exceeded.", maxDailyHours));
            }

            if (targetUserProjectData.MaxProjectHours != null)
            {
                var userProjectHours = State.DailyTime
                                       .Where(p => p.Date != command.At.Date)      /* Exclude reported hours */
                                       .Where(p => p.UserId == command.ForUserId)
                                       .SumOrDefault(p => p.TotalHours);
                if (userProjectHours + command.Hours > targetUserProjectData.MaxProjectHours)
                {
                    throw new IncorrectHoursException("All your hours available for the project are exceeded.");
                }
            }

            if (project.MaxTotalHours != null)
            {
                var totalProjectHours = State.DailyTime
                                        .Where(p => p.Date != command.At.Date)     /* Exclude reported hours */
                                        .SumOrDefault(p => p.TotalHours);

                if (totalProjectHours + command.Hours > project.MaxTotalHours)
                {
                    throw new IncorrectHoursException("Project maximum hours exceeded.");
                }
            }

            var @event = new TimeTrackedEvent
            {
                At                 = command.At.Date,
                Hours              = command.Hours,
                ProjectId          = project.Id,
                RegisteredAt       = DateTimeOffset.Now,
                RegisteredByUserId = command.ByUserId,
                UserId             = command.ForUserId,
                HourlyRate         = trackerUserData.HourlyRate
            };

            yield return(@event);
        }