/**
* @namespace Controller
* @property {module:BookController} BookController
*/
/**
* BookController handle with Book Resource Api.
* Pass a Chapter Object Model(\Models\BookModel) to the constructor
* of parent class (\Controller\BaseController) for it map the basic database crud operations
* to this Object.
* @module BookController
* @extends module:BaseController
*/
'use strict'
import BaseController from './Base.Controller'
import StudentController from './Student.Controller'
import ChapterController from './Chapter.Controller'
import Book from '../models/Book.Model'
import Student from '../models/Student.Model'
export default class BookController extends BaseController {
constructor () {
super(Book)
this._book = null
}
/**
* Book Save Method.
* Responds to POST /book.
* Saves the book with student ID, and then add book to student books list.
* If Success returns 200 status code and a json with this.Book saved data.
* If error return 400 status code and a json => { errors }.
* 500 status code only will be returned if the method generates some unexpected error.
*
* @name SaveBook
* @param {object} req - Express requisition object.
* @param {object} res - Express response object.
* @return {json} status and return object.
* @method saveBook
*/
saveBook (req, res) {
let bookWithStudent = req.body
bookWithStudent._student = req.user._id
// 1. Save book in DB, returning its ID
new this.Model(bookWithStudent).persist()
.then(data => {
this._book = data
return this._book._id
})
// 2. Add book ID to student books array list
.then(id => new Student().AddingBookToList(req.user._id, id))
// 3. Return book
.then(data => {
if (data) res.status(200).json(this._book)
else throw new Error('book_not_saved')
})
.catch(err => {
console.error(err)
if (err.message === 'book_not_saved') res.status(400).json(err.message).end()
else res.status(500).json(err.message).end()
})
}
/**
* RemoveBook Method.
* Responds to DELETE /book/:id.
* Delete book by its ID and remove itself from user book list.
* If Success returns 200 status code and a json with the deleted book.
* If error return 400 status code and a json => { errors }.
* 500 status code only will be returned if the method generates some unexpected error.
*
* @name RemoveBook
* @param {object} req - Express requisition object.
* @param {object} res - Express response object.
* @return {json} status and return object.
* @method RemoveBook
* @todo Write comments
*/
removeBook (req, res) {
let data = {
_id: req.params.id
}
let bookPromise = new this.Model(data).deleteById()
let chapterPromise = new ChapterController().removeByBookIdList([].concat(req.params.id))
let userPromise = new StudentController().removeBookFromList(req.user._id, req.params.id)
Promise.all([bookPromise, chapterPromise, userPromise])
.then(response => {
if (!response[0]) throw new Error('object_not_deleted')
else if (!response[1]) throw new Error('object_not_deleted')
else if (!response[2]) throw new Error('object_not_updated')
else res.status(200).json(response[0]).end()
})
.catch(err => {
console.error(err)
if (err.message === 'object_not_deleted' || err.message === 'object_not_updated') {
res.status(400).json(err.message).end()
} else res.status(500).json(err.message).end()
})
}
/**
* Get student books from books ID list
* @name GetStudentBooks
* @param {array} books
* @return {json} status and return array list of full books.
* @method getStudentBooks
*/
getStudentBooks (books) {
return new this.Model().findByIdList({
'_id': { $in: books }
})
}
/**
* Get book chapters and filter through passed chapter ID
* @name RemoveChapterFromList
* @param {Long} bookId
* @param {Long} chapterId
* @method removeChapterFromList
*/
removeChapterFromList (bookId, chapterId) {
return new this.Model({_id: bookId}).getById()
.then(book => {
book = book[0]
book.chapters = book.chapters.filter(chapter => chapter.toString() !== chapterId)
return new this.Model(book).updateById()
})
}
}