public void YearSumsCorrectly()
        {
            var org1 = TestFramework.TestOrganization.Create();
            var projectGrantAllocationExpenditures = BuildExpenditures(org1, "grant allocation 1", new Dictionary <int, decimal>
            {
                { 2010, 100.0m }, { 2011, 200.0m }, { 2012, 300.0m }, { 2013, 400.0m }
            });

            var org2 = TestFramework.TestOrganization.Create();

            projectGrantAllocationExpenditures.AddAll(BuildExpenditures(org2, "grant allocation 2", new Dictionary <int, decimal>
            {
                { 2010, 100.0m }, { 2011, 200.0m }, { 2012, 300.0m }, { 2013, 400.0m }
            }));

            var beginCalendarYear = projectGrantAllocationExpenditures.Min(x => x.CalendarYear);
            var endCalendarYear   = projectGrantAllocationExpenditures.Max(x => x.CalendarYear);
            var rangeOfYears      = FirmaDateUtilities.GetRangeOfYears(beginCalendarYear, endCalendarYear);

            var fullOrganizationTypeAndYearDictionary = projectGrantAllocationExpenditures.GetFullCategoryYearDictionary(x => x.GrantAllocation.BottommostOrganization.DisplayName,
                                                                                                                         new List <string> {
                org1.DisplayName, org2.DisplayName
            }, x => x.GrantAllocation.BottommostOrganization.DisplayName, rangeOfYears);

            Assert.That(fullOrganizationTypeAndYearDictionary.Sum(x => x.Value[2012]), Is.EqualTo(600.0m));
        }
예제 #2
0
        public void ProjectUpdateSubmittedTest()
        {
            // Find all project update batches for given reporting year that are approved
            // If none approved, then look for submitted
            var project       = TestFramework.TestProject.Create();
            var reportingYear = FirmaDateUtilities.CalculateCurrentYearToUseForRequiredReporting();

            // brand new project, should not have any updates
            AssertThatProjectHasNoSubmittedProjectUpdates(project, new List <int>(), $"Brand new {Models.FieldDefinition.Project.GetFieldDefinitionLabel()}, should not have any project updates submitted");

            var projectUpdateBatch = TestFramework.TestProjectUpdateBatch.Create(project);

            projectUpdateBatch.LastUpdateDate = DateTime.Now;
            // brand new project update batch, should still not have any updates
            AssertThatProjectHasNoSubmittedProjectUpdates(project, new List <int>(), $"Brand new {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} update batch, should not have any project updates submitted");

            var person = TestFramework.TestPerson.Create();

            // create a "submitted" transition
            TestFramework.TestProjectUpdateHistory.Create(projectUpdateBatch, ProjectUpdateState.Submitted, person);
            Assert.That(project.IsUpdateMandatory, Is.True, "In submitted state, no previous approvals for this reporting year, so we should be true");

            // add an "approved" transition
            TestFramework.TestProjectUpdateHistory.Create(projectUpdateBatch, ProjectUpdateState.Approved, person);
            Assert.That(project.IsUpdateMandatory, Is.True, "In approved state, no previous approvals for this reporting year, so we should be true");

            // user decides to do another update in the same reporting year
            var projectUpdateBatch2 = TestFramework.TestProjectUpdateBatch.Create(project);

            projectUpdateBatch2.LastUpdateDate = DateTime.Now;

            AssertThatProjectHasNoSubmittedProjectUpdates(project, new List <int> {
                reportingYear
            }, $"Should not have any {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} updates submitted except for the reporting year");
        }
예제 #3
0
        public EditProjectViewData(EditProjectType editProjectType,
                                   string taxonomyLeafDisplayName,
                                   IEnumerable <ProjectStage> projectStages,
                                   IEnumerable <ProjectFirmaModels.Models.Organization> organizations,
                                   IEnumerable <Person> primaryContactPeople,
                                   Person defaultPrimaryContactPerson,
                                   decimal?totalExpenditures,
                                   List <ProjectFirmaModels.Models.TaxonomyLeaf> taxonomyLeafs,
                                   IEnumerable <ProjectFirmaModels.Models.ProjectCustomAttributeType> projectCustomAttributeTypes,
                                   TenantAttribute tenantAttribute)
        {
            EditProjectType         = editProjectType;
            TaxonomyLeafDisplayName = taxonomyLeafDisplayName;
            TotalExpenditures       = totalExpenditures;
            ProjectStages           = projectStages.OrderBy(x => x.SortOrder).ToSelectListWithEmptyFirstRow(x => x.ProjectStageID.ToString(CultureInfo.InvariantCulture), y => y.ProjectStageDisplayName);
            ProjectStages           = projectStages.OrderBy(x => x.SortOrder).ToSelectListWithEmptyFirstRow(x => x.ProjectStageID.ToString(CultureInfo.InvariantCulture), y => y.ProjectStageDisplayName);
            Organizations           = organizations.ToSelectListWithEmptyFirstRow(x => x.OrganizationID.ToString(CultureInfo.InvariantCulture), y => y.GetDisplayName());
            PrimaryContactPeople    = primaryContactPeople.ToSelectListWithEmptyFirstRow(
                x => x.PersonID.ToString(CultureInfo.InvariantCulture), y => y.GetFullNameFirstLastAndOrgShortName(),
                $"<Set Based on {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}'s Associated {FieldDefinitionEnum.Organization.ToType().GetFieldDefinitionLabelPluralized()}>");
            DefaultPrimaryContactPerson = defaultPrimaryContactPerson;
            TaxonomyLeafs = taxonomyLeafs.ToGroupedSelectList();
            PlanningDesignStartYearRange    = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay).ToList();
            ImplementationStartYearRange    = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay).ToList();
            CompletionYearRange             = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay).ToList();
            HasThreeTierTaxonomy            = MultiTenantHelpers.IsTaxonomyLevelTrunk();
            DefaultPrimaryContactPersonName = DefaultPrimaryContactPerson != null?DefaultPrimaryContactPerson.GetFullNameFirstLastAndOrgShortName() : "nobody";

            ProjectCustomAttributeTypes = projectCustomAttributeTypes;
            TenantAttribute             = tenantAttribute;
            TenantUsesFiscalYears       = MultiTenantHelpers.UseFiscalYears();
        }
