Skip to content

Commit

Permalink
feat/2803
Browse files Browse the repository at this point in the history
-- new helper to get the abstraction period season
  • Loading branch information
Stephan-Hough committed Sep 22, 2020
1 parent 865ec77 commit fa455b4
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
node_modules/
.env
.vscode
.DS_Store
5 changes: 4 additions & 1 deletion src/returns/date/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ const { createReturnCycles } = require('./returns-cycles');
const { getPeriodStart } = require('./period-start');
const { getPeriodEnd } = require('./period-end');
const { isDateWithinAbstractionPeriod } = require('./date-in-abstraction-period');
const { getAbstractionPeriodSeason, isWithinAbstractionPeriod } = require('./season-in-abstraction-period');

module.exports = {
createReturnCycles,
getPeriodStart,
getPeriodEnd,
isDateWithinAbstractionPeriod
isDateWithinAbstractionPeriod,
getAbstractionPeriodSeason,
isWithinAbstractionPeriod
};
81 changes: 81 additions & 0 deletions src/returns/date/season-in-abstraction-period.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use-strict';

const moment = require('moment');
const summer = {
startDay: '01',
startMonth: '04',
endDay: '31',
endMonth: '10'
};

const winter = {
startDay: '01',
startMonth: '11',
endDay: '31',
endMonth: '03'
};

const CHARGE_SEASON = {
summer: 'summer',
winter: 'winter',
allYear: 'all year'
};

const createRange = (abstractionPeriod, startYear) => {
const { startDay, endDay, startMonth, endMonth } = abstractionPeriod;
const isCrossYear = (startMonth > endMonth || (startMonth === endMonth && startDay > endDay));
const endYear = isCrossYear ? startYear + 1 : startYear;

const mStart = moment({
year: startYear,
month: startMonth - 1,
date: startDay
});

const mEnd = moment({
year: endYear,
month: endMonth - 1,
date: endDay
});

return moment.range(mStart, mEnd);
};

/**
* Checks if the passed AbstractionPeriod contains this instance. In order
* for this to return true, this instance must fit inside the passed
* AbstractionPeriod, including the boundaries.
*
* @param {Object} abstractionPeriod should contain a startDay, startMonth, endDay and endMonth
* @param {Object} period should contain a startDay, startMonth, endDay and endMonth
*/
const isWithinAbstractionPeriod = (abstractionPeriod, period) => {
const abstractionRange = createRange(abstractionPeriod, 2018);
const testRanges = [createRange(period, 2017), createRange(period, 2018)];
return testRanges.some(range => range.contains(abstractionRange));
};

/**
* Gets a default charge season for the defined abstraction period.
*
* This is a starting point in some cases where additional logic (TPT etc)
* will need to be overlayed.
*/
const getAbstractionPeriodSeason = (abstractionPeriod) => {
// For the season to be summer, this abstraction period must
// sit within the summer period (01/04 - 31/10)
if (isWithinAbstractionPeriod(abstractionPeriod, summer)) {
return CHARGE_SEASON.summer;
}

// For the season to be winter, this abstraction period must
// sit within the winter period (01/11 - 31/03)
if (this.isWithinAbstractionPeriod(abstractionPeriod, winter)) {
return CHARGE_SEASON.winter;
}

return CHARGE_SEASON.allYear;
};

exports.isWithinAbstractionPeriod = isWithinAbstractionPeriod;
exports.getAbstractionPeriodSeason = getAbstractionPeriodSeason;
142 changes: 142 additions & 0 deletions test/returns/date/season-in-abstraction-period.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
'use strict';

const { experiment, test } = exports.lab = require('@hapi/lab').script();
const { expect } = require('@hapi/code');
const { not } = require('@hapi/joi');
const { returns: { date: { isWithinAbstractionPeriod, getAbstractionPeriodSeason } } } = require('../../../src');

const CHARGE_SEASON = {
summer: 'summer',
winter: 'winter',
allYear: 'all year'
};
const getPeriod = (startDay, startMonth, endDay, endMonth) => { return { startDay, startMonth, endDay, endMonth }; };

