From 43ec8ef7a341e725637f9db63752da8f11c8b41a Mon Sep 17 00:00:00 2001 From: "https://github.com': codeplus254" Date: Thu, 26 Sep 2019 18:23:54 +0300 Subject: [PATCH 1/5] categories requests has been done except product category --- package-lock.json | 41 ++++++++++++++++++++------- src/controllers/product.controller.js | 41 +++++++++++++++++++++------ src/routes/api/product.route.js | 3 +- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 07305f5..421d9c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3982,7 +3982,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4000,11 +4001,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4017,15 +4020,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4128,7 +4134,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4138,6 +4145,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4150,17 +4158,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4177,6 +4188,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4249,7 +4261,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4259,6 +4272,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4334,7 +4348,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4364,6 +4379,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4381,6 +4397,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4419,11 +4436,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.3", - "bundled": true + "bundled": true, + "optional": true } } }, diff --git a/src/controllers/product.controller.js b/src/controllers/product.controller.js index ba000db..480345c 100755 --- a/src/controllers/product.controller.js +++ b/src/controllers/product.controller.js @@ -80,7 +80,7 @@ class ProductController { } /** - * get all products by caetgory + * get all products by category * * @static * @param {object} req express request object @@ -215,7 +215,12 @@ class ProductController { */ static async getAllCategories(req, res, next) { // Implement code to get all categories here - return res.status(200).json({ message: 'this works' }); + try { + const categories = await Category.findAll(); + return res.status(200).json(categories); + } catch (error) { + return next(error); + } } /** @@ -225,9 +230,21 @@ class ProductController { * @param {*} next */ static async getSingleCategory(req, res, next) { - const { category_id } = req.params; // eslint-disable-line - // implement code to get a single category here - return res.status(200).json({ message: 'this works' }); + const { category_id } = req.params; // eslint-disable-line + try { + const category = await Category.findByPk(category_id); + if (category) { + return res.status(200).json(category); + } + return res.status(404).json({ + error: { + status: 404, + message: `Category with id ${category_id} does not exist`, // eslint-disable-line + } + }); + } catch (error) { + return next(error); + } } /** @@ -237,9 +254,17 @@ class ProductController { * @param {*} next */ static async getDepartmentCategories(req, res, next) { - const { department_id } = req.params; // eslint-disable-line - // implement code to get categories in a department here - return res.status(200).json({ message: 'this works' }); + try { + const { department_id } = req.params; // eslint-disable-line + const categories = await Category.findAll({ + where: { + department_id, + }, + }); + return res.status(200).json(categories); + } catch (error) { + return next(error); + } } } diff --git a/src/routes/api/product.route.js b/src/routes/api/product.route.js index c1436b1..bfd1787 100755 --- a/src/routes/api/product.route.js +++ b/src/routes/api/product.route.js @@ -12,7 +12,8 @@ router.get('/products/inDepartment/:department_id', ProductController.getProduct router.get('/departments', ProductController.getAllDepartments); router.get('/departments/:department_id', ProductController.getDepartment); router.get('/categories', ProductController.getAllCategories); -router.get('/categories/:category_id'); +router.get('/categories/:category_id', ProductController.getSingleCategory); router.get('/categories/inDepartment/:department_id', ProductController.getDepartmentCategories); +router.get('/categories/inProduct/:product_id', ProductController.getProductsByCategory); export default router; From 84162f2ef86d92fbbc954fd056357b04e13e074f Mon Sep 17 00:00:00 2001 From: "https://github.com': codeplus254" Date: Thu, 26 Sep 2019 19:52:01 +0300 Subject: [PATCH 2/5] all attribute endpoints now working but need optimization --- src/controllers/attributes.controller.js | 73 ++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/src/controllers/attributes.controller.js b/src/controllers/attributes.controller.js index 3652d4f..3b9a71d 100644 --- a/src/controllers/attributes.controller.js +++ b/src/controllers/attributes.controller.js @@ -10,6 +10,16 @@ * NB: Check the BACKEND CHALLENGE TEMPLATE DOCUMENTATION in the readme of this repository to see our recommended * endpoints, request body/param, and response object for each of these method */ +import { + Product, + ProductAttribute, + Department, + AttributeValue, + Attribute, + Category, + Sequelize, +} from '../database/models'; + class AttributeController { /** * This method get all attributes @@ -19,7 +29,12 @@ class AttributeController { */ static async getAllAttributes(req, res, next) { // write code to get all attributes from the database here - return res.status(200).json({ message: 'this works' }); + try { + const attributes = await Attribute.findAll(); + return res.status(200).json(attributes); + } catch (error) { + return next(error); + } } /** @@ -30,7 +45,21 @@ class AttributeController { */ static async getSingleAttribute(req, res, next) { // Write code to get a single attribute using the attribute id provided in the request param - return res.status(200).json({ message: 'this works' }); + const { attribute_id } = req.params; // eslint-disable-line + try { + const attribute = await Attribute.findByPk(attribute_id); + if (attribute) { + return res.status(200).json(attribute); + } + return res.status(404).json({ + error: { + status: 404, + message: `Attribute with id ${attribute_id} does not exist`, // eslint-disable-line + } + }); + } catch (error) { + return next(error); + } } /** @@ -42,7 +71,17 @@ class AttributeController { static async getAttributeValues(req, res, next) { // Write code to get all attribute values for an attribute using the attribute id provided in the request param // This function takes the param: attribute_id - return res.status(200).json({ message: 'this works' }); + try { + const { attribute_id } = req.params; // eslint-disable-line + const attributeValues = await AttributeValue.findAll({ + where: { + attribute_id, + }, + }); + return res.status(200).json(attributeValues); + } catch (error) { + return next(error); + } } /** @@ -53,7 +92,33 @@ class AttributeController { */ static async getProductAttributes(req, res, next) { // Write code to get all attribute values for a product using the product id provided in the request param - return res.status(200).json({ message: 'this works' }); + try { + const { product_id } = req.params; // eslint-disable-line + const productAttributeValuesID = await ProductAttribute.findAll({ + where: { + product_id, + }, + attributes: ['attribute_value_id'], + }); + const productAttributes = []; + const valuesIDArray = []; + productAttributeValuesID.map(id => valuesIDArray.push(id.attribute_value_id)); + // eslint-disable-next-line no-plusplus + for (let i = 0; i < valuesIDArray.length; i++) { + // eslint-disable-next-line no-await-in-loop + const productAttribute = await AttributeValue.findOne({ + where: { + attribute_value_id: valuesIDArray[i], + }, + }); + if (productAttribute) { + productAttributes.push(productAttribute) + } + } + return res.status(200).json(productAttributes); + } catch (error) { + return next(error); + } } } From 01e61c6874b17cb60b155764a7ac51441decec9d Mon Sep 17 00:00:00 2001 From: "https://github.com': codeplus254" Date: Sun, 29 Sep 2019 08:44:17 +0300 Subject: [PATCH 3/5] product endpoints now working --- src/controllers/attributes.controller.js | 2 +- src/controllers/product.controller.js | 242 ++++++++++++++++++++--- src/database/models/productCategory.js | 1 + src/database/models/review.js | 44 +++++ src/routes/api/product.route.js | 4 +- 5 files changed, 265 insertions(+), 28 deletions(-) create mode 100644 src/database/models/review.js diff --git a/src/controllers/attributes.controller.js b/src/controllers/attributes.controller.js index 3b9a71d..8583722 100644 --- a/src/controllers/attributes.controller.js +++ b/src/controllers/attributes.controller.js @@ -112,7 +112,7 @@ class AttributeController { }, }); if (productAttribute) { - productAttributes.push(productAttribute) + productAttributes.push(productAttribute); } } return res.status(200).json(productAttributes); diff --git a/src/controllers/product.controller.js b/src/controllers/product.controller.js index 480345c..7cb045e 100755 --- a/src/controllers/product.controller.js +++ b/src/controllers/product.controller.js @@ -19,10 +19,13 @@ */ import { Product, + ProductCategory, + Review, Department, AttributeValue, Attribute, Category, + Customer, Sequelize, } from '../database/models'; @@ -46,15 +49,35 @@ class ProductController { */ static async getAllProducts(req, res, next) { const { query } = req; - const { page, limit, offset } = query + // eslint-disable-next-line camelcase + let { page, limit, description_length } = query; + if (!page) { + page = 1; + } else if (page < 1) { + page = 1; + }; + if (!limit) { + limit = 20; + } + // eslint-disable-next-line camelcase + if (!description_length) { + // eslint-disable-next-line camelcase + description_length = 200; + } + const offset = Number(page) * Number(limit) - Number(limit); + const maximum = offset + Number(limit); const sqlQueryMap = { - limit, offset, + limit: Number(limit), + }; + const paginationMeta = { + currentPage: offset, + currentPageSize: limit, }; try { const products = await Product.findAndCountAll(sqlQueryMap); return res.status(200).json({ - status: true, + paginationMeta, products, }); } catch (error) { @@ -92,21 +115,44 @@ class ProductController { static async getProductsByCategory(req, res, next) { try { - const { category_id } = req.params; // eslint-disable-line - const products = await Product.findAndCountAll({ + const { query, params } = req; + const { category_id } = params; // eslint-disable-line + let { page, limit, description_length } = query; + const offset = Number(page) * Number(limit) - Number(limit); + if (!page) { + page = 1; + } else if (page < 1) { + page = 1; + } + if (!limit) { + limit = 20; + } + const products = await ProductCategory.findAll({ + where: { + category_id, + }, include: [ { - model: Department, - where: { - category_id, - }, - attributes: [], + model: Product, + as: 'product', + attributes: [ + 'product_id', + 'name', + 'description', + 'price', + 'discounted_price', + 'thumbnail', + ], }, ], - limit, + raw: true, + attributes: [], + limit: Number(limit), offset, }); - return next(products); + return res.status(200).json({ + rows: products, + }); } catch (error) { return next(error); } @@ -124,6 +170,65 @@ class ProductController { */ static async getProductsByDepartment(req, res, next) { // implement the method to get products by department + try { + const { query, params } = req; + const { department_id } = params; // eslint-disable-line + let { page, limit, description_length } = query; + const offset = Number(page) * Number(limit) - Number(limit); + if (!page) { + page = 1; + } else if (page < 1) { + page = 1; + } + if (!limit) { + limit = 20; + } + const categoryIDs = await Category.findAll({ + where: { + department_id, + }, + attributes: ['category_id'], + limit: Number(limit), + offset, + }); + const departmentalProducts = []; + const categoriesIDArray = []; + categoryIDs.map(id => categoriesIDArray.push(id.category_id)); + + // eslint-disable-next-line no-plusplus + for (let i = 0; i < categoriesIDArray.length; i++) { + // eslint-disable-next-line no-await-in-loop + const products = await ProductCategory.findAll({ + where: { + category_id: categoriesIDArray[i], + }, + include: [ + { + model: Product, + as: 'product', + attributes: [ + 'product_id', + 'name', + 'description', + 'price', + 'discounted_price', + 'thumbnail', + ], + }, + ], + attributes: [], + }); + if (products) { + departmentalProducts.push(products); + } + } + + return res.status(200).json({ + rows: departmentalProducts, + }); + } catch (error) { + return next(error); + } } /** @@ -137,28 +242,113 @@ class ProductController { * @memberof ProductController */ static async getProduct(req, res, next) { + const { query, params } = req; + // eslint-disable-next-line camelcase + let { description_length } = query; + const { product_id } = params; // eslint-disable-line + try { + const product = await Product.findByPk(product_id); + if (product) { + return res.status(200).json(product); + } + return res.status(404).json({ + error: { + status: 404, + message: `Product with id ${product_id} does not exist`, // eslint-disable-line + } + }); + } catch (error) { + return next(error); + } + } + /** + * get all reviews for a product + * + * @static + * @param {object} req express request object + * @param {object} res express response object + * @param {object} next next middleware + * @returns {json} json object with status and product data + * @memberof ProductController + */ + static async getProductReviews(req, res, next) { const { product_id } = req.params; // eslint-disable-line try { - const product = await Product.findByPk(product_id, { + const reviews = await Review.findAll({ + where: { + product_id, + }, include: [ { - model: AttributeValue, - as: 'attributes', - attributes: ['value'], - through: { - attributes: [], - }, - include: [ - { - model: Attribute, - as: 'attribute_type', - }, - ], + model: Customer, + as: 'customer', + attributes: ['name'], }, ], + raw: true, + attributes: [], + }); + if (reviews) { + return res.status(200).json(reviews); + } + return res.status(404).json({ + error: { + status: 404, + message: `Product with id ${product_id} does not exist`, // eslint-disable-line + }, + }); + } catch (error) { + return next(error); + } + } + + /** + * post a product review + * + * @static + * @param {object} req express request object + * @param {object} res express response object + * @param {object} next next middleware + * @returns {json} json object with status and product data + * @memberof ProductController + */ + static async postProductReview(req, res, next) { + const { product_id, review, rating } = req.params; // eslint-disable-line + try { + const product = await Product.findOne({ + where: { + product_id, + }, + }); + if (product) { + // check if the customer had reviewed the product before + const customerReview = await Review.findOne({ + where: { + product_id, + customer_id: 1, + }, + attributes: ['review_id'], + }); + + if (!customerReview) { + const productReview = await Review.upsert({ + customer_id: 1, + review, + rating, + created_on: Date.now(), + product_id: parseInt(product_id, 10), + }); + return res.status(201).send(productReview); + } + return res.status(409).json('You have already reviewed this product.'); + } + return res.status(404).json({ + error: { + status: 404, + message: `Product with id ${product_id} does not exist`, // eslint-disable-line + }, }); - return res.status(500).json({ message: 'This works!!1' }); } catch (error) { return next(error); } diff --git a/src/database/models/productCategory.js b/src/database/models/productCategory.js index 6cffe4d..614cf8b 100755 --- a/src/database/models/productCategory.js +++ b/src/database/models/productCategory.js @@ -23,6 +23,7 @@ module.exports = (sequelize, DataTypes) => { foreignKey: 'product_id', }); ProductCategory.belongsTo(Category, { + as: 'category', foreignKey: 'category_id', }); }; diff --git a/src/database/models/review.js b/src/database/models/review.js new file mode 100644 index 0000000..54fdfa4 --- /dev/null +++ b/src/database/models/review.js @@ -0,0 +1,44 @@ +module.exports = (sequelize, DataTypes) => { + const Review = sequelize.define ( + 'Review', + { + review_id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + customer_id: DataTypes.INTEGER, + product_id: DataTypes.INTEGER, + review: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: '', + }, + rating: { + type: DataTypes.SMALLINT, + allowNull: false, + defaultValue: 0, + }, + created_on: DataTypes.DATE, + }, + { + timestamps: false, + tableName: 'review', + } + ); + Review.associate = ({ Product, Customer }) => { + Review.belongsTo(Product, { + foreignKey: 'product_id', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + as: 'product', + }); + Review.belongsTo(Customer, { + foreignKey: 'customer_id', + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + as: 'customer', + }); + }; + return Review; +}; \ No newline at end of file diff --git a/src/routes/api/product.route.js b/src/routes/api/product.route.js index bfd1787..1420c0a 100755 --- a/src/routes/api/product.route.js +++ b/src/routes/api/product.route.js @@ -4,8 +4,10 @@ import ProductController from '../../controllers/product.controller'; // These are valid routes but they may contain a bug, please try to define and fix them const router = Router(); -router.get('/products', ProductController.toString); +router.get('/products', ProductController.getAllProducts); router.get('/products/:product_id', ProductController.getProduct); +router.get('/products/:product_id/reviews', ProductController.getProductReviews); +router.post('/products/:product_id/reviews', ProductController.postProductReview); router.get('/products/search', ProductController.searchProduct); router.get('/products/inCategory/:category_id', ProductController.getProductsByCategory); router.get('/products/inDepartment/:department_id', ProductController.getProductsByDepartment); From 27cb62129be58037f6a4681ac4907e21c0d61171 Mon Sep 17 00:00:00 2001 From: "https://github.com': codeplus254" Date: Sun, 29 Sep 2019 14:55:52 +0300 Subject: [PATCH 4/5] customer endpoints now working --- src/controllers/customer.controller.js | 195 +++++++++++++++++++++++-- src/routes/api/customer.route.js | 23 +-- 2 files changed, 190 insertions(+), 28 deletions(-) diff --git a/src/controllers/customer.controller.js b/src/controllers/customer.controller.js index 82fe3d3..816d8bc 100755 --- a/src/controllers/customer.controller.js +++ b/src/controllers/customer.controller.js @@ -14,6 +14,8 @@ */ import { Customer } from '../database/models'; +const jwt = require('jsonwebtoken'); +const bcrypt = require('bcrypt'); /** * * @@ -32,7 +34,33 @@ class CustomerController { */ static async create(req, res, next) { // Implement the function to create the customer account - return res.status(201).json({ message: 'this works' }); + const { name, email, password } = req.body; + + try { + const customer = await Customer.findOne({ + where: { + email, + }, + }); + if (!customer) { + // check if the customer with that email had registered before + const passwordHash = bcrypt.hashSync(password, 10); + const newCustomer = await Customer.upsert({ + name, + email, + password: passwordHash, + }); + return res.status(201).send(newCustomer); + } + return res.status(409).json({ + error: { + status: 409, + message: `User with email ${email} already exist`, + }, + }); + } catch (error) { + return next(email); + } } /** @@ -47,7 +75,72 @@ class CustomerController { */ static async login(req, res, next) { // implement function to login to user account - return res.status(200).json({ message: 'this works' }); + const { email, password } = req.body; + try { + const customer = await Customer.findOne({ + where: { + email, + password, + }, + }); + const accessToken = `Bearer ${await jwt.sign( + { customer_id: customer.customer_id }, + process.env.SECRET_KEY, + { expiresIn: '24h' } + )}`; + if (customer) { + return res.status(200).json({ + customer, + accessToken, + expiresIn: '24h', + }); + } + return res.status(404).json({ + error: { + status: 404, + message: `User does not exist`, + }, + }); + } catch (error) { + return next(error); + } + } + + /** + * log in a customer + * + * @static + * @param {object} req express request object + * @param {object} res express response object + * @param {object} next next middleware + * @returns {json} json object with status, and access token + * @memberof CustomerController + */ + static async facebookLogin(req, res, next) { + // implement function to login to user account + const { accessToken } = req.body; + try { + const customer = await Customer.findOne({ + where: { + accessToken, + }, + }); + if (customer) { + return res.status(200).json({ + customer, + accessToken: null, + expiresIn: null, + }); + } + return res.status(404).json({ + error: { + status: 404, + message: `User does not exist`, + }, + }); + } catch (error) { + return next(error); + } } /** @@ -61,13 +154,16 @@ class CustomerController { * @memberof CustomerController */ static async getCustomerProfile(req, res, next) { - // fix the bugs in this code - const { customer_id } = req; // eslint-disable-line + const accessToken = req.headers.authorization; + const decodedToken = jwt.decode(accessToken.substring(7)); // remove the Bearer tag + const customerId = decodedToken.customer_id; + try { - const customer = await Customer.findByPk(customer_id); - return res.status(400).json({ - customer, - }); + const customer = await Customer.findByPk(customerId); + if (customer) { + return res.status(200).json(customer); + } + return res.status(404).json('The user does not exist'); } catch (error) { return next(error); } @@ -85,7 +181,34 @@ class CustomerController { */ static async updateCustomerProfile(req, res, next) { // Implement function to update customer profile like name, day_phone, eve_phone and mob_phone - return res.status(200).json({ message: 'this works' }); + + // eslint-disable-next-line camelcase + const { email, name, day_phone, eve_phone, mob_phone } = req.body; + const accessToken = req.headers.authorization; + const decodedToken = jwt.decode(accessToken.substring(7)); // remove the Bearer tag + const customerId = decodedToken.customer_id; + try { + await Customer.update( + { + email, + name, + day_phone, + eve_phone, + mob_phone, + }, + { + returning: true, + where: { + // eslint-disable-next-line prettier/prettier + customer_id: customerId, + }, + } + ); + const customer = await Customer.findByPk(customerId); + return res.status(200).json(customer); + } catch (error) { + return next(error); + } } /** @@ -101,7 +224,35 @@ class CustomerController { static async updateCustomerAddress(req, res, next) { // write code to update customer address info such as address_1, address_2, city, region, postal_code, country // and shipping_region_id - return res.status(200).json({ message: 'this works' }); + // eslint-disable-next-line camelcase + const { address_1, address_2, city, region, postal_code, country, shipping_region_id } = req.body; + const accessToken = req.headers.authorization; + const decodedToken = jwt.decode(accessToken.substring(7)); // remove the Bearer tag + const customerId = decodedToken.customer_id; + try { + await Customer.update( + { + address_1, + address_2, + city, + region, + postal_code, + country, + shipping_region_id, + }, + { + returning: true, + where: { + // eslint-disable-next-line prettier/prettier + customer_id: customerId, + }, + } + ); + const customer = await Customer.findByPk(customerId); + return res.status(200).json(customer); + } catch (error) { + return next(error); + } } /** @@ -116,7 +267,29 @@ class CustomerController { */ static async updateCreditCard(req, res, next) { // write code to update customer credit card number - return res.status(200).json({ message: 'this works' }); + // eslint-disable-next-line camelcase + const { credit_card } = req.body; + const accessToken = req.headers.authorization; + const decodedToken = jwt.decode(accessToken.substring(7)); // remove the Bearer tag + const customerId = decodedToken.customer_id; + try { + await Customer.update( + { + credit_card, + }, + { + returning: true, + where: { + // eslint-disable-next-line prettier/prettier + customer_id: customerId, + }, + } + ); + const customer = await Customer.findByPk(customerId); + return res.status(200).json(customer); + } catch (error) { + return next(error); + } } } diff --git a/src/routes/api/customer.route.js b/src/routes/api/customer.route.js index 09e3ed4..bae1502 100755 --- a/src/routes/api/customer.route.js +++ b/src/routes/api/customer.route.js @@ -4,23 +4,12 @@ import CustomerController from '../../controllers/customer.controller'; // These are valid routes but they may contain a bug, please try to define and fix them const router = Router(); -router.post( - '/customers', - CustomerController.updateCreditCard -); -router.post('/customers/login', CustomerController.login); +router.post('/customers', CustomerController.create); +router.post('/customers/login', CustomerController.login); +router.post('/customers/facebook', CustomerController.facebookLogin); router.get('/customer', CustomerController.getCustomerProfile); -router.put( - '/customer', - CustomerController.apply -); -router.put( - '/customer/address', - CustomerController.updateCustomerAddress -); -router.put( - '/customer/creditCard', - CustomerController.updateCreditCard -); +router.put('/customer', CustomerController.updateCustomerProfile); +router.put('/customer/address', CustomerController.updateCustomerAddress); +router.put('/customer/creditCard', CustomerController.updateCreditCard); export default router; From af21012d07632cb0580e74a5c75b3fb4c0078a85 Mon Sep 17 00:00:00 2001 From: "https://github.com': codeplus254" Date: Sun, 29 Sep 2019 21:14:40 +0300 Subject: [PATCH 5/5] orders endpoints now working --- src/controllers/customer.controller.js | 2 +- src/controllers/shoppingCart.controller.js | 89 ++++++++++++++++++++-- src/routes/api/shoppingCart.route.js | 16 +--- 3 files changed, 89 insertions(+), 18 deletions(-) diff --git a/src/controllers/customer.controller.js b/src/controllers/customer.controller.js index 816d8bc..87418e7 100755 --- a/src/controllers/customer.controller.js +++ b/src/controllers/customer.controller.js @@ -35,7 +35,7 @@ class CustomerController { static async create(req, res, next) { // Implement the function to create the customer account const { name, email, password } = req.body; - + try { const customer = await Customer.findOne({ where: { diff --git a/src/controllers/shoppingCart.controller.js b/src/controllers/shoppingCart.controller.js index 8bc91e9..c4759d6 100755 --- a/src/controllers/shoppingCart.controller.js +++ b/src/controllers/shoppingCart.controller.js @@ -18,7 +18,9 @@ * endpoints, request body/param, and response object for each of these method */ - +import { Order, OrderDetail, Customer } from '../database/models'; + +const jwt = require('jsonwebtoken'); /** * * @@ -124,8 +126,24 @@ class ShoppingCartController { * @memberof ShoppingCartController */ static async createOrder(req, res, next) { + // eslint-disable-next-line camelcase + const { cart_id, shipping_id, tax_id } = req.body; + const accessToken = req.headers.authorization; + const decodedToken = jwt.decode(accessToken.substring(7)); // remove the Bearer tag + const customerId = decodedToken.customer_id; + try { - // implement code for creating order here + const order = await Order.upsert({ + customer_id: customerId, + cart_id, + shipping_id, + tax_id, + }); + if (order) { + const id = await Order.count(); + return res.status(201).json({ order_id: id }); + } + return res.status(400).json('Could not create the order.'); } catch (error) { return next(error); } @@ -142,8 +160,28 @@ class ShoppingCartController { */ static async getCustomerOrders(req, res, next) { const { customer_id } = req; // eslint-disable-line + const accessToken = req.headers.authorization; + const decodedToken = jwt.decode(accessToken.substring(7)); // remove the Bearer tag + const customerId = decodedToken.customer_id; try { - // implement code to get customer order + const orders = await Order.findAll({ + where: { + customer_id: customerId, + }, + include: [ + { + model: Customer, + as: 'name', + attributes: ['name'], + }, + ], + raw: true, + attributes: ['order_id', 'total_amount', 'created_on', 'shipped_on'], + }); + if (orders) { + return res.status(200).json(orders); + } + return res.status(400).json('You have not yet placed an order. '); } catch (error) { return next(error); } @@ -160,9 +198,50 @@ class ShoppingCartController { */ static async getOrderSummary(req, res, next) { const { order_id } = req.params; // eslint-disable-line - const { customer_id } = req; // eslint-disable-line try { - // write code to get order summary + const order = await OrderDetail.findByPk(order_id); + if (order) { + return res.status(200).json({ + order_id, + order_items: order, + }); + } + return res.status(404).json('The order does not exist'); + } catch (error) { + return next(error); + } + } + + /** + * + * + * @static + * @param {obj} req express request object + * @param {obj} res express response object + * @returns {json} returns json response with short details of order + * @memberof ShoppingCartController + */ + static async getOrderShortDetail(req, res, next) { + // eslint-disable-next-line camelcase + const { order_id } = req.params; + try { + const orders = await Order.findOne({ + where: { + order_id, + }, + include: [ + { + model: Customer, + attributes: ['name'], + }, + ], + raw: true, + attributes: ['order_id', 'total_amount', 'created_on', 'shipped_on', 'status'], + }); + if (orders) { + return res.status(200).json(orders); + } + return res.status(400).json('You have not yet placed an order. '); } catch (error) { return next(error); } diff --git a/src/routes/api/shoppingCart.route.js b/src/routes/api/shoppingCart.route.js index 0e2b899..6ffb757 100755 --- a/src/routes/api/shoppingCart.route.js +++ b/src/routes/api/shoppingCart.route.js @@ -9,17 +9,9 @@ router.put('/shoppingcart/update/:item_id', ShoppingCartController.updateCartIte router.delete('/shoppingcart/empty/:cart_id', ShoppingCartController.emptyCart); router.delete('/shoppingcart/removeProduct/:item_id', ShoppingCartController.removeItemFromCart); router.post('/orders', ShoppingCartController.createOrder); -router.get( - '/orders/inCustomer', - ShoppingCartController.getCustomerOrders -); -router.get( - '/orders/:order_id', - ShoppingCartController.getOrderSummary -); -router.post( - '/stripe/charge', - ShoppingCartController.processStripePayment -); +router.get('/orders/inCustomer', ShoppingCartController.getCustomerOrders); +router.get('/orders/:order_id', ShoppingCartController.getOrderSummary); +router.get('/orders/shortDetail/:order_id', ShoppingCartController.getOrderShortDetail); +router.post('/stripe/charge', ShoppingCartController.processStripePayment); export default router;