Esempio n. 1
0
    def put(self, patron_id):
        '''
        Edit a patron.

        Input: patron_id in URI and a JSON document as HTTP request body.
        Output HTTP responses:
            204 (when patron information was updated succesfully)
            400 (when JSON document didn't validate against the schema)
            404 (when patron_id is invalid)
            409 (when trying to change the barcode to one that is already reserved)
            415 (when HTTP request body is not JSON)
        '''
        if not request.json:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")

        try:
            validate(request.json, LibraryBuilder.patron_schema())
        except ValidationError as e:
            return create_error_response(400, "Invalid JSON document", str(e))

        if (Patron.query.filter_by(barcode=request.json["barcode"]).all()
                and int(
                    Patron.query.filter_by(
                        barcode=request.json["barcode"]).first().id) !=
                int(patron_id)):
            return create_error_response(
                409, "Patron barcode reserved",
                "Another patron already has a barcode '{}'".format(
                    request.json["barcode"]))

        if not Patron.query.filter_by(id=patron_id).all():
            return create_error_response(404, "Not found",
                                         "Patron does not exist")

        patron = Patron.query.filter_by(id=patron_id).first()
        regdate = patron.regdate

        db.session.delete(patron)
        db.session.commit()

        patron = Patron(id=patron_id, regdate=regdate, **request.json)

        db.session.add(patron)
        db.session.commit()

        return Response(status=204)
Esempio n. 2
0
    def put(self, book_id):
        '''
        Edit a book.

        Input: book_id in URI and a JSON document as HTTP request body.
        Output HTTP responses:
            204 (when book information was updated succesfully)
            400 (when JSON document didn't validate against the schema)
            404 (when book_id is invalid)
            409 (when trying to change the barcode to one that is already reserved)
            415 (when HTTP request body is not JSON)
        '''
        if not request.json:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")

        try:
            validate(request.json, LibraryBuilder.book_schema())
        except ValidationError as e:
            return create_error_response(400, "Invalid JSON document", str(e))

        if not Book.query.filter_by(id=book_id).all():
            return create_error_response(404, "Book not found", None)

        if (Book.query.filter_by(barcode=request.json["barcode"]).all()
                and int(
                    Book.query.filter_by(
                        barcode=request.json["barcode"]).first().id) !=
                int(book_id)):
            return create_error_response(
                409, "Barcode reserved",
                "Another book already has a barcode '{}'".format(
                    request.json["barcode"]))

        book = Book.query.filter_by(id=book_id).first()

        db.session.delete(book)
        db.session.commit()

        book = Book(id=book_id, **request.json)

        db.session.add(book)
        db.session.commit()

        return Response(status=204)
Esempio n. 3
0
    def post(self):
        '''
        Add a new patron in the database.

        Input: JSON document as HTTP request body.
        Output HTTP responses:
            201 (when patron was added succesfully)
            400 (when JSON document didn't validate against the schema)
            409 (when the barcode or email is already reserved)
            415 (when HTTP request body is not JSON)
        '''

        if not request.json:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")

        try:
            validate(request.json, LibraryBuilder.patron_schema())
        except ValidationError as e:
            return create_error_response(400, "Invalid JSON document", str(e))

        if (Patron.query.filter_by(barcode=request.json["barcode"]).all()):
            return create_error_response(
                409, "Already exists",
                "There is already a patron with the barcode '{}' in the collection"
                .format(request.json["barcode"]))

        if (Patron.query.filter_by(email=request.json["email"]).all()):
            return create_error_response(
                409, "Already exists",
                "There is already a patron with the email '{}' in the collection"
                .format(request.json["email"]))

        patron = Patron(regdate=datetime.now().date(), **request.json)

        db.session.add(patron)
        db.session.commit()

        headerDictionary = {}
        headerDictionary['Location'] = url_for(
            "api.patronitem",
            patron_id=Patron.query.filter_by(
                barcode=request.json["barcode"]).first().id)

        return Response(status=201, headers=headerDictionary)
