Skip to content

Commit

Permalink
Merge pull request #23 from dhis2/period-conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammer5 authored Jul 14, 2021
2 parents 4cc7ce0 + d9421ab commit b498116
Show file tree
Hide file tree
Showing 5 changed files with 595 additions and 21 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"@testing-library/react-hooks": "^7.0.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"identity-obj-proxy": "^3.0.0"
"identity-obj-proxy": "^3.0.0",
"mockdate": "^3.0.5"
},
"dependencies": {
"@dhis2/app-runtime": "^2.8.0",
Expand Down
2 changes: 1 addition & 1 deletion src/app-context/app-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const query = {
'displayName',
'dataApprovalLevels',
'periodType',
'dataSets[id,displayName]',
'dataSets[id,displayName,periodType]',
],
},
},
Expand Down
159 changes: 141 additions & 18 deletions src/top-bar/period-select/fixed-periods.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ import i18n from '@dhis2/d2-i18n'
*/

// Period types
const DAILY = 'Daily'
const WEEKLY = 'Weekly'
const WEEKLY_WEDNESDAY = 'WeeklyWednesday'
const WEEKLY_THURSDAY = 'WeeklyThursday'
const WEEKLY_SATURDAY = 'WeeklySaturday'
const WEEKLY_SUNDAY = 'WeeklySunday'
const BI_WEEKLY = 'BiWeekly'
const MONTHLY = 'Monthly'
const BI_MONTHLY = 'BiMonthly'
const QUARTERLY = 'Quarterly'
const SIX_MONTHLY = 'SixMonthly'
const SIX_MONTHLY_APRIL = 'SixMonthlyApril'
// const SIX_MONTHLY_NOV = 'SixMonthlyNov'
const YEARLY = 'Yearly'
const FINANCIAL_APRIL = 'FinancialApril'
const FINANCIAL_JULY = 'FinancialJuly'
const FINANCIAL_OCT = 'FinancialOct'
const FINANCIAL_NOV = 'FinancialNov'
export const DAILY = 'Daily'
export const WEEKLY = 'Weekly'
export const WEEKLY_WEDNESDAY = 'WeeklyWednesday'
export const WEEKLY_THURSDAY = 'WeeklyThursday'
export const WEEKLY_SATURDAY = 'WeeklySaturday'
export const WEEKLY_SUNDAY = 'WeeklySunday'
export const BI_WEEKLY = 'BiWeekly'
export const MONTHLY = 'Monthly'
export const BI_MONTHLY = 'BiMonthly'
export const QUARTERLY = 'Quarterly'
export const SIX_MONTHLY = 'SixMonthly'
export const SIX_MONTHLY_APRIL = 'SixMonthlyApril'
// export const SIX_MONTHLY_NOV = 'SixMonthlyNov'
export const YEARLY = 'Yearly'
export const FINANCIAL_APRIL = 'FinancialApril'
export const FINANCIAL_JULY = 'FinancialJuly'
export const FINANCIAL_OCT = 'FinancialOct'
export const FINANCIAL_NOV = 'FinancialNov'

const getMonthName = key => {
const monthNames = [
Expand Down Expand Up @@ -738,3 +738,126 @@ export const parsePeriodId = (id, allowedTypes) => {
periodType,
}
}

export const getFixedPeriodsForTypeAndDateRange = (
type,
startDate,
endDate
) => {
// Allow dates and date-strings
startDate = startDate instanceof Date ? startDate : new Date(startDate)
endDate = endDate instanceof Date ? endDate : new Date(endDate)

let year = endDate.getFullYear()
let startDateReached = false
const convertedPeriods = []

while (!startDateReached) {
getFixedPeriodsByTypeAndYear(type, year)
.reverse()
.forEach(period => {
const periodEnd = new Date(period.endDate)
// exclude periods that end before start date
const endsAfterPeriodStart = periodEnd >= startDate
// exclude periods that end after end date
const endsBeforePeriodEnd = periodEnd <= endDate

if (!endsAfterPeriodStart) {
startDateReached = true
}

if (endsAfterPeriodStart && endsBeforePeriodEnd) {
convertedPeriods.push(period)
}
})

--year
}

return convertedPeriods.reverse()
}

const FIXED_PERIODS_BY_LENGTH = [
[DAILY],
[WEEKLY, WEEKLY_WEDNESDAY, WEEKLY_THURSDAY, WEEKLY_SATURDAY, WEEKLY_SUNDAY],
[BI_WEEKLY],
[MONTHLY],
[BI_MONTHLY],
[QUARTERLY],
[SIX_MONTHLY, SIX_MONTHLY_APRIL],
[YEARLY, FINANCIAL_APRIL, FINANCIAL_JULY, FINANCIAL_OCT, FINANCIAL_NOV],
]

export const PERIOD_GREATER = 1
export const PERIOD_EQUAL = 0
export const PERIOD_SHORTER = -1

/*
* IF left < right THEN return 1
* IF left > right THEN return -1
* IF left = right THEN return 0
*
* Why right > left = 1 and not the other way?
* When partially applying this function, it makes sense this way:
*
* const compareWithWeekly = partial(compareFixedPeriodLength, 'WEEKLY')
* const isGreater = compareWithWeekly('YEARLY') === PERIOD_GREATER
* -> isGreater is true
*
* @param {string} right
* @param {string} left
* @returns {Int}
*/
export const compareFixedPeriodLength = (left, right) => {
const leftIndex = FIXED_PERIODS_BY_LENGTH.findIndex(types =>
types.includes(left)
)
const rightIndex = FIXED_PERIODS_BY_LENGTH.findIndex(types =>
types.includes(right)
)

if (leftIndex === rightIndex) return PERIOD_EQUAL
return leftIndex > rightIndex ? PERIOD_SHORTER : PERIOD_GREATER
}

export const getCurrentPeriodForType = type => {
const currentDate = new Date()
let year = currentDate.getFullYear()

// cover this and the next years as that
// should cover all existing period types
for (let i = 0; i < 2; ++i) {
const periods = getFixedPeriodsByTypeAndYear(type, year).reverse()

for (const period of periods) {
const periodStart = new Date(period.startDate)
const periodEnd = new Date(period.endDate)
const endsBeforePeriodEnd = currentDate <= periodEnd
const startsAfterPeriodStart = currentDate >= periodStart

if (endsBeforePeriodEnd && startsAfterPeriodStart) {
return period
}
}

++year
}

return null
}

export const isGreaterPeriodTypeEndDateWithinShorterPeriod = (
greaterPeriodType,
shorterPeriod
) => {
const greaterPeriod = getCurrentPeriodForType(greaterPeriodType)
const greaterPeriodEndDate = new Date(greaterPeriod.endDate)
const shorterPeriodEndDate = new Date(shorterPeriod.endDate)
const shorterPeriodStartDate = new Date(shorterPeriod.startDate)
const greaterEndsAfterShorterStarts =
greaterPeriodEndDate >= shorterPeriodStartDate
const greaterEndsBeforeShorterEnds =
greaterPeriodEndDate <= shorterPeriodEndDate

return greaterEndsAfterShorterStarts && greaterEndsBeforeShorterEnds
}
Loading

0 comments on commit b498116

Please sign in to comment.