diff --git a/Documentation.md b/Documentation.md index b11e89bb..2d88b530 100644 --- a/Documentation.md +++ b/Documentation.md @@ -148,7 +148,7 @@ The sendLunch function is responsible for sending a lunch from the current user #### Endpoint: /api/lunch -#### Request Format: Include the reciever id, quantity and the note in the request body. +#### Request Format: Include the receiver id, quantity and the note in the request body. #### HTTP Status Code: 200 OK @@ -160,14 +160,14 @@ The sendLunch function is responsible for sending a lunch from the current user ```json { "success": true, - "message": "Lunche sent successfully", + "message": "Lunch sent successfully", "data": "lunch" } ``` ## Functionality -1. Extracts the receiverId, quantity, and note from the request body. +1. Extracts the receiver_id, quantity, and note from the request body. 2. Creates a new lunch entry in the Lunch model with the sender's ID (obtained from the JWT token) and the provided receiver ID, quantity, and note. 3. Retrieves the sender and receiver user records from the User model. 4. Updates the sender's balance by subtracting the lunch quantity. diff --git a/app.js b/app.js index 1606a428..dbe180af 100644 --- a/app.js +++ b/app.js @@ -23,11 +23,6 @@ app.use('/api/organization', orgRoutes); app.use('/api/lunch', lunchRoutes); app.use('/api/withdrawals', withDrawalRoute); -app.use('/', (req, res) => { - res.status(200).send(`

Welcome to Team Lightning Free Lunch App

-

Click here to go to the API doc