Esempio n. 4
0
    def post(self):
        '''
        Add a new book in the database.

        Input: JSON document as HTTP request body.
        Output HTTP responses:
            201 (when book was added succesfully)
            400 (when JSON document didn't validate against the schema)
            409 (when the barcode is already reserved)
            415 (when HTTP request body is not JSON)
        '''

        if not request.json:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")

        try:
            validate(request.json, LibraryBuilder.book_schema())
        except ValidationError as e:
            return create_error_response(400, "Invalid JSON document", str(e))

        if (Book.query.filter_by(barcode=request.json["barcode"]).all()):
            return create_error_response(
                409, "Already exists",
                "Barcode '{}' already exists on another book.".format(
                    request.json["barcode"]))

        book = Book(**request.json)

        db.session.add(book)
        db.session.commit()

        headerDictionary = {}
        headerDictionary['Location'] = url_for(
            "api.bookitem",
            book_id=Book.query.filter_by(
                barcode=request.json["barcode"]).first().id)

        return Response(status=201, headers=headerDictionary)
Esempio n. 5
0
def api_entrypoint():
    body = LibraryBuilder()
    body.add_namespace("inlibris", LINK_RELATIONS_URL)
    body.add_control_all_patrons()
    body.add_control_all_books()
    return Response(json.dumps(body), 200, mimetype=MASON)
Esempio n. 6
0
    def get(self, book_id):
        '''
        Gets the information for a single book.

        Input: book_id
        Output HTTP responses:
            200 OK (when book_id is valid)
            404 Not Found (when book_id is invalid)
        '''
        book = Book.query.filter_by(id=book_id).first()
        if book is None:
            return create_error_response(
                404, "Not found",
                "No book was found with the id {}".format(book_id))

        body = LibraryBuilder(id=book.id,
                              barcode=book.barcode,
                              title=book.title,
                              author=book.author,
                              pubyear=book.pubyear,
                              format=book.format,
                              description=book.description,
                              loantime=book.loantime,
                              renewlimit=book.renewlimit)

        body.add_namespace("inlibris", LINK_RELATIONS_URL)
        body.add_control("self", url_for("api.bookitem", book_id=book.id))
        body.add_control("profile", BOOK_PROFILE)
        body.add_control("collection", url_for("api.bookcollection"))
        body.add_control_holds_on(book_id)
        body.add_control_loan_of(book_id)
        body.add_control_edit_book(book_id)
        body.add_control_delete_book(book_id)

        return Response(json.dumps(body), 200, mimetype=MASON)
Esempio n. 7
0
    def get(self):
        '''
        Gets the info for all books in the database.

        Input: None
        Output HTTP responses:
            200
        '''
        body = LibraryBuilder(items=[])
        books = Book.query.all()
        print(len(books))

        for book in books:
            item = LibraryBuilder(id=book.id,
                                  barcode=book.barcode,
                                  title=book.title,
                                  author=book.author,
                                  pubyear=book.pubyear,
                                  format=book.format,
                                  description=book.description,
                                  loantime=book.loantime,
                                  renewlimit=book.renewlimit)

            item.add_control("self", url_for("api.bookitem", book_id=book.id))
            item.add_control("profile", BOOK_PROFILE)
            body["items"].append(item)

        body.add_namespace("inlibris", LINK_RELATIONS_URL + "#")
        body.add_control("self", url_for("api.bookcollection"))
        body.add_control("profile", BOOK_PROFILE)
        body.add_control_all_patrons()
        body.add_control_add_book()

        return Response(json.dumps(body), 200, mimetype=MASON)
Esempio n. 8
0
    def get(self, patron_id):
        '''
        Gets the information for a single patron.

        Input: patron_id
        Output HTTP responses:
            200 OK (when patron_id is valid)
            404 Not Found (when patron_id is invalid)
        '''

        patron = Patron.query.filter_by(id=patron_id).first()
        if patron is None:
            return create_error_response(
                404, "Not found",
                "No patron was found with the id {}".format(patron_id))

        body = LibraryBuilder(id=patron.id,
                              barcode=patron.barcode,
                              firstname=patron.firstname,
                              lastname=patron.lastname,
                              email=patron.email,
                              group=patron.group,
                              status=patron.status,
                              regdate=str(patron.regdate.date()))

        body.add_namespace("inlibris", LINK_RELATIONS_URL)
        body.add_control("self", url_for("api.patronitem",
                                         patron_id=patron.id))
        body.add_control("profile", PATRON_PROFILE)
        body.add_control_loans_by(patron_id)
        body.add_control_holds_by(patron_id)
        body.add_control("collection", url_for("api.patroncollection"))
        body.add_control_edit_patron(patron_id)
        body.add_control_delete_patron(patron_id)

        return Response(json.dumps(body), 200, mimetype=MASON)
