No Metadata Documentation available.
Inheritance: ObjectContext
        public void CrossListedCourses_CommonCourse()
        {
            ApiController target = new ApiController();
              string courseID = ConstructCourseID(CourseID.FromString("ART","107"), true);
              JsonResult actual = target.CrossListedCourses(courseID, "** INVALID YRQ **");

              Assert.IsNotNull(actual, "Returned Result is NULL");
              Assert.IsNotNull(actual.Data, "JSON data is NULL");
              Assert.IsInstanceOfType(actual.Data, typeof(IEnumerable<CrossListedCourseModel>));

              IEnumerable<CrossListedCourseModel> obj = actual.Data as IEnumerable<CrossListedCourseModel>;
              Assert.IsNotNull(obj);

              string[] sectionIDs = obj.Select(o => o.SectionID.ToString()).ToArray();

              if (sectionIDs.Length > 0)
              {
            using (ClassScheduleDb db = new ClassScheduleDb())
            {
              IQueryable<SectionCourseCrosslisting> crosslistings = from x in db.SectionCourseCrosslistings
                                                                where sectionIDs.Contains(x.ClassID)
                                                                select x;
              Assert.IsTrue(crosslistings.Any(), "Did not find matching cross-listing record in the Class Schedule database. ('{0}' => [{1}]", courseID, sectionIDs.Mash());
            }
              }
              else
              {
            Assert.Inconclusive("The method did not return any cross-linked SectionIDs for '{0}'", courseID);
              }
        }
 /// <summary>
 /// Finds a <see cref="Subject"/> based on its <paramref name="slug"/> identifier
 /// </summary>
 /// <param name="slug">The slug identifier for a given <see cref="Subject"/></param>
 /// <returns><see cref="Subject"/> if found, otherwise <see langword="null" /></returns>
 public static Subject GetSubject(string slug)
 {
     using (ClassScheduleDb context = new ClassScheduleDb())
     {
         Subject subject = context.Subjects.Where(s => s.Slug.Equals(slug, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
         return subject;
     }
 }
        public ActionResult AllClasses(string letter, string format)
        {
            using (OdsRepository repository = new OdsRepository(HttpContext))
            {
                // TODO: Refactor the following code into its own method
                // after reconciling the noted differences between AllClasses() and YearQuarter() - 4/27/2012, [email protected]
                using (ClassScheduleDb db = new ClassScheduleDb())
                {
              // force CoursePrefixes to load up front for Subjects (otherwise we get an error trying to load after db has been disposed)
              db.ContextOptions.LazyLoadingEnabled = false;
              IList<Subject> subjects = db.Subjects.Include("CoursePrefixes").ToList();

              IList<char> subjectLetters = subjects.Select(s => s.Title.First()).Distinct().ToList();
              if (letter != null)
                    {
            subjects = subjects.Where(s => s.Title.StartsWith(letter, StringComparison.OrdinalIgnoreCase)).ToList();
                    }

            #if DEBUG
              Debug.Print("======= Subject list =======");
                  foreach (Subject subject in subjects)
                  {
                    Debug.Print("{0} ({1})", subject.Title, subject.CoursePrefixes.Select(p => p.CoursePrefixID).ToArray().Mash(", "));
                  }
              Debug.Print("===== END Subject list =====");
            #endif
              // Construct the model
              AllClassesModel model = new AllClassesModel
              {
            CurrentQuarter = repository.CurrentYearQuarter,
            NavigationQuarters = Helpers.GetYearQuarterListForMenus(repository),
            Subjects = subjects.Select(s => new SubjectModel
                                              {
                                                Title = s.Title,
                                                Slug = s.Slug,
                                                CoursePrefixes = s.CoursePrefixes.Select(p => p.CoursePrefixID).ToList()
                                              }).ToList(),
            LettersList = subjectLetters,
            ViewingLetter = String.IsNullOrEmpty(letter) ? (char?)null : letter.First()
              };

              if (format == "json")
              {
            // NOTE: AllowGet exposes the potential for JSON Hijacking (see http://haacked.com/archive/2009/06/25/json-hijacking.aspx)
            // but is not an issue here because we are receiving and returning public (e.g. non-sensitive) data
            return Json(model, JsonRequestBehavior.AllowGet);
              }

              // set up all the ancillary data we'll need to display the View
                    SetCommonViewBagVars(repository, string.Empty, letter);
                    ViewBag.LinkParams = Helpers.getLinkParams(Request);

              return View(model);
                }
            }
        }
        /// <summary>
        /// Takes a course <paramref name="prefix"/> parameter and returns all <see cref="Subject"/>s which own the prefix <see cref="Subject"/> entity.
        /// </summary>
        /// <param name="prefix"></param>
        /// <returns>The a list of the matching <see cref="Subject"/> entities</returns>
        public static Subject GetSubjectFromPrefix(string prefix)
        {
            Subject result = null;
              using (ClassScheduleDb db = new ClassScheduleDb())
              {
            // The CoursePrefixID is the primary key, so we know there will not be more than one result
            result = db.SubjectsCoursePrefixes.Where(s => s.CoursePrefixID.Equals(prefix, StringComparison.OrdinalIgnoreCase))
                                           .Select(s => s.Subject).FirstOrDefault();
              }

              if (result == null)
              {
            _log.Warn(m => m("Failed to retrieve Subject record for PrefixID '{0}'", prefix));
            return result;
              }

              return result;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="yearQuarter"></param>
        /// <returns></returns>
        public static IList<ScheduleCoursePrefix> GetSubjectList(string yearQuarter)
        {
            IList<ScheduleCoursePrefix> subjectList;
            using (OdsRepository db = new OdsRepository())
            {
              IList<CoursePrefix> data;
              data = string.IsNullOrWhiteSpace(yearQuarter) || yearQuarter.Equals("All", StringComparison.OrdinalIgnoreCase)
                   ? db.GetCourseSubjects()
                   : db.GetCourseSubjects(YearQuarter.FromFriendlyName(yearQuarter));
              IList<string> apiSubjects = data.Select(s => s.Subject).ToList();

              using (ClassScheduleDb classScheduleDb = new ClassScheduleDb())
              {
            // Entity Framework doesn't support all the functionality that LINQ does, so first grab the records from the database...
            var dbSubjects = (from s in classScheduleDb.Subjects
                              join p in classScheduleDb.SubjectsCoursePrefixes on s.SubjectID equals p.SubjectID
                              select new
                                       {
                                         s.Slug,
                                         p.CoursePrefixID,
                                         s.Title
                                       })
              .ToList();
            // ...then apply the necessary filtering (e.g. TrimEnd() - which isn't fully supported by EF
            subjectList = (from s in dbSubjects
                           // TODO: replace hard-coded '&' with CommonCourseChar from .config
                           where apiSubjects.Contains(s.CoursePrefixID.TrimEnd('&'))
                           select new ScheduleCoursePrefix
                                    {
                                      Slug = s.Slug,
                                      Subject = s.CoursePrefixID,
                                      Title = s.Title
                                    })
              .OrderBy(s => s.Title)
              .Distinct()
              .ToList();
              }
            }
            return subjectList;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="db"></param>
        /// <param name="searchterm"></param>
        /// <param name="yrq"></param>
        /// <returns></returns>
        private SearchResultNoSectionModel GetNoSectionSearchResults(ClassScheduleDb db, string searchterm, YearQuarter yrq)
        {
            SqlParameter[] parms = {
                            new SqlParameter("SearchWord", searchterm),
                            new SqlParameter("YearQuarterID", yrq.ID)
                                   };

              SearchResultNoSectionModel model = new SearchResultNoSectionModel {SearchedYearQuarter = yrq};
            using (_profiler.Step("Executing 'other classes' stored procedure"))
              {
            model.NoSectionSearchResults = db.ExecuteStoreQuery<SearchResultNoSection>("usp_CourseSearch @SearchWord, @YearQuarterID", parms).ToList();
              }
              return model;
        }
        //
        // POST: /Api/Subjects
        /// <summary>
        /// Retrieves and updates Seats Available data for the specified <see cref="Section"/>
        /// </summary>
        /// <param name="classID"></param>
        /// <returns></returns>
        public ActionResult GetSeats(string classID)
        {
            int? seats = null;
              string friendlyTime = string.Empty;

              string itemNumber = classID.Substring(0, 4);
              string yrq = classID.Substring(4, 4);

              CourseHPQuery query = new CourseHPQuery();
              int hpSeats = query.FindOpenSeats(itemNumber, yrq);

              using (ClassScheduleDb db = new ClassScheduleDb())
              {
            //if the HP query didn't fail, save the changes. Otherwise, leave the SeatAvailability table alone.
            //This way, the correct number of seats can be pulled by the app and displayed instead of updating the
            //table with a 0 for seats available.
            if (hpSeats >= 0)
            {
              IQueryable<SectionSeat> seatsAvailableLocal = from s in db.SectionSeats
                                                        where s.ClassID == classID
                                                        select s;
              int rows = seatsAvailableLocal.Count();

              if (rows > 0)
              {
            // TODO: Should only be updating one record
            //update the value
            foreach (SectionSeat seat in seatsAvailableLocal)
            {
              seat.SeatsAvailable = hpSeats;
              seat.LastUpdated = DateTime.Now;
            }
              }
              else
              {
            //insert the value
            SectionSeat newseat = new SectionSeat();
            newseat.ClassID = classID;
            newseat.SeatsAvailable = hpSeats;
            newseat.LastUpdated = DateTime.Now;

            db.SectionSeats.AddObject(newseat);
              }

              db.SaveChanges();
            }

            // retrieve updated seats data
            IQueryable<SectionSeat> seatsAvailable = from s in db.SectionSeats
                                                 where s.ClassID == classID
                                                 select s;

            SectionSeat newSeat = seatsAvailable.First();

            seats = newSeat.SeatsAvailable;
            friendlyTime = newSeat.LastUpdated.GetValueOrDefault().ToString("h:mm tt").ToLower();
              }

              string jsonReturnValue = string.Format("{0}|{1}", seats, friendlyTime);
              return Json(jsonReturnValue);
        }
        public ActionResult UpdateSectionFootnote(string classId, string newFootnoteText)
        {
            bool result = false;

            // Trim any whitespace
            if (!String.IsNullOrEmpty(newFootnoteText))
            {
                newFootnoteText = newFootnoteText.Trim();
            }

            if (HttpContext.User.Identity.IsAuthenticated == true)
            {
                using (ClassScheduleDb db = new ClassScheduleDb())
                {
                    IQueryable<SectionsMeta> footnotes = db.SectionsMetas.Where(s => s.ClassID == classId);

                    if (footnotes.Count() > 0)
                    {
                        // Should only update one section
                        foreach (SectionsMeta footnote in footnotes)
                        {
                            if (!String.Equals(footnote.Footnote, newFootnoteText))
                            {
                                footnote.Footnote = newFootnoteText;
                                footnote.LastUpdated = DateTime.Now;
                                //footnote.LastUpdatedBy

                                result = true;
                            }
                        }
                    }
                    else if (classId != null && !String.IsNullOrWhiteSpace(newFootnoteText))
                    {
                        // Insert footnote
                        SectionsMeta newFootnote = new SectionsMeta();
                        newFootnote.ClassID = classId;
                        newFootnote.Footnote = newFootnoteText;
                        newFootnote.LastUpdated = DateTime.Now;

                        db.SectionsMetas.AddObject(newFootnote);
                        result = true;
                    }

                    db.SaveChanges();
                }
            }

            return Json(new { result = result, footnote = newFootnoteText });
        }
        public ActionResult ClassEdit(FormCollection collection)
        {
            string referrer = collection["referrer"];

            if (HttpContext.User.Identity.IsAuthenticated)
            {
                string courseId = collection["CourseID"];
                string username = HttpContext.User.Identity.Name;
                string footnote = collection["Footnote"];

                footnote = Helpers.StripHtml(footnote);

                if (ModelState.IsValid)
                {
              CourseMeta itemToUpdate;

              using (ClassScheduleDb db = new ClassScheduleDb())
                    {
                      bool exists = db.CourseMetas.Any(c => c.CourseID == courseId);
                      itemToUpdate = exists ? db.CourseMetas.Single(c => c.CourseID == courseId) : new CourseMeta();

                        itemToUpdate.CourseID = courseId;
                        itemToUpdate.Footnote = footnote;
                        itemToUpdate.LastUpdated = DateTime.Now;
                        itemToUpdate.LastUpdatedBy = username;

                      if (!exists)
                      {
                        db.CourseMetas.AddObject(itemToUpdate);
                      }

                        db.SaveChanges();
                    }
                }
            }

            return Redirect(referrer);
        }
        public JsonResult CrossListedCourses(string courseID, string yearQuarterID)
        {
            // TODO: Validate incoming yearQuarterID value
              // see https://github.com/BellevueCollege/CtcApi/issues/8

            if (yearQuarterID.Length != 4)
            {
              _log.Error(m => m("An invalid YearQuarterID was provided for looking up cross-listed sections: '{0}'", yearQuarterID));
            }
            else
            {
              using (ClassScheduleDb db = new ClassScheduleDb())
              {
            string[] classIDs = (from c in db.SectionCourseCrosslistings
                                 where c.CourseID == courseID
                                       && c.ClassID.EndsWith(yearQuarterID)
                                 select c.ClassID).ToArray();

            if (!classIDs.Any())
            {
            _log.Warn(m => m("No cross-listed Sections were found for Course '{0}' in '{1}'", courseID, yearQuarterID));
              }
            else
            {
              int count = classIDs.Count();
              _log.Trace(m => m("{0} cross-listed sections found for '{1}': [{2}]", count, courseID, classIDs.Mash()));

            // HACK: SectionID constructors are currently protected, so we have to manually create them
              IList<ISectionID> sectionIDs = new List<ISectionID>(count);
              foreach (string id in classIDs)
              {
                sectionIDs.Add(SectionID.FromString(id));
              }

              // write a warning to the log if we've got too many courses cross-listed with this section
              if (_log.IsWarnEnabled && sectionIDs.Count > MAX_COURSE_CROSSLIST_WARNING_THRESHOLD)
              {
                _log.Warn(m => m("Cross-listing logic assumes a very small number of Sections will be cross-listed with any given Course, but is now being asked to process {0} Sections for '{1}'. (This warning triggers when more than {2} are detected.)",
                                  sectionIDs.Count, courseID, MAX_COURSE_CROSSLIST_WARNING_THRESHOLD));
              }

              using (OdsRepository ods = new OdsRepository())
              {
                IList<Section> odsSections = ods.GetSections(sectionIDs);

                IList<SectionWithSeats> classScheduleSections = Helpers.GetSectionsWithSeats(yearQuarterID,
                                                                                             odsSections.ToList(), db);

                IList<CrossListedCourseModel> crosslistings = (from c in classScheduleSections
                                                               select new CrossListedCourseModel
                                                                        {
                                                                          // BUG: API doesn't property notify CourseID in derived class
                                                                          CourseID = CourseID.FromString(c.CourseID),
                                                                          SectionID = c.ID,
                                                                          // HACK: Remove IsCommonCourse property when API is fixed (see above)
                                                                          IsCommonCourse = c.IsCommonCourse,
                                                                          Credits = c.Credits,
                                                                          IsVariableCredits = c.IsVariableCredits,
                                                                          Title = c.CourseTitle
                                                                        }).ToList();

                // NOTE: AllowGet exposes the potential for JSON Hijacking (see http://haacked.com/archive/2009/06/25/json-hijacking.aspx)
                // but is not an issue here because we are receiving and returning public (e.g. non-sensitive) data
                return Json(crosslistings, JsonRequestBehavior.AllowGet);
              }
            }
              }
            }
            return Json(null, JsonRequestBehavior.AllowGet);
        }
Esempio n. 11
0
        /// <summary>
        /// Gathers a <see cref="Subject"/>'s related <see cref="Department"/>, <see cref="Division"/>, and <see cref="SubjectsCoursePrefix"/>s
        /// </summary>
        /// <param name="slug">The slug identifier for a given <see cref="Subject"/></param>
        /// <returns>An instance of <see cref="SubjectInfoResult"/> containing data related to the <see cref="Subject"/>, or null if the subject was not found.</returns>
        public static SubjectInfoResult GetSubjectInfo(string slug)
        {
            SubjectInfoResult result = null;
            using (ClassScheduleDb context = new ClassScheduleDb())
            {
                Subject subject = GetSubject(slug, context);
                if (subject == null)
                {
                    return result;
                }

            result = new SubjectInfoResult
            {
              Subject = subject,
              CoursePrefixes = subject.CoursePrefixes.ToList(),
              Department = subject.Department ?? new Department(),
            };
            result.Division = result.Department.Division ?? new Division();

            // If the url is a fully qualified url (e.g. http://continuinged.bellevuecollege.edu/about)
            // or empty just return it, otherwise prepend with the current school url.
            string deptUrl = result.Department.URL ?? string.Empty;
            if (!string.IsNullOrWhiteSpace(deptUrl) && !Regex.IsMatch(deptUrl, @"^https?://"))
            {
              result.Department.URL = deptUrl;
            }
            }

            return result;
        }
        /// <summary>
        /// Takes a Subject, ClassNum and CourseID and finds the CMS Footnote for the course.
        /// </summary>
        /// <param name="courseID"></param>
        private string GetCmsFootnote(ICourseID courseID)
        {
            using (ClassScheduleDb db = new ClassScheduleDb())
              {
            using (_profiler.Step("Getting app-specific Section records from DB"))
            {
              string fullCourseID = Helpers.BuildCourseID(courseID.Number, courseID.Subject.TrimEnd(), courseID.IsCommonCourse);
              CourseMeta item = db.CourseMetas.Where(s => s.CourseID.Trim().Equals(fullCourseID, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

              if (item != null)
              {
            return item.Footnote;
              }

            }
              }
              return null;
        }
Esempio n. 13
0
        /// <summary>
        /// Groups a list of Sections by course, into descriptive SectionBlocks
        /// </summary>
        /// <param name="sections">List of sections to group</param>
        /// <param name="db"></param>
        /// <returns>List of SectionBlock objects which describe the block of sections</returns>
        public static IList<SectionsBlock> GroupSectionsIntoBlocks(IList<SectionWithSeats> sections, ClassScheduleDb db)
        {
            #if DEBUG
              /* COMMENT THIS LINE TO DEBUG
              if (sections.Any(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "266"))
              {
            SectionWithSeats zengl266 = sections.Where(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "266").First();
            Debug.Print("\n{0} - {1} {2}\t[{4}]\t(Linked to: {3})\n", zengl266.ID, zengl266.CourseID, zengl266.CourseTitle, zengl266.LinkedTo, zengl266.IsLinked ? "LINKED" : string.Empty);
              }
              else
              {
            Debug.Print("\nENGL 266 - NOT FOUND AMONG SECTIONS.\n");
              }
              // END DEBUGGING */
            #endif
            MiniProfiler profiler = MiniProfiler.Current;

              IList<SectionsBlock> results = new List<SectionsBlock>();
              //we need to captuer linked classes and exclude from the export:
              // Linked section defintion: An item number linking a class to another class in the next quarter. Automatic registration into the linked
              //class occurs in batch registration for students enrolled in the class containing the ITM-YRQ-LINK.
              IList<SectionWithSeats> allLinkedSections = sections.Where(s => s.IsLinked).ToList();
              IList<SectionWithSeats> nonLinkedSections;

              // minimize trips to the database, since this collection should be relatively small
              IList<SectionCourseCrosslisting> crosslistings;
              using (profiler.Step("Retrieving Section/Course cross-listings"))
              {
            crosslistings = db.SectionCourseCrosslistings.ToList();
              }

              // sort by the markers indicators where we need to being a new block (w/ course title, etc.)
              /* TODO: Implement a more configurable sort method. */
              using (profiler.Step("Sorting sections in preparation for grouping and linking"))
              {
            #if DEBUG
              /* COMMENT THIS LINE TO DEBUG
            IEnumerable<SectionWithSeats> d1 = sections.Where(s => s.ID.ItemNumber.StartsWith("410"));
            // END DEBUGGING */
            #endif
            nonLinkedSections = sections.Where(s => !s.IsLinked)
                          .OrderBy(s => s.CourseNumber)
                          .ThenBy(s => allLinkedSections.Where(l => l.LinkedTo == s.ID.ItemNumber).Count())
                          .ThenBy(s => s.CourseTitle)
                          .ThenByDescending(s => s.IsVariableCredits)     // johanna.aqui 9/11/2014 moved IsVariableCredits & Credits above starttime to keep correct section group
                          .ThenBy(s => s.Credits)
                          .ThenBy(s => s.IsOnline)
                          .ThenBy(s => s.Offered.First().StartTime)
                          .ThenBy(s => s.IsTelecourse)
                          .ThenBy(s => s.IsHybrid)
                          .ThenBy(s => s.IsOnCampus)
                          .ThenBy(s => s.SectionCode).ToList();

            //nonLinkedSections = sections.Where(s => !s.IsLinked)
            //                  .OrderBy(s => s.CourseNumber)
            //                  .ThenBy(s => allLinkedSections.Where(l => l.LinkedTo == s.ID.ItemNumber).Count())
            //                  .ThenBy(s => s.CourseTitle)
            //                  .ThenByDescending(s => s.IsVariableCredits)
            //                  .ThenBy(s => s.Credits)
            //                  .ThenBy(s => s.IsTelecourse)
            //                  .ThenBy(s => s.IsOnline)
            //                  .ThenBy(s => s.IsHybrid)
            //                  .ThenBy(s => s.IsOnCampus)
            //                  .ThenBy(s => s.SectionCode).ToList();
              }

            #if DEBUG
              /* COMMENT THIS LINE TO DEBUG
            foreach (SectionWithSeats zs in nonLinkedSections.Where(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "101"))
            {
              Debug.Print("{0} - {1} {2}\t{3}\t(Linked sections: {4})", zs.ID, zs.CourseID, zs.CourseTitle, zs.IsLinked ? " [LINKED] " : string.Empty,
                      allLinkedSections.Count(l => l.LinkedTo == zs.ID.ItemNumber));
            }
              if (!allLinkedSections.Any(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "266"))
            {
              Debug.Print("\nENGL 266 - NOT FOUND AMONG LINKED SECTIONS.");
            }
            else
            {
            SectionWithSeats zengl266 = allLinkedSections.Where(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "266").First();
            Debug.Print("\n{0} - {1} {2}\t(Linked to: {3})", zengl266.ID, zengl266.CourseID, zengl266.CourseTitle, zengl266.LinkedTo);
              }

              if (!allLinkedSections.Any(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "246"))
            {
              Debug.Print("\nENGL& 246 - NOT FOUND AMONG LINKED SECTIONS.");
            }
            else
            {
            SectionWithSeats zengl246 = allLinkedSections.Where(s => s.CourseSubject.StartsWith("ENGL") && s.CourseNumber == "246").First();
            Debug.Print("\n{0} - {1} {2}\t(Linked to: {3})", zengl246.ID, zengl246.CourseID, zengl246.CourseTitle, zengl246.LinkedTo);
              }
              // END DEBUGGING */
            #endif

              // Group all the sections into course blocks and determine which sections linked
              using (profiler.Step("Grouping/linking by course"))
              {
            int processedCount = 0;
            while (processedCount < nonLinkedSections.Count)
            {
              SectionsBlock courseBlock = new SectionsBlock();
              courseBlock.LinkedSections = new List<SectionWithSeats>();

              IList<SectionWithSeats> remainingSections = nonLinkedSections.Skip(processedCount).ToList();
              SectionWithSeats firstSection = remainingSections.First();
              // TODO: Replace BuildCourseID() with this logic - and pull in CommonCourceChar from .config
              string blockCourseID = String.Format("{0}{1} {2}", firstSection.CourseSubject, firstSection.IsCommonCourse ? "&" : String.Empty, firstSection.CourseNumber);

              if (allLinkedSections.Any(l => l.LinkedTo == firstSection.ID.ItemNumber))
              {
            // If a Section has other Sections linked to it, then it should be displayed in its own block
            courseBlock.Sections = new List<SectionWithSeats> {firstSection};
              }
              else
              {
            courseBlock.Sections = remainingSections.TakeWhile(s =>
                                                               s.CourseID == firstSection.CourseID &&
                                                               s.CourseTitle == firstSection.CourseTitle &&
                                                               s.Credits == firstSection.Credits &&
                                                               s.IsVariableCredits == firstSection.IsVariableCredits &&
                                                               allLinkedSections.All(l => l.LinkedTo != s.ID.ItemNumber)
                                                               ).ToList();
              }

            #if DEBUG
              /* COMMENT THIS LINE TO DEBUG
              // use the following variable as a conditional for breakpoints
              bool foo = courseBlock.Sections.Any(s => s.CourseSubject == "ACCT");
              // END DEBUGGING */

              /* COMMENT THIS LINE TO DEBUG
              Debug.Print("\nProcessing block: {0} - {1} {2}\t{3}\t(Crosslinks: {4})", firstSection.ID, firstSection.CourseID,
                                                                                     firstSection.IsCommonCourse ? "(&)" : string.Empty,
                                                                                     firstSection.CourseTitle,
                                                                                     crosslistings.Count(x => x.CourseID == blockCourseID));
              // END DEBUGGING */
            #endif
              // Flag whether or not this course block is crosslisted with other sections offered in the same quarter
              courseBlock.IsCrosslisted = crosslistings.Any(x => x.CourseID == blockCourseID && x.ClassID.EndsWith(firstSection.Yrq.ID));

              // Find all links associated to each of the grouped sections
              foreach (SectionWithSeats sec in courseBlock.Sections)
              {
            SectionWithSeats sect = sec;  // Use copy of object to ensure cross-compiler compatibility
            List<SectionWithSeats> linkedSections = allLinkedSections.Where(s => sect != null && s.LinkedTo == sect.ID.ItemNumber).ToList();
            if (linkedSections.Count > 0)
            {
              courseBlock.LinkedSections.AddRange(linkedSections);
            }
              }

              // Get a list of common footnotes shared with every section in the block
              courseBlock.CommonFootnotes = ExtractCommonFootnotes(courseBlock.Sections);

              processedCount += courseBlock.Sections.Count();
              results.Add(courseBlock);
            }
              }

              return results;
        }
Esempio n. 14
0
        /// <summary>
        /// Common method to retrieve <see cref="SectionWithSeats"/> records
        /// </summary>
        /// <param name="currentYrq"></param>
        /// <param name="sections"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public static IList<SectionWithSeats> GetSectionsWithSeats(string currentYrq, IList<Section> sections, ClassScheduleDb db)
        {
            MiniProfiler profiler = MiniProfiler.Current;

            // ensure we're ALWAYS getting the latest data from the database (i.e. ignore any cached data)
            // Reference: http://forums.asp.net/post/2848021.aspx
            db.vw_Class.MergeOption = MergeOption.OverwriteChanges;

            IList<vw_Class> classes;
              using (profiler.Step("API::Get Class Schedule Specific Data()"))
              {
                classes = db.vw_Class.Where(c => c.YearQuarterID == currentYrq).ToList();
              }

            IList<SectionWithSeats> sectionsEnum;
              using (profiler.Step("Joining all data"))
              {
              sectionsEnum = (
                  from c in sections
                      join d in classes on c.ID.ToString() equals d.ClassID into t1
                  from d in t1.DefaultIfEmpty()
                                            join ss in db.SectionSeats on (d != null ? d.ClassID : "") equals ss.ClassID into t2
                                            from ss in t2.DefaultIfEmpty()
                                            join sm in db.SectionsMetas on (d != null ? d.ClassID : "") equals sm.ClassID into t3
                                            from sm in t3.DefaultIfEmpty()
                      // NOTE:  This logic assumes that data will only be saved in ClassScheduleDb after having come through
                      //        the filter of the CtcApi - which normalizes spacing of the CourseID field data.
                      join cm in db.CourseMetas on (d != null ? d.CourseID : "") equals cm.CourseID into t4
                                            from cm in t4.DefaultIfEmpty()
            orderby c.Credits ,c.Offered.First().StartTime, c.Yrq.ID descending    //9/15/2014 johanna.aqui, added credit and start time to sort order.  Order applied at different times and has different effects depending on the controller (Search, Classes, Scheduler)
                  select new SectionWithSeats {
                                ParentObject = c,
                                SeatsAvailable = ss != null ? ss.SeatsAvailable : Int32.MinValue,	// allows us to identify past quarters (with no availability info)
                          SeatsLastUpdated = (ss != null ? ss.LastUpdated.GetValueOrDefault() : DateTime.MinValue).ToString(Settings.Default.SeatUpdatedDateTimeFormat).ToLower(),
                                LastUpdated = (d != null ? d.LastUpdated.GetValueOrDefault() : DateTime.MinValue).ToString("h:mm tt").ToLower(),
                                                    SectionFootnotes = sm != null && !String.IsNullOrWhiteSpace(sm.Footnote) ? sm.Footnote : String.Empty,
                                                    CourseFootnotes = cm != null && !String.IsNullOrWhiteSpace(cm.Footnote) ? cm.Footnote : String.Empty,
                          CourseTitle = sm != null && !String.IsNullOrWhiteSpace(sm.Title) ? sm.Title : c.CourseTitle,
                                                    CustomDescription = sm != null && !String.IsNullOrWhiteSpace(sm.Description) ? sm.Description : String.Empty,
                }).OrderBy(s => s.CourseNumber).ThenBy(s => s.CourseTitle).ToList();

              string _availValue = "";
              if (HttpContext.Current.Request.QueryString["avail"] != null)
              {
              _availValue = HttpContext.Current.Request.QueryString["avail"].ToString();
              }
              if (_availValue == "Open")
              {
              sectionsEnum = (from open in sectionsEnum
                             where open.SeatsAvailable != 0
                             select open).ToList();
              }

            #if DEBUG
              /* COMMENT THIS LINE TO DEBUG
              if (sectionsEnum.Any(s => s.CourseSubject.StartsWith("ACCT") && s.CourseNumber == "203" && s.IsCommonCourse))
              {
            SectionWithSeats zSec = sectionsEnum.Where(s => s.CourseSubject.StartsWith("ACCT") && s.CourseNumber == "202" && s.IsCommonCourse).First();
            string s1 = zSec.ID.ToString();
            Debug.Print("\n{0} - {1} {2}\t{3}\t(Crosslinks: {4})\n", zSec.ID, zSec.CourseID, zSec.IsCommonCourse ? "(&)" : string.Empty, zSec.CourseTitle,
                                                                 db.SectionCourseCrosslistings.Select(x => x.ClassID).Distinct().Count(x => x == s1));
              }
              else
              {
            Debug.Print("\nACCT& 202 - NOT FOUND AMONG SECTIONS.\n");
              }
              // END DEBUGGING */
            #endif

            // Flag sections that are cross-linked with a Course
            foreach (string sec in db.SectionCourseCrosslistings.Select(x => x.ClassID).Distinct())
            {
              if (sectionsEnum.Any(s => s.ID.ToString() == sec))
              {
            sectionsEnum.Single(s => s.ID.ToString() == sec).IsCrossListed = true;
              }
            }
              }

            return sectionsEnum;
        }
Esempio n. 15
0
        /// <summary>
        /// Gathers a List of <see cref="SubjectsCoursePrefix"/> based on the <see cref="Subject"/>'s <paramref name="slug"/> identifier
        /// </summary>
        /// <param name="slug">The slug identifier for a given <see cref="Subject"/></param>
        /// <returns>A List of all <see cref="SubjectsCoursePrefix"/>s located for the given <see cref="Subject"/></returns>
        public static IList<string> GetSubjectPrefixes(string slug)
        {
            IList<string> result = new List<string>();
            using (ClassScheduleDb context = new ClassScheduleDb())
            {
                Subject subject = GetSubject(slug, context);
                if (subject == null)
                {
              // if we didn't find a custom subject relationship, use the URL slug
              result.Add(slug);
                }
                else
                {
              result = subject.CoursePrefixes.Select(p => p.CoursePrefixID).ToList();
            }
            }

            return result;
        }
Esempio n. 16
0
        /// <summary>
        /// Gathers a <see cref="Subject"/>'s related <see cref="Department"/>, <see cref="Division"/>, and <see cref="SubjectsCoursePrefix"/>s
        /// </summary>
        /// <param name="prefix">The prefix identifier for a given <see cref="Subject"/></param>
        /// <returns>An instance of <see cref="SubjectInfoResult"/> containing data related to the <see cref="Subject"/>, or null if the subject was not found.</returns>
        public static SubjectInfoResult GetSubjectInfoFromPrefix(string prefix)
        {
            SubjectInfoResult result = null;
            using (ClassScheduleDb context = new ClassScheduleDb())
            {
              Subject subject = (from s in context.Subjects
                                join p in context.SubjectsCoursePrefixes on s.SubjectID equals p.SubjectID into j
                                from sub in j
                                where sub.CoursePrefixID == prefix
                                select s).FirstOrDefault();

                if (subject == null)
                {
              _log.Warn(m => m("Failed to retrieve Subject record for PrefixID '{0}'", prefix));
                    return result;
                }

            result = new SubjectInfoResult
            {
              Subject = subject,
              CoursePrefixes = subject.CoursePrefixes.ToList(),
              Department = subject.Department ?? new Department(),
            };
            result.Division = result.Department.Division ?? new Division();

            // If the url is a fully qualified url (e.g. http://continuinged.bellevuecollege.edu/about)
            // or empty just return it, otherwise prepend with the current school url.
            string deptUrl = result.Department.URL ?? string.Empty;
            if (!string.IsNullOrWhiteSpace(deptUrl) && !Regex.IsMatch(deptUrl, @"^https?://"))
            {
              result.Department.URL = deptUrl;
            }
            }

            return result;
        }
        public ActionResult YearQuarter(String YearQuarter, string timestart, string timeend, string day_su, string day_m, string day_t, string day_w, string day_th, string day_f, string day_s, string f_oncampus, string f_online, string f_hybrid, string avail, string letter, string latestart, string numcredits, string format)
        {
            _log.Trace(m => m("Calling: [.../classes/{0}...] From (referrer): [{1}]", YearQuarter, Request.UrlReferrer));

              // TODO: come up with a better way to maintain various State flags
              ViewBag.Modality = Helpers.ConstructModalityList(f_oncampus, f_online, f_hybrid);
              ViewBag.Days = Helpers.ConstructDaysList(day_su, day_m, day_t, day_w, day_th, day_f, day_s);
              ViewBag.LinkParams = Helpers.getLinkParams(Request);
              ViewBag.timestart = timestart;
              ViewBag.timeend = timeend;
              ViewBag.latestart = latestart;
              ViewBag.avail = avail;
              IList<ISectionFacet> facets = Helpers.addFacets(timestart, timeend, day_su, day_m, day_t, day_w, day_th, day_f, day_s, f_oncampus, f_online, f_hybrid, avail, latestart, numcredits);

              YearQuarterModel model = new YearQuarterModel
              {
            ViewingSubjects = new List<SubjectModel>(),
            SubjectLetters = new List<char>(),
              };

              try
              {
            using (OdsRepository repository = new OdsRepository(HttpContext))
            {
              YearQuarter yrq = Helpers.DetermineRegistrationQuarter(YearQuarter, repository.CurrentRegistrationQuarter, RouteData);
              model.ViewingQuarter = yrq;

              model.NavigationQuarters = Helpers.GetYearQuarterListForMenus(repository);

              // set up all the ancillary data we'll need to display the View
              SetCommonViewBagVars(repository, avail, letter);

              // TODO: Refactor the following code to use ApiController.GetSubjectList()
              // after reconciling the noted differences between AllClasses() and YearQuarter() - 4/27/2012, [email protected]
              using (ClassScheduleDb db = new ClassScheduleDb())
              {
            // Compile a list of active subjects
            char[] commonCourseChar = _apiSettings.RegexPatterns.CommonCourseChar.ToCharArray();
            IList<string> activePrefixes = repository.GetCourseSubjects(yrq, facets).Select(p => p.Subject).ToList();

            IList<Subject> subjects = new List<Subject>();
            // NOTE: Unable to reduce the following loop to a LINQ statement because it complains about not being able to use TrimEnd(char[]) w/ LINQ-to-Entities
            // (Although it appears to be doing so just fine in the if statement below). - [email protected]
            foreach (Subject sub in db.Subjects)
            {
              // TODO: whether the CoursePrefix has active courses or not, any Prefix with a '&' will be included
              //			 because GetCourseSubjects() does not include the common course char.
              if (sub.CoursePrefixes.Select(sp => sp.CoursePrefixID).Any(sp => activePrefixes.Contains(sp.TrimEnd(commonCourseChar))))
              {
                subjects.Add(sub);
              }
            }

            model.SubjectLetters = subjects.Select(s => s.Title.First()).Distinct().ToList();
            model.ViewingSubjects = (letter != null
                                       ? subjects.Where(s => s.Title.StartsWith(letter, StringComparison.OrdinalIgnoreCase)).Distinct()
                                       : subjects
                                    ).Select(s => new SubjectModel
                                            {
                                              Title = s.Title,
                                              Slug = s.Slug,
                                              CoursePrefixes = s.CoursePrefixes.Select(p => p.CoursePrefixID).ToList()
                                            }
                                    ).ToList();

            if (format == "json")
            {
              // NOTE: AllowGet exposes the potential for JSON Hijacking (see http://haacked.com/archive/2009/06/25/json-hijacking.aspx)
              // but is not an issue here because we are receiving and returning public (e.g. non-sensitive) data
              JsonResult json = Json(model, JsonRequestBehavior.AllowGet);
              return json;
            }

            return View(model);
              }
            }
              }
              catch (ArgumentOutOfRangeException ex)
              {
            if (ex.Message.ToUpper().Contains("MUST BE A VALID QUARTER TITLE"))
            {
              throw new HttpException(404, string.Format("'{0}' is not a recognized Quarter.", YearQuarter), ex);
            }
            _log.Error(m => m("An unhandled ArgumentOutOfRangeException ocurred, returning an empty Model to the YearQuarter view."), ex);
              }
              catch (Exception ex)
              {
            _log.Error(m => m("An unhandled exception occurred, returning an empty Model to the YearQuarter view."), ex);
              }

              // empty model
              return View(model);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="db"></param>
        /// <param name="searchterm"></param>
        /// <param name="quarter"></param>
        /// <returns></returns>
        private IList<SearchResult> GetSearchResults(ClassScheduleDb db, string searchterm, string quarter)
        {
            SqlParameter[] parms = {
                            new SqlParameter("SearchWord", searchterm),
                            new SqlParameter("YearQuarterID", YearQuarter.ToYearQuarterID(quarter))
                                   };

            using (_profiler.Step("Executing search stored procedure"))
            {
                return db.ExecuteStoreQuery<SearchResult>("usp_ClassSearch @SearchWord, @YearQuarterID", parms).ToList();
            }
        }
        public ActionResult ClassEdit(string CourseNumber, string Subject, bool IsCommonCourse)
        {
            if (HttpContext.User.Identity.IsAuthenticated)
            {
                string fullCourseId = Helpers.BuildCourseID(CourseNumber, Subject, IsCommonCourse);
            ICourseID courseID = CourseID.FromString(fullCourseId);

                CourseMeta itemToUpdate = null;
                var hpFootnotes = string.Empty;
                string courseTitle = string.Empty;

                using (ClassScheduleDb db = new ClassScheduleDb())
                {
                    if(db.CourseMetas.Any(s => s.CourseID.Trim().ToUpper() == fullCourseId.ToUpper()))
                    {
                        //itemToUpdate = db.CourseFootnotes.Single(s => s.CourseID.Substring(0, 5).Trim().ToUpper() == subject.Trim().ToUpper() &&
                        //																				 s.CourseID.Trim().EndsWith(courseID.Number)
                        itemToUpdate = db.CourseMetas.Single(s => s.CourseID.Trim().ToUpper() == fullCourseId.ToUpper());
                    }

                    using (OdsRepository repository = new OdsRepository())
                    {
                      try
                        {
                            IList<Course> coursesEnum = repository.GetCourses(courseID);

                            foreach (Course course in coursesEnum)
                            {
                              hpFootnotes = course.Footnotes.ToArray().Mash(" ");

                // BUG: If more than one course is returned from the API, this will ignore all Titles except for the last one
                                courseTitle = course.Title;
                            }
                        }
                        catch(InvalidOperationException ex)
                        {
                            _log.Warn(m => m("Ignoring Exception while attempting to retrieve footnote and title data for CourseID '{0}'\n{1}", courseID, ex));
                        }
                    }

                  ClassFootnote localClass = new ClassFootnote();
                    localClass.CourseID = MvcApplication.SafePropertyToString(itemToUpdate, "CourseID", fullCourseId);
                    localClass.Footnote = MvcApplication.SafePropertyToString(itemToUpdate, "Footnote", string.Empty);
                    localClass.HPFootnote = hpFootnotes;
                    localClass.LastUpdated = MvcApplication.SafePropertyToString(itemToUpdate, "LastUpdated", string.Empty);
                    localClass.LastUpdatedBy = MvcApplication.SafePropertyToString(itemToUpdate, "LastUpdatedBy", string.Empty);
                    localClass.CourseTitle = courseTitle;

                    return PartialView(localClass);
                }
            }

            return PartialView();
        }
        //
        // GET: /Search/
        public ActionResult Index(string searchterm, string Subject, string quarter, string timestart, string timeend, string day_su, string day_m, string day_t, string day_w, string day_th, string day_f, string day_s, string f_oncampus, string f_online, string f_hybrid, string avail, string latestart, string numcredits, int p_offset = 0)
        {
            // We don't currently support quoted phrases. - 4/19/2012, [email protected]
            searchterm = searchterm.Replace("\"", string.Empty);

            // TODO: This needs to be configurable
            if (quarter == "CE")
            {
                Response.Redirect("http://www.campusce.net/BC/Search/Search.aspx?q=" + searchterm, true);
                return null;
            }

            if (String.IsNullOrEmpty(searchterm.Trim()))
            {
                return RedirectToAction("AllClasses", "Classes", new { YearQuarterID = quarter });
            }

            ViewBag.timestart = timestart;
            ViewBag.timeend = timeend;
              ViewBag.avail = avail;
              ViewBag.Modality = Helpers.ConstructModalityList(f_oncampus, f_online, f_hybrid);
            ViewBag.Days = Helpers.ConstructDaysList(day_su, day_m, day_t, day_w, day_th, day_f, day_s);
            ViewBag.Subject = Subject;
            ViewBag.searchterm = Regex.Replace(searchterm, @"\s+", " ");	// replace each clump of whitespace w/ a single space (so the database can better handle it)
              ViewBag.ErrorMsg = string.Empty;

            IList<ISectionFacet> facets = Helpers.addFacets(timestart, timeend, day_su, day_m, day_t, day_w, day_th, day_f, day_s,
                                                            f_oncampus, f_online, f_hybrid, avail, latestart, numcredits);

            ViewBag.LinkParams = Helpers.getLinkParams(Request, "submit");

            using (OdsRepository repository = new OdsRepository())
            {
                YearQuarter yrq = string.IsNullOrWhiteSpace(quarter) ? repository.CurrentYearQuarter : YearQuarter.FromFriendlyName(quarter);
            IList<YearQuarter> menuQuarters = Helpers.GetYearQuarterListForMenus(repository);
              QuarterNavigationModel quarterNavigation = new QuarterNavigationModel
                                                           {
                                                             NavigationQuarters = menuQuarters,
                                                             CurrentQuarter = menuQuarters[0],
                                                             ViewingQuarter = yrq,
                                                           };

                IList<Section> sections;
                using (_profiler.Step("API::GetSections()"))
                {
                    if (string.IsNullOrWhiteSpace(Subject))
                    {
                        sections = repository.GetSections(yrq, facets);
                    }
                    else
                    {
            IList<string> prefixes = SubjectInfo.GetSubjectPrefixes(Subject);
                        sections = repository.GetSections(prefixes, yrq, facets);
                    }
                }

            int currentPage;
            int totalPages;
            int itemCount;
            IList<SectionWithSeats> sectionsEnum;
                IList<SearchResult> searchResults;
            SearchResultNoSectionModel noSectionSearchResults;
              IList<SectionsBlock> courseBlocks;
              using (ClassScheduleDb db = new ClassScheduleDb())
                {
                    searchResults = GetSearchResults(db, searchterm, quarter);
                    noSectionSearchResults = GetNoSectionSearchResults(db, searchterm, yrq);

              sections = (from s in sections
                      join r in searchResults on s.ID.ToString() equals r.ClassID
                      select s).ToList();

                    sectionsEnum = Helpers.GetSectionsWithSeats(yrq.ID, sections, db);

              // do not count Linked sections (since we don't display them)
              itemCount = sectionsEnum.Count(s => !s.IsLinked);

                  totalPages = (int)Math.Round((itemCount / ITEMS_PER_PAGE) + 0.5);
                  currentPage = p_offset + 1;

              using (_profiler.Step("Getting just records for page"))
              {
            if (currentPage > totalPages && totalPages > 0)
            {
              currentPage = totalPages;
            }
            sectionsEnum = sectionsEnum.Skip(p_offset * ITEMS_PER_PAGE).Take(ITEMS_PER_PAGE).ToList();
              }

              courseBlocks = Helpers.GroupSectionsIntoBlocks(sectionsEnum, db);
                }

                IEnumerable<string> allSubjects;
                using (_profiler.Step("Getting distinct list of subjects"))
                {
                    allSubjects = sectionsEnum.Select(c => c.CourseSubject).Distinct().OrderBy(c => c);
                }

            SearchResultsModel model = new SearchResultsModel
                                           {
                                             ItemCount = itemCount,
                                       TotalPages = totalPages,
                                       CurrentPage = currentPage,
                                       Courses = courseBlocks,
                                             SearchResultNoSection = noSectionSearchResults,
                                             AllSubjects = allSubjects,
                                       QuarterNavigation = quarterNavigation,
                                           };
                return View(model);
            }
        }
        public ActionResult YearQuarterSubject(String YearQuarter, string Subject, string timestart, string timeend, string day_su, string day_m, string day_t, string day_w, string day_th, string day_f, string day_s, string f_oncampus, string f_online, string f_hybrid, string avail, string latestart, string numcredits, string format)
        {
            IList<ISectionFacet> facets = Helpers.addFacets(timestart, timeend, day_su, day_m, day_t, day_w, day_th, day_f, day_s, f_oncampus, f_online, f_hybrid, avail, latestart, numcredits);

            using (OdsRepository repository = new OdsRepository())
            {
            YearQuarter yrq = Helpers.DetermineRegistrationQuarter(YearQuarter, repository.CurrentRegistrationQuarter, RouteData);

            // Get the courses to display on the View
                IList<Section> sections;
                using (_profiler.Step("ODSAPI::GetSections()"))
                {
                    IList<string> prefixes = SubjectInfo.GetSubjectPrefixes(Subject);
                    sections = repository.GetSections(prefixes, yrq, facets);
                }

            #if DEBUG
              /* COMMENT THIS LINE FOR DEBUGGING/TROUBLESHOOTING
            Debug.Print("==> sections");
            string zItemNum = "1230", zYrq = "B234";  // ENGL 266
            if (sections.Any(s => s.ID.ItemNumber == zItemNum && s.ID.YearQuarter == zYrq))
            {
              Section foo = sections.Where(s => s.ID.ItemNumber == zItemNum && s.ID.YearQuarter == zYrq).First();
              Debug.Print("\n{0} - {1} {2}\t(Linked to: {3})", foo.ID, foo.CourseID, foo.CourseTitle, foo.LinkedTo);
            }
            else
            {
              Debug.Print("ClassID '{0}{1}' not found.", zItemNum, zYrq);
            }
            // */
            #endif

            IList<SectionsBlock> courseBlocks;
              using (ClassScheduleDb db = new ClassScheduleDb())
                {
                    IList<SectionWithSeats> sectionsEnum;
                    using (_profiler.Step("Getting app-specific Section records from DB"))
                    {
                        sectionsEnum = Helpers.GetSectionsWithSeats(yrq.ID, sections, db);
                    }

            #if DEBUG
              /* COMMENT THIS LINE FOR DEBUGGING/TROUBLESHOOTING
                  Debug.Print("==> sectionsEnum");
            //				  string zItemNum, zYrq;
                  zItemNum = "1230"; zYrq = "B234"; // ENGL 266
              if (sectionsEnum.Any(s => s.ID.ItemNumber == zItemNum && s.ID.YearQuarter == zYrq))
                  {
                    SectionWithSeats foo = sectionsEnum.Where(s => s.ID.ItemNumber == zItemNum && s.ID.YearQuarter == zYrq).First();
                    Debug.Print("\n{0} - {1} {2}\t(Linked to: {3})", foo.ID, foo.CourseID, foo.CourseTitle, foo.LinkedTo);
                  }
              else
              {
            Debug.Print("ClassID '{0}{1}' not found.", zItemNum, zYrq);
              }
              // */

              /* COMMENT THIS LINE FOR DEBUGGING/TROUBLESHOOTING
                  IEnumerable<SectionWithSeats> s1 = sectionsEnum.Where(s => s.CourseSubject == "ENGL" && s.CourseNumber == "239");
              // */
            #endif
                    courseBlocks = Helpers.GroupSectionsIntoBlocks(sectionsEnum, db);
            }

            // Construct the model
            SubjectInfoResult subject = SubjectInfo.GetSubjectInfoFromPrefix(Subject);
            IList<YearQuarter> yrqRange = Helpers.GetYearQuarterListForMenus(repository);

              YearQuarterSubjectModel model = new YearQuarterSubjectModel
                                                {
                                                  Courses = courseBlocks,
                                                  CurrentQuarter = repository.CurrentYearQuarter,
                                                  CurrentRegistrationQuarter = yrqRange[0],
                                                  NavigationQuarters = yrqRange,
                                                  ViewingQuarter = yrq,
                                            // if we were unable to determine a Slug, use the Subject (e.g. Prefix) that brought us here
                                                  Slug = subject != null ? subject.Subject.Slug : Subject,
                                                  SubjectTitle = subject != null ? subject.Subject.Title : string.Empty,
                                                  SubjectIntro = subject != null ? subject.Subject.Intro : string.Empty,
                                                  DepartmentTitle = subject != null ? subject.Department.Title : string.Empty,
                                                  DepartmentURL = subject != null ? subject.Department.URL : string.Empty,
                                                };

                if (format == "json")
                {
                  // NOTE: AllowGet exposes the potential for JSON Hijacking (see http://haacked.com/archive/2009/06/25/json-hijacking.aspx)
                  // but is not an issue here because we are receiving and returning public (e.g. non-sensitive) data
                  return Json(model, JsonRequestBehavior.AllowGet);
                }

            // set up all the ancillary data we'll need to display the View
                ViewBag.timestart = timestart;
                ViewBag.timeend = timeend;
                ViewBag.avail = avail;
                ViewBag.latestart = latestart;
            ViewBag.Modality = Helpers.ConstructModalityList(f_oncampus, f_online, f_hybrid);
            ViewBag.Days = Helpers.ConstructDaysList(day_su, day_m, day_t, day_w, day_th, day_f, day_s);
            ViewBag.LinkParams = Helpers.getLinkParams(Request);
            SetCommonViewBagVars(repository, avail, string.Empty);

            // TODO: Add query string info (e.g. facets) to the routeValues dictionary so we can pass it all as one chunk.
                IDictionary<string, object> routeValues = new Dictionary<string, object>(3);
                routeValues.Add("YearQuarterID", YearQuarter);
                ViewBag.RouteValues = routeValues;

                return View(model);
            }
        }