예제 #4
0
        private void AssignParameters(IEnumerable <ProjectFirmaModels.Models.TaxonomyLeaf> taxonomyLeafs,
                                      IEnumerable <FundingType> fundingTypes,
                                      TenantAttribute tenantAttribute)
        {
            TaxonomyLeafs = taxonomyLeafs.ToList().OrderTaxonomyLeaves().ToList().ToGroupedSelectList();

            FundingTypes = fundingTypes.ToSelectList(x => x.FundingTypeID.ToString(CultureInfo.InvariantCulture), y => y.FundingTypeDisplayName);
            PlanningDesignStartYearRange = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay).ToList();
            ImplementationStartYearRange = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay).ToList();
            CompletionYearRange          = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay).ToList();
            HasCanStewardProjectsOrganizationRelationship = MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship();

            HasThreeTierTaxonomy = MultiTenantHelpers.IsTaxonomyLevelTrunk();

            var pagetitle = ShowProjectStageDropDown ? $"Add {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}" : $"Propose {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}";

            PageTitle = $"{pagetitle}";
            if (ProjectDisplayName != null)
            {
                PageTitle += $": {ProjectDisplayName}";
            }

            TenantAttribute       = tenantAttribute;
            TenantUsesFiscalYears = MultiTenantHelpers.UseFiscalYears();
        }
        private static List <int> GetYearRangesImpl(IProject projectUpdate, DateTime?startDate)
        {
            var currentYearToUse = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();

            if (projectUpdate != null)
            {
                if (startDate.HasValue && startDate.Value.Year < MultiTenantHelpers.GetMinimumYear() &&
                    (projectUpdate.GetCompletionYear().HasValue&& projectUpdate.GetCompletionYear().Value < MultiTenantHelpers.GetMinimumYear()))
                {
                    // both start and completion year are before the minimum year, so no year range required
                    return(new List <int>());
                }

                if (startDate.HasValue && startDate.Value.Year > currentYearToUse && (projectUpdate.GetCompletionYear().HasValue&& projectUpdate.GetCompletionYear().Value > currentYearToUse))
                {
                    return(new List <int>());
                }

                if (startDate.HasValue && projectUpdate.GetCompletionYear().HasValue&& startDate.Value.Year > projectUpdate.GetCompletionYear().Value)
                {
                    return(new List <int>());
                }
            }
            return(FirmaDateUtilities.CalculateCalendarYearRangeAccountingForExistingYears(new List <int>(),
                                                                                           startDate,
                                                                                           projectUpdate.GetCompletionYear(),
                                                                                           currentYearToUse,
                                                                                           MultiTenantHelpers.GetMinimumYear(),
                                                                                           currentYearToUse));
        }
        public EditProjectViewData(EditProjectType editProjectType,
                                   string projectTypeDisplayName,
                                   IEnumerable <ProjectStage> projectStages,
                                   IEnumerable <Models.Organization> organizations,
                                   IEnumerable <Person> primaryContactPeople,
                                   Person defaultPrimaryContactPerson,
                                   decimal?totalExpenditures,
                                   List <Models.ProjectType> projectTypes,
                                   IEnumerable <Models.FocusArea> focusAreas,
                                   bool projectTypeHasBeenSet,
                                   List <ProgramSimple> allPrograms,
                                   int projectID)
        {
            EditProjectTypeIntroductoryText = editProjectType.IntroductoryText;
            ProjectTypeDisplayName          = projectTypeDisplayName;
            TotalExpenditures = totalExpenditures;
            ProjectStages     = projectStages.OrderBy(x => x.SortOrder).ToSelectListWithEmptyFirstRow(x => x.ProjectStageID.ToString(CultureInfo.InvariantCulture), y => y.ProjectStageDisplayName);

            Organizations        = organizations.ToSelectListWithEmptyFirstRow(x => x.OrganizationID.ToString(CultureInfo.InvariantCulture), y => y.DisplayName);
            PrimaryContactPeople = primaryContactPeople.ToSelectListWithEmptyFirstRow(
                x => x.PersonID.ToString(CultureInfo.InvariantCulture), y => y.FullNameFirstLastAndOrgShortName,
                $"<Set Based on {Models.FieldDefinition.Project.GetFieldDefinitionLabel()}'s Associated {Models.FieldDefinition.Organization.GetFieldDefinitionLabelPluralized()}>");
            ProjectTypes                    = projectTypes.ToGroupedSelectList();
            StartYearRange                  = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay);
            CompletionDateRange             = FirmaDateUtilities.YearsForUserInput().ToSelectListWithEmptyFirstRow(x => x.CalendarYear.ToString(CultureInfo.InvariantCulture), x => x.CalendarYearDisplay);
            HasThreeTierTaxonomy            = MultiTenantHelpers.IsTaxonomyLevelTrunk();
            DefaultPrimaryContactPersonName = defaultPrimaryContactPerson?.FullNameFirstLastAndOrgShortName ?? "nobody";
            FocusAreas            = focusAreas.OrderBy(x => x.FocusAreaName).ToSelectListWithEmptyFirstRow(x => x.FocusAreaID.ToString(CultureInfo.InvariantCulture), y => y.FocusAreaName);
            ProjectTypeHasBeenSet = projectTypeHasBeenSet;
            AllPrograms           = allPrograms;
            ProjectID             = projectID;
        }
