Merge pull request #51 from ZeusWPI/feat/19/paid-indicator

Feat/19/paid indicator
This commit is contained in:
Feliciaan De Palmenaer 2015-06-04 22:08:27 +02:00
commit 8be04fc450
6 changed files with 143 additions and 36 deletions

View file

@ -0,0 +1,26 @@
"""Added order paid column
Revision ID: 57a00d0b7bc
Revises: 3243c3538fc
Create Date: 2015-06-04 19:16:47.888372
"""
# revision identifiers, used by Alembic.
revision = '57a00d0b7bc'
down_revision = '3243c3538fc'
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('order_item', sa.Column('paid', sa.Boolean(), nullable=True))
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_column('order_item', 'paid')
### end Alembic commands ###

View file

@ -65,7 +65,6 @@ class Product(db.Model):
price = db.Column(db.Integer, nullable=False) price = db.Column(db.Integer, nullable=False)
orderItems = db.relationship('OrderItem', backref='product', lazy='dynamic') orderItems = db.relationship('OrderItem', backref='product', lazy='dynamic')
def configure(self, location, name, price): def configure(self, location, name, price):
self.location = location self.location = location
self.name = name self.name = name
@ -94,15 +93,14 @@ class Order(db.Model):
return 'Order %d @ %s' % (self.id, self.location.name or 'None') return 'Order %d @ %s' % (self.id, self.location.name or 'None')
def group_by_user(self): def group_by_user(self):
group = defaultdict(list) group = dict()
for item in self.items: for item in self.items:
group[item.get_name()] += [item.product] user = group.get(item.get_name(), dict())
return group user["total"] = user.get("total", 0) + item.product.price
user["to_pay"] = user.get("to_pay", 0) + item.product.price if not item.paid else 0
def group_by_user_pay(self): user["paid"] = user.get("paid", True) and item.paid
group = defaultdict(int) user["products"] = user.get("products", []) + [item.product]
for item in self.items: group[item.get_name()] = user
group[item.get_name()] += item.product.price
return group return group
def group_by_product(self): def group_by_product(self):
@ -122,11 +120,13 @@ class Order(db.Model):
return True return True
return False return False
class OrderItem(db.Model): class OrderItem(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False) order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('product.id')) product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
paid = db.Column(db.Boolean, default=False)
name = db.Column(db.String(120)) name = db.Column(db.String(120))
def configure(self, user, order, product): def configure(self, user, order, product):

View file

