@Test
  public void testGetAllAssignedCoachesLite() {

    final Collection<CoachPersonLiteTO> expected =
        Lists.newArrayList(coachPersonLiteTOFor(COACH_1), coachPersonLiteTOFor(ADVISOR_0));

    final PagingWrapper<CoachPersonLiteTO> result1 =
        personService.getAllAssignedCoachesLite(
            SortingAndPaging.createForSingleSortWithPaging(
                ObjectStatus.ACTIVE, 0, 1000, "lastName", "ASC", "lastName"));

    assertCoachPersonLiteTOCollectionsEqual(expected, result1.getRows());
    // zero b/c the request specified no pagination, so impl skips total
    // result size calculation
    assertEquals(2, result1.getResults());

    // now prove that getAllAssignedCoachesLite() doesn't lazily
    // create/return new coaches by creating a fixture where it could do so,
    // run the same method again, then checking that we get the exact
    // same results as before
    final Set<String> newExternalCoachUsernames = addCoachesToExternalDataAndAttributeService(5);

    final PagingWrapper<CoachPersonLiteTO> result2 =
        personService.getAllAssignedCoachesLite(
            SortingAndPaging.createForSingleSortWithPaging(
                ObjectStatus.ACTIVE, 0, 1000, "lastName", "ASC", "lastName"));

    assertCoachPersonLiteTOCollectionsEqual(expected, result2.getRows());
    // zero b/c the request specified no pagination, so impl skips total
    // result size calculation
    assertEquals(2, result2.getResults());
  }