예제 #7
0
        public ManageViewData(Person currentPerson,
                              Models.FirmaPage firmaPage,
                              string customNotificationUrl,
                              ProjectUpdateStatusGridSpec projectsRequiringUpdateGridSpec,
                              string projectsRequiringUpdateGridDataUrl,
                              PeopleReceivingReminderGridSpec peopleReceivingReminderGridSpec,
                              string peopleReceivingReminderGridDataUrl, int projectsWithNoContactCount,
                              ProjectUpdateConfiguration projectUpdateConfiguration) : base(currentPerson, firmaPage)
        {
            var reportingYear = FirmaDateUtilities.CalculateCurrentYearToUseForRequiredReporting();

            PageTitle     = $"Manage {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} Updates";
            ReportingYear = reportingYear;

            ProjectsRequiringUpdateGridDataUrl = projectsRequiringUpdateGridDataUrl;
            ProjectsRequiringUpdateGridSpec    = projectsRequiringUpdateGridSpec;
            ProjectsRequiringUpdateGridName    = "projectsRequiringAnUpdateGrid";

            PeopleReceivingReminderGridDataUrl = peopleReceivingReminderGridDataUrl;
            ProjectsWithNoContactCount         = projectsWithNoContactCount;

            ProjectUpdateConfiguration = projectUpdateConfiguration ?? ProjectUpdateConfiguration.CreateNewBlank();

            PeopleReceivingReminderGridSpec = peopleReceivingReminderGridSpec;
            PeopleReceivingReminderGridName = "peopleReceivingAnReminderGrid";

            KickOffIntroPreviewUrl =
                SitkaRoute <ProjectUpdateController> .BuildUrlFromExpression(x => x.KickOffIntroPreview());

            ReminderIntroPreviewUrl =
                SitkaRoute <ProjectUpdateController> .BuildUrlFromExpression(x => x.ReminderIntroPreview());

            CloseOutIntroPreviewUrl =
                SitkaRoute <ProjectUpdateController> .BuildUrlFromExpression(x => x.CloseOutIntroPreview());

            var getPersonIDFunctionString =
                $"function() {{ return Sitka.{PeopleReceivingReminderGridName}.getValuesFromCheckedGridRows({0}, \'PersonID\', \'PersonIDList\'); }}";

            var modalDialogFormLink = ModalDialogFormHelper.ModalDialogFormLink(
                "<span class=\"glyphicon glyphicon-envelope\" style=\"margin-right:5px\"></span>Send Notification to Selected People",
                customNotificationUrl,
                "Send Notification to Selected People",
                700,
                "Send",
                "Cancel",
                new List <string>(),
                null,
                getPersonIDFunctionString);

            PeopleReceivingReminderGridSpec.ArbitraryHtml = new List <string> {
                modalDialogFormLink.ToString()
            };

            EditProjectUpdateConfigurationUrl =
                SitkaRoute <ProjectUpdateController> .BuildUrlFromExpression(x => x.EditProjectUpdateConfiguration());
        }
예제 #8
0
        private PartialViewResult ViewEditTechnicalAssistanceRequests(Project project, EditTechnicalAssistanceRequestsViewModel viewModel)
        {
            var firmaPage = FirmaPageTypeEnum.TechnicalAssistanceInstructions.GetFirmaPage();
            var technicalAssistanceTypes = TechnicalAssistanceType.All;
            var fiscalYearStrings        = FirmaDateUtilities.GetRangeOfYears(MultiTenantHelpers.GetMinimumYear(), FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting() + 2).OrderByDescending(x => x).Select(x => new CalendarYearString(x)).ToList();
            var personDictionary         = HttpRequestStorage.DatabaseEntities.People.Where(x => x.RoleID == Role.Admin.RoleID || x.RoleID == Role.ProjectSteward.RoleID).OrderBy(x => x.LastName).ThenBy(x => x.FirstName).ToList().Select(x => new PersonSimple(x)).ToList();
            var viewData = new EditTechnicalAssistanceRequestsViewData(CurrentFirmaSession, firmaPage, project, technicalAssistanceTypes, fiscalYearStrings, personDictionary);

            return(RazorPartialView <EditTechnicalAssistanceRequests, EditTechnicalAssistanceRequestsViewData, EditTechnicalAssistanceRequestsViewModel>(viewData, viewModel));
        }