Esempio n. 9
0
    def get(self):
        '''
        Gets the info for all the patrons in the database.

        Input: None
        Output HTTP responses:
            200
        '''

        body = LibraryBuilder(items=[])
        patrons = Patron.query.all()
        print(len(patrons))

        for patron in patrons:
            item = LibraryBuilder(id=patron.id,
                                  barcode=patron.barcode,
                                  firstname=patron.firstname,
                                  lastname=patron.lastname,
                                  email=patron.email,
                                  group=patron.group,
                                  status=patron.status,
                                  regdate=str(patron.regdate.date()))
            item.add_control("self",
                             url_for("api.patronitem", patron_id=patron.id))
            item.add_control("profile", PATRON_PROFILE)
            body["items"].append(item)

        body.add_namespace("inlibris", LINK_RELATIONS_URL)
        body.add_control("self", url_for("api.patroncollection"))
        body.add_control("profile", PATRON_PROFILE)
        body.add_control_add_patron()
        body.add_control_all_books()

        return Response(json.dumps(body), 200, mimetype=MASON)
Esempio n. 10
0
    def put(self, book_id):
        '''
        Edit a loan (e.g. renew)

        Input: book_id in URI and a JSON document as HTTP request body.
        Output HTTP responses:
            200 (when loan information was updated succesfully)
            204 (when book_id is valid but book is not on loan)
            400 (when JSON document didn't validate against the schema)
            404 (when book_id is invalid or patron barcode in request body is invalid)
            415 (when HTTP request body is not JSON)
        '''

        if not request.json:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")

        try:
            validate(request.json, LibraryBuilder.edit_loan_schema())
        except ValidationError as e:
            return create_error_response(400, "Invalid JSON document", str(e))

        book = Book.query.filter_by(id=book_id).first()
        patron = Patron.query.filter_by(
            barcode=request.json["patron_barcode"]).first()

        if patron is None:
            return create_error_response(404, "Patron not found", None)

        if book is None:
            return create_error_response(404, "Book not found", None)

        loan = Loan.query.filter_by(book_id=book_id).first()
        if loan is None:
            return Response(status=204)

        # TODO: Check more errors: what if they try to change book_id to a book that is already
        # on loan or something like that?

        db.session.delete(loan)
        db.session.commit()

        if "renewaldate" in request.json:
            renewaldate = date_converter(request.json["renewaldate"])
        else:
            renewaldate = None

        if "renewed" in request.json:
            renewed = request.json["renewed"]
        else:
            renewed = 0

        if "status" in request.json:
            status = request.json["status"]
        else:
            status = "Charged"

        loan = Loan(patron_id=patron.id,
                    book_id=book_id,
                    duedate=date_converter(request.json["duedate"]),
                    renewaldate=renewaldate,
                    loandate=date_converter(request.json["loandate"]),
                    renewed=renewed,
                    status=status)

        db.session.add(loan)
        db.session.commit()

        return Response(status=200)
Esempio n. 11
0
    def post(self, patron_id):
        '''
        Add a loan by a patron.

        Input: patron_id in URI and JSON document as HTTP request body.
        Output HTTP responses:
            201 (when loan was added succesfully)
            400 (when JSON document didn't validate against the schema)
            404 (when the patron_id is invalid or book_barcode in the request body is invalid)
            409 (when the book is already loaned)
            415 (when HTTP request body is not JSON)
        '''

        if not request.json:
            return create_error_response(415, "Unsupported media type",
                                         "Requests must be JSON")

        try:
            validate(request.json, LibraryBuilder.add_loan_schema())
        except ValidationError as e:
            return create_error_response(400, "Invalid JSON document", str(e))

        book = Book.query.filter_by(
            barcode=request.json["book_barcode"]).first()
        patron = Patron.query.filter_by(id=patron_id).first()

        if patron is None:
            return create_error_response(404, "Patron not found", None)

        if book is None:
            return create_error_response(404, "Book not found", None)

        conflict_loan = Loan.query.filter_by(book_id=book.id).first()

        if conflict_loan:
            conflict_patron = Patron.query.filter_by(
                id=conflict_loan.patron_id).first()
            return create_error_response(
                409, "Already exists",
                "Patron '{}' already has loan with book '{}'".format(
                    conflict_patron.barcode, book.barcode))

        if "duedate" in request.json:
            duedate = date_converter(request.json["duedate"])
        else:
            duedate = datetime.now() + timedelta(days=book.loantime)

        loan = Loan(patron_id=patron_id,
                    book_id=book.id,
                    loandate=datetime.now().date(),
                    duedate=duedate)

        db.session.add(loan)
        db.session.commit()

        headerDictionary = {}
        headerDictionary['Location'] = url_for(
            "api.loanitem",
            book_id=Book.query.filter_by(
                barcode=request.json["book_barcode"]).first().id)

        return Response(status=201, headers=headerDictionary)
