From a6d482b98bdedb39371f427b58b05933fd9c3247 Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 4 Feb 2022 16:36:46 +0000 Subject: [PATCH 1/3] HT-12 Create pay bill screen --- server/business/bill.business.js | 16 +++- server/controllers/bill.controller.js | 8 ++ server/datalayer/mongo.js | 9 +++ server/routes/bill.routes.js | 3 + server/utilities.js | 13 +++- ui/src/api/api.js | 13 ++++ ui/src/components/input.vue | 3 +- ui/src/components/navbar.vue | 4 +- ui/src/router/router.js | 3 + ui/src/styles/style.scss | 9 +++ ui/src/views/MyBills.vue | 7 +- ui/src/views/PayBill.vue | 101 +++++++++++++++++++++++++- 12 files changed, 176 insertions(+), 13 deletions(-) diff --git a/server/business/bill.business.js b/server/business/bill.business.js index 03b975d..c884164 100644 --- a/server/business/bill.business.js +++ b/server/business/bill.business.js @@ -1,6 +1,7 @@ const DataLayer = require("../datalayer/mongo"); const model = require("../database").getModel("bill"); const httpError = require("http-errors"); +const Utilities = require('../utilities') module.exports = class BillBusiness { constructor() { @@ -25,13 +26,24 @@ module.exports = class BillBusiness { } /** - * Get a bill by ID. + * Get bill by ID. + */ + async getBillById(billId) { + return this.dataLayer + .findByPropertyAndPopulate(billId, [{path: 'journey', populate: {path: 'entryLocation exitLocation'}}, {path: 'driver', select: 'username type email'}]) + .catch((error) => { + throw httpError(500, error.message) + }) + } + + /** + * Pay a bill by ID. */ async payBill(id) { const record = { paid: true } - return this.dataLayer.update(id, record) + return this.dataLayer.update(Utilities.convertToObjectId(id), record) .catch((error) => {throw httpError(404, error.message) }) } diff --git a/server/controllers/bill.controller.js b/server/controllers/bill.controller.js index 07f2c67..bb22674 100644 --- a/server/controllers/bill.controller.js +++ b/server/controllers/bill.controller.js @@ -10,7 +10,15 @@ exports.getAllBills = async (req, res) => { .catch((error) => { res.status(error.status).send({message: error.message}) }) +} +/** + * Get bill by ID. + */ +exports.getBillById = async (req, res) => { + billBusiness.getBillById(req.params.id) + .then((data) => {return res.status(200).send(data)}) + .catch((error) => {res.status(error.status).send({message: error.message})}) } /** diff --git a/server/datalayer/mongo.js b/server/datalayer/mongo.js index ff2677b..2bc8eae 100644 --- a/server/datalayer/mongo.js +++ b/server/datalayer/mongo.js @@ -18,6 +18,15 @@ class DataLayer { }) }) } + + /** + * Find all records in the database. + */ + async findByPropertyAndPopulate(id, populateFilter) { + return this.model.findById(id) + .orFail(new Error("Record can't be found in the database.")) + .populate(JSON.parse(JSON.stringify(populateFilter))) + } /** * Find a record by property in the database. diff --git a/server/routes/bill.routes.js b/server/routes/bill.routes.js index 848c979..338bcce 100644 --- a/server/routes/bill.routes.js +++ b/server/routes/bill.routes.js @@ -8,6 +8,9 @@ const billController = require("../controllers/bill.controller"); // Get All Bills router.get("/", checkJwtToken, billController.getAllBills); +// Get Bill By Id +router.get("/:id", checkJwtToken, billController.getBillById); + // Pay for bill router.put("/:id", checkJwtToken, billController.payBill); diff --git a/server/utilities.js b/server/utilities.js index 2f1a78f..ae96aba 100644 --- a/server/utilities.js +++ b/server/utilities.js @@ -1,9 +1,18 @@ const haversine = require("haversine") +const httpError = require("http-errors") +const objectId = require("mongoose").Types.ObjectId module.exports = class Utilities { static calculateCost(journey) { return (haversine(journey.entryLocation.coordinates, journey.exitLocation.coordinates) * this.costPerMile) } - - static costPerMile = 0.01 + + static convertToObjectId(id) { + if (objectId.isValid(id)) { + return objectId(id) + } + throw new httpError(400, "ID is not valid.") + } + + static costPerMile = 0.01 } \ No newline at end of file diff --git a/ui/src/api/api.js b/ui/src/api/api.js index 4db511d..abcaf2f 100644 --- a/ui/src/api/api.js +++ b/ui/src/api/api.js @@ -27,6 +27,19 @@ const api = class Api { }); } + async getBillById(billId) { + return axios + .get(`${this.baseUrl}/bill/${billId}`, { + withCredentials: true, + }) + .then((response) => { + return response.data; + }) + .catch((error) => { + throw error; + }); + } + async payBill(billId) { return axios .put( diff --git a/ui/src/components/input.vue b/ui/src/components/input.vue index 2e6c4dc..77d873d 100644 --- a/ui/src/components/input.vue +++ b/ui/src/components/input.vue @@ -2,7 +2,8 @@ diff --git a/ui/src/components/navbar.vue b/ui/src/components/navbar.vue index 0a0270c..8cfb66c 100644 --- a/ui/src/components/navbar.vue +++ b/ui/src/components/navbar.vue @@ -4,13 +4,13 @@ id="navbar" v-if="loggedIn" > -
+ Self Service Portal Logo

Self Service Portal

-
+ {{ formatCost(cell.item.cost) }} -