Example #2
0
  static List<Person> getCoaches(
      final UUID coachId, String homeDepartment, PersonService personService)
      throws ObjectNotFoundException {
    List<Person> coaches;
    if (coachId != null) {
      Person coach = personService.get(coachId);
      coaches = new ArrayList<Person>();
      coaches.add(coach);
    } else {
      coaches =
          new ArrayList<Person>(
              personService.getAllCurrentCoaches(Person.PERSON_NAME_AND_ID_COMPARATOR));

      if (homeDepartment != null && homeDepartment.length() > 0) {
        List<Person> homeCoaches = new ArrayList<Person>();
        for (Person coach : coaches) {
          if (coach.getStaffDetails() != null
              && coach.getStaffDetails().getDepartmentName() != null
              && coach.getStaffDetails().getDepartmentName().equals(homeDepartment))
            homeCoaches.add(coach);
        }
        coaches = homeCoaches;
      }
    }

    return coaches;
  }
  @Test
  public void testGetAllAssignedCoaches() throws ObjectNotFoundException {

    // basically the same as testGetAllAssignedCoachesLite() except
    // we expect Persons instead
    final Collection<UUID> expected = Lists.newArrayList(ADVISOR_0.id(), COACH_1.id());

    final PagingWrapper<Person> result1 = personService.getAllAssignedCoaches(null);

    assertPersonCollectionsHaveSameIds(expected, result1.getRows());
    // zero b/c the request specified no pagination, so impl skips total
    // result size calculation
    assertEquals(0, result1.getResults());

    // now prove that getAllAssignedCoaches() doesn't lazily
    // create/return new coaches by creating a fixture where it could do so,
    // run the same method again, then checking that we get the exact
    // same results as before
    final Set<String> newExternalCoachUsernames = addCoachesToExternalDataAndAttributeService(5);

    final PagingWrapper<Person> result2 = personService.getAllAssignedCoaches(null);

    assertPersonCollectionsHaveSameIds(expected, result2.getRows());
    // zero b/c the request specified no pagination, so impl skips total
    // result size calculation
    assertEquals(0, result2.getResults());
  }
  @Test
  public void testGetAllCurrentCoachesFiltersDuplicates() throws ObjectNotFoundException {
    final Person jamesDoe = person(JAMES_DOE);
    final Person advisor0 = person(ADVISOR_0);
    jamesDoe.setCoach(advisor0);
    personService.save(jamesDoe);
    sessionFactory.getCurrentSession().flush();

    final SortedSet<Person> result = personService.getAllCurrentCoaches(null);
    assertEquals(2, result.size());
  }
  /**
   * Ignored b/c it doesn't assert anything, it just demonstrates the performance (and behavioral)
   * differences between {@link PersonService#getAllCurrentCoaches(java.util.Comparator)} and {@link
   * PersonService#getAllCurrentCoachesLite(java.util.Comparator)}. There are (at least) three
   * problems with the former...
   *
   * <ol>
   *   <li>It lazily creates person records it hasn't encountered before, and
   *   <li>It looks up {@link Person}s one-by-one, and
   *   <li>Person lookups are just very expensive
   * </ol>
   *
   * <p>So if the total number of coaches returned from {@link
   * org.jasig.ssp.service.PersonAttributesService#getCoaches()} is large (anywhere into the 100s),
   * {@link PersonService#getAllCurrentCoaches(java.util.Comparator)} is unsuitable for invocation
   * in the request cycle, <em>even if all the referenced coaches have already been created as
   * {@link Person} records</em>.
   *
   * <p>{@link PersonService#getAllCurrentCoachesLite(java.util.Comparator)} is faster, but partly
   * b/c it doesn't make any attempt to lazily create new {@link Person}s. So it doesn't run the
   * risk of exceptionally long runtimes when first invoked. But it does so at the cost of
   * potentially not returning a completely up-to-date view of all coaches. <a
   * href="https://issues.jasig.org/browse/SSP-470">SSP-470</a> combats this by moving the {@link
   * Person} creation into a background job.
   *
   * <p>This test demonstrates the performance gradient by causing {@link
   * org.jasig.ssp.service.PersonAttributesService#getCoaches()} to return 500 coach usernames the
   * {@link PersonService} hasn't seen before, then making a series of calls to the methods of
   * interest. At this writing (Nov 20, 2012), in an all-local development env, the numbers looked
   * like this (execution time in {@link org.jasig.ssp.service.PersonAttributesService#getCoaches()}
   * is effecively negiligible b/c this test stubs that service):
   *
   * <ol>
   *   <li>{@link PersonService#getAllCurrentCoachesLite(java.util.Comparator)} (returns 1 record):
   *       55ms
   *   <li>{@link PersonService#getAllCurrentCoaches(java.util.Comparator)} (returns 501 records):
   *       29504ms
   *   <li>{@link PersonService#getAllCurrentCoaches(java.util.Comparator)} (returns 501 records):
   *       15428ms
   *   <li>{@link PersonService#getAllCurrentCoachesLite(java.util.Comparator)} (returns 501
   *       records): 59ms
   * </ol>
   *
   * <p>Keep in mind again that {@link PersonService#getAllCurrentCoachesLite(java.util.Comparator)}
   * doesn't make any of the lazy-creation promises of {@link
   * PersonService#getAllCurrentCoaches(java.util.Comparator)}, so the comparison isn't completely
   * fair. But the calls to the latter are sufficiently slow that it would be nice to find a way to
   * drop them both down... maybe through a combination of bulk db reads and writes and by
   * simplifying the object graph returned with all {@link Person} lookups.
   */
  @Test
  @Ignore
  public void testLiteCoachLookupMuchFasterButPotentiallyIncomplete() {
    int externalCoachQuota = 500;
    Set<String> addedCoachUsernames =
        addCoachesToExternalDataAndAttributeService(externalCoachQuota);

    long started = new Date().getTime();
    final PagingWrapper<CoachPersonLiteTO> allCoachesLite1 = personService.getAllCoachesLite(null);
    long ended = new Date().getTime();
    System.out.println(
        "Lite Person lookups, no external Persons created yet: "
            + (ended - started)
            + "ms ("
            + allCoachesLite1.getResults()
            + " total records returned)");

    started = new Date().getTime();
    final SortedSet<Person> lazyCreatedCoaches1 = personService.getAllCurrentCoaches(null);
    ended = new Date().getTime();
    System.out.println(
        "Full Person lookups, lazy Person record creation: "
            + (ended - started)
            + "ms ("
            + externalCoachQuota
            + " lazy records, "
            + lazyCreatedCoaches1.size()
            + " total records returned)");

    started = new Date().getTime();
    final SortedSet<Person> lazyCreatedCoaches2 = personService.getAllCurrentCoaches(null);
    ended = new Date().getTime();
    System.out.println(
        "Full Person lookups, all Persons already created: "
            + (ended - started)
            + "ms ("
            + lazyCreatedCoaches2.size()
            + " total records returned)");

    started = new Date().getTime();
    final PagingWrapper<CoachPersonLiteTO> allCoachesLite2 = personService.getAllCoachesLite(null);
    ended = new Date().getTime();
    System.out.println(
        "Lite Person lookups, all Persons already created: "
            + (ended - started)
            + "ms ("
            + allCoachesLite2.getResults()
            + " total records returned)");
  }
 // Faculty names are not added to the external courses by default
 // this method should fix ssp-3041 - Scody
 private void updateFactultyNames(ExternalStudentRecordsTO recordTO) {
   List<ExternalStudentTranscriptCourseTO> courses = recordTO.getTerms();
   if (courses != null) {
     for (ExternalStudentTranscriptCourseTO course : courses) {
       try {
         Person person =
             !StringUtils.isNotBlank(course.getFacultySchoolId())
                 ? null
                 : personService.getInternalOrExternalPersonBySchoolId(
                     course.getFacultySchoolId(),
                     false); // TODO: getInternalOrExternalPersonBySchoolId is slow refactor?
         if (person != null) {
           course.setFacultyName(person.getFullName());
         }
       } catch (ObjectNotFoundException e) {
         course.setFacultyName("None Listed");
         LOGGER.debug(
             "FACULTY SCHOOL ID WAS NOT RESOLVED WHILE LOADING TRANSCRIPT RECORD.  Faculty School_id: "
                 + course.getFacultySchoolId()
                 + " Student ID: "
                 + course.getSchoolId()
                 + " Course: "
                 + course.getFormattedCourse());
       }
     }
   }
 }
  @Test
  public void testGetAllCurrentCoachesLite() throws ObjectNotFoundException {

    final Collection<CoachPersonLiteTO> expected =
        Lists.newArrayList(coachPersonLiteTOFor(ADVISOR_0), coachPersonLiteTOFor(COACH_1));

    final SortedSet<CoachPersonLiteTO> result1 = personService.getAllCurrentCoachesLite(null);

    assertCoachPersonLiteTOCollectionsEqual(expected, result1);

    final Set<String> newExternalCoachUsernames = addCoachesToExternalDataAndAttributeService(2);

    final SortedSet<CoachPersonLiteTO> result2 = personService.getAllCurrentCoachesLite(null);

    assertCoachPersonLiteTOCollectionsEqual(expected, result2);
  }
