Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: switch to valueof when doing unix conversion #1320

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/components/learner-credit-management/data/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,6 @@ export const EMPTY_CONTENT_PRICE_VALUE = 0;
// Late enrollments feature
export const LATE_ENROLLMENTS_BUFFER_DAYS = 30;

export const MAX_MILLISECONDS = 8640000000000000;

// Query Key factory for the learner credit management module, intended to be used with `@tanstack/react-query`.
// Inspired by https://tkdodo.eu/blog/effective-react-query-keys#use-query-key-factories.
export const learnerCreditManagementQueryKeys = {
Expand Down
110 changes: 62 additions & 48 deletions src/components/learner-credit-management/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
LATE_ENROLLMENTS_BUFFER_DAYS,
LOW_REMAINING_BALANCE_PERCENT_THRESHOLD,
MAX_ALLOWABLE_REFUND_THRESHOLD_DAYS,
MAX_MILLISECONDS,
NO_BALANCE_REMAINING_DOLLAR_THRESHOLD,
START_DATE_DEFAULT_TO_TODAY_THRESHOLD_DAYS,
} from './constants';
Expand Down Expand Up @@ -567,33 +566,8 @@
*/
export const isDateBeforeToday = date => dayjs(date).isBefore(dayjs());

export const minimumEnrollByDateFromToday = ({ subsidyExpirationDatetime }) => Math.min(
dayjs(subsidyExpirationDatetime).subtract(MAX_ALLOWABLE_REFUND_THRESHOLD_DAYS, 'days').toDate(),
);

const subsidyExpirationRefundCutoffDate = ({ subsidyExpirationDatetime }) => dayjs(subsidyExpirationDatetime).subtract(MAX_ALLOWABLE_REFUND_THRESHOLD_DAYS, 'days').toDate();

const isStartDateWithinThreshold = ({ enrollStart, start, subsidyExpirationDatetime }) => {
if (!start && !enrollStart) {
return true;
}
const timeStampStartDate = dayjs(start).unix() || MAX_MILLISECONDS;
const timeStampEnrollStartDate = dayjs(enrollStart).unix() || MAX_MILLISECONDS;
const earliestStartDate = Math.min(timeStampStartDate, timeStampEnrollStartDate);
return dayjs(
earliestStartDate,
).isBefore(subsidyExpirationRefundCutoffDate({ subsidyExpirationDatetime }), 'seconds');
};

const isEnrollByDateWithinThreshold = ({ enrollBy, isLateRedemptionAllowed = false }) => {
if (!enrollBy) { return true; }
let enrollmentEffectiveDate = dayjs();
if (isLateRedemptionAllowed) {
enrollmentEffectiveDate = enrollmentEffectiveDate.subtract(LATE_ENROLLMENTS_BUFFER_DAYS, 'days');
}
return dayjs(enrollBy).isAfter(enrollmentEffectiveDate, 'seconds');
};

export const isCourseSelfPaced = ({ pacingType }) => pacingType === COURSE_PACING_MAP.SELF_PACED;

export const hasTimeToComplete = ({ end, weeksToComplete }) => {
Expand Down Expand Up @@ -647,23 +621,50 @@
return enrollBy;
};

const isStartDateWithinThreshold = ({
hasEnrollStart, enrollStart, start, subsidyExpirationDatetime,
}) => {
if (!start && !hasEnrollStart) {
return true;

Check warning on line 628 in src/components/learner-credit-management/data/utils.js

View check run for this annotation

Codecov / codecov/patch

src/components/learner-credit-management/data/utils.js#L628

Added line #L628 was not covered by tests
}
const validStartDates = [];
if (start) {
validStartDates.push(dayjs(start).valueOf());
}
if (hasEnrollStart) {
validStartDates.push(dayjs(enrollStart).valueOf());
}
const earliestStartDate = Math.min(...validStartDates);
const subsidyExpirationDate = subsidyExpirationRefundCutoffDate({ subsidyExpirationDatetime });
return dayjs(earliestStartDate).isBefore(subsidyExpirationDate, 'seconds');
};

const isEnrollByDateWithinThreshold = ({ hasEnrollBy, enrollBy, isLateRedemptionAllowed = false }) => {
if (!hasEnrollBy) { return true; }
let enrollmentEffectiveDate = dayjs();
if (isLateRedemptionAllowed) {
enrollmentEffectiveDate = enrollmentEffectiveDate.subtract(LATE_ENROLLMENTS_BUFFER_DAYS, 'days');

Check warning on line 646 in src/components/learner-credit-management/data/utils.js

View check run for this annotation

Codecov / codecov/patch

src/components/learner-credit-management/data/utils.js#L646

Added line #L646 was not covered by tests
}
return dayjs(enrollBy).isAfter(enrollmentEffectiveDate, 'seconds');
};