experiment('.getAbstractionPeriodSeason()', () => {
experiment('when the period matches the summer period', () => {
test('the season is all year', async () => {
const period = getPeriod('01', '04', '31', '10');
expect(getAbstractionPeriodSeason(period)).to.equal(CHARGE_SEASON.summer);
});
});

experiment('when the period matches the winter period', () => {
test('the season is all year', async () => {
const winter = getPeriod(1, 11, 31, 3);
expect(getAbstractionPeriodSeason(winter)).to.equal(CHARGE_SEASON.winter);
});
});

experiment('when the period is within the summer period', () => {
test('the season is summer', async () => {
const april = getPeriod(2, 4, 30, 4);
expect(getAbstractionPeriodSeason(april)).to.equal(CHARGE_SEASON.summer);

const october = getPeriod(2, 10, 25, 10);
expect(getAbstractionPeriodSeason(october)).to.equal(CHARGE_SEASON.summer);
});
});

experiment('when the period is within the winter period', () => {
test('the season is winter', async () => {
const november = getPeriod(2, 11, 30, 11);
expect(getAbstractionPeriodSeason(november)).to.equal(CHARGE_SEASON.winter);

const march = getPeriod(2, 3, 25, 3);
expect(getAbstractionPeriodSeason(march)).to.equal(CHARGE_SEASON.winter);

const xmasHols = getPeriod(20, 12, 4, 1);
expect(getAbstractionPeriodSeason(xmasHols)).to.equal(CHARGE_SEASON.winter);
});
});
});

experiment('.isWithinAbstractionPeriod', () => {
experiment('when the abstraction period is in the same year', () => {
test('returns true if the start dates are the same', async () => {
const summer = getPeriod(1, 4, 31, 10);
const period = getPeriod(1, 4, 1, 10);
expect(isWithinAbstractionPeriod(period, summer)).to.equal(true);
});

test('returns true if the end dates are the same', async () => {
const summer = getPeriod(1, 4, 31, 10);
const period = getPeriod(1, 5, 31, 10);
expect(isWithinAbstractionPeriod(period, summer)).to.equal(true);
});

test('returns true if both start and end dates are the same', async () => {
const summer = getPeriod(1, 4, 31, 10);
const period = getPeriod(1, 4, 31, 10);
expect(isWithinAbstractionPeriod(period, summer)).to.equal(true);
});

test('returns true if both dates are in between the period', async () => {
const summer = getPeriod(1, 4, 31, 10);
const period = getPeriod(1, 5, 1, 6);
expect(isWithinAbstractionPeriod(period, summer)).to.equal(true);
});

test('return false if the start date is before the range', async () => {
const summer = getPeriod(1, 4, 31, 10);
const beforeSummer = getPeriod(1, 3, 31, 10);
expect(isWithinAbstractionPeriod(beforeSummer, summer)).to.equal(false);
});

test('return false if the end date is after the range', async () => {
const summer = getPeriod(1, 4, 31, 10);
const afterSummer = getPeriod(1, 4, 31, 11);
expect(isWithinAbstractionPeriod(afterSummer, summer)).to.equal(false);
});

test('return false if the start and end dates are outside the range', async () => {
const summer = getPeriod(1, 4, 31, 10);
const notSummer = getPeriod(1, 3, 31, 11);
expect(isWithinAbstractionPeriod(notSummer, summer)).to.equal(false);
});
});

experiment('when the abstraction period spans two years', () => {
test('returns true if the start dates are the same', async () => {
const winter = getPeriod(1, 11, 31, 3);
const period = getPeriod(1, 11, 1, 3);
expect(isWithinAbstractionPeriod(period, winter)).to.equal(true);
});

test('returns true if the end dates are the same', async () => {
const winter = getPeriod(1, 11, 31, 3);
const period = getPeriod(1, 2, 31, 3);
expect(isWithinAbstractionPeriod(period, winter)).to.equal(true);
});

test('returns true if both start and end dates are the same', async () => {
const winter = getPeriod(1, 11, 31, 3);
const period = getPeriod(1, 11, 31, 3);
expect(isWithinAbstractionPeriod(period, winter)).to.equal(true);
});

test('returns true if both dates are in between the period', async () => {
const winter = getPeriod(1, 11, 31, 3);
const period = getPeriod(1, 12, 1, 3);
expect(isWithinAbstractionPeriod(period, winter)).to.equal(true);
});

test('return false if the start date is before the range', async () => {
const winter = getPeriod(1, 11, 31, 3);
const beforewinter = getPeriod(1, 10, 31, 3);
expect(isWithinAbstractionPeriod(beforewinter, winter)).to.equal(false);
});

test('return false if the end date is after the range', async () => {
const winter = getPeriod(1, 11, 31, 3);
const afterSummer = getPeriod(1, 11, 31, 4);
expect(isWithinAbstractionPeriod(afterSummer, winter)).to.equal(false);
});

test('return false if the start and end dates are outside the range', async () => {
const winter = getPeriod(1, 11, 31, 3);
const notWinter = getPeriod(1, 10, 31, 4);
expect(isWithinAbstractionPeriod(notWinter, winter)).to.equal(false);
});
});
});

0 comments on commit fa455b4

Please sign in to comment.