diff --git a/main/urls.py b/main/urls.py index 61a7626..9eccc07 100644 --- a/main/urls.py +++ b/main/urls.py @@ -6,8 +6,9 @@ urlpatterns = patterns('main.views', url(r'^log/$', 'log', name='log'), url(r'^log/all$', 'log', kwargs={'limit': None}, name='log-all'), url(r'^stats/$', 'stats', name='stats'), - url(r'^stats/orders$', 'stats_orders', name='stats-orders'), - url(r'^stats/product/(?P[0-9]+)$', 'stats_product', name='stats-product'), - url(r'^products/(?P[0-9]+)', 'products', name='json-product'), + url(r'^stats/orders/$', 'stats_orders', name='stats-orders'), + url(r'^stats/products/$', 'stats_products', name='stats-products'), + url(r'^stats/products/(?P[0-9]+)/$', 'stats_products', name='stats-product'), + url(r'^products/(?P[0-9]+)/$', 'products', name='json-product'), url(r'^products/$', 'products', name='json-products'), ) diff --git a/main/views.py b/main/views.py index 919b905..ce5bc28 100755 --- a/main/views.py +++ b/main/views.py @@ -12,7 +12,7 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.forms.formsets import formset_factory from django.contrib import messages -from django.db.models import Count +from django.db.models import Count, Sum from models import * @@ -143,10 +143,7 @@ def serialize_product(product): f_product = {} for attr in Product._meta.get_all_field_names(): if hasattr(product, attr) and product.__getattribute__(attr): - #print type(product.__getattribute__(attr)) if type(product.__getattribute__(attr)) is datetime: - # TODO parse datetime - date = product.__getattribute__(attr) f_product[attr] = str(product.__getattribute__(attr)) else: f_product[attr] = product.__getattribute__(attr) @@ -167,21 +164,45 @@ def products(request, product_id=None): return HttpResponse(json.dumps(f_products), content_type='application/javascript; charset=utf8') -def stats_product(request, product): +def stats_product(product): sales = OrderLine.objects.filter(product=product) - total = float(sales.count()) - per_user = sales.values('order__customer__first_name','order__customer__last_name').annotate(num=Count('order__customer')).order_by('num') + # reverse lookup via order, customer + per_user = sales.values('order__customer__first_name','order__customer__last_name').annotate(num=Sum('amount')).order_by('num').reverse() f_per_user = [] for row in per_user: who = row['order__customer__first_name'] + " " + row['order__customer__last_name'][0] num = row['num'] f_per_user.append([who, num]) - return HttpResponse(json.dumps(f_per_user), content_type='application/javascript; charset=utf8') + 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 HttpResponse(json.dumps(response), content_type='application/javascript; charset=utf8') def stats_orders(request): - total = float(Order.objects.count()) - per_user = Order.objects.values('customer__first_name','customer__last_name').annotate(num=Count('customer')).order_by('num') + 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: who = row['customer__first_name'] + " " + row['customer__last_name'][0] diff --git a/static/js/stats.js b/static/js/stats.js index faa8c28..92cacf1 100644 --- a/static/js/stats.js +++ b/static/js/stats.js @@ -1,40 +1,73 @@ $(document).ready(function() { var charts = []; - var products_url = '/products'; + var products_url = '/stats/products/'; + var order_url = '/stats/orders/'; - /* drink beer and... */ + /* orders */ + $.getJSON(order_url, function(data) { + var render_to = 'order_chart'; + + // define the options + var options = { + credits: { + enabled: false + }, + chart: { + renderTo: render_to, + plotBackgroundColor: null, + plotBorderWidth: null, + plotShadow: false + }, + title: { + text: 'Fordeling av ordre på person' + }, + tooltip: { + formatter: function() { + return ''+ this.point.name +': '+ Highcharts.numberFormat(this.percentage, 1) +' %'; + } + }, + plotOptions: { + pie: { + allowPointSelect: true, + cursor: 'pointer', + dataLabels: { + enabled: true, + color: '#000000', + connectorColor: '#000000', + formatter: function() { + return ''+ this.point.name +': '+ Highcharts.numberFormat(this.percentage, 1) +' %'; + } + } + } + }, + series: [{ + type: 'pie', + name: 'Orders', + data: data + }] + }; + charts.push(new Highcharts.Chart(options)); + }); + + /* products */ $.getJSON(products_url, function(data) { - var graph_mappings = [ - { - 'url' : '/stats/orders', - 'render_to' : 'order_chart' - }]; - var products = data; + var products = data.response.products; for(i in products) { - var mapping = { - 'url' : '/stats/product/' + products[i].id, - 'info_url' : '/products/' + products[i].id, - 'render_to' : 'product_chart' + products[i].id - }; - graph_mappings.push(mapping); - } - for(i in graph_mappings) { + var render_to = 'product_chart' + products[i].product.id; + var series_data = products[i].counts; // define the options var options = { credits: { enabled: false }, chart: { - /* TODO this is not updated right. - * ie. how to get ajax-callback to update the right options-object? - * */ - renderTo: graph_mappings[i].render_to, + renderTo: render_to, plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false }, title: { - text: 'Antall ordre per bruker' + text: products[i].product.name }, tooltip: { formatter: function() { @@ -50,7 +83,7 @@ $(document).ready(function() { color: '#000000', connectorColor: '#000000', formatter: function() { - return ''+ this.point.name +': '+ Highcharts.numberFormat(this.percentage, 1) +' %'; + return ''+ this.point.name +': ' + this.y; } } } @@ -58,14 +91,10 @@ $(document).ready(function() { series: [{ type: 'pie', name: 'Orders', - data: [] + data: series_data }] }; - $.getJSON(graph_mappings[i].url, function(data) { - options.series[0].data = data, - charts.push(new Highcharts.Chart(options)); - }); + charts.push(new Highcharts.Chart(options)); } - console.log(charts); }); }); diff --git a/templates/stats.html b/templates/stats.html index 96194f8..be9792e 100644 --- a/templates/stats.html +++ b/templates/stats.html @@ -13,15 +13,17 @@ - {% for product in products %} -
-
-

{{ product }}

-
- -
-
- {% endfor %} +
+

Produkter

+ {% for product in products %} +
+
+
+ +
+
+ {% endfor %} +
{% endblock %} {% block tailinc %}