Adds initial profile page

This commit is contained in:
nikolark committed 2014-10-11 17:03:58 +02:00
1 parent fc65e15d98
commit f8a94b7bee
10 files changed
+196 -23

No files matched your search

+9 -6
View File
@@ -50,19 +50,22 @@ class Product(models.Model):
class Order(models.Model):
customer = models.ForeignKey(User, null=True, blank=True)
customer = models.ForeignKey(User, null=True, blank=True, related_name='orders')
order_sum = models.FloatField(db_column='sum')
created = models.DateTimeField(auto_now_add=True)
def is_external(self):
return self.customer is None
def reciept(self):
return u"{0}".format(u", ".join([str(ol) for ol in self.orderlines.all()]))
def __unicode__(self):
return u"{0}: {1} kr".format(self.customer or u"Ekstern", self.order_sum)
class OrderLine(models.Model):
order = models.ForeignKey('main.Order')
order = models.ForeignKey('main.Order', related_name='orderlines')
product = models.ForeignKey('main.Product', related_name='orderlines')
amount = models.IntegerField()
unit_price = models.FloatField(verbose_name=_('Enhetspris'))
@@ -80,7 +83,7 @@ class OrderLine(models.Model):
class Transaction(models.Model):
""" Money """
user = models.ForeignKey(User)
user = models.ForeignKey(User, related_name='transactions')
amount = models.FloatField()
created = models.DateTimeField(auto_now_add=True)
@@ -90,7 +93,7 @@ class Transaction(models.Model):
class InventoryTransaction(models.Model):
""" Goods """
user = models.ForeignKey(User)
user = models.ForeignKey(User, related_name='inventory_transactions')
product = models.ForeignKey('main.Product', related_name='transactions', verbose_name=_('Produkt'))
amount = models.FloatField(verbose_name=_('Antall'))
unit_price = models.FloatField(verbose_name=_('Enhetspris'))
@@ -117,9 +120,9 @@ class UserProfile(models.Model):
image = models.URLField(blank=True)
def last_purchase(self):
if len(self.user.order_set.all()) == 0:
if len(self.user.orders.all()) == 0:
return None
return self.user.order_set.order_by('created').reverse()[0]
return self.user.orders.order_by('created').reverse()[0]
def last_purchase_date(self):
last = self.last_purchase()
+2
View File
@@ -12,9 +12,11 @@ urlpatterns = patterns('main.views',
url(r'^stats/orders/products_realtime$', 'stats_products_realtime', name='stats-products-realtime'),
url(r'^stats/products/$', 'stats_products', name='stats-products'),
url(r'^stats/products/(?P<product>[0-9]+)/$', 'stats_products', name='stats-product'),
url(r'^stats/products/by_user/(?P<user_id>[0-9]+)/$', 'stats_products_per_user', name='stats-products-per-user'),
url(r'^products/(?P<product_id>[0-9]+)/$', 'products_json', name='json-product'),
url(r'^products/$', 'products_json', name='json-products'),
url(r'^user/create/$', 'create_user', name='create-user'),
url(r'^profile/$', 'profile', name='profile'),
url(r'^inventory/$', 'inventory', name='inventory'),
url(r'^inventory/add/$', 'inventory_add', name='inventory-add'),
url(r'^report$', 'report', name='report'),
+55 -3
View File
@@ -4,9 +4,11 @@ from itertools import groupby
import json
import time
from django.db import connection
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login, logout as auth_logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db.models import Count, Sum, Min
@@ -14,7 +16,6 @@ from django.forms.formsets import formset_factory
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, render, get_object_or_404, redirect
from django.template import RequestContext
from forms import *
from models import *
import utils
@@ -309,7 +310,7 @@ def stats_orders_hourly(request):
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:
@@ -488,3 +489,54 @@ def report(request):
saldo_diff = saldo_end - saldo_start
return render(request, 'report.html', locals())
@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 stats_products_per_user(request, user_id=None):
if not user_id:
return HttpResponse(
json.dumps({'error': 'Missing param user_id'}),
content_type='application/javascript; charset=utf8')
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 HttpResponse(json.dumps(serialized_products), content_type='application/javascript; charset=utf8')
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
+43 -9
View File
@@ -105,6 +105,13 @@ $(document).ready(function() {
update_total(this);
});
/* Set Global Highcharts options */
Highcharts.setOptions({
credits: {
enabled: false
}
});
/*
* View: Register
@@ -163,9 +170,6 @@ $(document).ready(function() {
// define the options
var options = {
credits: {
enabled: false
},
chart: {
renderTo: render_to,
plotBackgroundColor: null,
@@ -211,9 +215,6 @@ $(document).ready(function() {
var series_data = products[i].counts;
// define the options
var options = {
credits: {
enabled: false
},
chart: {
renderTo: render_to,
plotBackgroundColor: null,
@@ -257,9 +258,6 @@ $(document).ready(function() {
// define the options
var options = {
credits: {
enabled: false
},
chart: {
renderTo: render_to,
type: 'column'
@@ -443,4 +441,40 @@ $(document).ready(function() {
}).on('changeDate', function(e) {
start_field.datepicker('setEndDate', e.date);
});
/*
* View: Profile
*/
if( $('#user-profile').length ) {
var products_by_user_url = '/stats/products/by_user/';
var user_id = $('#user-profile').attr('data-user-id');
$.getJSON(products_by_user_url + user_id, function(data) {
if(data.hasOwnProperty('error')) {
return;
}
$(".profile-stats-orderline").highcharts({
title: {
text: false
},
xAxis: {
type: "datetime"
},
yAxis: {
title: {
text: "Kjøp"
}
},
plotOptions: {
series: {
marker: {
radius: 3
}
}
},
series: data
});
});
}
});
+10
View File
@@ -156,6 +156,16 @@ body {
}
}
}
#user-profile {
.profile-name {
display: inline-block;
line-height: 50px;
vertical-align: bottom;
}
.profile-image {
border-radius: 50% 50%;
}
}
#footer .credits {
text-align: center;
margin: 2em;
+1 -1
View File
@@ -1 +1 @@
function enable_all_customers(){$("li.customer").each(function(){$(this).removeClass("marked"),$(this).show()})}function filter_customers(t){setTimeout(function(){$("li.customer").each(function(){var e=new RegExp(t,"i"),r=$(this).children("span.name").text();if(e.test(r)){$(this).show();var a=r.toLowerCase()==t.toLowerCase(),o=1==$("li.customer:visible").length;console.log(a,o),a?$(this).addClass("marked"):$(this).removeClass("marked")}else $(this).hide(),$(this).removeClass("marked")})},50)}function enable_all_products(){$("li.product").each(function(){$(this).removeClass("marked"),$(this).show()})}function reset_qtys(){$(".qty").each(function(){$(this).html("0")}),$("input[name$=amount]").each(function(){$(this).val("0")})}function update_total(){var t=0;$("li.product").each(function(){var e=Number($(this).find("[name$=amount]").val()),r=".sale_price_int";"Ekstern"===$("#id_customer_typeahead").val()&&(r=".sale_price_ext");var a=Number($(this).find(r).text());t+=e*a}),0===t&&(t=""),$("span.total_text").html(t)}$(document).ready(function(){function t(t){var e=s;for(var r in t.products)if(null===e.get(r)){e.addSeries({data:[],id:r,name:r});var a=e.get(r);_.each(t.products[r],function(t){a.addPoint({id:t[0],x:t[0],y:t[1]})})}else{var a=e.get(r);_.each(t.products[r],function(t){null===e.get(t[0])&&a.addPoint({id:t[0],x:t[0],y:t[1]})})}}function e(){$.ajax({url:n,dataType:"json",success:function(r){t(r),setTimeout(function(){e()},15e3)},cache:!1})}if($("a[data-dismiss=alert]").click(function(){$(this).parent().parent().parent().slideUp()}),setTimeout(function(){$("a[data-dismiss=alert]").parent().parent().parent().slideUp()},5e3),$("h2").tooltip({placement:"right"}),$("img.customer").tooltip(),$("a.product").tooltip(),$("#footer .credits .love").tooltip(),$("#id_customer_typeahead").keyup(function(t){filter_customers(t.target.value)}),$("li.customer").click(function(){enable_all_customers(),$(this).addClass("marked");var t=$(this).children("span.name").text();$("#id_customer_typeahead").val(t);var e=$(this).children("span.id").text();$("#id_customer option, #id_user option").removeAttr("selected"),""===e?$("#id_customer option:first-child, #id_user option:first-child").attr("selected","selected"):$("#id_customer option[value="+e+"], #id_user option[value="+e+"]").attr("selected","selected"),update_total(this)}),$("#register li.product").click(function(){$(this).addClass("marked");var t=$(this).children("input[name$=amount]"),e=$(this).children(".qty"),r=Number(t.val())+1;t.val(r),e.html(r),update_total(this)}),$("#register button[type=reset]").click(function(){$("#id_customer option").removeAttr("selected"),$("#id_customer_typeahead").val(""),$("span.total_text").html(""),enable_all_customers(),enable_all_products(),reset_qtys()}),$(".toggle-infrequent-users").on("click",function(t){t.preventDefault(),$("li.customer.infrequent").toggleClass("hidden"),$(".users-description .infrequent-users").toggleClass("hidden"),$(this).text("Vis alle"===$(this).text()?"Skjul gamliser":"Vis alle")}),$("#stats").length>0){var r=[],a="/stats/products/",o="/stats/orders/",i="/stats/orders/hourly",n="/stats/orders/products_realtime";$.getJSON(o,function(t){var e="order_chart",a={credits:{enabled:!1},chart:{renderTo:e,plotBackgroundColor:null,plotBorderWidth:null,plotShadow:!1},title:{text:"Fordeling av ordre på person"},tooltip:{formatter:function(){return"<b>"+this.point.name+"</b>: "+Highcharts.numberFormat(this.percentage,1)+" %"}},plotOptions:{pie:{allowPointSelect:!0,cursor:"pointer",dataLabels:{enabled:!0,color:"#000000",connectorColor:"#000000",formatter:function(){return"<b>"+this.point.name+"</b>: "+this.y}}}},series:[{type:"pie",name:"Orders",data:t}]};r.push(new Highcharts.Chart(a))}),$.getJSON(a,function(t){var e=t.response.products;for(var a in e){var o="product_chart"+e[a].product.id,i=e[a].counts,n={credits:{enabled:!1},chart:{renderTo:o,plotBackgroundColor:null,plotBorderWidth:null,plotShadow:!1},title:{text:e[a].product.name},tooltip:{formatter:function(){return"<b>"+this.point.name+"</b>: "+Highcharts.numberFormat(this.percentage,1)+" %"}},plotOptions:{pie:{allowPointSelect:!0,cursor:"pointer",dataLabels:{enabled:!0,color:"#000000",connectorColor:"#000000",formatter:function(){return"<b>"+this.point.name+"</b>: "+this.y}}}},series:[{type:"pie",name:"Orders",data:i}]};r.push(new Highcharts.Chart(n))}}),$.getJSON(i,function(t){var e="order_hourly_chart",a={credits:{enabled:!1},chart:{renderTo:e,type:"column"},title:{text:"Ordre - time for time"},tooltip:{formatter:function(){return this.y+" stk"}},yAxis:{title:{text:"Ordre"}},xAxis:{title:{text:"Tid (h)"},labels:{formatter:function(){return this.value+":00"}}},plotOptions:{column:{minPointLength:3},series:{groupPadding:0,pointPadding:.05}},series:[{name:"Ordre",data:t.hourly}]};r.push(new Highcharts.Chart(a))});var s=new Highcharts.Chart({chart:{renderTo:"products_realtime_chart"},title:{text:"Produkter solgt over tid"},xAxis:{type:"datetime"},yAxis:{title:{textLine truncated
function enable_all_customers(){$("li.customer").each(function(){$(this).removeClass("marked"),$(this).show()})}function filter_customers(t){setTimeout(function(){$("li.customer").each(function(){var e=new RegExp(t,"i"),r=$(this).children("span.name").text();if(e.test(r)){$(this).show();var a=r.toLowerCase()==t.toLowerCase(),i=1==$("li.customer:visible").length;console.log(a,i),a?$(this).addClass("marked"):$(this).removeClass("marked")}else $(this).hide(),$(this).removeClass("marked")})},50)}function enable_all_products(){$("li.product").each(function(){$(this).removeClass("marked"),$(this).show()})}function reset_qtys(){$(".qty").each(function(){$(this).html("0")}),$("input[name$=amount]").each(function(){$(this).val("0")})}function update_total(){var t=0;$("li.product").each(function(){var e=Number($(this).find("[name$=amount]").val()),r=".sale_price_int";"Ekstern"===$("#id_customer_typeahead").val()&&(r=".sale_price_ext");var a=Number($(this).find(r).text());t+=e*a}),0===t&&(t=""),$("span.total_text").html(t)}$(document).ready(function(){function t(t){var e=n;for(var r in t.products)if(null===e.get(r)){e.addSeries({data:[],id:r,name:r});var a=e.get(r);_.each(t.products[r],function(t){a.addPoint({id:t[0],x:t[0],y:t[1]})})}else{var a=e.get(r);_.each(t.products[r],function(t){null===e.get(t[0])&&a.addPoint({id:t[0],x:t[0],y:t[1]})})}}function e(){$.ajax({url:s,dataType:"json",success:function(r){t(r),setTimeout(function(){e()},15e3)},cache:!1})}if($("a[data-dismiss=alert]").click(function(){$(this).parent().parent().parent().slideUp()}),setTimeout(function(){$("a[data-dismiss=alert]").parent().parent().parent().slideUp()},5e3),$("h2").tooltip({placement:"right"}),$("img.customer").tooltip(),$("a.product").tooltip(),$("#footer .credits .love").tooltip(),$("#id_customer_typeahead").keyup(function(t){filter_customers(t.target.value)}),$("li.customer").click(function(){enable_all_customers(),$(this).addClass("marked");var t=$(this).children("span.name").text();$("#id_customer_typeahead").val(t);var e=$(this).children("span.id").text();$("#id_customer option, #id_user option").removeAttr("selected"),""===e?$("#id_customer option:first-child, #id_user option:first-child").attr("selected","selected"):$("#id_customer option[value="+e+"], #id_user option[value="+e+"]").attr("selected","selected"),update_total(this)}),Highcharts.setOptions({credits:{enabled:!1}}),$("#register li.product").click(function(){$(this).addClass("marked");var t=$(this).children("input[name$=amount]"),e=$(this).children(".qty"),r=Number(t.val())+1;t.val(r),e.html(r),update_total(this)}),$("#register button[type=reset]").click(function(){$("#id_customer option").removeAttr("selected"),$("#id_customer_typeahead").val(""),$("span.total_text").html(""),enable_all_customers(),enable_all_products(),reset_qtys()}),$(".toggle-infrequent-users").on("click",function(t){t.preventDefault(),$("li.customer.infrequent").toggleClass("hidden"),$(".users-description .infrequent-users").toggleClass("hidden"),$(this).text("Vis alle"===$(this).text()?"Skjul gamliser":"Vis alle")}),$("#stats").length>0){var r=[],a="/stats/products/",i="/stats/orders/",o="/stats/orders/hourly",s="/stats/orders/products_realtime";$.getJSON(i,function(t){var e="order_chart",a={chart:{renderTo:e,plotBackgroundColor:null,plotBorderWidth:null,plotShadow:!1},title:{text:"Fordeling av ordre på person"},tooltip:{formatter:function(){return"<b>"+this.point.name+"</b>: "+Highcharts.numberFormat(this.percentage,1)+" %"}},plotOptions:{pie:{allowPointSelect:!0,cursor:"pointer",dataLabels:{enabled:!0,color:"#000000",connectorColor:"#000000",formatter:function(){return"<b>"+this.point.name+"</b>: "+this.y}}}},series:[{type:"pie",name:"Orders",data:t}]};r.push(new Highcharts.Chart(a))}),$.getJSON(a,function(t){var e=t.response.products;for(var a in e){var i="product_chart"+e[a].product.id,o=e[a].counts,s={chart:{renderTo:i,plotBackgroundColor:null,plotBorderWidth:null,plotShadow:!1},title:{text:e[a].product.name},tooltip:{formatter:function(){return"<b>"+this.point.name+"</b>: "+Highcharts.numberFormat(this.percentage,1)+" %"}},plotOptions:{pie:{allowPointSelect:!0,cursor:"pointer",dataLabels:{enabled:!0,color:"#000000",connectorColor:"#000000",formatter:function(){return"<b>"+this.point.name+"</b>: "+this.y}}}},series:[{type:"pie",name:"Orders",data:o}]};r.push(new Highcharts.Chart(s))}}),$.getJSON(o,function(t){var e="order_hourly_chart",a={chart:{renderTo:e,type:"column"},title:{text:"Ordre - time for time"},tooltip:{formatter:function(){return this.y+" stk"}},yAxis:{title:{text:"Ordre"}},xAxis:{title:{text:"Tid (h)"},labels:{formatter:function(){return this.value+":00"}}},plotOptions:{column:{minPointLength:3},series:{groupPadding:0,pointPadding:.05}},series:[{name:"Ordre",data:t.hourly}]};r.push(new Highcharts.Chart(a))});var n=new Highcharts.Chart({chart:{renderTo:"products_realtime_chart"},title:{text:"Produkter solgt over tid"},xAxis:{type:"datetime"},yAxis:{title:{text:"Antall solgt"}}Line truncated
+1 -1
View File
@@ -1 +1 @@
/*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url('/static/dist/fonts/glyphicons-halflings-regular.eot');src:url('/static/dist/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('/static/dist/fonts/glyphicons-halflings-regular.woff') format('woff'),url('/static/dist/fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('/static/dist/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{Line truncated
/*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url('/static/dist/fonts/glyphicons-halflings-regular.eot');src:url('/static/dist/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('/static/dist/fonts/glyphicons-halflings-regular.woff') format('woff'),url('/static/dist/fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('/static/dist/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{Line truncated
+1
View File
@@ -40,6 +40,7 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="{{ user.get_profile.profile_image_url }}" /><span class="name">{{ user.first_name }}</span> <b class="caret"></b></a>
<ul class="dropdown-menu">
{% if request.user.is_authenticated %}<li class="{% block active_profile %}{% endblock %}"><a href="{% url 'profile' %}"><i class="glyphicon glyphicon-user"></i> Profil</a></li>{% endif %}
<li class="{% block active_create_user %}{% endblock %}"><a href="{% url 'create-user' %}"><i class="glyphicon glyphicon-plus"></i> Ny bruker</a></li>
{% if request.user.is_superuser %}<li><a href="/admin"><i class="glyphicon glyphicon-cog"></i> Administrasjon</a></li>{% endif %}
{% if request.user.is_superuser %}<li class="{% block active_inventory %}{% endblock %}"><a href="{% url 'inventory' %}"><i class="glyphicon glyphicon-briefcase"></i> Varebeholdning</a></li>{% endif %}
+3 -3
View File
@@ -32,13 +32,13 @@
<td>{{ product.wholesale_unit_price|default:"-" }}</td>
<td>{{ product.wholesale_value|default:"-" }}</td>
<td class="product-active">{% if product.active %}<i class="glyphicon glyphicon-ok"></i>{% endif %}</td>
<td>{{ product.updated }}</td>
<td>{{ product.updated|date:"c" }}</td>
</tr>
{% endfor %}
<tr>
<td></td>
<td>{{ num_products }} totalt</td>
<td>Sum</td>
<td>{{ num_products }}</td>
<td></td>
<td>{{ wholesale_value }}</td>
<td></td>
+71
View File
@@ -0,0 +1,71 @@
{% extends "base.html" %}
{% block active_profile %}active{% endblock %}
{% block content %}
<section id="user-profile" data-user-id="{{request.user.pk}}">
<div class="row">
<div class="col-md-12">
<h1 class="profile-name"><img src="{{ request.user.get_profile.profile_image_url }}" class="profile-image" /> {{user.first_name}}</h1>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">Saldo</div>
<div class="panel-body">
<h2>{{request.user.get_profile.balance }} kr</h2>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Kjøp totalt</div>
<div class="panel-body">
<h2>{{orders_totals.sum }} kr</h2>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Topp 5 måneder</div>
<div class="panel-body">
{% for o in top_months %}
<li>{{ o.month|date:"F Y"}}: <strong>{{ o.num }}</strong> kjøp på totalt <strong>{{ o.sum }} kr</strong></li>
{% endfor %}
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-heading">Kjøp over tid per produkt</div>
<div class="panel-body">
<div class="profile-stats-orderline"></div>
</div>
</div>
</div>
</div>
{% comment %}<div class="row">
<div class="col-md-5">
<div class="panel panel-default">
<div class="panel-heading">Ordre</div>
<div class="panel-body">
<ul>
{% for o in orders %}
<li>{{ o.created|date:"c" }}: {{ o.reciept }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">Transaksjoner</div>
<div class="panel-body">
<ul>
{% for t in transactions %}
<li>{{ t.created|date:"c" }} {{ t.amount }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
{% endcomment %}
</section>
{% endblock %}