import { Request, Response } from "express"; import BoatType from "../db/models/BoatType"; import Boat from "../db/models/Boat"; import Sport from "../db/models/Sport"; import BoatHasSport from "../db/models/BoatHasSport"; //create boat const createBoat = async (req: Request, res: Response) => { try { if (!(res.locals.user.role == "coordinator")) { return res .status(403) .json({ success: false, error: "MustBeCoordinator" }); } const newBoatInput = req.body; //check if boattype exists const boatType = await BoatType.findByPk(newBoatInput.boattype); if (!boatType) { return res .status(404) .json({ success: false, error: "boattypeNotFound" }); } //check if given sport-ids can be found const sportsArray = newBoatInput.sports; var check = true; //if sports provided in the request body if (!(sportsArray === undefined)) { //define empty array, where we store founded/not founded names of sports assigned to boat's id var listIfNotFound = new Array(); var listIfFound = new Array(); //check wether each new given id exists or not for (let i = 0; i < sportsArray.length; i++) { const found = await Sport.findByPk(sportsArray[i]); if (!found) { listIfNotFound.push(sportsArray[i]); var check = false; } if (found) { const showSportName = await ( await Sport.findByPk(sportsArray[i]) ).name; listIfFound.push(showSportName); } } } //if there is a sport, which isn't in the database, we return an array with the names of the missing sports if (check === false) { console.log("list", listIfNotFound); return res.status(404).json({ success: false, error: "The SportIDs: " + listIfNotFound + " cannotBeFound", }); } //create the boat const newBoat = await Boat.create(newBoatInput); //another check if sports array was provided and it's with valid sport ids => create entry in BoatHasSport table with the new created boat id and corresponding sport is if (!(sportsArray == undefined)) { if (listIfFound.length === sportsArray.length) { const boatid = newBoat.id; //create entry (boatid, each id of given sportIds) for (let i = 0; i < sportsArray.length; i++) { const sportid = sportsArray[i]; const entry = { boatid, sportid }; //create new entry in boatHasBoatType await BoatHasSport.create(entry); } } } //return created boat + the assigned sports if (newBoat) { return res.status(201).json({ success: true, result: { id: newBoat.id, name: newBoat.name, boattype: newBoat.boattype, status: newBoat.status, tags: newBoat.tags, minP: newBoat.minP, maxP: newBoat.maxP, sports: listIfFound, }, }); } } catch (error) { console.error(error.message); return res.status(500).json({ success: false, error: "serverError" }); } }; //show all boats const showAllBoatsController = async (req: Request, res: Response) => { try { const allBoats = await Boat.findAll(); return res.status(200).send({ success: true, result: allBoats.map((boat) => { return { id: boat.id, name: boat.name, boattype: boat.boattype, status: boat.status, tags: boat.tags, minP: boat.minP, maxP: boat.maxP, }; }), }); } catch (error) { console.error("server error: ", error.message); return res.status(500).json({ success: false, error: "serverError" }); } }; //show specific boat using given id const showBoatById = async (req: Request, res: Response) => { try { const givenId = req.params.id; const boat = await Boat.findByPk(givenId); if (boat) { return res.status(200).json({ success: true, result: { id: boat.id, name: boat.name, boattype: boat.boattype, status: boat.status, tags: boat.tags, minP: boat.minP, maxP: boat.maxP, }, }); } return res.status(404).json({ success: false, error: "boatIdNotFound" }); } catch (error) { console.error("server error: ", error.message); return res.status(500).json({ success: false, error: "serverError" }); } }; //delete specific boat using given id const deleteBoatById = async (req: Request, res: Response) => { try { if (!(res.locals.user.role === "coordinator")) { return res .status(403) .json({ success: false, error: "MustBeCoordinator" }); } const givenId = req.params.id; //first we need to destroy entries where the to-be-deleted boat is connected with sport in BoatHasSport table, because it violates the foreign constraint await BoatHasSport.destroy({ where: { boatid: givenId, }, }); const boatToDelete = await Boat.destroy({ where: { id: givenId, }, }); if (boatToDelete == 0) { return res .status(404) .json({ success: false, error: "BoatIdDoesNotExist" }); } return res.status(204).json({ success: true }); } catch (error) { console.error("server error: ", error.message); return res.status(500).json({ success: false, error: "serverError" }); } }; //update boat by given id const updateBoatById = async (req: Request, res: Response) => { try { //check authority if (!(res.locals.user.role === "coordinator")) { return res .status(403) .json({ success: false, error: "MustBeCoordinator" }); } //get new input const input = req.body; //return 200 with empty response if no data was given if (Object.keys(input).length === 0) { return res .status(200) .json({ success: true, result: {}, message: "noInputFound" }); } //get id const givenId = req.params.id; //check if boat can be found using givenId const foundBoat = await Boat.findByPk(givenId); if (!foundBoat) { return res.status(404).json({ success: false, error: "boatIdNotFound" }); } const givenBoatType = input.boattype; //we need to check if boattype is not null(wasn't provided in body), otherwise we have server error: Cannot read properties of undefined if (!(givenBoatType === undefined)) { //check if new boattype can be found const checkBoatTypeId = await BoatType.findByPk(input.boattype); if (!checkBoatTypeId) { return res .status(404) .json({ success: false, error: "givenBoatTypeIdNotFound" }); } } //check if new given sport-ids can be found const newSportsArray = input.sports; if (!(newSportsArray === undefined)) { //define empty array, where we store founded/not founded names of sports assigned to boat's id var listIfNotFound = new Array(); var listIfFound = new Array(); //help variable in order to return the Array with the sport ids, which weren't founded var check = true; //check wether each new given id exists or not for (let i = 0; i < newSportsArray.length; i++) { const found = await Sport.findByPk(newSportsArray[i]); // if not founded, push id's into listIfNotFound Array if (!found) { listIfNotFound.push(newSportsArray[i]); var check = false; } if (found) { //check if sport already assigned to boat, if yes continue, no need for error message const getBoatIdInBoatHasSport = await BoatHasSport.findOne({ where: { boatid: givenId, sportid: newSportsArray[i], }, }); //if boat is not already assigned to existing sport id => put id into listIfFound if (getBoatIdInBoatHasSport === null) { listIfFound.push(newSportsArray[i]); } } } //if the updated-to-be sportid(sportids) doesn't exist if (check === false) { console.log("list", listIfNotFound); return res .status(404) .json({ success: false, error: listIfNotFound + " sportIdNotFound" }); } //if sports Array is with valid id's, assign them to boat; create entry (boatid, each id of given sportIds) inf BoatHasSport table for (let i = 0; i < listIfFound.length; i++) { const boatid = givenId; const sportid = listIfFound[i]; const entry = { boatid, sportid }; //create new entry in boatHasBoatType await BoatHasSport.create(entry); } } //try to update the attributes, which are in Boat table const updatedBoat = await Boat.update(input, { where: { id: givenId, }, returning: true, }); //help Array in order to print as response the name of the updated new sports to boat var listOfNames = new Array(); const findBoatInfo = await Boat.findByPk(givenId); for (let i = 0; i < listIfFound.length; i++) { const findSportName = await (await Sport.findByPk(listIfFound[i])).name; listOfNames.push(findSportName); } //we need this special case res, because sports is not an attribute assigned to Boat table, and if only sports provided as request body error happens if (!(updatedBoat === undefined)) { //return after updating return res.status(200).json({ success: true, result: { id: givenId, name: findBoatInfo.name, boattype: findBoatInfo.boattype, status: findBoatInfo.status, tags: findBoatInfo.tags, minP: findBoatInfo.minP, maxP: findBoatInfo.maxP, sports: listOfNames, }, }); } //case where in request body attributes from Boat provided + sports which is an attribute in Sport table and connection between Boat and Sport is saved in BoatHasSport table const boatDataAfterUpdate = updatedBoat[1][0]; return res.status(200).json({ success: true, result: { id: boatDataAfterUpdate.id, name: boatDataAfterUpdate.name, boattype: boatDataAfterUpdate.boattype, status: boatDataAfterUpdate.status, tags: boatDataAfterUpdate.tags, minP: boatDataAfterUpdate.minP, maxP: boatDataAfterUpdate.maxP, sports: listOfNames, }, }); } catch (error) { console.error("server error: ", error.message); return res.status(500).json({ success: false, error: "serverError" }); } }; const boatControllers = { showAllBoatsController, showBoatById, deleteBoatById, createBoat, updateBoatById, }; export default boatControllers;