Example #8
0
  /**
   * Returns an html page valid for printing
   *
   * <p>
   *
   * @param obj instance to print.
   * @return html text strem
   * @throws ObjectNotFoundException If specified object could not be found.
   * @throws SendFailedException
   */
  @PreAuthorize("hasRole('ROLE_PERSON_READ') or hasRole('ROLE_PERSON_MAP_READ')")
  @RequestMapping(value = "/emailCurrent", method = RequestMethod.POST)
  public @ResponseBody String email(
      final HttpServletResponse response,
      final @PathVariable UUID personId,
      @RequestBody final PlanOutputTO planOutputDataTO)
      throws ObjectNotFoundException {

    Plan currentPlan = service.getCurrentForStudent(personId);
    PlanTO planTO = getFactory().from(currentPlan);
    planOutputDataTO.setPlan(planTO);

    SubjectAndBody messageText = service.createOutput(planOutputDataTO);
    if (messageText == null) return null;
    Person person = personService.get(UUID.fromString(planOutputDataTO.getPlan().getPersonId()));
    Set<String> watcherAddresses = new HashSet<String>(person.getWatcherEmailAddresses());
    watcherAddresses.addAll(
        org.springframework.util.StringUtils.commaDelimitedListToSet(
            planOutputDataTO.getEmailCC()));

    messageService.createMessage(
        planOutputDataTO.getEmailTo(),
        org.springframework.util.StringUtils.arrayToCommaDelimitedString(
            watcherAddresses.toArray(new String[watcherAddresses.size()])),
        messageText);

    return "Map Plan has been queued.";
  }
Example #9
0
 static final PersonTO getPerson(
     final UUID personId, PersonService personService, PersonTOFactory personTOFactory)
     throws ObjectNotFoundException {
   if (personId != null) {
     return personTOFactory.from(personService.get(personId));
   }
   return null;
 }
Example #10
0
 private PlanTO validatePlan(PlanTO plan) throws ObjectNotFoundException {
   String schoolId = null;
   if (StringUtils.isNotBlank(plan.getPersonId())) {
     Person student = personService.get(UUID.fromString(plan.getPersonId()));
     schoolId = student.getSchoolId();
   }
   return getService().validate(plan);
 }
 private Person findEnabledPersonByUsernameOrFail(String username)
     throws ObjectNotFoundException, UserNotEnabledException {
   Person person = personService.personFromUsername(username);
   if (person.isDisabled()) {
     throw new UserNotEnabledException("User '" + username + "' is disabled.");
   }
   return person;
 }
  /**
   * Load the specified Person.
   *
   * <p>Be careful when walking the tree to avoid performance issues that can arise if eager
   * fetching from the database layer is not used appropriately.
   */
  @Override
  public AccommodationForm loadForPerson(final UUID studentId) throws ObjectNotFoundException {
    final AccommodationForm form = new AccommodationForm();

    final Person person = personService.get(studentId);
    form.setPerson(person);

    return form;
  }
  @RequestMapping(value = "/transcript/currentcourses", method = RequestMethod.GET)
  @PreAuthorize(Permission.SECURITY_PERSON_READ)
  public @ResponseBody List<ExternalStudentTranscriptCourseTO> loadCurrentCourses(
      final @PathVariable UUID id) throws ObjectNotFoundException {
    String schoolId = getStudentId(id);

    Term currentTerm;
    try {
      currentTerm = termService.getCurrentTerm();
    } catch (ObjectNotFoundException e) {
      currentTerm = new Term();
      LOGGER.error(
          "CURRENT TERM NOT SET, org.jasig.ssp.web.api.external.ExternalStudentRecordsController.loadCurrentCourses(UUID) is being called but will not function properly");
    }
    List<ExternalStudentTranscriptCourseTO> courses =
        externalStudentTranscriptCourseFactory.asTOList(
            externalStudentTranscriptCourseService.getTranscriptsBySchoolIdAndTermCode(
                schoolId, currentTerm.getCode()));
    Collection<EnrollmentStatus> mappings = statusCodeMappings();

    String defaultStatusCode = getDefaultStatusCode(mappings);

    for (ExternalStudentTranscriptCourseTO course : courses) {
      try {
        Person person =
            !StringUtils.isNotBlank(course.getFacultySchoolId())
                ? null
                : personService.getInternalOrExternalPersonBySchoolId(
                    course.getFacultySchoolId(),
                    false); // TODO: getInternalOrExternalPersonBySchoolId is slow refactor?
        if (person != null) {
          course.setFacultyName(person.getFullName());
        }
      } catch (ObjectNotFoundException e) {
        course.setFacultyName("None Listed");
        LOGGER.debug(
            "FACULTY SCHOOL ID WAS NOT RESOLVED WHILE LOADING TRANSCRIPT RECORD.  Factulty School_id: "
                + course.getFacultySchoolId()
                + " Student ID: "
                + course.getSchoolId()
                + " Course: "
                + course.getFormattedCourse());
      }

      if (StringUtils.isBlank(course.getStatusCode())) {
        course.setStatusCode(defaultStatusCode);
      } else if (mappings != null && !mappings.isEmpty()) {
        for (EnrollmentStatus enrollmentStatus : mappings) {
          if (enrollmentStatus.getCode().equals(course.getStatusCode())) {
            course.setStatusCode(enrollmentStatus.getName());
          }
        }
      }
    }
    return courses;
  }
 /**
  * Using the Student UUID passed, return the ExternalStudentRecordsLiteTO in its current state,
  * creating it if necessary.
  *
  * @param id Student identifier Any errors will throw this generic exception.
  * @return Service response with success value, in the JSON format.
  * @throws ObjectNotFoundException, IOException If any reference data could not be loaded.
  */
 @RequestMapping(value = "/test/details", method = RequestMethod.GET)
 @PreAuthorize(Permission.SECURITY_PERSON_READ)
 public String getTestProviderDetails(
     final @PathVariable UUID id,
     final @RequestParam(required = true) String testCode,
     final @RequestParam(required = false) String subTestCode,
     HttpServletResponse httpServletResponse)
     throws ObjectNotFoundException, IOException {
   Person person = personService.get(id);
   String url = (String) externalStudentTestService.getTestDetails(testCode, subTestCode, person);
   return "redirect:" + url;
 }
  /** Persist the form contents */
  @Override
  public boolean save(final AccommodationForm form) throws ObjectNotFoundException {
    if (form.getPerson() == null) {
      throw new ObjectNotFoundException("Missing (null) Person.", "Person");
    }

    final Person person = form.getPerson();

    // Save changes to persistent storage.
    personService.save(person);

    return true;
  }