Esempio n. 12
0
    def get(self, patron_id):
        '''
        Get the info for all the loans by a patron.

        Input: patron_id
        Output HTTP responses:
            200 (patron_id is valid)
            404 (patron_id is invalid)
        '''

        patron = Patron.query.filter_by(id=patron_id).first()

        if patron is None:
            return create_error_response(404, "Patron not found", None)

        loans = Loan.query.filter_by(patron_id=patron_id).all()
        body = LibraryBuilder(items=[])

        for loan in loans:
            book_barcode = Book.query.filter_by(
                id=loan.book_id).first().barcode
            patron_barcode = Patron.query.filter_by(
                id=patron_id).first().barcode

            item = LibraryBuilder(id=loan.id,
                                  book_barcode=book_barcode,
                                  patron_barcode=patron_barcode,
                                  loandate=str(loan.loandate.date()),
                                  renewaldate=None if not loan.renewaldate else
                                  str(loan.renewaldate.date()),
                                  duedate=str(loan.duedate.date()),
                                  renewed=loan.renewed,
                                  status=loan.status)

            item.add_control("self",
                             url_for("api.loanitem", book_id=loan.book_id))
            item.add_control("profile", LOAN_PROFILE)
            body["items"].append(item)

        body.add_namespace("inlibris", LINK_RELATIONS_URL)
        body.add_control("self",
                         url_for("api.loansbypatron", patron_id=patron_id))
        body.add_control("author",
                         url_for("api.patronitem", patron_id=patron_id))
        body.add_control("profile", LOAN_PROFILE)
        body.add_control_all_patrons()
        body.add_control_all_books()
        body.add_control_add_loan(patron_id)

        return Response(json.dumps(body), 200, mimetype=MASON)
Esempio n. 13
0
    def get(self, book_id):
        '''
        Gets the information for a single loan.

        Input: book_id
        Output HTTP responses:
            200 (when book_id is valid)
            400 (when book_id is valid but book is not loaned)
            404 (when book_id is invalid)
        '''

        book = Book.query.filter_by(id=book_id).first()
        if book is None:
            return create_error_response(404, "Book not found", None)

        loan = Loan.query.filter_by(book_id=book_id).first()
        if loan is None:
            return create_error_response(400, "Book not loaned", None)

        book_barcode = Book.query.filter_by(id=book_id).first().barcode
        patron_barcode = Patron.query.filter_by(
            id=loan.patron_id).first().barcode

        body = LibraryBuilder(id=loan.id,
                              book_barcode=book_barcode,
                              patron_barcode=patron_barcode,
                              loandate=str(loan.loandate.date()),
                              renewaldate=None if not loan.renewaldate else
                              str(loan.renewaldate.date()),
                              duedate=str(loan.duedate.date()),
                              renewed=loan.renewed,
                              status=loan.status)

        body.add_namespace("inlibris", LINK_RELATIONS_URL)
        body.add_control("self", url_for("api.loanitem", book_id=book_id))
        body.add_control("profile", LOAN_PROFILE)
        body.add_control("author",
                         url_for("api.patronitem", patron_id=loan.patron_id))
        body.add_control_loans_by(loan.patron_id)
        body.add_control_target_book(book_id)
        body.add_control_all_books()
        body.add_control_all_patrons()
        body.add_control_edit_loan(book_id)
        body.add_control_delete_loan(book_id)

        return Response(json.dumps(body), 200, mimetype=MASON)