@ -12,17 +12,27 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-5"> <div class="col-sm-5">
<h3>Open orders</h3> {% if orders|count > 0 -%}
{% for order in orders %} <h3>Open orders:</h3>
{{ util.render_order(order) }} {% for order in orders %}
{% endfor %} {{ util.render_order(order) }}
{% endfor %}
{% else %}
<h4>No orders available.</h4>
{% if not current_user.is_anonymous() %}
To create an order, fill in the form on the right.
{% else %}
Login to create an order, or ask someone else.
{% endif %}
{%- endif %}
</div> </div>
<div class="col-sm-5 col-sm-push-2"> <div class="col-sm-5 col-sm-push-2">
<h3>Recently closed orders</h3> {% if orders|count > 0 -%}
{% for order in recently_closed %} <h3>Recently closed orders:</h3>
{{ util.render_order(order) }} {% for order in recently_closed %}
{% endfor %} {{ util.render_order(order) }}
</ul> {% endfor %}
{%- endif %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,5 +1,7 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% set active_page = "orders" -%} {% set active_page = "orders" -%}
{% set order_items = order.group_by_user() -%}
{% set courier_or_admin = order.can_close(current_user.id) -%}
{% import "utils.html" as util %} {% import "utils.html" as util %}
@ -7,7 +9,7 @@
<div class="row"> <div class="row">
<div class="col-md-push-1 col-md-10 darker"><!-- Shitty html--> <div class="col-md-push-1 col-md-10 darker"><!-- Shitty html-->
<h3>Order {{ order.id }} <h3>Order {{ order.id }}
{% if order.can_close(current_user.id) -%} {% if courier_or_admin -%}
<a class="btn btn-danger pull-right" href="{{ url_for('.close_order', id=order.id) }}">Close</a><br/> <a class="btn btn-danger pull-right" href="{{ url_for('.close_order', id=order.id) }}">Close</a><br/>
<a class="btn btn-warning pull-right" href="{{ url_for('.order_edit', id=order.id) }}">Edit</a> <a class="btn btn-warning pull-right" href="{{ url_for('.order_edit', id=order.id) }}">Edit</a>
{%- endif %}</h3> {%- endif %}</h3>
@ -21,7 +23,7 @@
telephone: <a href="tel://{{ order.location.telephone }}">{{ order.location.telephone }}</a><br/> telephone: <a href="tel://{{ order.location.telephone }}">{{ order.location.telephone }}</a><br/>
{% endif %} {% endif %}
<b>status:</b> {% if order.stoptime %}<span class="time">{{ order.stoptime|countdown }}</span>{% else %}open{% endif %}<br/> <b>status:</b> {% if order.stoptime %}<span class="time">{{ order.stoptime|countdown }}</span>{% else %}open{% endif %}<br/>
total price: {{ total_price|euro }} total price: {{ total_price|euro }} {% if courier_or_admin %}- remaining debts: {{ debts|euro }}{% endif %}
</div> </div>
{% if form -%} {% if form -%}
<div class="col-md-push-1 col-md-10 darker"> <div class="col-md-push-1 col-md-10 darker">
@ -48,26 +50,50 @@
{%- endif %} {%- endif %}
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-push-1 col-md-4 darker"> <div class="col-md-push-1 col-md-5 darker">
<h3>Items</h3> <h3>Items</h3>
{% for item in order.items %} <table class="table table-hover table-condensed">
{{ item.get_name() }} - {{ item.product.name }} - {{ item.product.price|euro }} <thead>
{% if item.can_delete(order.id, current_user.id, session.get('anon_name', '')) -%}<a href="{{ url_for('.delete_item', order_id=order.id, item_id=item.id) }}"><span class="glyphicon glyphicon-remove"></span></a>{%- endif %}<br/> <tr><th>Name</th><th>Item</th><th>Price</th>{% if courier_or_admin %}<th>Paid?</th>{% endif %}<th>Delete</th></tr>
{% endfor %} </thead>
<tbody>
{% for item in order.items -%}
<tr>
<td>{{ item.get_name() }}</td>
<td>{{ item.product.name }}</td>
<td>{{ item.product.price|euro }}</td>
{% if courier_or_admin %}<td>{% if not item.paid %} <a class="btn btn-xs btn-primary" href="{{ url_for('.item_paid', order_id=order.id, item_id=item.id) }}">Pay</a> {% else %} <span class="glyphicon glyphicon-chevron-down"></span> {% endif %}</td>{% endif %}
<td>{% if item.can_delete(order.id, current_user.id, session.get('anon_name', '')) or courier_or_admin -%}<a href="{{ url_for('.delete_item', order_id=order.id, item_id=item.id) }}"><span class="glyphicon glyphicon-remove"></span></a>{%- endif %}<br/></td>
</tr>
{%- endfor %}
</tbody>
</table>
</div> </div>
<div class="col-md-push-3 col-md-4 darker"> <div class="col-md-push-2 col-md-4 darker">
<h3>Ordered products:</h3> <h3>Ordered products:</h3>
{% for key, value in order.group_by_product().items() %} {% for key, value in order.group_by_product().items() -%}
{{ key }} - {{ value }}<br/> {{ key }} - {{ value }}<br/>
{% endfor %} {%- endfor %}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-push-1 col-md-4 darker"> <div class="col-md-push-1 col-md-5 darker">
<h3>Debts</h3> <h3>Debts</h3>
{% for key, value in order.group_by_user_pay().items() %} <table class="table table-hover table-condensed">
{{ key }} - {{ value|euro }}<br/> <thead>
{% endfor %} <tr><th>Name</th><th>Total</th><th>To pay</th>{% if courier_or_admin %}<th>Paid?</th>{% endif %}</tr>
</thead>
<tbody>
{% for key, value in order_items.items() -%}
<tr>
<td>{{ key }}</td>
<td>{{ value["total"]|euro }}</td>
<td>{{ value["to_pay"]|euro }}</td>
{% if courier_or_admin %}<td>{% if not value["to_pay"] == 0 %} <a class="btn btn-xs btn-primary" href="{{ url_for('.items_user_paid', order_id=order.id, user_name=key) }}">Pay</a> {% else %} <span class="glyphicon glyphicon-chevron-down"></span> {% endif %}</td>{% endif %}
</tr>
{%- endfor %}
</tbody>
</table>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -7,10 +7,19 @@
{% block container %} {% block container %}
<div class="row"> <div class="row">
<div class="col-md-5"> <div class="col-md-5">
{% if orders|count > 0 -%}
<h3>Open orders:</h3> <h3>Open orders:</h3>
{% for order in orders %} {% for order in orders %}
{{ util.render_order(order) }} {{ util.render_order(order) }}
{% endfor %} {% endfor %}
{% else %}
<h4>No orders available.</h4>
{% if not current_user.is_anonymous() %}
To create an order, fill in the form on the right.
{% else %}
Login to create an order, or ask someone else.
{% endif %}
{%- endif %}
</div> </div>
{% if not current_user.is_anonymous() %} {% if not current_user.is_anonymous() %}
<div class="col-md-push-1 col-md-6"> <div class="col-md-push-1 col-md-6">