Example #16
0
  @Override
  public EarlyAlert create(@NotNull final EarlyAlert earlyAlert)
      throws ObjectNotFoundException, ValidationException {
    // Validate objects
    if (earlyAlert == null) {
      throw new IllegalArgumentException("EarlyAlert must be provided.");
    }

    if (earlyAlert.getPerson() == null) {
      throw new ValidationException("EarlyAlert Student data must be provided.");
    }

    final Person student = earlyAlert.getPerson();

    // Figure student advisor or early alert coordinator
    final UUID assignedAdvisor = getEarlyAlertAdvisor(earlyAlert);
    if (assignedAdvisor == null) {
      throw new ValidationException(
          "Could not determine the Early Alert Advisor for student ID " + student.getId());
    }

    if (student.getCoach() == null || assignedAdvisor.equals(student.getCoach().getId())) {
      student.setCoach(personService.get(assignedAdvisor));
    }

    ensureValidAlertedOnPersonStateNoFail(student);

    // Create alert
    final EarlyAlert saved = getDao().save(earlyAlert);

    // Send e-mail to assigned advisor (coach)
    try {
      sendMessageToAdvisor(saved, earlyAlert.getEmailCC());
    } catch (final SendFailedException e) {
      LOGGER.warn("Could not send Early Alert message to advisor.", e);
      throw new ValidationException(
          "Early Alert notification e-mail could not be sent to advisor. Early Alert was NOT created.",
          e);
    }

    // Send e-mail CONFIRMATION to faculty
    try {
      sendConfirmationMessageToFaculty(saved);
    } catch (final SendFailedException e) {
      LOGGER.warn("Could not send Early Alert confirmation to faculty.", e);
      throw new ValidationException(
          "Early Alert confirmation e-mail could not be sent. Early Alert was NOT created.", e);
    }

    return saved;
  }
  @Test
  public void testGetAllCurrentCoachesFiltersDuplicatesByIdNotName()
      throws ObjectNotFoundException {
    final String duplicatePersonSchoolId = ADVISOR_0.schoolId() + "_foo";
    this.createExternalPerson(
        duplicatePersonSchoolId,
        ADVISOR_0.username() + "_foo",
        ADVISOR_0.firstName(), // everything else the same
        ADVISOR_0.lastName(),
        ADVISOR_0.middleName(),
        ADVISOR_0.primaryEmailAddress());

    // this should create the person record
    Person duplicatePerson = personService.getBySchoolId(duplicatePersonSchoolId, true);
    assertNotNull(duplicatePerson); // sanity check
    final Person jamesDoe = person(JAMES_DOE);
    jamesDoe.setCoach(duplicatePerson);
    personService.save(jamesDoe);
    sessionFactory.getCurrentSession().flush();

    final SortedSet<Person> result = personService.getAllCurrentCoaches(null);
    assertEquals(3, result.size());
  }
  @Test
  public void testGetAllCurrentCoaches() throws ObjectNotFoundException {

    // unlike the getAllAssignedCoaches()/getAllAssignedCoachesLite()
    // pair, getAllCurrentCoaches()/getAllCurrentCoachesLite() have
    // significantly different behavior. Specifically the non-lite version,
    // tested here, *does* lazily create and return new Persons. The lite
    // version does not.
    final SortedSet<Person> result1 = personService.getAllCurrentCoaches(null);

    assertPersonCollectionsHaveSameIds(Lists.newArrayList(ADVISOR_0.id(), COACH_1.id()), result1);

    final Set<String> newExternalCoachUsernames = addCoachesToExternalDataAndAttributeService(2);

    final SortedSet<Person> result2 = personService.getAllCurrentCoaches(null);

    assertPersonCollectionsHaveSameIds(
        Lists.newArrayList(
            personService.personFromUsername("bulk_coach_001").getId(),
            personService.personFromUsername("bulk_coach_002").getId(),
            ADVISOR_0.id(),
            COACH_1.id()),
        result2);
  }
Example #19
0
  @Override
  public EarlyAlert save(@NotNull final EarlyAlert obj) throws ObjectNotFoundException {
    final EarlyAlert current = getDao().get(obj.getId());

    current.setCourseName(obj.getCourseName());
    current.setCourseTitle(obj.getCourseTitle());
    current.setEmailCC(obj.getEmailCC());
    current.setCampus(obj.getCampus());
    current.setEarlyAlertReasonOtherDescription(obj.getEarlyAlertReasonOtherDescription());
    current.setComment(obj.getComment());
    current.setClosedDate(obj.getClosedDate());
    current.setClosedById(obj.getClosedById());

    if (obj.getPerson() == null) {
      current.setPerson(null);
    } else {
      current.setPerson(personService.get(obj.getPerson().getId()));
    }

    final Set<EarlyAlertReason> earlyAlertReasons = new HashSet<EarlyAlertReason>();
    if (obj.getEarlyAlertReasonIds() != null) {
      for (final EarlyAlertReason reason : obj.getEarlyAlertReasonIds()) {
        earlyAlertReasons.add(earlyAlertReasonService.load(reason.getId()));
      }
    }

    current.setEarlyAlertReasonIds(earlyAlertReasons);

    final Set<EarlyAlertSuggestion> earlyAlertSuggestions = new HashSet<EarlyAlertSuggestion>();
    if (obj.getEarlyAlertSuggestionIds() != null) {
      for (final EarlyAlertSuggestion reason : obj.getEarlyAlertSuggestionIds()) {
        earlyAlertSuggestions.add(earlyAlertSuggestionService.load(reason.getId()));
      }
    }

    current.setEarlyAlertSuggestionIds(earlyAlertSuggestions);

    return getDao().save(current);
  }