예제 #9
0
        public static IEnumerable <CalendarYearReportedValue> ToCalendarYearReportedValues(IEnumerable <ProjectGrantAllocationExpenditure> projectGrantAllocationExpenditures)
        {
            var yearRange = FirmaDateUtilities.GetRangeOfYearsForReporting();

            return(yearRange.OrderBy(cy => cy).Select(cy =>
            {
                var pmavForThisCalendarYear = projectGrantAllocationExpenditures.Where(x => x.CalendarYear == cy).ToList();
                return new CalendarYearReportedValue(cy, pmavForThisCalendarYear.Any() ? (double?)pmavForThisCalendarYear.Sum(y => y.ExpenditureAmount) : null);
            }));
        }
예제 #10
0
        private static bool TodayIsReminderDayForProjectUpdateConfiguration(
            ProjectUpdateSetting projectUpdateSetting)
        {
            var projectUpdateKickOffDate  = FirmaDateUtilities.LastReportingPeriodStartDateForBackgroundJob(projectUpdateSetting.ProjectUpdateKickOffDate.GetValueOrDefault());
            var projectUpdateCloseOutDate = FirmaDateUtilities.LastReportingPeriodEndDateForBackgroundJob(projectUpdateSetting.ProjectUpdateKickOffDate.GetValueOrDefault(), projectUpdateSetting.ProjectUpdateCloseOutDate.GetValueOrDefault());
            var isReminderDay             = DateTime.Today != projectUpdateKickOffDate && (DateTime.Today - projectUpdateKickOffDate).Days % projectUpdateSetting.ProjectUpdateReminderInterval == 0;
            var isAfterCloseOut           = DateTime.Today.IsDateAfter(projectUpdateCloseOutDate);

            return(isReminderDay && !isAfterCloseOut);
        }
        public static List <int> CalculateCalendarYearRangeForExpenditures(this IEnumerable <ProjectFundingSourceExpenditure> projectFundingSourceExpenditures, FundingSource fundingSource)
        {
            var existingYears = projectFundingSourceExpenditures.Select(x => x.CalendarYear).ToList();

            return(FirmaDateUtilities.CalculateCalendarYearRangeAccountingForExistingYears(existingYears,
                                                                                           fundingSource.GetProjectsWhereYouAreTheFundingSourceMinCalendarYear(),
                                                                                           fundingSource.GetProjectsWhereYouAreTheFundingSourceMaxCalendarYear(),
                                                                                           DateTime.Today.Year,
                                                                                           MultiTenantHelpers.GetMinimumYear(),
                                                                                           null));
        }
예제 #12
0
        protected virtual void ProcessRemindersImpl()
        {
            Logger.Info($"Processing '{JobName}' notifications.");

            // we're "tenant-agnostic" right now
            var projectUpdateSettings = DbContext.AllProjectUpdateSettings.ToList();


            foreach (var projectUpdateSetting in projectUpdateSettings)
            {
                var notifications    = new List <Notification>();
                var tenantID         = projectUpdateSetting.TenantID;
                var databaseEntities = new DatabaseEntities(tenantID);
                var projects         = databaseEntities.Projects.ToList();

                var tenantAttribute = databaseEntities.TenantAttributes.Single();
                var reminderSubject = $"Time to update your {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralizedForBackgroundJob(tenantAttribute.TenantID)}";
                if (projectUpdateSetting.EnableProjectUpdateReminders)
                {
                    var projectUpdateKickOffDate = FirmaDateUtilities.LastReportingPeriodStartDateForBackgroundJob(projectUpdateSetting.ProjectUpdateKickOffDate.GetValueOrDefault());
                    if (DateTime.Today == projectUpdateKickOffDate)
                    {
                        notifications.AddRange(RunNotifications(projects, reminderSubject,
                                                                projectUpdateSetting.ProjectUpdateKickOffIntroContent, tenantAttribute));
                    }
                }

                if (projectUpdateSetting.SendPeriodicReminders)
                {
                    if (TodayIsReminderDayForProjectUpdateConfiguration(projectUpdateSetting))
                    {
                        notifications.AddRange(RunNotifications(projects, reminderSubject, projectUpdateSetting.ProjectUpdateReminderIntroContent, tenantAttribute));
                        // notifyOnAll is false b/c we only send periodic reminders for projects whose updates haven't been submitted yet.
                    }
                }

                if (projectUpdateSetting.SendCloseOutNotification)
                {
                    var closeOutReminderDate = FirmaDateUtilities.LastReportingPeriodEndDateForBackgroundJob(projectUpdateSetting.ProjectUpdateKickOffDate.GetValueOrDefault(), projectUpdateSetting.ProjectUpdateCloseOutDate.GetValueOrDefault());
                    if (projectUpdateSetting.DaysBeforeCloseOutDateForReminder.HasValue)
                    {
                        closeOutReminderDate = closeOutReminderDate.AddDays(-projectUpdateSetting.DaysBeforeCloseOutDateForReminder.Value);
                    }
                    if (DateTime.Today == closeOutReminderDate)
                    {
                        notifications.AddRange(RunNotifications(projects, reminderSubject,
                                                                projectUpdateSetting.ProjectUpdateCloseOutIntroContent, tenantAttribute));
                    }
                }

                databaseEntities.AllNotifications.AddRange(notifications);
                databaseEntities.SaveChangesWithNoAuditing(tenantID);
            }
        }
