Skip to content

Commit

Permalink
BRS-294: passStatus set to active if booking during active hours (#62)
Browse files Browse the repository at this point in the history
* BRS-294: passStatus set to active if booking during active hours

* BRS-294: improving date check

* BRS-294: fixing date check edge cases
  • Loading branch information
cameronpettit authored Jan 6, 2022
1 parent 6bad176 commit ab3658a
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 8 deletions.
52 changes: 45 additions & 7 deletions __tests__/writePass.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,40 @@ describe('Pass Fails', () => {
}
);
});

test('Handler - 400 Bad Request - Booking date in the past', async () => {
const event = {
body: JSON.stringify({
parkName: '',
firstName: '',
lastName: '',
facilityName: '',
email: '',
date: "1970-01-01T00:00:00.758Z",
type: '',
numberOfGuests: 1,
phoneNumber: '',
facilityType: '',
license: '',
captchaJwt: token
})
};
expect(await writePassHandler.handler(event, null)).toMatchObject(
{
"body": JSON.stringify({
msg: "You cannot book for a date in the past.",
title: "Booking date in the past"
}),
"headers": {
"Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
"Access-Control-Allow-Methods": "OPTIONS,GET",
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
"statusCode": 400
}
);
});

test('Handler - 400 Bad Request - One or more params are invalid.', async () => {
const event = {
Expand Down Expand Up @@ -271,7 +305,7 @@ describe('Pass Successes', () => {
facilityName: 'Parking lot A',
email: 'noreply@gov.bc.ca',
date: new Date(),
type: 'AM',
type: 'DAY',
numberOfGuests: 1,
phoneNumber: '2505555555',
facilityType: 'Trail',
Expand All @@ -290,10 +324,10 @@ describe('Pass Successes', () => {
expect(body.facilityName).toEqual('Parking lot A');
expect(body.email).toEqual('noreply@gov.bc.ca');
expect(typeof body.date).toBe('string');
expect(body.type).toEqual('AM');
expect(body.type).toEqual('DAY');
expect(typeof body.registrationNumber).toBe('string');
expect(body.numberOfGuests).toEqual(1);
expect(body.passStatus).toEqual('reserved');
expect(['reserved','active']).toContain(body.passStatus);
expect(body.phoneNumber).toEqual('2505555555');
expect(body.facilityType).toEqual('Trail');
expect(typeof body.err).toBe('string');
Expand All @@ -308,7 +342,7 @@ describe('Pass Successes', () => {
facilityName: 'Parking lot A',
email: 'noreply@gov.bc.ca',
date: new Date(),
type: 'AM',
type: 'DAY',
numberOfGuests: 1,
phoneNumber: '2505555555',
facilityType: 'Parking',
Expand All @@ -328,10 +362,10 @@ describe('Pass Successes', () => {
expect(body.facilityName).toEqual('Parking lot A');
expect(body.email).toEqual('noreply@gov.bc.ca');
expect(typeof body.date).toBe('string');
expect(body.type).toEqual('AM');
expect(body.type).toEqual('DAY');
expect(typeof body.registrationNumber).toBe('string');
expect(body.numberOfGuests).toEqual(1);
expect(body.passStatus).toEqual('reserved');
expect(['reserved','active']).toContain(body.passStatus);
expect(body.phoneNumber).toEqual('2505555555');
expect(body.facilityType).toEqual('Parking');
expect(typeof body.err).toBe('string');
Expand Down Expand Up @@ -366,10 +400,14 @@ async function databaseOperation(version, mode) {
"AM": {
"max": 25
},
"DAY": {
"max": 25
},
},
"reservations": {
"20211207": {
"AM": 1
"AM": 1,
"DAY": 1
}
},
"status": "open",
Expand Down
72 changes: 71 additions & 1 deletion lambda/writePass/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ const axios = require('axios');
const { verifyJWT } = require('../captchaUtil');
const { dynamodb, runQuery } = require('../dynamoUtil');
const { sendResponse } = require('../responseUtil');
const { utcToZonedTime } = require('date-fns-tz');

const TABLE_NAME = process.env.TABLE_NAME || 'parksreso';

// default opening/closing hours in 24h time
const DEFAULT_AM_OPENING_HOUR = 7;
const DEFAULT_PM_OPENING_HOUR = 12;

exports.handler = async (event, context) => {
let passObject = {
TableName: TABLE_NAME,
Expand Down Expand Up @@ -72,6 +77,59 @@ exports.handler = async (event, context) => {
numberOfGuests = 1;
}

// Get current time vs booking time information
const localDate = utcToZonedTime(Date.now(), 'America/Vancouver');
const currentHour = localDate.getHours();
const bookingDate = new Date(date);

let facilityObj = {
TableName: TABLE_NAME
};

// check if booking date in the past
localDate.setHours(0,0,0,0);
if (localDate > bookingDate) {
return sendResponse(400, {
msg: 'You cannot book for a date in the past.',
title: 'Booking date in the past'
});
}

facilityObj.ExpressionAttributeValues = {};
facilityObj.ExpressionAttributeValues[':pk'] = { S: 'facility::' + parkName };
facilityObj.ExpressionAttributeValues[':sk'] = { S: facilityName };
facilityObj.KeyConditionExpression = 'pk =:pk AND sk =:sk';
const facilityData = await runQuery(facilityObj);

// There should only be 1 facility.
let openingHour = facilityData[0].bookingOpeningHour || DEFAULT_AM_OPENING_HOUR;
let closingHour = DEFAULT_PM_OPENING_HOUR;

let status = 'reserved';

// check if booking same-day
if (localDate.getDate() === bookingDate.getDate()) {
// check if AM/PM/DAY is currently open
if (type === 'AM' && currentHour >= DEFAULT_PM_OPENING_HOUR) {
// it is beyond AM closing time
return sendResponse(400, {
msg:
'It is too late to book an AM pass on this day (AM time slot is from ' +
to12hTimeString(openingHour) +
' to ' +
to12hTimeString(closingHour) +
').',
title: 'AM time slot has expired'
});
}
if (type === 'PM') {
openingHour = DEFAULT_PM_OPENING_HOUR;
}
if (currentHour >= openingHour) {
status = 'active';
}
}

passObject.Item = {};
passObject.Item['pk'] = { S: 'pass::' + parkName };
passObject.Item['sk'] = { S: registrationNumber };
Expand All @@ -83,7 +141,7 @@ exports.handler = async (event, context) => {
passObject.Item['type'] = { S: type };
passObject.Item['registrationNumber'] = { S: registrationNumber };
passObject.Item['numberOfGuests'] = AWS.DynamoDB.Converter.input(numberOfGuests);
passObject.Item['passStatus'] = { S: 'reserved' };
passObject.Item['passStatus'] = { S: status };
passObject.Item['phoneNumber'] = AWS.DynamoDB.Converter.input(phoneNumber);
passObject.Item['facilityType'] = { S: facilityType };

Expand Down Expand Up @@ -297,6 +355,18 @@ exports.handler = async (event, context) => {
}
};

function to12hTimeString(hour) {
let period = 'am';
if (hour > 11) {
period = 'pm';
if (hour > 12) {
hour -= 12;
}
}
let hourStr = hour === 0 ? '12' : hour.toString();
return hourStr + period;
}

function generate(count) {
// TODO: Make this better
return Math.random().toString().substr(count);
Expand Down

0 comments on commit ab3658a

Please sign in to comment.