Upgrade to django 1.8, ++

This commit is contained in:
nikolark committed 2015-11-17 13:12:37 +01:00
1 parent 8c004276a7
commit b47ee8f832
22 files changed
+767 -1051

No files matched your search

View File
Whitespace-only changes.
+171
View File
@@ -0,0 +1,171 @@
# coding: utf-8
from __future__ import unicode_literals
from datetime import datetime, timedelta
import settings
from django.contrib import messages
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.db.models import Min
from django.forms import formset_factory
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
from main.forms import OrderLineForm, OrderForm, DepositForm
from main.models import Product, OrderLine, Order, Transaction
from main.utils import users_format_js, users_with_perm
def register(request):
products = Product.objects.filter(active=True)
cheapest_product_price = products.aggregate(Min('sale_price_int')).values()[0] or 0
half_a_year_ago = datetime.now() - timedelta(days=180)
users = User.objects.filter(profile__balance__gte=cheapest_product_price)
# sort users after user's last purchase time
users = sorted(users, key=lambda u: u.profile.last_purchase_date(), reverse=True)
users_js = users_format_js(users)
# multiple orderlines (one per product)
OrderLineFormSet = formset_factory(OrderLineForm)
if request.method == "POST":
orderform = OrderForm(request.POST)
formset = OrderLineFormSet(request.POST)
if formset.is_valid() and orderform.is_valid():
order = orderform.save(commit=False)
if order.is_external():
order_sum = sum([ol['amount'] * ol['unit_price_ext'] for ol in formset.cleaned_data])
else:
order_sum = sum([ol['amount'] * ol['unit_price_int'] for ol in formset.cleaned_data])
# empty order?
if order_sum == 0:
messages.error(request, 'Du har ikke valgt hva du skal kjøpe...')
return HttpResponseRedirect(reverse('register'))
if not order.is_external():
profile = order.customer.profile
# can she afford it?
if order_sum >= profile.balance:
messages.error(request, '{0} {1} har ikke råd, mangler {2} kr.'.format(
order.customer.first_name,
order.customer.last_name,
int(order_sum - profile.balance)))
return HttpResponseRedirect(reverse('register'))
# substract order from balance
profile.balance -= order_sum
profile.save()
order.order_sum = order_sum
order.save()
orderlines = []
for ol in formset.cleaned_data:
if ol['amount'] > 0:
product = Product.objects.get(pk=ol['product'])
if order.is_external():
unit_price = ol['unit_price_ext']
else:
unit_price = ol['unit_price_int']
OrderLine.objects.create(
order=order,
product=product,
amount=ol['amount'],
unit_price=unit_price)
product.inventory_amount -= ol['amount']
product.save()
orderlines.append("{0} {1}".format(ol['amount'], product))
if order.is_external():
messages.success(request, 'Ekstern kjøpte {0}.'.format(", ".join(orderlines)))
else:
messages.success(request, '{0} {1} kjøpte {2}.'.format(
order.customer.first_name,
order.customer.last_name,
", ".join(orderlines)
))
return redirect('register')
else:
# TODO specify error(s)
messages.error(request, 'Skjemaet er ikke gyldig.')
orderform = OrderForm(request.POST)
formset = OrderLineFormSet(request.POST)
else:
orderform = OrderForm()
formset = OrderLineFormSet()
return render(request, 'register.html', locals())
def deposit(request):
users = User.objects.all().order_by('first_name', 'last_name')
users_js = users_format_js(users)
allowed_users = users_with_perm('add_transaction')
error_message_template = '{0} {1} kan ikke sette inn {2} kr, det overskrider maks saldo ({3} kr) med {4} kr'
# FIXME: dont need this
try:
limit_deposists = settings.BBS_LIMIT_DEPOSITS
except:
pass
if request.method == "POST":
form = DepositForm(request.POST)
if form.is_valid():
amount = form.cleaned_data['amount']
user = form.cleaned_data['user']
if amount + user.profile.balance > settings.BBS_SALDO_MAX and amount + user.profile.balance != 1337:
messages.error(request, error_message_template.format(
user.first_name,
user.last_name,
amount,
settings.BBS_SALDO_MAX,
amount + user.profile.balance - settings.BBS_SALDO_MAX
))
return HttpResponseRedirect(reverse('deposit'))
transaction = form.save()
profile = transaction.user.profile
profile.balance += transaction.amount
profile.save()
messages.success(request, '{0} {1} satte inn {2} kr. Ny saldo er {3}'.format(
transaction.user.first_name,
transaction.user.last_name,
transaction.amount,
profile.balance))
return HttpResponseRedirect(reverse('deposit'))
else:
messages.error(request, 'Skjemaet er ikke gyldig.')
form = DepositForm(request.POST)
else:
form = DepositForm()
return render(request, 'deposit.html', locals())
def log(request, limit=datetime.now()-timedelta(days=2)):
if limit:
# display last two days of orders and transactions
orders = Order.objects.filter(created__gte=limit).order_by('-created')
transactions = Transaction.objects.filter(created__gte=limit).order_by('-created')
# no action in the last two days?
# ...then display the last 5 items
if len(orders) == 0:
orders = Order.objects.all().order_by('-created')[:5]
if len(transactions) == 0:
transactions = Transaction.objects.all().order_by('-created')[:5]
else:
# display everything
orders = Order.objects.all().order_by('-created')
transactions = Transaction.objects.all().order_by('-created')
return render(request, 'log.html', locals())
+136
View File
@@ -0,0 +1,136 @@
from datetime import datetime, timedelta
from itertools import groupby
from django.contrib import messages
from django.shortcuts import render, redirect
from main.forms import DateRangeForm, InventoryTransactionForm
from main.models import Product, InventoryTransaction, UserProfile, Transaction, Order
def report(request):
# FIXME: split this up in smaller pieces
datetime_now = datetime.now()
start_time = datetime.now() - timedelta(days=30)
# start of day, 1 month
start_time = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
# end of day
end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999)
if request.GET.get('start_time', False) or request.GET.get('end_time', False):
form = DateRangeForm(request.GET)
if form.is_valid():
start_time = form.cleaned_data['start_time']
# end of day
end_time = form.cleaned_data['end_time'].replace(hour=23, minute=59, second=59, microsecond=999)
else:
form = DateRangeForm(initial={
'start_time': start_time.strftime("%Y-%m-%d"),
'end_time': end_time.strftime("%Y-%m-%d")
})
# Inventory
products = Product.objects\
.filter(transactions__created__range=[start_time, end_time])\
.values('name', 'transactions__unit_price', 'transactions__amount')\
.order_by('name')
# group by name and sum
inventory_products = {}
for k, g in groupby(products, lambda x: x['name']):
group = []
for el in g:
el['transactions__price'] = el['transactions__amount'] * el['transactions__unit_price']
group.append(el)
inventory_products.update({k: {
'name': k,
"transactions": group,
"transactions_sum": sum(map(lambda x: x['transactions__price'], group)),
"transactions_units": sum(map(lambda x: x['transactions__amount'], group))
}})
itrans = InventoryTransaction.objects.filter(created__range=[start_time, end_time])
inv_in = sum(map(lambda x: x[1].get('transactions_sum', 0), inventory_products.items()))
# out
out_products = Product.objects\
.filter(orderlines__order__created__range=[start_time, end_time])\
.values('name', 'orderlines__unit_price', 'orderlines__amount')\
.order_by('name')
# group by name and sum
for k, g in groupby(out_products, lambda x: x['name']):
group = []
for el in g:
el['orderlines__price'] = el['orderlines__amount'] * el['orderlines__unit_price']
group.append(el)
product = {
'name': k,
"orderlines": group,
"orderlines_sum": sum(map(lambda x: x['orderlines__price'], group)),
"orderlines_units": sum(map(lambda x: x['orderlines__amount'], group))
}
if k in inventory_products:
# add diff
inventory_products[k].update(product)
else:
inventory_products.update({k: product})
for p in inventory_products.items():
p[1]['value_diff'] = p[1].get('transactions_sum', 0) - p[1].get('orderlines_sum', 0)
p[1]['units_diff'] = p[1].get('transactions_units', 0) - p[1].get('orderlines_units', 0)
inv_out = sum(map(lambda x: x[1].get('orderlines_sum', 0), inventory_products.items()))
inv_diff = inv_in - inv_out
# Deposits and sales
saldo_profiles = sum(UserProfile.objects.all().values_list('balance', flat=True))
deposits = sum(Transaction.objects.all().values_list('amount', flat=True))
purchases = sum(Order.objects.all().values_list('order_sum', flat=True))
saldo = deposits - purchases
deposits_start = sum(Transaction.objects.filter(created__lt=start_time).values_list('amount', flat=True))
purchases_start = sum(Order.objects.filter(created__lt=start_time).values_list('order_sum', flat=True))
saldo_start = deposits_start - purchases_start
deposits_end = sum(Transaction.objects.filter(created__lt=end_time).values_list('amount', flat=True))
purchases_end = sum(Order.objects.filter(created__lt=end_time).values_list('order_sum', flat=True))
saldo_end = deposits_end - purchases_end
deposits_diff = deposits_end - deposits_start
purchases_diff = purchases_end - purchases_start
saldo_diff = saldo_end - saldo_start
return render(request, 'report.html', locals())
def inventory(request):
products = Product.objects.all().order_by('-active', 'inventory_amount', 'name')
transactions = InventoryTransaction.objects.all().order_by('-created')
products_active = products.filter(active=True)
wholesale_value = sum([p.wholesale_value for p in products_active])
num_products = sum(products_active.values_list('inventory_amount', flat=True))
return render(request, 'inventory.html', locals())
def inventory_add(request):
if request.method == "POST":
form = InventoryTransactionForm(data=request.POST)
if form.is_valid():
itrans = form.save(commit=False)
# Add amount and user, then save
itrans.product.inventory_amount += itrans.amount
itrans.user = request.user
itrans.product.save()
itrans.save()
messages.success(request, "Satt inn {0} stk {1}.".format(itrans.amount, itrans.product))
return redirect('inventory-add')
else:
messages.error(request, 'Feil med skjemaet, se under.')
form = InventoryTransactionForm(data=request.POST)
else:
form = InventoryTransactionForm()
return render(request, 'inventory_add.html', locals())
+176
View File
@@ -0,0 +1,176 @@
from __future__ import unicode_literals
from datetime import datetime, timedelta, time
from django.db.models import Sum, Count
from django.http import JsonResponse
from django.shortcuts import render, get_object_or_404
from itertools import groupby
from main.models import Product, OrderLine, Order
def stats_list(request):
products = Product.objects.filter(active=True)
return render(request, 'stats.html', {'products': products})
def serialize_product(product):
f_product = {}
for attr in Product._meta.get_all_field_names():
if attr in ["transactions", "orderlines", "image"]:
continue
if hasattr(product, attr) and product.__getattribute__(attr):
if type(product.__getattribute__(attr)) is datetime:
f_product[attr] = str(product.__getattribute__(attr))
else:
f_product[attr] = product.__getattribute__(attr)
return f_product
def products_json(request, product_id=None):
if product_id:
# single
products = get_object_or_404(Product, pk=product_id)
else:
# many
products = Product.objects.filter(active=True)
if product_id:
f_products = serialize_product(products)
else:
f_products = [serialize_product(product) for product in products]
return JsonResponse(f_products)
def stats_product(product):
# reverse lookup via order, customer
per_user = OrderLine.objects\
.filter(product=product)\
.values('order__customer__first_name', 'order__customer__last_name')\
.annotate(num=Sum('amount'))\
.order_by('-num')
f_per_user = []
for row in per_user:
if row['order__customer__first_name'] is not None:
who = row['order__customer__first_name'] + " " + row['order__customer__last_name']
else:
who = "Ekstern"
num = row['num']
f_per_user.append([who, num])
response = {
'product': serialize_product(Product.objects.get(pk=product)) if type(product) is unicode else serialize_product(product),
'counts': f_per_user,
'total_counts': sum([row['num'] for row in per_user]),
}
return response
def stats_products(request, product=None):
if product:
# single
f_products = [stats_product(product)]
sales = OrderLine.objects.filter(product=product)
else:
# all
sales = OrderLine.objects.filter(product__active=True)
f_products = [stats_product(p) for p in Product.objects.filter(active=True)]
totals = float(sum([sale.amount for sale in sales]))
response = {
'request': 'all' if not product else product,
'response': {
'products': f_products,
'total_count': totals,
}
}
return JsonResponse(response)
def stats_orders(request):
num_external_orders = Order.objects.filter(customer=None).count()
per_user = Order.objects\
.values('customer__first_name', 'customer__last_name')\
.annotate(num=Count('customer'))\
.order_by('num').reverse()
f_per_user = []
for row in per_user:
if row['customer__first_name'] is not None:
who = row['customer__first_name'] + " " + row['customer__last_name']
num = row['num']
else:
who = "Ekstern"
num = num_external_orders
f_per_user.append([who, num])
return JsonResponse(f_per_user, safe=False)
def stats_orders_hourly(request):
orders = Order.objects.all()
f_hourly = dict([(key, 0) for key in range(0, 24)]) # init
# group by hour
for key, values in groupby(orders, key=lambda row: row.created.hour):
count = len(list(values))
f_hourly[key] += count
if len(orders) == 0:
return JsonResponse({})
response = {
'start': str(orders[0].created),
'hourly': [[k, v] for k, v in f_hourly.iteritems()],
'total': sum(f_hourly.values()),
}
return JsonResponse(response)
def stats_products_realtime(request):
end_time = datetime.now()
start_time = datetime.now() - timedelta(hours=24)
order_lines = OrderLine.objects.filter(order__created__range=(start_time, end_time)).order_by("order__created")
products = {}
for order_line in order_lines:
order_time_in_milliseconds = int(time.mktime(order_line.order.created.timetuple()) * 1000)
if order_line.product not in products:
products[order_line.product] = [[order_time_in_milliseconds, order_line.amount]]
else:
prev_entry = products[order_line.product][-1]
products[order_line.product].append([order_time_in_milliseconds, prev_entry[1] + order_line.amount])
serialized_products = {}
for product, value in products.iteritems():
serialized_products[product.name] = value
response = {
'products': serialized_products
}
return JsonResponse(response)
def stats_products_per_user(request, user_id=None):
if not user_id:
return JsonResponse({'error': 'Missing param user_id'})
order_lines = OrderLine.objects.filter(order__customer__pk=user_id).order_by("order__created")
products = {}
for order_line in order_lines:
order_time_in_milliseconds = int(time.mktime(order_line.order.created.timetuple()) * 1000)
if order_line.product not in products:
products[order_line.product] = [[order_time_in_milliseconds, order_line.amount]]
else:
prev_entry = products[order_line.product][-1]
products[order_line.product].append([order_time_in_milliseconds, prev_entry[1] + order_line.amount])
serialized_products = []
for product, value in products.iteritems():
serialized_products.append({
'name': product.name,
'data': value
})
return JsonResponse(serialized_products)
+61
View File
@@ -0,0 +1,61 @@
# coding: utf-8
from __future__ import unicode_literals
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db import connection
from django.db.models import Sum, Count
from django.shortcuts import render, redirect
from django.contrib.auth import logout as auth_logout
from main.forms import SimpleCreateUserForm
from main.models import Order
from main.models import Transaction
def logout(request):
auth_logout(request)
return render(request, 'registration/logout.html')
def create_user(request):
if request.method == "POST":
form = SimpleCreateUserForm(data=request.POST)
if form.is_valid():
user = form.save()
messages.success(request, "Hurra! {0} {1} er lagt til".format(user.first_name, user.last_name))
return redirect('create-user')
else:
messages.error(request, 'Feil med skjemaet, se under.')
form = SimpleCreateUserForm(data=request.POST)
else:
form = SimpleCreateUserForm()
return render(request, 'registration/create_user.html', {'form': form})
@login_required
def profile(request):
transactions = Transaction.objects.filter(user=request.user.pk)
transaction_totals = {
'sum': sum([t.amount for t in transactions])
}
orders = Order.objects.filter(customer=request.user.pk)
orders_totals = {
'sum': sum([o.order_sum for o in orders])
}
# order_lines = OrderLine.objects.filter(order__customer__pk=1).order_by("order__created")
order_report = _orders_monthly(filter_by={'customer': request.user.pk})
top_months = order_report.order_by('-sum')[:5]
return render(request, 'profile.html', locals())
def _orders_monthly(filter_by={}, order_by='month'):
truncate_date = connection.ops.date_trunc_sql('month', 'created')
qs = Order.objects.filter(**filter_by).extra({'month': truncate_date})
order_report = qs.values('month').annotate(sum=Sum('order_sum'), num=Count('pk')).order_by(order_by)
return order_report