예제 #13
0
            public ViewDataForAngularClass(ProjectFirmaModels.Models.Project project,
                                           List <FundingSourceSimple> allFundingSources,
                                           List <int> requiredCalendarYearRange)
            {
                RequiredCalendarYearRange = requiredCalendarYearRange;
                AllFundingSources         = allFundingSources;
                ProjectID = project.ProjectID;

                MaxYear        = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();
                UseFiscalYears = MultiTenantHelpers.UseFiscalYears();
            }
            public ViewDataForAngularClass(Models.Project project,
                                           List <GrantAllocationSimple> allGrantAllocations,
                                           List <int> calendarYearRange, bool showNoExpendituresExplanation)
            {
                CalendarYearRange             = calendarYearRange;
                ShowNoExpendituresExplanation = showNoExpendituresExplanation;
                AllGrantAllocations           = allGrantAllocations;
                ProjectID = project.ProjectID;

                MaxYear        = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();
                UseFiscalYears = MultiTenantHelpers.UseFiscalYears();
            }
        private static List <int> GetRangeOfYears(List <ProjectFundingSourceExpenditure> projectFundingSourceExpenditures)
        {
            if (!projectFundingSourceExpenditures.Any())
            {
                return(new List <int>());
            }

            var beginCalendarYear = projectFundingSourceExpenditures.Min(x => x.CalendarYear);
            var endCalendarYear   = projectFundingSourceExpenditures.Max(x => x.CalendarYear);
            var rangeOfYears      = FirmaDateUtilities.GetRangeOfYears(beginCalendarYear, endCalendarYear);

            return(rangeOfYears);
        }
        public static List <int> CalculateCalendarYearRangeForExpendituresWithoutAccountingForExistingYears(this ProjectUpdate projectUpdate)
        {
            if (projectUpdate.CompletionYear < projectUpdate.ImplementationStartYear)
            {
                return(new List <int>());
            }
            if (projectUpdate.CompletionYear < projectUpdate.PlanningDesignStartYear)
            {
                return(new List <int>());
            }

            return(FirmaDateUtilities.CalculateCalendarYearRangeForExpendituresAccountingForExistingYears(new List <int>(), projectUpdate, FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting()));
        }
예제 #17
0
        private EditPerformanceMeasureActualsViewData(List <ProjectSimple> allProjects, List <Models.PerformanceMeasure> allPerformanceMeasures, Models.Project project, bool showExemptYears)
        {
            ShowExemptYears        = showExemptYears;
            ProjectID              = project.ProjectID;
            AllPerformanceMeasures = allPerformanceMeasures.SortByOrderThenName().Select(x => new PerformanceMeasureSimple(x)).ToList();
            var performanceMeasureSubcategories =
                allPerformanceMeasures.SelectMany(x => x.PerformanceMeasureSubcategories).Distinct(new HavePrimaryKeyComparer <PerformanceMeasureSubcategory>()).ToList();

            AllPerformanceMeasureSubcategories      = performanceMeasureSubcategories.Select(x => new PerformanceMeasureSubcategorySimple(x)).ToList();
            AllPerformanceMeasureSubcategoryOptions = performanceMeasureSubcategories.SelectMany(y => y.PerformanceMeasureSubcategoryOptions.Select(z => new PerformanceMeasureSubcategoryOptionSimple(z))).ToList();
            AllProjects         = allProjects;
            CalendarYearStrings = FirmaDateUtilities.ReportingYearsForUserInput().OrderByDescending(x => x.CalendarYear).ToList();
        }
예제 #18
0
        public static List <int> CalculateCalendarYearRangeForExpenditures(this IEnumerable <ProjectGrantAllocationExpenditure> projectGrantAllocationExpenditures, GrantAllocation grantAllocation)
        {
            var existingYears = projectGrantAllocationExpenditures.Select(x => x.CalendarYear).ToList();
            var grantAllocationProjectsWhereYouAreTheGrantAllocationMinCalendarYear = grantAllocation.ProjectsWhereYouAreTheGrantAllocationMinCalendarYear;

            return(FirmaDateUtilities.CalculateCalendarYearRangeAccountingForExistingYears(existingYears,
                                                                                           grantAllocationProjectsWhereYouAreTheGrantAllocationMinCalendarYear.HasValue ?
                                                                                           (DateTime?)new DateTime(grantAllocationProjectsWhereYouAreTheGrantAllocationMinCalendarYear.Value, 1, 1) : null,
                                                                                           grantAllocation.ProjectsWhereYouAreTheGrantAllocationMaxCalendarYear,
                                                                                           DateTime.Today.Year,
                                                                                           MultiTenantHelpers.GetMinimumYear(),
                                                                                           null));
        }
