Skip to content
Snippets Groups Projects
Commit 1c47aad0 authored by Benjamin Bertrand's avatar Benjamin Bertrand
Browse files

Add method to create an item via the API

parent 4a427cbf
No related branches found
No related tags found
No related merge requests found
......@@ -9,11 +9,13 @@ This module implements the items API.
:license: BSD 2-Clause, see LICENSE for more details.
"""
import sqlalchemy as sa
from flask import (current_app, Blueprint, jsonify, request)
from flask_jwt_extended import create_access_token, jwt_required
from flask_ldap3_login import AuthenticationResponseStatus
from ..extensions import ldap_manager, db
from ..models import User
from ..models import User, Item
from .. import utils
bp = Blueprint('api', __name__)
......@@ -42,13 +44,29 @@ def login():
@bp.route('/items')
@jwt_required
def get_items():
sql = """SELECT item.id, item.name, manufacturer.name, model.name, location.name, status.name
FROM item
INNER JOIN manufacturer ON manufacturer.id = item.manufacturer_id
INNER JOIN model ON model.id = item.model_id
INNER JOIN location ON location.id = item.location_id
INNER JOIN status ON status.id = item.status_id
"""
result = db.engine.execute(sql)
data = [[item for item in row] for row in result]
return jsonify(data=data)
# TODO: add pagination
items = Item.query.order_by(Item._created)
data = [item.to_dict() for item in items]
return jsonify({'items': data})
@bp.route('/items', methods=['POST'])
@jwt_required
def create_item():
data = request.get_json()
if data is None:
raise utils.InventoryError('Body should be a JSON object')
if 'serial_number' not in data:
raise utils.InventoryError('serial_number is mandatory')
try:
item = Item(**data)
except TypeError as e:
message = str(e).replace('__init__() got an ', '')
raise utils.InventoryError(message)
db.session.add(item)
try:
db.session.commit()
except sa.exc.IntegrityError as e:
db.session.rollback()
raise utils.InventoryError('IntegrityError', status_code=409)
return jsonify(item.to_dict()), 201
......@@ -184,11 +184,25 @@ class Item(db.Model):
# All arguments must be optional for this class to work with flask-admin!
self.serial_number = serial_number
self.name = name
self.manufacturer = manufacturer
self.model = model
self.location = location
self.status = status
self.manufacturer = utils.convert_to_model(manufacturer, Manufacturer)
self.model = utils.convert_to_model(model, Model)
self.location = utils.convert_to_model(location, Location)
self.status = utils.convert_to_model(status, Status)
self.hash = utils.compute_hash(serial_number)
def __str__(self):
return self.serial_number
def to_dict(self):
return {
'id': self.id,
'serial_number': self.serial_number,
'name': self.name,
'hash': self.hash,
'manufacturer': utils.format_field(self.manufacturer),
'model': utils.format_field(self.model),
'location': utils.format_field(self.location),
'status': utils.format_field(self.status),
'updated': utils.format_field(self._updated),
'created': utils.format_field(self._created),
}
......@@ -65,3 +65,21 @@ def format_field(field):
if isinstance(field, datetime.datetime):
return field.strftime('%Y-%m-%d %H:%M')
return str(field)
def convert_to_model(item, model):
"""Convert item to an instance of model
Allow to convert a string to an instance of model
Raise an exception if the given name is not found
:returns: an instance of model
"""
if item is None:
return None
if not isinstance(item, model):
instance = model.query.filter_by(name=item).first()
if instance is None:
raise InventoryError(f'{item} is not a valid {model.__name__.lower()}')
return instance
return item
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment