Functional product stats

This commit is contained in:
nikolark committed 2012-04-15 14:44:12 +02:00
1 parent 598e2a8e57
commit 3229d54365
4 files changed
+96 -43

No files matched your search

+4 -3
View File
@@ -6,8 +6,9 @@ urlpatterns = patterns('main.views',
url(r'^log/$', 'log', name='log'), url(r'^log/$', 'log', name='log'),
url(r'^log/all$', 'log', kwargs={'limit': None}, name='log-all'), url(r'^log/all$', 'log', kwargs={'limit': None}, name='log-all'),
url(r'^stats/$', 'stats', name='stats'), url(r'^stats/$', 'stats', name='stats'),
url(r'^stats/orders$', 'stats_orders', name='stats-orders'), url(r'^stats/orders/$', 'stats_orders', name='stats-orders'),
url(r'^stats/product/(?P<product>[0-9]+)$', 'stats_product', name='stats-product'), url(r'^stats/products/$', 'stats_products', name='stats-products'),
url(r'^products/(?P<product_id>[0-9]+)', 'products', name='json-product'), url(r'^stats/products/(?P<product>[0-9]+)/$', 'stats_products', name='stats-product'),
url(r'^products/(?P<product_id>[0-9]+)/$', 'products', name='json-product'),
url(r'^products/$', 'products', name='json-products'), url(r'^products/$', 'products', name='json-products'),
) )
+31 -10
View File
@@ -12,7 +12,7 @@ from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from django.forms.formsets import formset_factory from django.forms.formsets import formset_factory
from django.contrib import messages from django.contrib import messages
from django.db.models import Count from django.db.models import Count, Sum
from models import * from models import *
@@ -143,10 +143,7 @@ def serialize_product(product):
f_product = {} f_product = {}
for attr in Product._meta.get_all_field_names(): for attr in Product._meta.get_all_field_names():
if hasattr(product, attr) and product.__getattribute__(attr): if hasattr(product, attr) and product.__getattribute__(attr):
#print type(product.__getattribute__(attr))
if type(product.__getattribute__(attr)) is datetime: if type(product.__getattribute__(attr)) is datetime:
# TODO parse datetime
date = product.__getattribute__(attr)
f_product[attr] = str(product.__getattribute__(attr)) f_product[attr] = str(product.__getattribute__(attr))
else: else:
f_product[attr] = product.__getattribute__(attr) 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') 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) sales = OrderLine.objects.filter(product=product)
total = float(sales.count()) # reverse lookup via order, customer
per_user = sales.values('order__customer__first_name','order__customer__last_name').annotate(num=Count('order__customer')).order_by('num') per_user = sales.values('order__customer__first_name','order__customer__last_name').annotate(num=Sum('amount')).order_by('num').reverse()
f_per_user = [] f_per_user = []
for row in per_user: for row in per_user:
who = row['order__customer__first_name'] + " " + row['order__customer__last_name'][0] who = row['order__customer__first_name'] + " " + row['order__customer__last_name'][0]
num = row['num'] num = row['num']
f_per_user.append([who, 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): def stats_orders(request):
total = float(Order.objects.count()) 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 = [] f_per_user = []
for row in per_user: for row in per_user:
who = row['customer__first_name'] + " " + row['customer__last_name'][0] who = row['customer__first_name'] + " " + row['customer__last_name'][0]
+56 -27
View File
@@ -1,40 +1,25 @@
$(document).ready(function() { $(document).ready(function() {
var charts = []; var charts = [];
var products_url = '/products'; var products_url = '/stats/products/';
var order_url = '/stats/orders/';
/* orders */
$.getJSON(order_url, function(data) {
var render_to = 'order_chart';
/* drink beer and... */
$.getJSON(products_url, function(data) {
var graph_mappings = [
{
'url' : '/stats/orders',
'render_to' : 'order_chart'
}];
var products = data;
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) {
// define the options // define the options
var options = { var options = {
credits: { credits: {
enabled: false enabled: false
}, },
chart: { chart: {
/* TODO this is not updated right. renderTo: render_to,
* ie. how to get ajax-callback to update the right options-object?
* */
renderTo: graph_mappings[i].render_to,
plotBackgroundColor: null, plotBackgroundColor: null,
plotBorderWidth: null, plotBorderWidth: null,
plotShadow: false plotShadow: false
}, },
title: { title: {
text: 'Antall ordre per bruker' text: 'Fordeling av ordre på person'
}, },
tooltip: { tooltip: {
formatter: function() { formatter: function() {
@@ -58,14 +43,58 @@ $(document).ready(function() {
series: [{ series: [{
type: 'pie', type: 'pie',
name: 'Orders', name: 'Orders',
data: [] data: 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));
}); });
/* products */
$.getJSON(products_url, function(data) {
var products = data.response.products;
for(i in products) {
var render_to = 'product_chart' + products[i].product.id;
var series_data = products[i].counts;
// define the options
var options = {
credits: {
enabled: false
},
chart: {
renderTo: render_to,
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: products[i].product.name
},
tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ Highcharts.numberFormat(this.percentage, 1) +' %';
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
color: '#000000',
connectorColor: '#000000',
formatter: function() {
return '<b>'+ this.point.name +'</b>: ' + this.y;
}
}
}
},
series: [{
type: 'pie',
name: 'Orders',
data: series_data
}]
};
charts.push(new Highcharts.Chart(options));
} }
console.log(charts);
}); });
}); });
+5 -3
View File
@@ -13,16 +13,18 @@
</div> </div>
</section> </section>
<section id="product" class="row-fluid">
<h2>Produkter</h2>
{% for product in products %} {% for product in products %}
<section id="product_{{ product.id }}" class="row-fluid"> <section id="product_{{ product.id }}">
<div class="span12"> <div class="span6">
<h2>{{ product }}</h2>
<div id="product_chart{{ product.id }}"></div> <div id="product_chart{{ product.id }}"></div>
<!--<div id="container" style="width: 800px; height: 400px; margin: 0 auto;"></div> --> <!--<div id="container" style="width: 800px; height: 400px; margin: 0 auto;"></div> -->
</div> </div>
</section> </section>
{% endfor %} {% endfor %}
</section> </section>
</section>
{% endblock %} {% endblock %}
{% block tailinc %} {% block tailinc %}
<script src="{{ STATIC_URL }}js/bootstrap-typeahead.js"></script> <script src="{{ STATIC_URL }}js/bootstrap-typeahead.js"></script>