`) -}) - // Middlewares app.use(errorHandlerMiddleware); app.use(notFound); diff --git a/controllers/authController.js b/controllers/authController.js index 52561790..ba7cb5ac 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -13,12 +13,12 @@ async function createUser(req, res, next) { const { first_name, last_name, + email, phone, + org_id, password, - is_admin, - profile_pic, lunch_credit_balance, - refresh_token, + is_admin, bank_code, bank_name, bank_number, @@ -35,16 +35,15 @@ async function createUser(req, res, next) { const hashedPassword = await bcrypt.hash(password, salt); const user = { - first_name: 'John', - last_name: 'Doe', - email: req.email, + first_name: first_name || 'John', + last_name: last_name || 'Doe', + email: req.email || email, phone, password_hash: hashedPassword, - is_admin, + is_admin: is_admin || false, profile_pic: 'https://cdn-icons-png.flaticon.com/512/147/147142.png', - org_id: req.org_id, - lunch_credit_balance: 10, - refresh_token, + org_id: req.org_id || org_id, + lunch_credit_balance: lunch_credit_balance || 1000, bank_code, bank_name, bank_number, @@ -155,7 +154,7 @@ async function createOrgAndUser(req, res, next) { // TODO: truly validate data throw createCustomError('Missing required fields', 400); } - + // Create the organization const organization = await Organization.create({ name: org_name, diff --git a/controllers/giftLunchController.js b/controllers/giftLunchController.js index 02c7be3e..da4dbca2 100644 --- a/controllers/giftLunchController.js +++ b/controllers/giftLunchController.js @@ -1,16 +1,16 @@ +/* eslint-disable camelcase */ // const { Op } = require('sequelize'); const Lunch = require('../models/lunches.model'); const User = require('../models/user.model'); const response = require('../utils/response'); const giftLunch = async (req, res) => { - console.log('gift lunch'); try { const userId = req.user.id; - const { receiverId, quantity, note } = req.body; + const { receiver_id, quantity, note } = req.body; - if (!receiverId || !quantity || !note) + if (!receiver_id || !quantity || !note) return res .status(400) .json(response(false, 'Missing required fields', null)); @@ -22,7 +22,7 @@ const giftLunch = async (req, res) => { const lunch = { sender_id: userId, - receiver_id: receiverId, + receiver_id: receiver_id, quantity, note, redeemed: true, @@ -33,7 +33,7 @@ const giftLunch = async (req, res) => { const sender = await User.findOne({ where: { id: userId } }); - const receiver = await User.findOne({ where: { id: receiverId } }); + const receiver = await User.findOne({ where: { id: receiver_id } }); const org = await user.getOrganization(); diff --git a/controllers/lunchControllers.js b/controllers/lunchControllers.js index c4b83667..7ff1fcce 100644 --- a/controllers/lunchControllers.js +++ b/controllers/lunchControllers.js @@ -4,6 +4,7 @@ const Lunch = require('../models/lunches.model'); const User = require('../models/user.model'); const Withdrawals = require('../models/withdrawals.model'); const { createCustomError } = require('../errors/custom-errors'); +const Organization = require('../models/organization.model'); //GET endpoint to retrieve all available lunches for a user const getAllLunch = async (req, res) => { @@ -41,30 +42,67 @@ const getAllLunch = async (req, res) => { }; const sendLunch = async (req, res) => { - const { receiverId, quantity, note } = req.body; + const { receiver_id, quantity, note } = req.body; try { + console.log( + 'The user', + req.user.id, + 'Rec:', + receiver_id, + 'Qty:', + quantity, + 'note:', + note, + 'Org:', + req.user.org_id, + ); //Create a new lunch const lunch = await Lunch.create({ sender_id: req.user.id, - receiver_id: receiverId, + receiver_id, + org_id: req.user.org_id, quantity, note, }); - const sender = await User.findOne({ where: { id: req.id } }); - const receiver = await User.findOne({ where: { id: receiverId } }); + const org = await Organization.findOne({ where: { id: req.user.org_id } }); + const totalLunchPrice = org.lunch_price * (quantity || 1); + + // Find the sender and receiver + const [sender, receiver] = await Promise.all([ + User.findOne({ where: { id: req.user.id } }), + User.findOne({ where: { id: receiver_id } }), + ]); - //Update the sender's balance + // Check if the sender has enough balance + if (sender.lunch_credit_balance < totalLunchPrice) { + throw new Error('Insufficient balance'); + } + // Debit the sender's balance await sender.update({ - balance: sender.balance - quantity, + lunch_credit_balance: sender.lunch_credit_balance - totalLunchPrice, }); - //Update the receiver's balance + console.log('Total lunch costs ', totalLunchPrice); + console.log( + 'Sender', + sender.lunch_credit_balance, + 'Receiver', + receiver.lunch_credit_balance, + ); + // Credit the receiver's balance await receiver.update({ - balance: receiver.balance + quantity, + lunch_credit_balance: receiver.lunch_credit_balance + totalLunchPrice, }); + console.log( + 'Sender', + sender.lunch_credit_balance, + 'Receiver', + receiver.lunch_credit_balance, + ); + res.status(201).json({ success: true, message: 'Lunch sent successfully', @@ -105,7 +143,7 @@ async function redeemGiftController(req, res) { const sender = await User.findOne({ where: { email } }); const senderLunchEntry = await Lunch.findOne({ - where: { senderId: sender.id }, + where: { sender_id: sender.id }, }); await senderLunchEntry.update({ redeemed: true }); await senderLunchEntry.save(); diff --git a/controllers/withdraw.controller.js b/controllers/withdraw.controller.js index 8db7e877..fca966c8 100644 --- a/controllers/withdraw.controller.js +++ b/controllers/withdraw.controller.js @@ -37,7 +37,7 @@ async function withdrawCashController(req, res, next) { }); // const sender = await User.findOne({ where: { email } }); // const senderLunchEntry = await Lunch.findOne({ - // where: { senderId: sender.id }, + // where: { sender_id: sender.id }, // }); // await senderLunchEntry.update({ redeemed: true }); // await senderLunchEntry.save(); diff --git a/middlewares/auth.js b/middlewares/auth.js index bf801e9d..3514b83c 100644 --- a/middlewares/auth.js +++ b/middlewares/auth.js @@ -2,16 +2,18 @@ const dotenv = require('dotenv'); const jwt = require('jsonwebtoken'); const { createCustomError } = require('../errors/custom-errors'); -const User = require('../models/user.model'); +const User = require('../models/user.model'); dotenv.config(); async function auth(req, res, next) { try { - const token = req.header('Authorization').replace('Bearer ', ''); // Remove 'Bearer ' from the token string + let token = req.header('Authorization'); if (!token) { throw new Error('Token is missing'); // Handle missing token } + + token = token.replace('Bearer ', ''); // Remove 'Bearer ' from the token string const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY); const user = await User.findByPk(decoded.id); diff --git a/middlewares/error-handler.js b/middlewares/error-handler.js index 23eb17ce..72f8ee3b 100644 --- a/middlewares/error-handler.js +++ b/middlewares/error-handler.js @@ -1,10 +1,9 @@ const { CustomErrorClass } = require('../errors/custom-errors'); const errorHandlerMiddleware = (err, req, res, next) => { - console.log(err.message); - if (err instanceof CustomErrorClass) { + if (err instanceof CustomErrorClass || err.message) { return res - .status(err.statusCode) + .status(err.statusCode || 401) .json({ success: false, message: err.message, data: null }); } return res.status(500).json({ diff --git a/models/index.js b/models/index.js index 4033d87e..897c1096 100644 --- a/models/index.js +++ b/models/index.js @@ -17,14 +17,14 @@ const Lunch = connection.define('Lunch', { key: 'org_id', }, }, - senderId: { + sender_id: { type: Sequelize.TEXT, references: { model: 'Users', key: 'id', }, }, - receiverId: { + receiver_id: { type: Sequelize.TEXT, references: { model: 'Users', diff --git a/models/lunches.model.js b/models/lunches.model.js index c9e5654f..07c016c4 100644 --- a/models/lunches.model.js +++ b/models/lunches.model.js @@ -29,11 +29,9 @@ const Lunch = sequelize.define( }, quantity: { type: DataTypes.INTEGER, - allowNull: false, }, redeemed: { type: DataTypes.BOOLEAN, - allowNull: false, }, note: { type: DataTypes.TEXT, @@ -44,7 +42,7 @@ const Lunch = sequelize.define( // foreign key to user from receiver to allow usage like // lunch.user Lunch.belongsTo(User, { - foreignKey: 'reciever_id', + foreignKey: 'receiver_id', }); // foreign key to user from sender to allow usage like diff --git a/routes/lunchRoutes.js b/routes/lunchRoutes.js index 0ce2df5b..8b97c1bc 100644 --- a/routes/lunchRoutes.js +++ b/routes/lunchRoutes.js @@ -1,25 +1,29 @@ const express = require('express'); const router = express.Router(); -const lunchControllers = require('../controllers/lunchControllers'); -const { giftLunch } = require('../controllers/giftLunchController'); +const { + getAllLunch, + getLunchDetail, + sendLunch, +} = require('../controllers/lunchControllers'); +// const { giftLunch } = require('../controllers/giftLunchController'); const { getLunchDetailsByUserId } = require('../controllers/lunchControllers'); const { auth } = require('../middlewares/auth'); // Add auth middleware router.use(auth); - // Define a route to get lunch details by user ID router.get('/:userId', getLunchDetailsByUserId); //GET all available lunches for a user -router.get('/', lunchControllers.getAllLunch); +router.get('/', getAllLunch); // Gift Launch -router.post('/send', giftLunch); +// router.post('/send', giftLunch); +router.post('/send', sendLunch); // get lunch detail -router.get('/:lunchId', lunchControllers.getLunchDetail); +router.get('/:lunchId', getLunchDetail); module.exports = router;