Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
boat.controllers.ts 11.60 KiB
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 name of boat already exists
    if (!(newBoatInput.name === undefined)) {
      const checkBoatName = await Boat.findOne({
        where: {
          name: newBoatInput.name,
        },
      });

      if (!(checkBoatName === null)) {
        return res
          .status(400)
          .json({ success: false, error: "boatNameAlreadyExists" });
      }
    }

    //check if minP is bigger than maxP => error
    if (
      !(newBoatInput.minP === undefined) &&
      !(newBoatInput.maxP === undefined)
    ) {
      if (newBoatInput.minP > newBoatInput.maxP) {
        return res.status(409).json({
          success: false,
          error: "maximumNumberOfSeatsMustBeBiggerOrEqualMinimalNumberOfSeats",
        });
      }
    }

    //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) {
      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" });
    }

    //check if name of boat already exists
    if (!(input.name === undefined)) {
      const checkBoatName = await Boat.findOne({
        where: {
          name: input.name,
        },
      });

      if (!(checkBoatName === null)) {
        return res
          .status(404)
          .json({ success: false, error: "boatNameAlreadyExists" });
      }
    }

    //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 (!(input.boattype === 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" });
      }
    }

    //try to update the attributes, which are in Boat table
    const updatedBoat = await Boat.update(input, {
      where: {
        id: givenId,
      },
      returning: true,
    });

    //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) {
        return res
          .status(404)
          .json({ success: false, error: listIfNotFound + " sportIdNotFound" });
      }
      // help Array in order to print as response the name of the updated new sports to boat
      var listOfNames = new Array();
      //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);

        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
    // check if in the requested body only values for sports were provided
    if (Object.keys(input).length === 1 && !(input.sports === undefined)) {
      //return after updating
      return res.status(200).json({
        success: true,
        result: {
          id: givenId,
          name: foundBoat.name,
          boattype: foundBoat.boattype,
          status: foundBoat.status,
          tags: foundBoat.tags,
          minP: foundBoat.minP,
          maxP: foundBoat.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;