Adds external user sale
This commit is contained in:
1 parent
1a68e4b95b
commit
ea7174815b
7 files changed
+227
-47
No files matched your search
+19
-9
@@ -1,6 +1,5 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from models import *
|
from models import *
|
||||||
@@ -9,9 +8,20 @@ import utils
|
|||||||
|
|
||||||
|
|
||||||
class OrderForm(forms.ModelForm):
|
class OrderForm(forms.ModelForm):
|
||||||
|
customer_name = forms.CharField(required=False)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if self.cleaned_data['customer'] is None and self.cleaned_data['customer_name'] != u"Ekstern":
|
||||||
|
raise forms.ValidationError(_(u"Du har ikke valgt hvem som skal kjøpe."))
|
||||||
|
|
||||||
|
return self.cleaned_data
|
||||||
|
|
||||||
def clean_customer(self):
|
def clean_customer(self):
|
||||||
|
if self.cleaned_data['customer'] is None:
|
||||||
|
return self.cleaned_data['customer']
|
||||||
|
|
||||||
if self.cleaned_data['customer'].get_profile().balance <= 0:
|
if self.cleaned_data['customer'].get_profile().balance <= 0:
|
||||||
raise forms.ValidationError(_("Du har negativ saldo og kan ikke kjøpe noe."))
|
raise forms.ValidationError(_(u"Du har negativ saldo og kan ikke kjøpe noe."))
|
||||||
|
|
||||||
return self.cleaned_data['customer']
|
return self.cleaned_data['customer']
|
||||||
|
|
||||||
@@ -23,7 +33,8 @@ class OrderForm(forms.ModelForm):
|
|||||||
class OrderLineForm(forms.Form):
|
class OrderLineForm(forms.Form):
|
||||||
product = forms.IntegerField(required=True)
|
product = forms.IntegerField(required=True)
|
||||||
amount = forms.IntegerField(required=True)
|
amount = forms.IntegerField(required=True)
|
||||||
unit_price = forms.FloatField(required=True, localize=True)
|
unit_price_int = forms.FloatField(required=True, localize=True)
|
||||||
|
unit_price_ext = forms.FloatField(required=True, localize=True)
|
||||||
|
|
||||||
|
|
||||||
class DepositForm(forms.ModelForm):
|
class DepositForm(forms.ModelForm):
|
||||||
@@ -38,10 +49,10 @@ class SimpleCreateUserForm(forms.Form):
|
|||||||
email = forms.EmailField(required=True, label="E-post")
|
email = forms.EmailField(required=True, label="E-post")
|
||||||
facebook_username = forms.CharField(required=False, label="Facebook-brukernavn")
|
facebook_username = forms.CharField(required=False, label="Facebook-brukernavn")
|
||||||
|
|
||||||
def _get_facebook_url(self, facebook_username):
|
def _get_facebook_url(self):
|
||||||
if facebook_username == "":
|
if self.cleaned_data['facebook_username'] == "":
|
||||||
return ""
|
return ""
|
||||||
return "https://graph.facebook.com/{0}/picture".format(facebook_username)
|
return "https://graph.facebook.com/{0}/picture".format(self.cleaned_data['facebook_username'])
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
username = utils.format_username(self.cleaned_data['first_name'], self.cleaned_data['last_name'])
|
username = utils.format_username(self.cleaned_data['first_name'], self.cleaned_data['last_name'])
|
||||||
@@ -50,7 +61,7 @@ class SimpleCreateUserForm(forms.Form):
|
|||||||
user.last_name = self.cleaned_data['last_name']
|
user.last_name = self.cleaned_data['last_name']
|
||||||
|
|
||||||
profile = user.get_profile()
|
profile = user.get_profile()
|
||||||
profile.image = self._get_facebook_url(self.cleaned_data['facebook_username'])
|
profile.image = self._get_facebook_url()
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
user.save()
|
user.save()
|
||||||
@@ -64,7 +75,7 @@ class InventoryTransactionForm(forms.ModelForm):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# Only show active products
|
# Only show active products
|
||||||
super (InventoryTransactionForm, self).__init__(*args,**kwargs)
|
super(InventoryTransactionForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['product'].queryset = Product.objects.filter(active=True)
|
self.fields['product'].queryset = Product.objects.filter(active=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -75,4 +86,3 @@ class InventoryTransactionForm(forms.ModelForm):
|
|||||||
class DateRangeForm(forms.Form):
|
class DateRangeForm(forms.Form):
|
||||||
start_time = forms.DateTimeField(required=False, label=_("Fra"))
|
start_time = forms.DateTimeField(required=False, label=_("Fra"))
|
||||||
end_time = forms.DateTimeField(required=False, label=_("Til"))
|
end_time = forms.DateTimeField(required=False, label=_("Til"))
|
||||||
|
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from south.utils import datetime_utils as datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import SchemaMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(SchemaMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
|
||||||
|
# Changing field 'Order.customer'
|
||||||
|
db.alter_column(u'main_order', 'customer_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True))
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
|
||||||
|
# User chose to not deal with backwards NULL issues for 'Order.customer'
|
||||||
|
raise RuntimeError("Cannot reverse this migration. 'Order.customer' and its values cannot be restored.")
|
||||||
|
|
||||||
|
# The following code is provided here to aid in writing a correct migration
|
||||||
|
# Changing field 'Order.customer'
|
||||||
|
db.alter_column(u'main_order', 'customer_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User']))
|
||||||
|
|
||||||
|
models = {
|
||||||
|
u'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
u'auth.permission': {
|
||||||
|
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
u'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
u'contenttypes.contenttype': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
u'main.inventorytransaction': {
|
||||||
|
'Meta': {'object_name': 'InventoryTransaction'},
|
||||||
|
'amount': ('django.db.models.fields.FloatField', [], {}),
|
||||||
|
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transactions'", 'to': u"orm['main.Product']"}),
|
||||||
|
'unit_price': ('django.db.models.fields.FloatField', [], {}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
|
||||||
|
},
|
||||||
|
u'main.order': {
|
||||||
|
'Meta': {'object_name': 'Order'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'customer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'order_sum': ('django.db.models.fields.FloatField', [], {'db_column': "'sum'"})
|
||||||
|
},
|
||||||
|
u'main.orderline': {
|
||||||
|
'Meta': {'unique_together': "(('order', 'product'),)", 'object_name': 'OrderLine'},
|
||||||
|
'amount': ('django.db.models.fields.IntegerField', [], {}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['main.Order']"}),
|
||||||
|
'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'orderlines'", 'to': u"orm['main.Product']"}),
|
||||||
|
'unit_price': ('django.db.models.fields.FloatField', [], {})
|
||||||
|
},
|
||||||
|
u'main.product': {
|
||||||
|
'Meta': {'ordering': "['name']", 'object_name': 'Product'},
|
||||||
|
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'alcohol_percent': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'customer_support': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'inventory_amount': ('django.db.models.fields.FloatField', [], {'default': '0'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'sale_price_ext': ('django.db.models.fields.FloatField', [], {}),
|
||||||
|
'sale_price_int': ('django.db.models.fields.FloatField', [], {}),
|
||||||
|
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'volume_liter': ('django.db.models.fields.FloatField', [], {'null': 'True'})
|
||||||
|
},
|
||||||
|
u'main.transaction': {
|
||||||
|
'Meta': {'object_name': 'Transaction'},
|
||||||
|
'amount': ('django.db.models.fields.FloatField', [], {}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
|
||||||
|
},
|
||||||
|
u'main.userprofile': {
|
||||||
|
'Meta': {'object_name': 'UserProfile'},
|
||||||
|
'balance': ('django.db.models.fields.FloatField', [], {'default': '0.0'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['main']
|
||||||
+24
-4
@@ -25,20 +25,40 @@ class Product(models.Model):
|
|||||||
updated = models.DateTimeField(auto_now=True)
|
updated = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def inventory_value(self):
|
def wholesale_unit_price(self):
|
||||||
return self.inventory_amount * self.sale_price_int
|
"""
|
||||||
|
This is not accurate.
|
||||||
|
"""
|
||||||
|
if self.inventory_amount <= 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
unit_prices = self.transactions.order_by('created').values('amount', 'unit_price')
|
||||||
|
sum_units = 0
|
||||||
|
for up in unit_prices:
|
||||||
|
sum_units += up['amount']
|
||||||
|
if self.inventory_amount <= sum_units:
|
||||||
|
return up['unit_price']
|
||||||
|
|
||||||
|
return unit_prices[0]['unit_price']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wholesale_value(self):
|
||||||
|
return self.wholesale_unit_price * self.inventory_amount
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
|
|
||||||
|
|
||||||
class Order(models.Model):
|
class Order(models.Model):
|
||||||
customer = models.ForeignKey(User)
|
customer = models.ForeignKey(User, null=True, blank=True)
|
||||||
order_sum = models.FloatField(db_column='sum')
|
order_sum = models.FloatField(db_column='sum')
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
def is_external(self):
|
||||||
|
return self.customer is None
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"{0}: {1} kr".format(self.customer, self.order_sum)
|
return u"{0}: {1} kr".format(self.customer or u"Ekstern", self.order_sum)
|
||||||
|
|
||||||
|
|
||||||
class OrderLine(models.Model):
|
class OrderLine(models.Model):
|
||||||
|
|||||||
+50
-23
@@ -51,45 +51,64 @@ def register(request):
|
|||||||
formset = OrderLineFormSet(request.POST)
|
formset = OrderLineFormSet(request.POST)
|
||||||
|
|
||||||
if formset.is_valid() and orderform.is_valid():
|
if formset.is_valid() and orderform.is_valid():
|
||||||
order_sum = sum([ol['amount'] * ol['unit_price'] for ol in formset.cleaned_data])
|
|
||||||
order = orderform.save(commit=False)
|
order = orderform.save(commit=False)
|
||||||
# can he afford it?
|
|
||||||
profile = order.customer.get_profile()
|
if order.is_external():
|
||||||
if order_sum > profile.balance:
|
order_sum = sum([ol['amount'] * ol['unit_price_ext'] for ol in formset.cleaned_data])
|
||||||
messages.error(request, u'{0} {1} har ikke råd, mangler {2} kr.'.format(
|
else:
|
||||||
order.customer.first_name,
|
order_sum = sum([ol['amount'] * ol['unit_price_int'] for ol in formset.cleaned_data])
|
||||||
order.customer.last_name,
|
|
||||||
int(order_sum - profile.balance)))
|
|
||||||
return HttpResponseRedirect(reverse('main.views.register'))
|
|
||||||
# empty order?
|
# empty order?
|
||||||
if order_sum == 0:
|
if order_sum == 0:
|
||||||
messages.error(request, u'Du har ikke valgt hva du skal kjøpe...')
|
messages.error(request, u'Du har ikke valgt hva du skal kjøpe...')
|
||||||
return HttpResponseRedirect(reverse('main.views.register'))
|
return HttpResponseRedirect(reverse('main.views.register'))
|
||||||
|
|
||||||
|
if not order.is_external():
|
||||||
|
profile = order.customer.get_profile()
|
||||||
|
# can she afford it?
|
||||||
|
if order_sum > profile.balance:
|
||||||
|
messages.error(request, u'{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('main.views.register'))
|
||||||
|
# substract order from balance
|
||||||
|
profile.balance -= order.order_sum
|
||||||
|
profile.save()
|
||||||
|
|
||||||
order.order_sum = order_sum
|
order.order_sum = order_sum
|
||||||
order.save()
|
order.save()
|
||||||
# substract order from balance
|
|
||||||
profile.balance -= order.order_sum
|
|
||||||
profile.save()
|
|
||||||
|
|
||||||
orderlines = []
|
orderlines = []
|
||||||
for ol in formset.cleaned_data:
|
for ol in formset.cleaned_data:
|
||||||
if ol['amount'] > 0:
|
if ol['amount'] > 0:
|
||||||
product = Product.objects.get(pk=ol['product'])
|
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(
|
OrderLine.objects.create(
|
||||||
order=order,
|
order=order,
|
||||||
product=product,
|
product=product,
|
||||||
amount=ol['amount'],
|
amount=ol['amount'],
|
||||||
unit_price=ol['unit_price'])
|
unit_price=unit_price)
|
||||||
|
|
||||||
product.inventory_amount -= ol['amount']
|
product.inventory_amount -= ol['amount']
|
||||||
product.save()
|
product.save()
|
||||||
|
|
||||||
orderlines.append(u"{0} {1}".format(ol['amount'], product))
|
orderlines.append(u"{0} {1}".format(ol['amount'], product))
|
||||||
|
|
||||||
messages.success(request, u'{0} {1} kjøpte {2}.'.format(
|
if order.is_external():
|
||||||
order.customer.first_name,
|
messages.success(request, u'Ekstern kjøpte {0}.'.format(u", ".join(orderlines)))
|
||||||
order.customer.last_name,
|
else:
|
||||||
u", ".join(orderlines)
|
messages.success(request, u'{0} {1} kjøpte {2}.'.format(
|
||||||
))
|
order.customer.first_name,
|
||||||
|
order.customer.last_name,
|
||||||
|
u", ".join(orderlines)
|
||||||
|
))
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse('main.views.register'))
|
return HttpResponseRedirect(reverse('main.views.register'))
|
||||||
else:
|
else:
|
||||||
# TODO specify error(s)
|
# TODO specify error(s)
|
||||||
@@ -216,7 +235,10 @@ def stats_product(product):
|
|||||||
.reverse()
|
.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']
|
if row['order__customer__first_name'] is not None:
|
||||||
|
who = row['order__customer__first_name'] + " " + row['order__customer__last_name']
|
||||||
|
else:
|
||||||
|
who = u"Ekstern"
|
||||||
num = row['num']
|
num = row['num']
|
||||||
f_per_user.append([who, num])
|
f_per_user.append([who, num])
|
||||||
response = {
|
response = {
|
||||||
@@ -249,14 +271,19 @@ def stats_products(request, product=None):
|
|||||||
|
|
||||||
|
|
||||||
def stats_orders(request):
|
def stats_orders(request):
|
||||||
|
num_external_orders = Order.objects.filter(customer=None).count()
|
||||||
per_user = Order.objects\
|
per_user = Order.objects\
|
||||||
.values('customer__first_name', 'customer__last_name')\
|
.values('customer__first_name', 'customer__last_name')\
|
||||||
.annotate(num=Count('customer'))\
|
.annotate(num=Count('customer'))\
|
||||||
.order_by('num').reverse()
|
.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']
|
if row['customer__first_name'] is not None:
|
||||||
num = row['num']
|
who = row['customer__first_name'] + " " + row['customer__last_name']
|
||||||
|
num = row['num']
|
||||||
|
else:
|
||||||
|
who = u"Ekstern"
|
||||||
|
num = num_external_orders
|
||||||
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')
|
return HttpResponse(json.dumps(f_per_user), content_type='application/javascript; charset=utf8')
|
||||||
|
|
||||||
@@ -338,7 +365,7 @@ def inventory(request):
|
|||||||
products = Product.objects.all().order_by('-active', 'inventory_amount', 'name')
|
products = Product.objects.all().order_by('-active', 'inventory_amount', 'name')
|
||||||
transactions = InventoryTransaction.objects.all().order_by('-created')
|
transactions = InventoryTransaction.objects.all().order_by('-created')
|
||||||
products_active = products.filter(active=True)
|
products_active = products.filter(active=True)
|
||||||
inventory_value = sum(map(lambda x: x[0] * x[1], products_active.values_list('inventory_amount', 'sale_price_int')))
|
wholesale_value = sum([p.wholesale_value for p in products_active])
|
||||||
num_products = sum(products_active.values_list('inventory_amount', flat=True))
|
num_products = sum(products_active.values_list('inventory_amount', flat=True))
|
||||||
|
|
||||||
return render(request, 'inventory.html', locals())
|
return render(request, 'inventory.html', locals())
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Vare</th>
|
<th>Vare</th>
|
||||||
<th>Beholdning</th>
|
<th>Beholdning</th>
|
||||||
<th>Pris (intern)</th>
|
<th>Innkjøpspris</th>
|
||||||
<th>Salgsverdi (intern)</th>
|
<th>Verdi</th>
|
||||||
<th>I salg</th>
|
<th>I salg</th>
|
||||||
<th>Sist oppdatert</th>
|
<th>Sist oppdatert</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -31,19 +31,18 @@
|
|||||||
<tr class="{% if not product.active %}info inactive{% elif product.inventory_amount <= 0 %}warning{% else %}success{% endif %}">
|
<tr class="{% if not product.active %}info inactive{% elif product.inventory_amount <= 0 %}warning{% else %}success{% endif %}">
|
||||||
<td>{{ product.name }}</td>
|
<td>{{ product.name }}</td>
|
||||||
<td class="product-amount">{{ product.inventory_amount }}</td>
|
<td class="product-amount">{{ product.inventory_amount }}</td>
|
||||||
<td>{{ product.sale_price_int }}</td>
|
<td>{{ product.wholesale_unit_price|default:"-" }}</td>
|
||||||
<td>{{ product.inventory_value }}</td>
|
<td>{{ product.wholesale_value|default:"-" }}</td>
|
||||||
<td class="product-active">{% if product.active %}<i class="glyphicon glyphicon-ok"></i>{% endif %}</td>
|
<td class="product-active">{% if product.active %}<i class="glyphicon glyphicon-ok"></i>{% endif %}</td>
|
||||||
<td>{{ product.updated }}</td>
|
<td>{{ product.updated }}</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><em>Sum</em></td>
|
|
||||||
<td> {{ num_products }}</td>
|
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><b>{{ inventory_value }}</b></td>
|
<td>{{ num_products }} totalt</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
<td>{{ wholesale_value }}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@
|
|||||||
{% for order in orders %}
|
{% for order in orders %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ order.created }}</td>
|
<td>{{ order.created }}</td>
|
||||||
<td>{% if order.customer.get_profile.image %}<img src="{{ order.customer.get_profile.image }}" class="customer" title="{{ order.customer.first_name }} {{ order.customer.last_name|slice:":1"}}" />{% else %}{{ order.customer.first_name }} {{ order.customer.last_name|slice:":1"}}{% endif %}</td>
|
<td>{% if order.customer %}{% if order.customer.get_profile.image %}<img src="{{ order.customer.get_profile.image }}" class="customer" title="{{ order.customer.first_name }} {{ order.customer.last_name|slice:":1"}}" />{% else %}{{ order.customer.first_name }} {{ order.customer.last_name|slice:":1"}}{% endif %}{% else %}Ekstern{% endif %}</td>
|
||||||
<td>{% for line in order.orderline_set.all %}
|
<td>{% for line in order.orderline_set.all %}
|
||||||
<span class="amount">{{ line.amount}}</span> <a href="#" class="product" title="{{ line.unit_price}} per">{{ line.product }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
|
<span class="amount">{{ line.amount}}</span> <a href="#" class="product" title="{{ line.unit_price}} per">{{ line.product }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
|
||||||
<td>{{ order.order_sum }}</td>
|
<td>{{ order.order_sum }}</td>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<section class="row">
|
<section class="row">
|
||||||
<div class="col-xs-4">
|
<div class="col-xs-4">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
<div {% if message.tags %}class="alert alert-{{ message.tags }}"{% endif %}>{{ message }}<a class="close" data-dismiss="alert">×</a></div>
|
<div{% if message.tags %} class="alert alert-{{ message.tags }}"{% endif %}>{{ message }}<a class="close" data-dismiss="alert">×</a></div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -41,6 +41,11 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<ul class="well">
|
<ul class="well">
|
||||||
|
<li class="customer">{% spaceless %}
|
||||||
|
<img class="profile" src="{{ STATIC_URL }}img/unknown_person.png" alt="Profile picture" /><br />
|
||||||
|
<span class="name">Ekstern</span><br />
|
||||||
|
<span class="balance"> </span>
|
||||||
|
{% endspaceless %}</li>
|
||||||
{% for user in users %}<li class="customer{% if user.get_profile.last_purchase_date < half_a_year_ago and not user.get_profile.last_purchase == None %} infrequent hidden{% endif %}">{% spaceless %}
|
{% for user in users %}<li class="customer{% if user.get_profile.last_purchase_date < half_a_year_ago and not user.get_profile.last_purchase == None %} infrequent hidden{% endif %}">{% spaceless %}
|
||||||
{% if user.get_profile.image %}
|
{% if user.get_profile.image %}
|
||||||
<img class="profile" src="{{ user.get_profile.image }}" alt="Profile picture" /><br />
|
<img class="profile" src="{{ user.get_profile.image }}" alt="Profile picture" /><br />
|
||||||
@@ -74,14 +79,15 @@
|
|||||||
{% for product in products %}
|
{% for product in products %}
|
||||||
<li id="form-{{forloop.counter0}}" class="product"><input type="hidden" name="form-{{ forloop.counter0 }}-product" value="{{product.id }}" />
|
<li id="form-{{forloop.counter0}}" class="product"><input type="hidden" name="form-{{ forloop.counter0 }}-product" value="{{product.id }}" />
|
||||||
<input type="hidden" id="form-{{ forloop.counter0 }}-amount" name="form-{{ forloop.counter0 }}-amount" value="0" class="span2" size="2" />
|
<input type="hidden" id="form-{{ forloop.counter0 }}-amount" name="form-{{ forloop.counter0 }}-amount" value="0" class="span2" size="2" />
|
||||||
<input type="hidden" name="form-{{ forloop.counter0 }}-unit_price" value="{{product.sale_price_int }}" />
|
<input type="hidden" name="form-{{ forloop.counter0 }}-unit_price_int" value="{{product.sale_price_int }}" />
|
||||||
|
<input type="hidden" name="form-{{ forloop.counter0 }}-unit_price_ext" value="{{product.sale_price_ext }}" />
|
||||||
<span class="qty">0</span>
|
<span class="qty">0</span>
|
||||||
{% if product.image %}
|
{% if product.image %}
|
||||||
<img class="product" src="{{ product.image.url }}" /><br />
|
<img class="product" src="{{ product.image.url }}" /><br />
|
||||||
{% else %}
|
{% else %}
|
||||||
<img class="product" src="{{ STATIC_URL }}img/product.png" /><br />
|
<img class="product" src="{{ STATIC_URL }}img/product.png" /><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="name">{{ product.name }}</span> - <span class="sale_price_int">{{product.sale_price_int|floatformat:0}}</span>
|
<span class="name">{{ product.name }}</span> - <span class="sale_price_ext">{{product.sale_price_ext|floatformat:0}}</span>/<span class="sale_price_int">{{product.sale_price_int|floatformat:0}}</span>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in new issue
Block a user