View file

@ -1,3 +1,4 @@
__author__ = 'feliciaan' __author__ = 'feliciaan'
from flask import url_for, render_template, abort, redirect, Blueprint, flash, session, request from flask import url_for, render_template, abort, redirect, Blueprint, flash, session, request
from flask.ext.login import current_user, login_required from flask.ext.login import current_user, login_required
@ -5,7 +6,7 @@ import random
from datetime import datetime from datetime import datetime
from app import app, db from app import app, db
from models import Order, OrderItem from models import Order, OrderItem, User
from forms import OrderItemForm, OrderForm, AnonOrderItemForm from forms import OrderItemForm, OrderForm, AnonOrderItemForm
order_bp = Blueprint('order_bp', 'order') order_bp = Blueprint('order_bp', 'order')
@ -46,7 +47,8 @@ def order(id, form=None):
if order.stoptime and order.stoptime < datetime.now(): if order.stoptime and order.stoptime < datetime.now():
form = None form = None
total_price = sum([o.product.price for o in order.items]) total_price = sum([o.product.price for o in order.items])
return render_template('order.html', order=order, form=form, total_price=total_price) debts = sum([o.product.price for o in order.items if not o.paid])
return render_template('order.html', order=order, form=form, total_price=total_price, debts=debts)
@order_bp.route('/<id>/edit', methods=['GET', 'POST']) @order_bp.route('/<id>/edit', methods=['GET', 'POST'])
@ -93,6 +95,40 @@ def order_item_create(id):
return order(id, form=form) return order(id, form=form)
@order_bp.route('/<order_id>/<item_id>/paid')
@login_required
def item_paid(order_id, item_id):
item = OrderItem.query.filter(OrderItem.id == item_id).first()
id = current_user.id
if item.order.courrier_id == id or current_user.admin:
item.paid = True
db.session.commit()
flash('Paid %s by %s' % (item.product.name, item.user.username), 'success')
return redirect(url_for('.order', id=order_id))
abort(404)
@order_bp.route('/<order_id>/<user_name>/user_paid')
@login_required
def items_user_paid(order_id, user_name):
user = User.query.filter(User.username == user_name).first()
items = []
if user:
items = OrderItem.query.filter((OrderItem.user_id == user.id) & (OrderItem.order_id == order_id))
else:
items = OrderItem.query.filter((OrderItem.name == user_name) & (OrderItem.order_id == order_id))
current_order = Order.query.filter(Order.id == order_id).first()
for item in items:
print(item)
if current_order.courrier_id == current_user.id or current_user.admin:
for item in items:
item.paid = True
db.session.commit()
flash('Paid %d items for %s' % (items.count(), item.get_name()), 'success')
return redirect(url_for('.order', id=order_id))
abort(404)
@order_bp.route('/<order_id>/<item_id>/delete') @order_bp.route('/<order_id>/<item_id>/delete')
def delete_item(order_id, item_id): def delete_item(order_id, item_id):
item = OrderItem.query.filter(OrderItem.id == item_id).first() item = OrderItem.query.filter(OrderItem.id == item_id).first()
@ -103,7 +139,7 @@ def delete_item(order_id, item_id):
product_name = item.product.name product_name = item.product.name
db.session.delete(item) db.session.delete(item)
db.session.commit() db.session.commit()
flash('Deleted %s' % product_name, 'info') flash('Deleted %s' % product_name, 'success')
return redirect(url_for('.order', id=order_id)) return redirect(url_for('.order', id=order_id))
abort(404) abort(404)