diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/__init__.py | 8 | ||||
-rw-r--r-- | app/models.py | 33 | ||||
-rw-r--r-- | app/views.py | 110 |
3 files changed, 151 insertions, 0 deletions
diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..f441218 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,8 @@ +from flask import Flask +from flask.ext.sqlalchemy import SQLAlchemy + +app = Flask(__name__) +app.config.from_object('config') +db = SQLAlchemy(app) + +from app import views, models diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..4df6689 --- /dev/null +++ b/app/models.py @@ -0,0 +1,33 @@ +from app import db +import datetime + +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + nickname = db.Column(db.String(64), index=True, unique=True) + email = db.Column(db.String(120), index=True, unique=True) + opened = db.relationship('Ticket', backref='opened_by', lazy='dynamic', primaryjoin = 'Ticket.opened_by_user_id == User.id') + assigned = db.relationship('Ticket', backref='assigned_to', lazy='dynamic', primaryjoin = 'Ticket.assigned_to_user_id == User.id') + + + def __repr__(self): + return '<User %r>' % (self.nickname) + +class Ticket(db.Model): + id = db.Column(db.Integer, primary_key=True) + + summary = db.Column(db.String(140), nullable=False) + body = db.Column(db.Text, nullable=False) + + opened_at = db.Column(db.DateTime, nullable=False) + updated_at = db.Column(db.DateTime) + + status = db.Column(db.String(64), nullable=False, default='open') + resolution = db.Column(db.String(64)) + reason = db.Column(db.String(140)) + deleted = db.Column(db.Boolean, default=False) + + opened_by_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + assigned_to_user_id = db.Column(db.Integer, db.ForeignKey('user.id')) + + def __repr__(self): + return '<Ticket %r>' % (self.id) diff --git a/app/views.py b/app/views.py new file mode 100644 index 0000000..2e6ba6f --- /dev/null +++ b/app/views.py @@ -0,0 +1,110 @@ +from flask import jsonify, abort, make_response, request, url_for +from datetime import datetime +from app import app, db, models + +def make_public_ticket(ticket): + new_ticket = ticket.copy() + new_ticket['uri'] = url_for('get_ticket', ticket_id=ticket['id'], _external=True) + return new_ticket + +def ticket_to_dict(ticket): + nt = {} + nt['id'] = ticket.id + + nt['deleted'] = ticket.deleted + + nt['summary'] = ticket.summary + nt['body'] = ticket.body + + nt['opened_at'] = ticket.opened_at.strftime('%Y-%m-%dT%H:%M:%S') + + if ticket.updated_at: + nt['updated_at'] = ticket.updated_at.strftime('%Y-%m-%dT%H:%M:%S') + else: + nt['updated_at'] = None + + nt['status'] = ticket.status + + nt['resolution'] = ticket.resolution + nt['reason'] = ticket.reason + + if ticket.opened_by: + nt['opened_by'] = { + 'id': ticket.opened_by.id, + 'nickname': ticket.opened_by.nickname, + 'email': ticket.opened_by.email, + } + else: + nt['opened_by'] = {'id': None, 'nickname': None, 'email': None} + + if ticket.assigned_to: + nt['assigned_to'] = { + 'id': ticket.assigned_to.id, + 'nickname': ticket.assigned_to.nickname, + 'email': ticket.assigned_to.email, + } + else: + nt['assigned_to'] = None + + return nt + +@app.route('/tbt/api/1.0/tickets', methods=['GET']) +def get_tickets(): + ts = models.Ticket.query.filter(models.Ticket.deleted != True).all() + tickets = map(ticket_to_dict, ts) + return jsonify({'tickets': list(map(make_public_ticket, tickets))}) + +@app.route('/tbt/api/1.0/ticket', methods=['POST']) +def create_ticket(): + if not request.json or not ('summary' and 'body' and 'user_nickname') in request.json: + abort(400) + + user = models.User.query.filter(models.User.nickname == request.json['user_nickname']).first() + + ticket = models.Ticket(summary=request.json['summary'], + body=request.json['body'], + opened_by=user, + opened_at=datetime.utcnow()) + db.session.add(ticket) + db.session.commit() + + td = ticket_to_dict(ticket) + + return jsonify({'ticket': make_public_ticket(td)}), 201 + +@app.route('/tbt/api/1.0/ticket/<int:ticket_id>', methods=['GET']) +def get_ticket(ticket_id): + ticket = models.Ticket.query.get(ticket_id) + if not ticket: + abort(404) + + return jsonify({'ticket': make_public_ticket(ticket_to_dict(ticket))}) + +@app.route('/tbt/api/1.0/ticket/<int:ticket_id>', methods=['PUT']) +def update_ticket(ticket_id): + ticket = next((t for t in tickets if t['id'] == ticket_id), None) + if not ticket: + abort(404) + if not request.json: + abort(400) + ticket['summary'] = request.json.get('summary', ticket['summary']) + ticket['body'] = request.json.get('body', ticket['body']) + ticket['status'] = request.json.get('status', ticket['status']) + ticket['resolution'] = request.json.get('resolution', ticket['resolution']) + ticket['reason'] = request.json.get('reason', ticket['reason']) + ticket['assigned-to'] = request.json.get('assigned-to', ticket['assigned-to']) + return jsonify({'ticket': make_public_ticket(ticket)}) + +@app.route('/tbt/api/1.0/ticket/<int:ticket_id>', methods=['DELETE']) +def delete_ticket(ticket_id): + ticket = next((t for t in tickets if t['id'] == ticket_id), None) + if not ticket: + abort(404) + #tickets.remove(ticket) + ticket['deleted'] = True + return jsonify({'result': True}) + +@app.errorhandler(404) +def not_found(error): + return make_response(jsonify({'error': 'Not found'}), 404) + |