Summer Headers and Trailers
Use the Standard Academic Year (SAY) Summer Configurator to define when a student population should have a summer term treated as a header or trailer.
The SAY Summer Configurator uses Groovy scripts to determine when to award a summer term and whether to treat it as a header or trailer. However, you can always manually add a summer term as a header, trailer, or remove a summer term for a student in Oracle Fusion Cloud Student Financial Planning (SFP).
What's a Summer Term?
Summer terms are either before an upcoming academic year as header or after a completed academic year as a trailer. Summer terms are optional and most students attend them voluntarily if they want to progress quicker than normal or to repeat courses for a better grade. You can decide if you how you want to treat the summer term as its placement impacts students fund eligibility.
FasSafiSyncEventV2 (SAFI) Message: SummerTerm Element
The Summer Term element in the Student Academic and Financial Information (SAFI) message is nested within the <Term> Element, but after the <AcademicYears> element because:
- It isn't technically part of the academic year.
- It can be added as a header or trailer based on the configuration.
The summer term should contain all <TermPeriods> eligible to be summer terms regardless if the student is attending that term or not. Also, it can't overlap with any other term.
Oracle PeopleSoft Campus Solutions delivers Summer Term integration with the product. The <SummerTerm> element of the SAFI message includes terms with TERM_TBL - TERM_CATEGORY = “Summer Term”.
<Term>
<TermType>Semester</TermType>
<AcademicYears>
<AcademicYear>
<AcademicYearNumber>1</AcademicYearNumber>
<StartDate>2018-08-28</StartDate>
<EndDate>2019-05-16</EndDate>
<TermPeriods>
<TermPeriod>
<Description>Fall Semester, 2018</Description>
<StartDate>2018-08-28</StartDate>
<EndDate>2018-12-13</EndDate>
</TermPeriod>
<TermPeriod>
<Description>Spring Semester, 2019</Description>
<StartDate>2019-01-22</StartDate>
<EndDate>2019-05-16</EndDate>
</TermPeriod>
</TermPeriods>
</AcademicYear>
</AcademicYears>
<SummerTerm>
<!--A Summer Term will be outside of the normal Academic Years sent in the SAFI as it could be a header or trailer (not always up to the SIS)-->
<TermPeriods>
<!--Term period element will be identical to the existing ones. Summer terms must not overlap other terms-->
<TermPeriod>
<Description>Summer Term 2018</Description>
<StartDate>2018-06-15</StartDate>
<EndDate>2018-08-15</EndDate>
</TermPeriod>
<TermPeriod>
<Description>Summer Term 2019</Description>
<StartDate>2019-06-10</StartDate>
<EndDate>2019-08-05</EndDate>
</TermPeriod>
</TermPeriods>
</SummerTerm>
</Term>
Configure the Summer Term as a Header or Trailer
Using Groovy scripts, you can configure SFP to add a summer term automatically as a header or a trailer if there is enrollment in the term. The configuration to control this behavior has two controls: first, the CSV file and second, the Groovy script.
- CSV File
- PKGSCHEDATTRIB.csv
- Column: SUMMER_TERM_SCRIPT (this is the file path)
- Data Type: Groovy Script
- Level: Set per OPEID.
The Groovy Script .
This code block is a simple example of a Groovy script that returns a summer term as a summer trailer.
return "trailer";
Summer Header or Trailer Groovy Script: Explained
You have complete flexibility through Groovy scripting to treat summer terms as headers or trailers globally or for very specific student populations.
Review the following table to see an example of a few simple scripts and their descriptions.
| Sample Groovy Script | Description |
| return "header"; | SFP automatically defaults students with an enrollment in a summer term to be a summer header. |
| return "trailer"; |
SFP automatically defaults students with an enrollment in a summer term to be a summer trailer. If the summer term is before the first academic year, then the summer term is considered a header. |
| null |
SFP automatically defaults students with an enrollment in a summer term to be a summer trailer. If the summer term is before the first academic year, then the summer term is considered a header. |
Configure When Summer Terms Are Awarded
-
When to start awarding a summer term. For example, 20 days before spring term ends plus enrollment in the summer term.
-
When to freeze the fall/spring awards and roll over the remaining eligibility for Direct Loans to the summer term plus any additional funds. For example, grade level increases.
You have complete flexibility as to when you want to start packaging a summer term through Groovy configuration. The delivered baseline configuration packages a summer term when the standard academic year has ended, but you can package the summer trailer much earlier if you want, but modifying the Groovy script provided through the baseline configuration.
The configuration to control this behavior has two controls: first, the CSV file and second, the Groovy script.
- The CSV file:
- FAS_FUND_CONFIG.csv
- Column: AWARD_OVERRIDE_CRITERIA
- Data Type: CLOB (Groovy Script)
- Level: Set per Fund
- Possible Values:
- The Groovy script
This code block is a copy of the baseline configuration Groovy script for Direct Subsidized Loans (DSUB) and Direct Unsubsidized Loans (DUNSUB).
/* Baseline - Award Overriding Criteria for DSUB DUNSUB - combined Term and Non-Term */
import org.joda.time.LocalDate;
optimizer
.setCumulativeGradeLevelLimitApplicable(
(term == null || term.isStandard())
&& (program.isUndergraduate() || !isLastAcy))
.setFundingForPeriodFilter {fundCode, fundType -> fundCode != "DISCOUNT"};
if (pp.getStatus() == "CANCELED")
{
return awardInfo.withMaxAmount(0).withRetainedAmount(0);
}
if (program.isTerm())
{
def overlappingTerms = primaryProgram.getTerms().getOverlappingWith(term);
/* Methods returning collection, as well as filters, will be plural; otherwise singular */
if (overlappingTerms.getStudentsTermStatuses().contains("WITHDRAWN"))
{
log.debug("STUDENT TERM IS WITHDRAWN");
def r2t4OverlappingTerms = r2t4.getOverlappingWith(term)
.getWithProcessStatuses(["NOT_REQUIRED", "COMPLETED"])
.getWithOldas(overlappingTerms.getOldas());
if (!r2t4OverlappingTerms.isEmpty())
{
log.debug("R2T4 Overlapping Terms isn't empty, FREEZING!");
def sum = disbursements.getInAcademicYear(acyNo)
.getWithFundCode(fundCode)
.getInAwardYear(awy)
.getInLoanPeriod(lpNo)
.getInPaymentPeriod(ppNo)
.filterStatuses { status -> status != "DISBURSEMENT_CANCELED" }
.getPpMaxDisbursementAmount();
return awardInfo.withMaxAmount(sum).withRetainedAmount(sum);
}
else
{
log.debug("R2T4 PROCESS NOT YET IN A FREEZING STATE");
}
}
if (enrollmentStatus == "NOT_ATTENDING" || enrollmentStatus == "LESS_THAN_HALF_TIME" || (sapStatus != null && sapStatus == "FD_FINANCIAL_AID_DISQUALIFICATION"))
{
log.debug("ZEROING - enrollmentStatus={}, sapStatus={} ", enrollmentStatus, sapStatus);
return awardInfo.withMaxAmount(0).withRetainedAmount(0);
}
def freezingDateForStandard = acy.getTerms()
.filter {t -> t.isSummerTrailer() && t.isAttending() }
.min() // get the earliest (yields an optional value)
.map {t -> t.getStartDate()} // map optional to its start date
.getOrElse(lp.getEndDate()); // if optional absent (no summer trailers) take lp.getEndDate
def now = LocalDate.now();
if (log.debug(lp.getEndDate() <= now, "LOAN PERIOD IN THE PAST") // Update this line to determine when to freeze the standard terms and roll over unused funds to summer terms
|| log.debug(term.isStandard() && freezingDateForStandard <= now, "SUMMER TRAILER STARTING")
|| log.debug(term.isSummerHeader(), "SUMMER HEADER")
|| log.debug(term.isSummerTrailer() && now < freezingDateForStandard, "TOO EARLY FOR SUMMER TRAILER"))
{
def sum = disbursements.getInAcademicYear(acyNo)
.getWithFundCode(fundCode)
.getInAwardYear(awy)
.getInLoanPeriod(lpNo)
.getInPaymentPeriod(ppNo)
.filterStatuses { status -> status != "DISBURSEMENT_CANCELED" }
.getTotalDisbursementAmount();
log.debug("FREEZING TO {}", sum);
return awardInfo.withMaxAmount(sum).withRetainedAmount(sum);
}
}
return awardInfo;
Summer Term Section of the Groovy Script: Explained
Using the baseline configuration Groovy script for Direct Subsidized Loans (DSUB) and Direct Unsubsidized Loans (DUNSUB), SFP doesn't award or package the student for loans until the standard academic year (SAY) ends. For example, when both the fall and spring terms are complete.
Once the academic year ends, SFP lowers the awards for the fall and spring to match the sum of the disbursements. For example, down to the accepted amount. Then SFP rolls any remaining eligibility for the loan period over to the summer term (summer trailer).
This code block is the portion of the baseline configuration Groovy script for DSUB and DUNSUB that is associated with packaging a summer term.
def freezingDateForStandard = acy.getTerms()
.filter {t -> t.isSummerTrailer() && t.isAttending() }
.min() // get the earliest (yields an optional value)
.map {t -> t.getStartDate()} // map optional to its start date
.getOrElse(lp.getEndDate()); // if optional absent (no summer trailers) take lp.getEndDate
def now = LocalDate.now();
if (log.debug(lp.getEndDate() <= now, "LOAN PERIOD IN THE PAST") // Update this line to determine when to freeze the standard terms and roll over unused funds to summer terms
|| log.debug(term.isStandard() && freezingDateForStandard <= now, "SUMMER TRAILER STARTING")
|| log.debug(term.isSummerHeader(), "SUMMER HEADER")
|| log.debug(term.isSummerTrailer() && now < freezingDateForStandard, "TOO EARLY FOR SUMMER TRAILER"))
{
def sum = disbursements.getInAcademicYear(acyNo)
.getWithFundCode(fundCode)
.getInAwardYear(awy)
.getInLoanPeriod(lpNo)
.getInPaymentPeriod(ppNo)
.filterStatuses { status -> status != "DISBURSEMENT_CANCELED" }
.getTotalDisbursementAmount();
log.debug("FREEZING TO {}", sum);
return awardInfo.withMaxAmount(sum).withRetainedAmount(sum);
}
}
return awardInfo;
Conditions
-
Freezing a term means SFP is setting its award for the specific fund under evaluation to the total disbursement amount of noncanceled disbursements for that term—usually one disbursement. This also works for summer terms without disbursements, in which case their awards are frozen to $0.00. When the term is frozen, its award isn't subject to fund optimization. This means that it's taken into consideration, affecting other term awards that aren't frozen, but isn't amenable to change.
Freezing a term is done in the
thenpart of the lastifstatement.def sum = disbursements.getInAcademicYear(acyNo) .getWithFundCode(fundCode) .getInAwardYear(awy) .getInLoanPeriod(lpNo) .getInPaymentPeriod(ppNo) .filterStatuses { status -> status != "DISBURSEMENT_CANCELED" } .getTotalDisbursementAmount(); log.debug("FREEZING TO {}", sum); return awardInfo.withMaxAmount(sum).withRetainedAmount(sum); -
freezingDateForStandard
The main dynamics being implemented here is: Summer Headers are always frozen and then either standard terms or summer trailers are frozen. Summer trailers remain frozen to $0.00 when they are in the future. When the first summer trailer in an academic year has passed, standard terms are frozen, and SFP allows the summer trailer to receive remaining fund eligibility due to fund optimization. So, an important variable is freezingDateForStandard, which defined as:
def freezingDateForStandard = acy.getTerms() .filter {t -> t.isSummerTrailer() && t.isAttending() } // from summer trailers (probably at most 1) .min() // get the earliest (yields an optional value) .map {t -> t.getStartDate()} // map optional to its start date .getOrElse(lp.getEndDate()); // if optional absent (no summer trailers) take lp.getEndDatefreezingDateForStandard is defined as the start date of the earliest summer trailer (hence
min())having attendance in that academic year. Or, in the event there are no summer trailers, SFP defaults tolp.getEndDate(), which is the end date of the respective loan period. Now all the relevant freezing rules appear in the condition through the last if statement, namely:if (log.debug(lp.getEndDate() <= now, "LOAN PERIOD IN THE PAST") || log.debug(term.isStandard() && freezingDateForStandard <= now, "SUMMER TRAILER STARTING") || log.debug(term.isSummerHeader(), "SUMMER HEADER") || log.debug(term.isSummerTrailer() && now < freezingDateForStandard, "TOO EARLY FOR SUMMER TRAILER")) -
The respective loan period is in the past.
This happens for any term if the respective loan period is in the past is being frozen. This is what freezes earlier terms in donut scenarios. A donut scenario is when a student attends term 1, does not attend term 2, and returns in term 3.
-
The summer trailer starting.
In this condition, you can see
term.isStandard()so the term under evaluation is a standard term and the current date is past thefreezingDateForStandard(if this happens to belp.getEndDate(), this condition is equivalent to the respective loan period being in the past). Therefore, SFP freezes the standard term and rolls resources over to the summer trailer. -
PART 5 - SUMMER HEADER
For this condition, SFP freezes all summer headers regardless. If this condition is removed, summer headers are awarded just like standard terms and compete for available resources. Summer headers are frozen to $0.00 unless there are disbursements for them.
-
PART 6 - TOO EARLY FOR SUMMER TRAILER
This is exactly what prevents summer trailers from being awarded early and competing for resources with standard terms. In this condition, you can see
term.isSummerTrailer()so the term under evaluation is a summer trailer and is in the future, so SFP freezes it and the value is $0.00 unless there are disbursements.Note: The conditions "summer trailer starting" and "too early for summer trailer" are mutually exclusive. When you freeze standard terms, you aren't freezing summer trailers unless the respective loan is in the past.
Other Configuration Considerations
-
Months Calculation
You may want to analyze your institution's months configuration and update it to calculate the designated number of months for summer terms (see lines 10-12 in the sample below).
- Table: FAS_PACK_SCHED_CONF
- Filed: PP_MONTHS_SCRIPT
Here's an example of the Months Calculation Groovy script.
import org.joda.time.LocalDate; def returnValue = 0.0; if (program.getTermType() == null) { log.debug("PP MONTHS CALCULATION CONFIG: ERROR, null value passed from API"); return 0.0; } log.debug("PP MONTHS CALCULATION CONFIG: Program Term Type = {}", program.getTermType()); def programTermType = program.getTermType(); def safiTerm = program.getTerms().getOverlappingWith(term).get(0); if (safiTerm.isSummer()) { returnValue = 2.0; } // Standard from this point on else if (programTermType == "Semester") { returnValue = 4.5; } else if (programTermType == "Trimester") { returnValue = 3.0; } else if (programTermType == "Quarter") { returnValue = 3.0; } return returnValue; -
Cost of Attendance Calculation
You may want to update your institution's cost of attendance for summer terms if it differs from standard terms.
-
Enrollment Status Configuration
You may want to update the enrollment status configuration if the enrollment status calculation is different for summer terms.
-
Other Areas
Anytime your institution treats summer terms differently than standard terms.
Notable Behaviors
-
What if there are no courses in the summer term?
SFP packages the student according to the academic years and terms sent in the SAFI message and ignores the summer terms.
-
What if there are two summer terms and the student is taking the second as a trailer?
SFP adds the second summer term as a trailer and doesn't package the student with funds for the first summer term.
-
What if there's no SUMMER_TERM_SCRIPT configured?
- If the summer term exists before academic year 1, and the summer term has enrollment, SFP defaults the summer term to be a header.
- If the summer term exists after academic year 1 and there is summer term enrollment, SFP defaults the summer term to be a trailer.
-
What if the Groovy script associated with the SUMMER_TERM_SCRIPT column in the PKGSCHEDATTRIB.csv configuration workbook is malformed?
SFP acts as if there is no SUMMER_TERM_SCRIPT configured and logs an APP_EVT warning message to notify you of the malformed Groovy script.
-
What happens if I manually update a summer term?
If you manually modify the configured behavior of a summer term, SFP ignores the default configuration for that summer term moving forward.
If you've manually overridden an award or fund for a term for which you later need to move or remove, you must:
- Reduce the award down to $0.00 manually.
- Remove the term from the academic year.
- Add the term to the new academic year (if applicable).
- Increase the fund in the new academic year manually, if applicable.
Required Role Permissions
To view, add, edit, or remove a summer term, users must have these roles:
- Student
- Manage Summer Term
- Package Fund Edit
See Set General Permissions Matrix for additional information.
Navigation to Packaging and Disbursing Details
From Oracle Fusion Cloud Student Financial Planning, navigate to:
- , to view packaging details.
- , to view disbursing details.