예제 #19
0
        public BasicsValidationResult(ProjectFirmaModels.Models.ProjectUpdate projectUpdate)
        {
            _warningMessages = new List <string>();

            if (projectUpdate.PlanningDesignStartYear == null)
            {
                _warningMessages.Add(PlanningDesignStartYearIsRequired);
            }
            if (projectUpdate.ImplementationStartYear == null && projectUpdate.ProjectStage != ProjectStage.Terminated && projectUpdate.ProjectStage != ProjectStage.Deferred)
            {
                _warningMessages.Add(ImplementationStartYearIsRequired);
            }

            if ((projectUpdate.ProjectStage == ProjectStage.Completed || projectUpdate.ProjectStage == ProjectStage.PostImplementation) && projectUpdate.CompletionYear == null)
            {
                _warningMessages.Add(CompletionYearIsRequired);
            }

            if (GeneralUtility.IsNullOrEmptyOrOnlyWhitespace(projectUpdate.ProjectDescription))
            {
                _warningMessages.Add(ProjectDescriptionIsRequired);
            }

            var currentYear = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();

            if ((projectUpdate.ProjectStage == ProjectStage.Completed || projectUpdate.ProjectStage == ProjectStage.PostImplementation) && projectUpdate.CompletionYear > currentYear)
            {
                _warningMessages.Add(CompletionYearShouldBeLessThanCurrentYear);
            }
            if (projectUpdate.ProjectStage == ProjectStage.PlanningDesign && projectUpdate.PlanningDesignStartYear > currentYear)
            {
                _warningMessages.Add(PlanningDesignStartYearShouldBeLessThanCurrentYear);
            }
            if (projectUpdate.ProjectStage == ProjectStage.Implementation && projectUpdate.ImplementationStartYear > currentYear)
            {
                _warningMessages.Add(ImplementationStartYearShouldBeLessThanCurrentYear);
            }

            if (projectUpdate.ImplementationStartYear < projectUpdate.PlanningDesignStartYear)
            {
                _warningMessages.Add(FirmaValidationMessages.ImplementationStartYearGreaterThanPlanningDesignStartYear);
            }
            if (projectUpdate.CompletionYear < projectUpdate.ImplementationStartYear)
            {
                _warningMessages.Add(FirmaValidationMessages.CompletionYearGreaterThanEqualToImplementationStartYear);
            }
            if (projectUpdate.CompletionYear < projectUpdate.PlanningDesignStartYear)
            {
                _warningMessages.Add(FirmaValidationMessages.CompletionYearGreaterThanEqualToPlanningDesignStartYear);
            }
        }
예제 #20
0
 public ViewDataForAngularClass(ProjectUpdateBatch projectUpdateBatch,
                                List <FundingSourceSimple> allFundingSources,
                                List <CostTypeSimple> allCostTypes,
                                List <int> requiredCalendarYearRange,
                                IEnumerable <SelectListItem> fundingTypes)
 {
     RequiredCalendarYearRange = requiredCalendarYearRange;
     AllFundingSources         = allFundingSources;
     AllCostTypes         = allCostTypes;
     ProjectID            = projectUpdateBatch.ProjectID;
     ProjectUpdateBatchID = projectUpdateBatch.ProjectUpdateBatchID;
     FundingTypes         = fundingTypes;
     MaxYear = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();
 }
        public void ProjectUpdateYearRangesTest()
        {
            var projectUpdate = TestFramework.TestProjectUpdate.Create();

            projectUpdate.ProjectStageID = ProjectStage.Completed.ProjectStageID;
            var warningMessages = new BasicsValidationResult(projectUpdate).GetWarningMessages();

            Assert.That(warningMessages.Contains(BasicsValidationResult.PlanningDesignStartYearIsRequired));
            Assert.That(warningMessages.Contains(BasicsValidationResult.ImplementationStartYearIsRequired));
            Assert.That(warningMessages.Contains(BasicsValidationResult.CompletionYearIsRequired));

            projectUpdate.CompletionYear = 2007;
            warningMessages = new BasicsValidationResult(projectUpdate).GetWarningMessages();

            Assert.That(warningMessages.Contains(BasicsValidationResult.PlanningDesignStartYearIsRequired));
            Assert.That(warningMessages.Contains(BasicsValidationResult.ImplementationStartYearIsRequired));
            Assert.That(!warningMessages.Contains(BasicsValidationResult.CompletionYearIsRequired));

            projectUpdate.ImplementationStartYear = 2010;
            warningMessages = new BasicsValidationResult(projectUpdate).GetWarningMessages();

            Assert.That(warningMessages.Contains(BasicsValidationResult.PlanningDesignStartYearIsRequired));
            Assert.That(!warningMessages.Contains(BasicsValidationResult.ImplementationStartYearIsRequired));
            Assert.That(!warningMessages.Contains(BasicsValidationResult.CompletionYearIsRequired));
            Assert.That(warningMessages.Contains(FirmaValidationMessages.CompletionYearGreaterThanEqualToImplementationStartYear));

            projectUpdate.ImplementationStartYear = 2006;
            warningMessages = new BasicsValidationResult(projectUpdate).GetWarningMessages();

            Assert.That(!warningMessages.Contains(FirmaValidationMessages.CompletionYearGreaterThanEqualToImplementationStartYear));

            // This should always be the next calendar year, I believe -- SLG 1/2/2020 (writing after this test started crashing)
            int nextCalendarYear = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting() + 1;

            projectUpdate.ProjectStageID          = ProjectStage.PlanningDesign.ProjectStageID;
            projectUpdate.PlanningDesignStartYear = nextCalendarYear;
            warningMessages = new BasicsValidationResult(projectUpdate).GetWarningMessages();

            Assert.That(!warningMessages.Contains(BasicsValidationResult.PlanningDesignStartYearIsRequired));
            Assert.That(warningMessages.Contains(BasicsValidationResult.PlanningDesignStartYearShouldBeLessThanCurrentYear));
            Assert.That(warningMessages.Contains(FirmaValidationMessages.ImplementationStartYearGreaterThanPlanningDesignStartYear));


            projectUpdate.ProjectStageID          = ProjectStage.Implementation.ProjectStageID;
            projectUpdate.ImplementationStartYear = nextCalendarYear;
            warningMessages = new BasicsValidationResult(projectUpdate).GetWarningMessages();

            Assert.That(warningMessages.Contains(BasicsValidationResult.ImplementationStartYearShouldBeLessThanCurrentYear));
        }