Example #20
0
 /**
  * Return plan status for given student.
  *
  * @param personId Explicit personId to the instance to persist.
  * @return The current plan status of the student.
  */
 @DynamicPermissionChecking
 @RequestMapping(value = "/planstatus", method = RequestMethod.GET)
 public @ResponseBody ExternalPersonPlanStatusTO getPlanStatus(
     final HttpServletRequest request,
     final HttpServletResponse response,
     @PathVariable final UUID personId)
     throws ObjectNotFoundException {
   assertStandardMapReadApiAuthorization(request);
   if (personId == null) {
     return null;
   }
   String schoolId = null;
   Person student = personService.get(personId);
   schoolId = student.getSchoolId();
   // TODO not the cleanest way to handle but clientside generates 500 error in console
   // Currently plan status is not required.
   try {
     return planStatusFactory.from(externalPlanStatusService.getBySchoolId(schoolId));
   } catch (Exception exp) {
     return null;
   }
 }
  private Person findOrCreateEnabledPersonForCurrentPortletUser(final PortletRequest req)
      throws UserNotEnabledException, UnableToCreateAccountException {
    Person person = null;
    @SuppressWarnings("unchecked")
    Map<String, String> userInfo = (Map<String, String>) req.getAttribute(PortletRequest.USER_INFO);
    String username = null;
    if (userInfo != null) {
      username = userInfo.get(PortletRequest.P3PUserInfos.USER_LOGIN_ID.toString());
    }
    username = StringUtils.isNotBlank(username) ? username : req.getRemoteUser();
    if (!(StringUtils.isNotBlank(username))) {
      throw new IllegalArgumentException("Cannot lookup nor create an account without a username");
    }

    try {
      person = findEnabledPersonByUsernameOrFail(username);
    } catch (ObjectNotFoundException e) {
      try {
        return personService.createUserAccountForCurrentPortletUser(username, req);
      } catch (ObjectExistsException ee) {
        try {
          person = findEnabledPersonByUsernameOrFail(username);
        } catch (ObjectNotFoundException eee) {
          throw new UnableToCreateAccountException(
              "Couldn't create account with username"
                  + username
                  + " because an account with that username seemed"
                  + " to already exist, but was unable to load that"
                  + " existing account.",
              eee);
        } // UserNotEnabledException is helpfully descriptive so just
        // let it bubble up
      }
    }
    return person;
  }
 String getStudentId(UUID personId) throws ObjectNotFoundException {
   return personService.getSchoolIdForPersonId(personId);
 }
  @RequestMapping(value = "/studentactivity", method = RequestMethod.GET)
  @PreAuthorize(Permission.SECURITY_PERSON_READ)
  public @ResponseBody List<RecentActivityTO> loadRecentStudentActivity(final @PathVariable UUID id)
      throws ObjectNotFoundException {
    List<RecentActivityTO> recentActivities = new ArrayList<RecentActivityTO>();
    Person person = personService.get(id);
    SortingAndPaging sAndP =
        SortingAndPaging.createForSingleSortWithPaging(
            ObjectStatus.ACTIVE, 0, 1000, "createdDate", "DESC", "createdDate");

    PagingWrapper<EarlyAlert> earlyAlerts = earlyAlertService.getAllForPerson(person, sAndP);
    SspUser currentUser = securityService.currentUser();
    List<EarlyAlertTO> earlyAlertTOs = earlyAlertTOFactory.asTOList(earlyAlerts.getRows());

    PagingWrapper<JournalEntry> journalEntries =
        journalEntryService.getAllForPerson(person, currentUser, sAndP);

    List<JournalEntryTO> journalEntriesTOs =
        journalEntryTOFactory.asTOList(journalEntries.getRows());

    PagingWrapper<Task> actions = taskService.getAllForPerson(person, currentUser, sAndP);

    List<TaskTO> actionsTOs = taskTOFactory.asTOList(actions.getRows());

    PagingWrapper<Plan> plans =
        planService.getAllForStudent(
            SortingAndPaging.createForSingleSortWithPaging(
                ObjectStatus.ALL, 0, 1000, null, null, null),
            id);

    List<PlanTO> planTOs = planTOFactory.asTOList(plans.getRows());

    for (EarlyAlertTO earlyAlert : earlyAlertTOs) {
      if (earlyAlert.getClosedDate() != null) {
        recentActivities.add(
            new RecentActivityTO(
                earlyAlert.getClosedById(),
                earlyAlert.getClosedByName(),
                "Early Alert Closed",
                earlyAlert.getClosedDate()));
      } else {
        recentActivities.add(
            new RecentActivityTO(
                earlyAlert.getCreatedBy().getId(),
                getPersonLiteName(earlyAlert.getCreatedBy()),
                "Early Alert Created",
                earlyAlert.getCreatedDate()));
      }
    }

    for (JournalEntryTO journalEntry : journalEntriesTOs) {
      recentActivities.add(
          new RecentActivityTO(
              journalEntry.getCreatedBy().getId(),
              getPersonLiteName(journalEntry.getCreatedBy()),
              "Journal Entry",
              journalEntry.getEntryDate()));
    }

    for (TaskTO action : actionsTOs) {
      if (action.isCompleted()) {
        recentActivities.add(
            new RecentActivityTO(
                action.getModifiedBy().getId(),
                getPersonLiteName(action.getModifiedBy()),
                "Action Plan Task Created",
                action.getCompletedDate()));
      } else {
        recentActivities.add(
            new RecentActivityTO(
                action.getCreatedBy().getId(),
                getPersonLiteName(action.getCreatedBy()),
                "Action Plan Task Created",
                action.getCreatedDate()));
      }
    }

    for (PlanTO planTO : planTOs) {
      Date testDate = DateUtils.addDays(planTO.getCreatedDate(), 1);
      String planName = planTO.getName();
      if (planTO.getModifiedDate().before(testDate)) {
        recentActivities.add(
            new RecentActivityTO(
                planTO.getCreatedBy().getId(),
                getPersonLiteName(planTO.getCreatedBy()),
                "Map Plan (" + planName + ") Created",
                planTO.getModifiedDate()));
      } else {
        recentActivities.add(
            new RecentActivityTO(
                planTO.getModifiedBy().getId(),
                getPersonLiteName(planTO.getModifiedBy()),
                "Map Plan (" + planName + ") Updated",
                planTO.getModifiedDate()));
      }
    }

    if (person.getStudentIntakeCompleteDate() != null) {
      recentActivities.add(
          new RecentActivityTO(
              person.getCoach().getId(),
              person.getCoach().getFullName(),
              "Student Intake Completed",
              person.getStudentIntakeCompleteDate()));
    }
    if (person.getStudentIntakeRequestDate() != null) {
      recentActivities.add(
          new RecentActivityTO(
              person.getCoach().getId(),
              person.getCoach().getFullName(),
              "Student Intake Requested",
              person.getStudentIntakeRequestDate()));
    }

    Collections.sort(recentActivities, RecentActivityTO.RECENT_ACTIVITY_TO_DATE_COMPARATOR);
    return recentActivities;
  }
  @RequestMapping(method = RequestMethod.GET)
  @PreAuthorize("(hasRole('ROLE_REPORT_READ') and hasRole('ROLE_ACCOMMODATION_READ'))")
  @ResponseBody
  public void getDisabilityServicesReport(
      final HttpServletResponse response,
      final @RequestParam(required = false) ObjectStatus status,
      final @RequestParam(required = true) UUID coachId,
      final @RequestParam(required = true) UUID watcherId,
      final @RequestParam(required = false) UUID odsCoachId,
      final @RequestParam(required = false) UUID disabilityStatusId,
      final @RequestParam(required = false) UUID disabilityTypeId,
      final @RequestParam(required = false) UUID programStatus,
      final @RequestParam(required = false) List<UUID> specialServiceGroupIds,
      final @RequestParam(required = false) List<UUID> referralSourcesIds,
      final @RequestParam(required = false) List<UUID> studentTypeIds,
      final @RequestParam(required = false) List<UUID> serviceReasonIds,
      final @RequestParam(required = false) Integer anticipatedStartYear,
      final @RequestParam(required = false) String anticipatedStartTerm,
      final @RequestParam(required = false) Integer actualStartYear,
      final @RequestParam(required = false) String actualStartTerm,
      final @RequestParam(required = false) Date createDateFrom,
      final @RequestParam(required = false) Date createDateTo,
      final @RequestParam(required = false) String termCode,
      final @RequestParam(required = false) String homeDepartment,
      final @RequestParam(required = false) String rosterStatus,
      final @RequestParam(required = false, defaultValue = DEFAULT_REPORT_TYPE) String reportType)
      throws ObjectNotFoundException, IOException {

    final Map<String, Object> parameters = Maps.newHashMap();
    final PersonSearchFormTO personSearchForm = new PersonSearchFormTO();
    SearchParameters.addCoach(
        coachId, parameters, personSearchForm, personService, personTOFactory);
    SearchParameters.addOdsCoach(
        odsCoachId, parameters, personSearchForm, personService, personTOFactory);
    SearchParameters.addWatcher(
        watcherId, parameters, personSearchForm, personService, personTOFactory);
    SearchParameters.addReferenceLists(
        studentTypeIds,
        specialServiceGroupIds,
        referralSourcesIds,
        serviceReasonIds,
        parameters,
        personSearchForm,
        studentTypeService,
        ssgService,
        referralSourcesService,
        serviceReasonService);

    SearchParameters.addDateRange(
        createDateFrom, createDateTo, termCode, parameters, personSearchForm, termService);

    SearchParameters.addReferenceTypes(
        programStatus,
        disabilityStatusId,
        disabilityTypeId,
        true,
        rosterStatus,
        homeDepartment,
        parameters,
        personSearchForm,
        programStatusService,
        disabilityStatusService,
        disabilityTypeService);

    SearchParameters.addAnticipatedAndActualStartTerms(
        anticipatedStartTerm,
        anticipatedStartYear,
        actualStartTerm,
        actualStartYear,
        parameters,
        personSearchForm);

    // TODO Specifying person name sort fields in the SaP doesn't seem to
    // work... end up with empty results need to dig into actual query
    // building
    final PagingWrapper<DisabilityServicesReportTO> people =
        personService.getDisabilityReport(
            personSearchForm, SearchParameters.getReportPersonSortingAndPagingAll(status));
    List<DisabilityServicesReportTO> compressedReports = this.processStudentReportTOs(people);

    SearchParameters.addStudentCount(compressedReports, parameters);

    renderReport(
        response,
        parameters,
        compressedReports,
        REPORT_TYPE_PDF.equals(reportType) ? REPORT_URL_PDF : null,
        reportType,
        REPORT_FILE_TITLE);
  }
  @RenderMapping(params = "action=enterAlert")
  public ModelAndView showForm(
      final PortletRequest req,
      @RequestParam(required = false) final String schoolId,
      @RequestParam(required = false) final String formattedCourse,
      @RequestParam(required = false) final String studentUserName,
      @RequestParam(required = false) final String sectionCode,
      @RequestParam(required = false) final String termCode,
      ModelMap model) {
    // Do not use a @ModelAttribute-annotated argument to get the user
    // out of the model b/c Spring will attempt to set properties on it
    // by matching up request param names. This will overwrite user.schoolId
    // with the method param of that name, effectively copying the student's
    // school ID into the faculty user's record.
    if (!StringUtils.isNotBlank(schoolId) && !StringUtils.isNotBlank(studentUserName)) {
      throw new EarlyAlertPortletControllerRuntimeException("Missing student identifier.");
    }

    if (!StringUtils.isNotBlank(formattedCourse) && !StringUtils.isNotBlank(sectionCode)) {
      throw new EarlyAlertPortletControllerRuntimeException("Missing course identifier/s.");
    }
    Person user = (Person) model.get("user");
    if (user == null) {
      throw new EarlyAlertPortletControllerRuntimeException(
          "Missing or deactivated account for current user.");
    }
    FacultyCourse course = null;
    Person student = null;
    ExternalFacultyCourseRoster enrollment = null;
    try {
      // Should really always have a term code (see deprecation notes for
      // getCourseByFacultySchoolIdAndFormattedCourse) but we know at
      // least one real-world deployment (SPC) cannot/does not send term
      // codes when deep linking to the EA form *and* this just happens to
      // work b/c their formattedCourse values are globally unique. So
      // we preserve the option of not filtering by term code.
      course =
          facultyCourseService.getCourseBySearchFacultyCourseTO(
              new SearchFacultyCourseTO(
                  user.getSchoolId(), termCode, sectionCode, formattedCourse));

      if (course == null) {
        throw new EarlyAlertPortletControllerRuntimeException(
            buildErrorMesssage(
                "Course not found or current user is not listed as the instructor of record:",
                user.getSchoolId(),
                schoolId,
                studentUserName,
                formattedCourse,
                termCode,
                sectionCode));
      }

      /*
       * NB:  It's on us to translate from schoolId <-> studentId (SSP
       * UUID) at this point in the Early Alert process.  Previous APIs
       * user the former where following APIs use the later.
       */
      if (StringUtils.isNotBlank(schoolId)) {
        try {
          student = personService.getBySchoolId(schoolId, true); // TODO:  Handle error better??
          if (student == null) {
            throw new EarlyAlertPortletControllerRuntimeException(
                "Student not found by school ID: " + schoolId);
          }
        } catch (ObjectNotFoundException e) {
          throw new EarlyAlertPortletControllerRuntimeException(
              "Student not found by school ID: " + schoolId, e);
        }
      } else {
        try {
          student = personService.getByUsername(studentUserName, true);
          if (student == null) {
            throw new EarlyAlertPortletControllerRuntimeException(
                "Student not found by username: "******"Student not found by username: "******"Selected student has no school ID. Username: "******"Enrollment not found for: ",
                user.getSchoolId(),
                student.getSchoolId(),
                student.getUsername(),
                formattedCourse,
                termCode,
                sectionCode));
      }
    } catch (EarlyAlertPortletControllerRuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(
          buildErrorMesssage(
              "System error looking up course or enrollment for: ",
              user.getSchoolId(),
              student == null ? schoolId : student.getSchoolId(),
              student == null ? studentUserName : student.getUsername(),
              formattedCourse,
              termCode,
              sectionCode),
          e);
    }
    /*
     *  SANITY CHECK (is this even necessary?  wanted?)
     *    - Confirm that the logged in user is the faculty of record on the
     *      course
     */
    if (!course.getFacultySchoolId().equals(user.getSchoolId())) {
      throw new EarlyAlertPortletControllerRuntimeException(
          buildErrorMesssage(
              "Current user is not listed as the instructor of record on the specified course: ",
              user.getSchoolId(),
              student.getSchoolId(),
              student.getUsername(),
              formattedCourse,
              termCode,
              sectionCode));
    }

    EarlyAlertSearchForm form = new EarlyAlertSearchForm();
    form.setAuthor(user);
    form.setStudent(student);

    form.setSortAndPage(buildSortAndPage(-1, 0));
    PagedResponse<EarlyAlertSearchResultTO> results = earlyAlertService.searchEarlyAlert(form);

    model.put(KEY_STUDENT_ID, student.getId()); // Student UUID
    model.put(KEY_COURSE, course);
    model.put(KEY_ENROLLMENT, enrollment);
    model.put(KEY_EARLY_ALERT_RESULTS, results.getRows());
    try {
      Term term = termService.getByCode(course.getTermCode());
      model.put(KEY_COURSE_TERM_NAME, term.getName());
    } catch (Exception exp) {
      model.put(KEY_COURSE_TERM_NAME, course.getTermCode());
    }

    return new ModelAndView("ea-form", model);
  }
Example #26
0
  @Override
  public Map<String, Object> fillTemplateParameters(@NotNull final EarlyAlert earlyAlert) {
    if (earlyAlert == null) {
      throw new IllegalArgumentException("EarlyAlert was missing.");
    }

    if (earlyAlert.getPerson() == null) {
      throw new IllegalArgumentException("EarlyAlert.Person is missing.");
    }

    if (earlyAlert.getCreatedBy() == null) {
      throw new IllegalArgumentException("EarlyAlert.CreatedBy is missing.");
    }

    if (earlyAlert.getCampus() == null) {
      throw new IllegalArgumentException("EarlyAlert.Campus is missing.");
    }

    // ensure earlyAlert.createdBy is populated
    if ((earlyAlert.getCreatedBy().getFirstName() == null)
        || (earlyAlert.getCreatedBy().getLastName() == null)) {
      if (earlyAlert.getCreatedBy().getId() == null) {
        throw new IllegalArgumentException("EarlyAlert.CreatedBy.Id is missing.");
      }

      try {
        earlyAlert.setCreatedBy(personService.get(earlyAlert.getCreatedBy().getId()));
      } catch (final ObjectNotFoundException e) {
        throw new IllegalArgumentException("EarlyAlert.CreatedBy.Id could not be loaded.", e);
      }
    }

    final Map<String, Object> templateParameters = Maps.newHashMap();

    final String courseName = earlyAlert.getCourseName();
    if (StringUtils.isNotBlank(courseName)) {
      final String facultySchoolId = earlyAlert.getCreatedBy().getSchoolId();
      if ((StringUtils.isNotBlank(facultySchoolId))) {
        String termCode = earlyAlert.getCourseTermCode();
        FacultyCourse course = null;
        try {
          if (StringUtils.isBlank(termCode)) {
            course =
                facultyCourseService.getCourseByFacultySchoolIdAndFormattedCourse(
                    facultySchoolId, courseName);
          } else {
            course =
                facultyCourseService.getCourseByFacultySchoolIdAndFormattedCourseAndTermCode(
                    facultySchoolId, courseName, termCode);
          }
        } catch (ObjectNotFoundException e) {
          // Trace irrelevant. see below for logging. prefer to
          // do it there, after the null check b/c not all service
          // methods implement ObjectNotFoundException reliably.
        }
        if (course != null) {
          templateParameters.put("course", course);
          if (StringUtils.isBlank(termCode)) {
            termCode = course.getTermCode();
          }
          if (StringUtils.isNotBlank(termCode)) {
            Term term = null;
            try {
              term = termService.getByCode(termCode);
            } catch (ObjectNotFoundException e) {
              // Trace irrelevant. See below for logging.
            }
            if (term != null) {
              templateParameters.put("term", term);
            } else {
              LOGGER.info(
                  "Not adding term to message template"
                      + " params or early alert {} because"
                      + " the term code {} did not resolve to"
                      + " an external term record",
                  earlyAlert.getId(),
                  termCode);
            }
          }
        } else {
          LOGGER.info(
              "Not adding course nor term to message template"
                  + " params for early alert {} because the associated"
                  + " course {} and faculty school id {} did not"
                  + " resolve to an external course record.",
              new Object[] {earlyAlert.getId(), courseName, facultySchoolId});
        }
      }
    }

    templateParameters.put("earlyAlert", earlyAlert);
    templateParameters.put(
        "termToRepresentEarlyAlert", configService.getByNameEmpty("term_to_represent_early_alert"));
    templateParameters.put("linkToSSP", configService.getByNameEmpty("serverExternalPath"));
    templateParameters.put("applicationTitle", configService.getByNameEmpty("app_title"));
    templateParameters.put("institutionName", configService.getByNameEmpty("inst_name"));

    return templateParameters;
  }