/**
* Filters assignable course runs based on the following criteria:
* - If hasEnrollBy, we return assignments with enroll before the soonest date: The subsidy expiration
* date - refund threshold
* - If isLateRedemptionAllowed, we consider only the isLateEnrollmentEligible field returned by Algolia for
* each run.
* - If the start date or enrollStart date (min date) is before the subsidy expiration - 14 day threshold
* AND
* If the enrollBy date is after current date
*
* Based on the above criteria, if isLateRedemptionAllowed is false, filter on if the course run isActive AND
* isEligibleForEnrollment
* isEligibleForEnrollment otherwise, if isLateRedemptionAllowed, the enrollBy date is modified to take into account
* late enrollment in the initial comparison.
*
* The main purpose of the filter is to ensure that course runs for a
* course are within the enterprises LC subsidy duration
* The inclusion of the increased sensitivity reduces the chance of a specific run
* (which may be allocated but not accepted) falling outside the date range of the subsidy expiration date
* refund threshold.
*
* We transform the assignedCourseRuns data to normalize the start and enrollBy dates based on the functions
* We transform the assignedCourseRuns data to normalize the start, enrollBy and enrollStart dates
*
* Furthermore, we return assignable course runs sorted by the enrollBy date (soonest to latest). If the enrollBy dates
* are equivalent, sort by the start date.
Expand All @@ -680,36 +681,49 @@
enrollStart: courseRun.hasEnrollStart ? dayjs.unix(courseRun.enrollStart).toISOString() : null,
upgradeDeadline: dayjs.unix(courseRun.upgradeDeadline).toISOString(),
}));

const assignableCourseRunsFilter = ({
enrollBy, enrollStart, start, isActive, hasEnrollBy, isLateEnrollmentEligible,
enrollBy, enrollStart, start, hasEnrollBy, hasEnrollStart, isActive, isLateEnrollmentEligible,
}) => {
const isEnrollByDateValid = isEnrollByDateWithinThreshold({
hasEnrollBy,
enrollBy,
isLateRedemptionAllowed,
});
const isStartDateValid = isStartDateWithinThreshold({
hasEnrollStart,
enrollStart,
start,
subsidyExpirationDatetime,
});

// Determine eligibility based on the provided enrollBy, start, and enrollStart date
const isEligibleForEnrollment = isEnrollByDateWithinThreshold(
{
enrollBy,
isLateRedemptionAllowed,
},
) && isStartDateWithinThreshold(
{
enrollStart,
start,
subsidyExpirationDatetime,
},
);
const isEligibleForEnrollment = isEnrollByDateValid && isStartDateValid;

if (!isEligibleForEnrollment) {
// Basic checks against this content's critical dates and their relation to
// the current date and subsidy expiration date have failed.
return false;

Check warning on line 706 in src/components/learner-credit-management/data/utils.js

View check run for this annotation

Codecov / codecov/patch

src/components/learner-credit-management/data/utils.js#L706

Added line #L706 was not covered by tests
}
if (hasEnrollBy && isLateRedemptionAllowed && isDateBeforeToday(enrollBy)) {
return isLateEnrollmentEligible && isEligibleForEnrollment;
// Special case: late enrollment has been enabled by ECS for this budget, and
// isEligibleForEnrollment already succeeded, so we know that late enrollment
// would be happy given enrollment deadline of the course. Now all we need
// to do is make sure the run itself is generally eligible for late enrollment
return isLateEnrollmentEligible;

Check warning on line 713 in src/components/learner-credit-management/data/utils.js

View check run for this annotation

Codecov / codecov/patch

src/components/learner-credit-management/data/utils.js#L713

Added line #L713 was not covered by tests
}
// General courseware filter
return isActive && isEligibleForEnrollment;
return isActive;
};

// Main function that transforms the cloned course runs to the normalizedStart and normalizedEnrollBy dates
const assignableCourseRuns = clonedCourseRuns.filter(assignableCourseRunsFilter).map(courseRun => {
if (!courseRun.hasEnrollBy) {
return {
...courseRun,
start: getNormalizedStartDate(courseRun),
enrollBy: getNormalizedEnrollByDate(
minimumEnrollByDateFromToday({ subsidyExpirationDatetime }),
subsidyExpirationRefundCutoffDate({ subsidyExpirationDatetime }),
),
hasEnrollBy: true,
};
Expand Down