예제 #22
0
        public static List <int> CalculateCalendarYearRangeForExpenditures(this IList <ProjectGrantAllocationExpenditureUpdate> projectGrantAllocationExpenditureUpdates, ProjectUpdate projectUpdate)
        {
            if (projectUpdate.GetCompletionYear() < projectUpdate.GetImplementationStartYear())
            {
                return(new List <int>());
            }
            if (projectUpdate.GetCompletionYear() < projectUpdate.PlannedDate.GetValueOrDefault().Year)
            {
                return(new List <int>());
            }

            var existingYears = projectGrantAllocationExpenditureUpdates.Select(x => x.CalendarYear).ToList();

            return(FirmaDateUtilities.CalculateCalendarYearRangeForExpendituresAccountingForExistingYears(existingYears, projectUpdate, FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting()));
        }
        public static List <int> CalculateCalendarYearRangeForExpenditures(this IList <ProjectFundingSourceExpenditureUpdate> projectFundingSourceExpenditureUpdates, ProjectUpdate projectUpdate)
        {
            if (projectUpdate.CompletionYear < projectUpdate.ImplementationStartYear)
            {
                return(new List <int>());
            }
            if (projectUpdate.CompletionYear < projectUpdate.PlanningDesignStartYear)
            {
                return(new List <int>());
            }

            var existingYears = projectFundingSourceExpenditureUpdates.Select(x => x.CalendarYear).ToList();

            return(FirmaDateUtilities.CalculateCalendarYearRangeForExpendituresAccountingForExistingYears(existingYears, projectUpdate, FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting()));
        }
예제 #24
0
        public List <PerformanceMeasureSubcategoriesTotalReportedValue> SubcategoriesTotalReportedValues(Person currentPerson)
        {
            var groupByProjectAndSubcategory =
                GetReportedPerformanceMeasureValues(currentPerson)
                .Where(x => FirmaDateUtilities.DateIsInReportingRange(x.CalendarYear))
                .GroupBy(x => new { x.Project, x.PerformanceMeasureSubcategoriesAsString })
                .ToList();

            return
                (groupByProjectAndSubcategory.Select(
                     reportedValuesGroup =>
                     new PerformanceMeasureSubcategoriesTotalReportedValue(reportedValuesGroup.Key.Project,
                                                                           reportedValuesGroup.First().PerformanceMeasureSubcategoryOptions,
                                                                           this,
                                                                           reportedValuesGroup.Sum(x => x.ReportedValue))).ToList());
        }
        public decimal?CalculateWeightedTotalExpenditure()
        {
            var reportedValuesForAllSubcategories = PerformanceMeasure.GetReportedPerformanceMeasureValues(Project)
                                                    .Where(x => FirmaDateUtilities.DateIsInReportingRange(x.CalendarYear))
                                                    .Sum(x => x.ReportedValue ?? 0);

            if (Math.Abs(reportedValuesForAllSubcategories) < double.Epsilon)
            {
                return(null);
            }

            var projectGrantAllocationExpenditures = Project.ProjectGrantAllocationExpenditures.Where(x => FirmaDateUtilities.DateIsInReportingRange(x.CalendarYear)).ToList();
            var weight = TotalReportedValue / reportedValuesForAllSubcategories;

            return(projectGrantAllocationExpenditures.Sum(x => x.ExpenditureAmount) * Convert.ToDecimal(weight));
        }
        public static List <PerformanceMeasureSubcategoriesTotalReportedValue> SubcategoriesTotalReportedValues(FirmaSession currentFirmaSession, PerformanceMeasure performanceMeasure)
        {
            var groupByProjectAndSubcategory =
                performanceMeasure.GetReportedPerformanceMeasureValues(currentFirmaSession)
                .Where(x => FirmaDateUtilities.DateIsInReportingRange(x.CalendarYear))
                .GroupBy(x => new { x.Project, PerformanceMeasureSubcategoriesAsString = x.GetPerformanceMeasureSubcategoriesAsString() })
                .ToList();

            return
                (groupByProjectAndSubcategory.Select(
                     reportedValuesGroup =>
                     new PerformanceMeasureSubcategoriesTotalReportedValue(reportedValuesGroup.Key.Project,
                                                                           reportedValuesGroup.First().GetPerformanceMeasureSubcategoryOptions(),
                                                                           performanceMeasure,
                                                                           reportedValuesGroup.Sum(x => x.GetReportedValue()))).ToList());
        }
예제 #27
0
        public ProjectTimelineUpdateEvent(ProjectUpdateBatch projectUpdateBatch)
        {
            var approvedProjectUpdateHistory = projectUpdateBatch.ProjectUpdateHistories.First(x => x.ProjectUpdateState == ProjectUpdateState.Approved);

            Date        = approvedProjectUpdateHistory.TransitionDate;
            DateDisplay = Date.ToString("MMM dd, yyyy");
            FiscalYear  = FirmaDateUtilities.CalculateFiscalYearForTenant(Date);
            Quarter     = (Quarter)FirmaDateUtilities.CalculateQuarterForTenant(Date);
            ProjectTimelineEventType       = ProjectTimelineEventType.Update;
            TimelineEventTypeDisplayName   = "Update";
            TimelineEventPersonDisplayName = approvedProjectUpdateHistory.UpdatePerson.GetPersonDisplayNameWithContactTypesListForProject(projectUpdateBatch.Project);
            ProjectTimelineSide            = ProjectTimelineSide.Left;
            EditButton   = new HtmlString(string.Empty);
            DeleteButton = new HtmlString(string.Empty);
            ShowDetailsLinkHtmlString = ProjectTimeline.MakeProjectUpdateDetailsLinkButton(projectUpdateBatch);
        }
예제 #28
0
 public EditProjectFundingSourceBudgetByCostTypeViewDataForAngular(ProjectFirmaModels.Models.ProjectUpdateBatch projectUpdateBatch,
                                                                   List <FundingSourceSimple> allFundingSources,
                                                                   List <CostTypeSimple> allCostTypes,
                                                                   List <int> requiredCalendarYearRange,
                                                                   IEnumerable <SelectListItem> fundingTypes)
 {
     RequiredCalendarYearRange = requiredCalendarYearRange;
     AllFundingSources         = allFundingSources;
     AllCostTypes   = allCostTypes;
     ProjectID      = projectUpdateBatch.ProjectID;
     FundingTypes   = fundingTypes;
     MaxYear        = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();
     UseFiscalYears = MultiTenantHelpers.UseFiscalYears();
     ObligationItemBudgetRollUps  = projectUpdateBatch.Project.GetObligationItemBudgetRollUpByYearAndCostTypeAndFundingSourceSimples();
     ObligationItemInvoiceRollUps = projectUpdateBatch.Project.GetObligationItemInvoiceRollUpByYearAndCostTypeAndFundingSourceSimples();
 }
예제 #29
0
        public IEnumerable <ValidationResult> Validate(ValidationContext validationContext)
        {
            if (ImplementationStartYear < PlanningDesignStartYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(
                                 FirmaValidationMessages.ImplementationStartYearGreaterThanPlanningDesignStartYear,
                                 m => m.ImplementationStartYear));
            }

            if (CompletionYear < ImplementationStartYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(
                                 FirmaValidationMessages.CompletionYearGreaterThanEqualToImplementationStartYear,
                                 m => m.CompletionYear));
            }

            if (ProjectStageID == ProjectStage.Completed.ProjectStageID && !CompletionYear.HasValue)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>($"Since the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the Completed stage, the Completion year is required", m => m.CompletionYear));
            }

            if (ProjectStageID == ProjectStage.PostImplementation.ProjectStageID && !CompletionYear.HasValue)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>($"Since the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the Post-Implementation stage, the Completion year is required", m => m.CompletionYear));
            }

            var isCompletedOrPostImplementation = ProjectStageID == ProjectStage.Completed.ProjectStageID || ProjectStageID == ProjectStage.PostImplementation.ProjectStageID;
            var currentYear = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();

            if (isCompletedOrPostImplementation && CompletionYear > currentYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(
                                 $"The {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in Completed or Post-Implementation stage; the Completion Year must be less than or equal to the current year",
                                 m => m.CompletionYear));
            }

            if (!string.IsNullOrEmpty(BpaProjectNumber))
            {
                var regexMatch = Regex.Match(BpaProjectNumber, "^" + ProjectModelExtensions.BpaProjectNumberRegexString);
                if (!regexMatch.Success)
                {
                    yield return(new SitkaValidationResult <BasicsViewModel, string>(
                                     $"You must enter a valid {FieldDefinitionEnum.BpaProjectNumber.ToType().GetFieldDefinitionLabel()} (e.g. XXXX-XXX-XX).",
                                     m => m.BpaProjectNumber));
                }
            }
        }
예제 #30
0
        public ProjectTimelineProjectStatusChangeEvent(ProjectProjectStatus projectProjectStatus, bool canEditProjectProjectStatus, bool canEditFinalStatusReport)
        {
            Date        = projectProjectStatus.ProjectProjectStatusUpdateDate;
            DateDisplay = Date.ToString("MMM dd, yyyy");
            FiscalYear  = FirmaDateUtilities.CalculateFiscalYearForTenant(Date);
            Quarter     = (Quarter)FirmaDateUtilities.CalculateQuarterForTenant(Date);
            ProjectTimelineEventType       = ProjectTimelineEventType.ProjectStatusChange;
            TimelineEventTypeDisplayName   = projectProjectStatus.IsFinalStatusUpdate ? "Final Status Update" : "Status Updated";
            TimelineEventPersonDisplayName = projectProjectStatus.ProjectProjectStatusCreatePerson.GetPersonDisplayNameWithContactTypesListForProject(projectProjectStatus.Project);
            ProjectTimelineSide            = ProjectTimelineSide.Right;

            EditButton   = ProjectTimeline.MakeProjectStatusEditLinkButton(projectProjectStatus, canEditProjectProjectStatus, canEditFinalStatusReport);
            DeleteButton = ProjectTimeline.MakeProjectStatusDeleteLinkButton(projectProjectStatus, canEditProjectProjectStatus, canEditFinalStatusReport);
            Color        = projectProjectStatus.ProjectStatus.ProjectStatusColor;
            ShowDetailsLinkHtmlString = ProjectTimeline.MakeProjectStatusDetailsLinkButton(projectProjectStatus);
            ProjectProjectStatus      = projectProjectStatus;
        }