Upgrade to django 1.8, ++
This commit is contained in:
1 parent
8c004276a7
commit
b47ee8f832
22 files changed
+767
-1051
No files matched your search
+26
-22
@@ -4,7 +4,6 @@ import os
|
|||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
TEMPLATE_DEBUG = DEBUG
|
|
||||||
|
|
||||||
ADMINS = (
|
ADMINS = (
|
||||||
# ('Your Name', 'your_email@example.com'),
|
# ('Your Name', 'your_email@example.com'),
|
||||||
@@ -14,12 +13,8 @@ MANAGERS = ADMINS
|
|||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': 'db.sqlite3', # Or path to database file if using sqlite3.
|
'NAME': 'db.sqlite3',
|
||||||
'USER': '', # Not used with sqlite3.
|
|
||||||
'PASSWORD': '', # Not used with sqlite3.
|
|
||||||
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
|
|
||||||
'PORT': '', # Set to empty string for default. Not used with sqlite3.
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +85,26 @@ STATICFILES_FINDERS = (
|
|||||||
# Make this unique, and don't share it with anybody.
|
# Make this unique, and don't share it with anybody.
|
||||||
SECRET_KEY = 'osv$uy-ea$*%lc)+xiwt5@2b7au%u*c!pa6hmh#vl)*+tp%fss'
|
SECRET_KEY = 'osv$uy-ea$*%lc)+xiwt5@2b7au%u*c!pa6hmh#vl)*+tp%fss'
|
||||||
|
|
||||||
# List of callables that know how to import templates from various sources.
|
TEMPLATES = [
|
||||||
TEMPLATE_LOADERS = (
|
{
|
||||||
'django.template.loaders.filesystem.Loader',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'django.template.loaders.app_directories.Loader',
|
'DIRS': [
|
||||||
# 'django.template.loaders.eggs.Loader',
|
os.path.join(BASE_DIR, 'templates'),
|
||||||
)
|
],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.i18n',
|
||||||
|
'django.template.context_processors.media',
|
||||||
|
'django.template.context_processors.static',
|
||||||
|
'django.template.context_processors.tz',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE_CLASSES = (
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@@ -107,13 +116,6 @@ MIDDLEWARE_CLASSES = (
|
|||||||
|
|
||||||
ROOT_URLCONF = 'bbssite.urls'
|
ROOT_URLCONF = 'bbssite.urls'
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
|
||||||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
|
||||||
# Always use forward slashes, even on Windows.
|
|
||||||
# Don't forget to use absolute paths, not relative paths.
|
|
||||||
os.path.join(BASE_DIR, 'templates'),
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
@@ -122,13 +124,15 @@ INSTALLED_APPS = (
|
|||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'main',
|
|
||||||
'widget_tweaks',
|
'widget_tweaks',
|
||||||
'south',
|
|
||||||
'bootstrapform',
|
'bootstrapform',
|
||||||
'compressor',
|
'compressor',
|
||||||
'django_extensions',
|
'django_extensions',
|
||||||
)
|
)
|
||||||
|
LOCAL_APPS = (
|
||||||
|
'main',
|
||||||
|
)
|
||||||
|
INSTALLED_APPS += LOCAL_APPS
|
||||||
|
|
||||||
# A sample logging configuration. The only tangible logging
|
# A sample logging configuration. The only tangible logging
|
||||||
# performed by this configuration is to send an email to
|
# performed by this configuration is to send an email to
|
||||||
|
|||||||
+15
-7
@@ -1,17 +1,25 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import patterns, include, url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||||
|
|
||||||
|
from main import urls as main_urls
|
||||||
|
|
||||||
|
|
||||||
admin.autodiscover()
|
admin.autodiscover()
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = [
|
||||||
url(r'^$', 'main.views.register', name='home'),
|
url(r'', include(main_urls)),
|
||||||
url(r'', include('main.urls')),
|
|
||||||
url(r'^accounts/login/$', 'django.contrib.auth.views.login', name='login'),
|
url(r'^accounts/login/$', 'django.contrib.auth.views.login', name='login'),
|
||||||
url(r'^logout/$', 'main.views.logout', name='logout'),
|
url(r'^accounts/logout/$', 'main.views.users.logout', name='logout'),
|
||||||
|
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
)
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
|
||||||
urlpatterns += staticfiles_urlpatterns()
|
urlpatterns += staticfiles_urlpatterns()
|
||||||
|
urlpatterns += [
|
||||||
|
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
|
||||||
|
'document_root': settings.MEDIA_ROOT,
|
||||||
|
})
|
||||||
|
]
|
||||||
+11
-9
@@ -1,18 +1,19 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
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 main.models import Order, Transaction, InventoryTransaction, Product
|
||||||
|
from main.utils import format_username
|
||||||
import utils
|
|
||||||
|
|
||||||
|
|
||||||
class OrderForm(forms.ModelForm):
|
class OrderForm(forms.ModelForm):
|
||||||
customer_name = forms.CharField(required=False)
|
customer_name = forms.CharField(required=False)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.cleaned_data['customer'] is None and self.cleaned_data['customer_name'] != u"Ekstern":
|
if self.cleaned_data['customer'] is None and self.cleaned_data['customer_name'] != "Ekstern":
|
||||||
raise forms.ValidationError(_(u"Du har ikke valgt hvem som skal kjøpe."))
|
raise forms.ValidationError(_("Du har ikke valgt hvem som skal kjøpe."))
|
||||||
|
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
@@ -20,8 +21,8 @@ class OrderForm(forms.ModelForm):
|
|||||||
if self.cleaned_data['customer'] is None:
|
if self.cleaned_data['customer'] is None:
|
||||||
return self.cleaned_data['customer']
|
return self.cleaned_data['customer']
|
||||||
|
|
||||||
if self.cleaned_data['customer'].get_profile().balance <= 0:
|
if self.cleaned_data['customer'].profile.balance <= 0:
|
||||||
raise forms.ValidationError(_(u"Du har negativ saldo og kan ikke kjøpe noe."))
|
raise forms.ValidationError(_("Du har negativ saldo og kan ikke kjøpe noe."))
|
||||||
|
|
||||||
return self.cleaned_data['customer']
|
return self.cleaned_data['customer']
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ class DepositForm(forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Transaction
|
model = Transaction
|
||||||
|
fields = ['user', 'amount']
|
||||||
|
|
||||||
|
|
||||||
class SimpleCreateUserForm(forms.Form):
|
class SimpleCreateUserForm(forms.Form):
|
||||||
@@ -55,12 +57,12 @@ class SimpleCreateUserForm(forms.Form):
|
|||||||
return "https://graph.facebook.com/{0}/picture".format(self.cleaned_data['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 = format_username(self.cleaned_data['first_name'], self.cleaned_data['last_name'])
|
||||||
user = User.objects.create_user(username, email=self.cleaned_data['email'])
|
user = User.objects.create_user(username, email=self.cleaned_data['email'])
|
||||||
user.first_name = self.cleaned_data['first_name']
|
user.first_name = self.cleaned_data['first_name']
|
||||||
user.last_name = self.cleaned_data['last_name']
|
user.last_name = self.cleaned_data['last_name']
|
||||||
|
|
||||||
profile = user.get_profile()
|
profile = user.profile
|
||||||
profile.image = self._get_facebook_url()
|
profile.image = self._get_facebook_url()
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
|
|||||||
+96
-167
@@ -1,172 +1,101 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from south.utils import datetime_utils as datetime
|
from __future__ import unicode_literals
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
from django.db import migrations, models
|
||||||
from django.db import models
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
def forwards(self, orm):
|
dependencies = [
|
||||||
# Adding model 'Product'
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
db.create_table('main_product', (
|
]
|
||||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
|
||||||
('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
|
|
||||||
('sale_price_int', self.gf('django.db.models.fields.FloatField')()),
|
|
||||||
('sale_price_ext', self.gf('django.db.models.fields.FloatField')()),
|
|
||||||
('description', self.gf('django.db.models.fields.CharField')(max_length=256, blank=True)),
|
|
||||||
('volume_liter', self.gf('django.db.models.fields.FloatField')(null=True)),
|
|
||||||
('alcohol_percent', self.gf('django.db.models.fields.FloatField')(null=True)),
|
|
||||||
('image', self.gf('django.db.models.fields.files.ImageField')(max_length=100, blank=True)),
|
|
||||||
('customer_support', self.gf('django.db.models.fields.CharField')(max_length=32, blank=True)),
|
|
||||||
('active', self.gf('django.db.models.fields.BooleanField')(default=True)),
|
|
||||||
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
|
||||||
('updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
|
|
||||||
))
|
|
||||||
db.send_create_signal('main', ['Product'])
|
|
||||||
|
|
||||||
# Adding model 'Order'
|
operations = [
|
||||||
db.create_table('main_order', (
|
migrations.CreateModel(
|
||||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
name='InventoryTransaction',
|
||||||
('customer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
|
fields=[
|
||||||
('order_sum', self.gf('django.db.models.fields.FloatField')(db_column='sum')),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
('amount', models.FloatField(verbose_name='Antall')),
|
||||||
))
|
('unit_price', models.FloatField(verbose_name='Enhetspris')),
|
||||||
db.send_create_signal('main', ['Order'])
|
('comment', models.TextField(verbose_name='Kommentar', blank=True)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
# Adding model 'OrderLine'
|
],
|
||||||
db.create_table('main_orderline', (
|
),
|
||||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
migrations.CreateModel(
|
||||||
('order', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['main.Order'])),
|
name='Order',
|
||||||
('product', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['main.Product'])),
|
fields=[
|
||||||
('amount', self.gf('django.db.models.fields.IntegerField')()),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('unit_price', self.gf('django.db.models.fields.FloatField')()),
|
('order_sum', models.FloatField(db_column=b'sum')),
|
||||||
))
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
db.send_create_signal('main', ['OrderLine'])
|
('customer', models.ForeignKey(related_name='orders', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
|
||||||
|
],
|
||||||
# Adding unique constraint on 'OrderLine', fields ['order', 'product']
|
),
|
||||||
db.create_unique('main_orderline', ['order_id', 'product_id'])
|
migrations.CreateModel(
|
||||||
|
name='OrderLine',
|
||||||
# Adding model 'Transaction'
|
fields=[
|
||||||
db.create_table('main_transaction', (
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
('amount', models.IntegerField()),
|
||||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
|
('unit_price', models.FloatField(verbose_name='Enhetspris')),
|
||||||
('amount', self.gf('django.db.models.fields.FloatField')()),
|
('order', models.ForeignKey(related_name='orderlines', to='main.Order')),
|
||||||
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
],
|
||||||
))
|
),
|
||||||
db.send_create_signal('main', ['Transaction'])
|
migrations.CreateModel(
|
||||||
|
name='Product',
|
||||||
# Adding model 'UserProfile'
|
fields=[
|
||||||
db.create_table('main_userprofile', (
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
('name', models.CharField(max_length=64)),
|
||||||
('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)),
|
('sale_price_int', models.FloatField()),
|
||||||
('balance', self.gf('django.db.models.fields.FloatField')(default=0.0)),
|
('sale_price_ext', models.FloatField()),
|
||||||
('image', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
|
('description', models.CharField(max_length=256, blank=True)),
|
||||||
))
|
('volume_liter', models.FloatField(null=True)),
|
||||||
db.send_create_signal('main', ['UserProfile'])
|
('alcohol_percent', models.FloatField(null=True)),
|
||||||
|
('image', models.ImageField(upload_to=b'products', blank=True)),
|
||||||
|
('customer_support', models.CharField(max_length=32, blank=True)),
|
||||||
def backwards(self, orm):
|
('inventory_amount', models.FloatField(default=0)),
|
||||||
# Removing unique constraint on 'OrderLine', fields ['order', 'product']
|
('active', models.BooleanField(default=True)),
|
||||||
db.delete_unique('main_orderline', ['order_id', 'product_id'])
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated', models.DateTimeField(auto_now=True)),
|
||||||
# Deleting model 'Product'
|
],
|
||||||
db.delete_table('main_product')
|
options={
|
||||||
|
'ordering': ['name'],
|
||||||
# Deleting model 'Order'
|
},
|
||||||
db.delete_table('main_order')
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
# Deleting model 'OrderLine'
|
name='Transaction',
|
||||||
db.delete_table('main_orderline')
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
# Deleting model 'Transaction'
|
('amount', models.FloatField()),
|
||||||
db.delete_table('main_transaction')
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('user', models.ForeignKey(related_name='transactions', to=settings.AUTH_USER_MODEL)),
|
||||||
# Deleting model 'UserProfile'
|
],
|
||||||
db.delete_table('main_userprofile')
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserProfile',
|
||||||
models = {
|
fields=[
|
||||||
'auth.group': {
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
'Meta': {'object_name': 'Group'},
|
('balance', models.FloatField(default=0.0)),
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
('image', models.URLField(blank=True)),
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
('user', models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL)),
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
],
|
||||||
},
|
),
|
||||||
'auth.permission': {
|
migrations.AddField(
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
model_name='orderline',
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
name='product',
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
field=models.ForeignKey(related_name='orderlines', to='main.Product'),
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
),
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
migrations.AddField(
|
||||||
},
|
model_name='inventorytransaction',
|
||||||
'auth.user': {
|
name='product',
|
||||||
'Meta': {'object_name': 'User'},
|
field=models.ForeignKey(related_name='transactions', verbose_name='Produkt', to='main.Product'),
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
),
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
migrations.AddField(
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
model_name='inventorytransaction',
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
name='user',
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
field=models.ForeignKey(related_name='inventory_transactions', to=settings.AUTH_USER_MODEL),
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
),
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
migrations.AlterUniqueTogether(
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
name='orderline',
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
unique_together=set([('order', 'product')]),
|
||||||
'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', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'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'}),
|
|
||||||
'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'})
|
|
||||||
},
|
|
||||||
'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': "orm['auth.User']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'order_sum': ('django.db.models.fields.FloatField', [], {'db_column': "'sum'"})
|
|
||||||
},
|
|
||||||
'main.orderline': {
|
|
||||||
'Meta': {'unique_together': "(('order', 'product'),)", 'object_name': 'OrderLine'},
|
|
||||||
'amount': ('django.db.models.fields.IntegerField', [], {}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'order': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Order']"}),
|
|
||||||
'product': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Product']"}),
|
|
||||||
'unit_price': ('django.db.models.fields.FloatField', [], {})
|
|
||||||
},
|
|
||||||
'main.product': {
|
|
||||||
'Meta': {'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'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
|
|
||||||
'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'})
|
|
||||||
},
|
|
||||||
'main.transaction': {
|
|
||||||
'Meta': {'object_name': 'Transaction'},
|
|
||||||
'amount': ('django.db.models.fields.FloatField', [], {}),
|
|
||||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
|
||||||
},
|
|
||||||
'main.userprofile': {
|
|
||||||
'Meta': {'object_name': 'UserProfile'},
|
|
||||||
'balance': ('django.db.models.fields.FloatField', [], {'default': '0.0'}),
|
|
||||||
'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': "orm['auth.User']", 'unique': 'True'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['main']
|
|
||||||
-131
@@ -1,131 +0,0 @@
|
|||||||
# -*- 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):
|
|
||||||
# Adding model 'InventoryTransaction'
|
|
||||||
db.create_table(u'main_inventorytransaction', (
|
|
||||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
|
||||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
|
|
||||||
('product', self.gf('django.db.models.fields.related.ForeignKey')(related_name='transactions', to=orm['main.Product'])),
|
|
||||||
('amount', self.gf('django.db.models.fields.FloatField')()),
|
|
||||||
('unit_price', self.gf('django.db.models.fields.FloatField')()),
|
|
||||||
('comment', self.gf('django.db.models.fields.TextField')(blank=True)),
|
|
||||||
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
|
||||||
))
|
|
||||||
db.send_create_signal(u'main', ['InventoryTransaction'])
|
|
||||||
|
|
||||||
# Adding field 'Product.inventory_amount'
|
|
||||||
db.add_column(u'main_product', 'inventory_amount',
|
|
||||||
self.gf('django.db.models.fields.FloatField')(default=0),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting model 'InventoryTransaction'
|
|
||||||
db.delete_table(u'main_inventorytransaction')
|
|
||||||
|
|
||||||
# Deleting field 'Product.inventory_amount'
|
|
||||||
db.delete_column(u'main_product', 'inventory_amount')
|
|
||||||
|
|
||||||
|
|
||||||
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']"}),
|
|
||||||
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']
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
# -*- 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']
|
|
||||||
+1
-1
@@ -117,7 +117,7 @@ class InventoryTransaction(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class UserProfile(models.Model):
|
class UserProfile(models.Model):
|
||||||
user = models.OneToOneField(User)
|
user = models.OneToOneField(User, related_name='profile')
|
||||||
balance = models.FloatField(default=0.0)
|
balance = models.FloatField(default=0.0)
|
||||||
#image = models.ImageField(upload_to='users', blank=True)
|
#image = models.ImageField(upload_to='users', blank=True)
|
||||||
image = models.URLField(blank=True)
|
image = models.URLField(blank=True)
|
||||||
|
|||||||
+31
-22
@@ -1,24 +1,33 @@
|
|||||||
from django.conf.urls import patterns, include, url
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from main.views.stats import stats_list, stats_orders, stats_orders_hourly, stats_products_realtime, stats_products, \
|
||||||
|
stats_products_per_user, products_json
|
||||||
|
from main.views.general import register, deposit, log
|
||||||
|
from main.views.reports import inventory, inventory_add, report
|
||||||
|
from main.views.users import create_user, profile
|
||||||
|
|
||||||
urlpatterns = patterns('main.views',
|
urlpatterns = [
|
||||||
url(r'^register/$', 'register', name='register'),
|
url(r'^$', register, name='home'),
|
||||||
url(r'^deposit/$', 'deposit', name='deposit'),
|
url(r'^register/$', register, name='register'),
|
||||||
url(r'^log/$', 'log', name='log'),
|
url(r'^deposit/$', deposit, name='deposit'),
|
||||||
url(r'^log/all$', 'log', kwargs={'limit': None}, name='log-all'),
|
url(r'^log/$', log, name='log'),
|
||||||
url(r'^stats/$', 'stats', name='stats'),
|
url(r'^log/all$', log, kwargs={'limit': None}, name='log-all'),
|
||||||
url(r'^stats/orders/$', 'stats_orders', name='stats-orders'),
|
# Stats
|
||||||
url(r'^stats/orders/hourly$', 'stats_orders_hourly', name='stats-orders-hourly'),
|
url(r'^stats/$', stats_list, name='stats'),
|
||||||
url(r'^stats/orders/products_realtime$', 'stats_products_realtime', name='stats-products-realtime'),
|
url(r'^stats/orders/$', stats_orders, name='stats-orders'),
|
||||||
url(r'^stats/products/$', 'stats_products', name='stats-products'),
|
url(r'^stats/orders/hourly$', stats_orders_hourly, name='stats-orders-hourly'),
|
||||||
url(r'^stats/products/(?P<product>[0-9]+)/$', 'stats_products', name='stats-product'),
|
url(r'^stats/orders/products_realtime$', stats_products_realtime, name='stats-products-realtime'),
|
||||||
url(r'^stats/products/by_user/(?P<user_id>[0-9]+)/$', 'stats_products_per_user', name='stats-products-per-user'),
|
url(r'^stats/products/$', stats_products, name='stats-products'),
|
||||||
url(r'^products/(?P<product_id>[0-9]+)/$', 'products_json', name='json-product'),
|
url(r'^stats/products/(?P<product>[0-9]+)/$', stats_products, name='stats-product'),
|
||||||
url(r'^products/$', 'products_json', name='json-products'),
|
url(r'^stats/products/by_user/(?P<user_id>[0-9]+)/$', stats_products_per_user, name='stats-products-per-user'),
|
||||||
url(r'^user/create/$', 'create_user', name='create-user'),
|
# Products
|
||||||
url(r'^profile/$', 'profile', name='profile'),
|
url(r'^products/(?P<product_id>[0-9]+)/$', products_json, name='json-product'),
|
||||||
url(r'^inventory/$', 'inventory', name='inventory'),
|
url(r'^products/$', products_json, name='json-products'),
|
||||||
url(r'^inventory/add/$', 'inventory_add', name='inventory-add'),
|
# Users
|
||||||
url(r'^report$', 'report', name='report'),
|
url(r'^user/create/$', create_user, name='create-user'),
|
||||||
|
url(r'^profile/$', profile, name='profile'),
|
||||||
)
|
# Reports
|
||||||
|
url(r'^inventory/$', inventory, name='inventory'),
|
||||||
|
url(r'^inventory/add/$', inventory_add, name='inventory-add'),
|
||||||
|
url(r'^report$', report, name='report'),
|
||||||
|
]
|
||||||
@@ -1,14 +1,25 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
|
||||||
def format_username(firstname, lastname):
|
def format_username(firstname, lastname):
|
||||||
first = firstname.lower().strip().replace(" ", "")[:6].encode('ascii', 'ignore')
|
first = firstname.lower().strip().replace(" ", "")[:6].encode('ascii', 'ignore')
|
||||||
last = lastname.lower().strip().replace(" ", "")[:6].encode('ascii', 'ignore')
|
last = lastname.lower().strip().replace(" ", "")[:6].encode('ascii', 'ignore')
|
||||||
|
|
||||||
return "{0}{1}".format(first, last)
|
return "{0}{1}".format(first, last)
|
||||||
|
|
||||||
|
|
||||||
def users_with_perm(perm_name):
|
def users_with_perm(perm_name):
|
||||||
return User.objects.filter(
|
return User.objects.filter(
|
||||||
Q(is_superuser=True) |
|
Q(is_superuser=True) |
|
||||||
Q(user_permissions__codename=perm_name) |
|
Q(user_permissions__codename=perm_name) |
|
||||||
Q(groups__permissions__codename=perm_name)).distinct()
|
Q(groups__permissions__codename=perm_name)).distinct()
|
||||||
|
|
||||||
|
|
||||||
|
def users_format_js(users):
|
||||||
|
users_js = []
|
||||||
|
for user in users:
|
||||||
|
users_js.append('"' + user.first_name + ' ' + user.last_name[:1] + '"')
|
||||||
|
users_js = "[{0}]".format(u",".join(users_js))
|
||||||
|
return users_js
|
||||||
-542
@@ -1,542 +0,0 @@
|
|||||||
# coding: utf-8
|
|
||||||
from datetime import timedelta
|
|
||||||
from itertools import groupby
|
|
||||||
import json
|
|
||||||
import time
|
|
||||||
|
|
||||||
from django.db import connection
|
|
||||||
from django.conf import settings
|
|
||||||
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
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def home(request):
|
|
||||||
if request.method == "POST":
|
|
||||||
form = AuthenticationForm(data=request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
# Log the user in.
|
|
||||||
login(request, form.get_user())
|
|
||||||
else:
|
|
||||||
if request.user.is_authenticated():
|
|
||||||
# Redirect to the register
|
|
||||||
return HttpResponseRedirect(reverse('main.views.register'))
|
|
||||||
else:
|
|
||||||
form = AuthenticationForm(request)
|
|
||||||
return render_to_response('home.html', locals(), context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
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(userprofile__balance__gt=cheapest_product_price)
|
|
||||||
# sort users after user's last purchase time
|
|
||||||
users = sorted(users, key=lambda u: u.get_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, u'Du har ikke valgt hva du skal kjøpe...')
|
|
||||||
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_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(u"{0} {1}".format(ol['amount'], product))
|
|
||||||
|
|
||||||
if order.is_external():
|
|
||||||
messages.success(request, u'Ekstern kjøpte {0}.'.format(u", ".join(orderlines)))
|
|
||||||
else:
|
|
||||||
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'))
|
|
||||||
else:
|
|
||||||
# TODO specify error(s)
|
|
||||||
messages.error(request, u'Skjemaet er ikke gyldig.')
|
|
||||||
orderform = OrderForm(request.POST)
|
|
||||||
formset = OrderLineFormSet(request.POST)
|
|
||||||
else:
|
|
||||||
orderform = OrderForm()
|
|
||||||
formset = OrderLineFormSet()
|
|
||||||
return render_to_response('register.html', locals(), context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
def deposit(request):
|
|
||||||
users = User.objects.all().order_by('first_name', 'last_name')
|
|
||||||
users_js = users_format_js(users)
|
|
||||||
allowed_users = utils.users_with_perm('add_transaction')
|
|
||||||
error_message_template = u'{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.get_profile().balance > settings.BBS_SALDO_MAX and amount + user.get_profile().balance != 1337:
|
|
||||||
messages.error(request, error_message_template.format(
|
|
||||||
user.first_name,
|
|
||||||
user.last_name,
|
|
||||||
amount,
|
|
||||||
settings.BBS_SALDO_MAX,
|
|
||||||
amount + user.get_profile().balance - settings.BBS_SALDO_MAX
|
|
||||||
))
|
|
||||||
return HttpResponseRedirect(reverse('main.views.deposit'))
|
|
||||||
|
|
||||||
transaction = form.save()
|
|
||||||
profile = transaction.user.get_profile()
|
|
||||||
profile.balance += transaction.amount
|
|
||||||
profile.save()
|
|
||||||
|
|
||||||
messages.success(request, u'{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('main.views.deposit'))
|
|
||||||
else:
|
|
||||||
messages.error(request, u'Skjemaet er ikke gyldig.')
|
|
||||||
form = DepositForm(request.POST)
|
|
||||||
else:
|
|
||||||
form = DepositForm()
|
|
||||||
|
|
||||||
return render_to_response('deposit.html', locals(), context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
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_to_response('log.html', locals(), context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
def stats(request):
|
|
||||||
products = Product.objects.filter(active=True)
|
|
||||||
|
|
||||||
return render_to_response('stats.html', locals(), context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
def serialize_product(product):
|
|
||||||
f_product = {}
|
|
||||||
for attr in Product._meta.get_all_field_names():
|
|
||||||
if attr == "transactions" or attr == "orderlines":
|
|
||||||
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 HttpResponse(json.dumps(f_products), content_type='application/javascript; charset=utf8')
|
|
||||||
|
|
||||||
|
|
||||||
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')\
|
|
||||||
.reverse()
|
|
||||||
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 = u"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 HttpResponse(json.dumps(response), content_type='application/javascript; charset=utf8')
|
|
||||||
|
|
||||||
|
|
||||||
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 = u"Ekstern"
|
|
||||||
num = num_external_orders
|
|
||||||
f_per_user.append([who, num])
|
|
||||||
return HttpResponse(json.dumps(f_per_user), content_type='application/javascript; charset=utf8')
|
|
||||||
|
|
||||||
|
|
||||||
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 HttpResponse(json.dumps({}), content_type='application/javascript; charset=utf8')
|
|
||||||
response = {
|
|
||||||
'start': str(orders[0].created),
|
|
||||||
'hourly': [[k, v] for k, v in f_hourly.iteritems()],
|
|
||||||
'total': sum(f_hourly.values()),
|
|
||||||
}
|
|
||||||
return HttpResponse(json.dumps(response), content_type='application/javascript; charset=utf8')
|
|
||||||
|
|
||||||
|
|
||||||
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 HttpResponse(json.dumps(response), content_type='application/javascript; charset=utf8')
|
|
||||||
|
|
||||||
|
|
||||||
def logout(request):
|
|
||||||
auth_logout(request)
|
|
||||||
return render_to_response('registration/logout.html', locals(), context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
def users_format_js(users):
|
|
||||||
users_js = []
|
|
||||||
for user in users:
|
|
||||||
users_js.append('"' + user.first_name + ' ' + user.last_name[:1] + '"')
|
|
||||||
users_js = u"[{0}]".format(u",".join(users_js))
|
|
||||||
return users_js
|
|
||||||
|
|
||||||
|
|
||||||
def create_user(request):
|
|
||||||
if request.method == "POST":
|
|
||||||
form = SimpleCreateUserForm(data=request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
user = form.save()
|
|
||||||
messages.success(request, u"Hurra! {0} {1} er lagt til".format(user.first_name, user.last_name))
|
|
||||||
return redirect('create-user')
|
|
||||||
|
|
||||||
else:
|
|
||||||
messages.error(request, u'Feil med skjemaet, se under.')
|
|
||||||
form = SimpleCreateUserForm(data=request.POST)
|
|
||||||
else:
|
|
||||||
form = SimpleCreateUserForm()
|
|
||||||
|
|
||||||
return render(request, 'registration/create_user.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, u"Satt inn {0} stk {1}.".format(itrans.amount, itrans.product))
|
|
||||||
return redirect('inventory-add')
|
|
||||||
|
|
||||||
else:
|
|
||||||
messages.error(request, u'Feil med skjemaet, se under.')
|
|
||||||
form = InventoryTransactionForm(data=request.POST)
|
|
||||||
else:
|
|
||||||
form = InventoryTransactionForm()
|
|
||||||
|
|
||||||
return render(request, 'inventory_add.html', locals())
|
|
||||||
|
|
||||||
|
|
||||||
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())
|
|
||||||
|
|
||||||
|
|
||||||
@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
|
|
||||||
Whitespace-only changes.
@@ -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())
|
||||||
@@ -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())
|
||||||
@@ -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)
|
||||||
@@ -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
|
||||||
+3
-4
@@ -1,9 +1,8 @@
|
|||||||
Django>=1.6,<1.7
|
Django>=1.8,<1.9
|
||||||
django-bootstrap-form==3.1
|
django-bootstrap-form==3.1
|
||||||
django-compressor==1.4
|
django-compressor==1.4
|
||||||
django-extensions==1.5.5
|
django-extensions==1.5.9
|
||||||
django-widget-tweaks==1.3
|
django-widget-tweaks==1.3
|
||||||
facebook-sdk==0.4.0
|
facebook-sdk==0.4.0
|
||||||
mysqlclient==1.3.6
|
mysqlclient==1.3.6
|
||||||
Pillow==2.5.1
|
Pillow==3.0.0
|
||||||
South==1.0
|
|
||||||
+14
-14
@@ -1,13 +1,13 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
{% load compress %}
|
{% load compress staticfiles %}
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>{%block title%}BBS{%endblock%}</title>
|
<title>{%block title%}BBS{%endblock%}</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="x-django-static-url" content="{{ STATIC_URL }}">
|
<meta name="x-django-static-url" content="{% static "" %}">
|
||||||
{% compress css %}
|
{% compress css %}
|
||||||
<link rel="stylesheet" href="{{ STATIC_URL }}dist/styles/screen.css" type="text/css" media="screen, projection">
|
<link rel="stylesheet" href="{% static "dist/styles/screen.css" %}" type="text/css" media="screen, projection">
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{%block headinc %}{%endblock%}
|
{%block headinc %}{%endblock%}
|
||||||
</head>
|
</head>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<li><a href="{% url 'login' %}">Logg inn</a></li>
|
<li><a href="{% url 'login' %}">Logg inn</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="dropdown">
|
<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>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="{{ user.profile.profile_image_url }}" /><span class="name">{{ user.first_name }}</span> <b class="caret"></b></a>
|
||||||
<ul class="dropdown-menu">
|
<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 %}
|
{% 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>
|
<li class="{% block active_create_user %}{% endblock %}"><a href="{% url 'create-user' %}"><i class="glyphicon glyphicon-plus"></i> Ny bruker</a></li>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
{%block footer %}
|
{%block footer %}
|
||||||
<div class="credits">
|
<div class="credits">
|
||||||
Laget med <span class="love" title="kærlighed">♥</span> av <a href="http://edb.neuf.no/">EDB-gjengen i KAK</a><br/>
|
Laget med <span class="love" title="kærlighed">♥</span> av <a href="http://edb.neuf.no/">EDB-gjengen i KAK</a><br/>
|
||||||
<a href="http://edb.neuf.no/"><img src="{{ STATIC_URL }}dist/images/edb_brick.png" alt="EDB" /></a>
|
<a href="http://edb.neuf.no/"><img src="{% static "dist/images/edb_brick.png" %}" alt="EDB" /></a>
|
||||||
</div>
|
</div>
|
||||||
{%endblock%}
|
{%endblock%}
|
||||||
</div>
|
</div>
|
||||||
@@ -72,15 +72,15 @@
|
|||||||
|
|
||||||
|
|
||||||
{% compress js %}
|
{% compress js %}
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/jquery/dist/jquery.min.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/jquery/dist/jquery.min.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/collapse.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/collapse.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/dropdown.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/dropdown.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/tooltip.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/tooltip.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/bootstrap-datepicker/js/locales/bootstrap-datepicker.nb.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/bootstrap-datepicker/js/locales/bootstrap-datepicker.nb.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/highcharts/highcharts.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/highcharts/highcharts.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}app/bower_components/underscore/underscore-min.js"></script>
|
<script type="text/javascript" src="{% static "app/bower_components/underscore/underscore-min.js" %}"></script>
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}dist/js/app.js"></script>
|
<script type="text/javascript" src="{% static "dist/js/app.js" %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{%block tailinc %}{%endblock%}
|
{%block tailinc %}{%endblock%}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<p>Spør en av disse om de kan hjelpe deg:</p>
|
<p>Spør en av disse om de kan hjelpe deg:</p>
|
||||||
<ul>
|
<ul>
|
||||||
{% for u in allowed_users %}
|
{% for u in allowed_users %}
|
||||||
<li style="padding-bottom: 8px;"><img src="{{u.get_profile.image }}" />{{u.first_name }} {{u.last_name }}</li>
|
<li style="padding-bottom: 8px;"><img src="{{u.profile.image }}" />{{u.first_name }} {{u.last_name }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
<ul class="well">
|
<ul class="well">
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
<li class="customer">{% spaceless %}
|
<li class="customer">{% spaceless %}
|
||||||
<img class="profile" src="{{ user.get_profile.profile_image_url }}" alt="Profile picture"/><br />
|
<img class="profile" src="{{ user.profile.profile_image_url }}" alt="Profile picture"/><br />
|
||||||
<span class="name">{{ user.first_name }} {{ user.last_name|slice:":1"}}</span><br />
|
<span class="name">{{ user.first_name }} {{ user.last_name|slice:":1"}}</span><br />
|
||||||
<span class="balance">{{ user.get_profile.balance }}</span>
|
<span class="balance">{{ user.profile.balance }}</span>
|
||||||
<span class="id" style="display:none;">{{ user.id }}</span>
|
<span class="id" style="display:none;">{{ user.id }}</span>
|
||||||
{% endspaceless %}</li>
|
{% endspaceless %}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
<td>{{ t.created }}</td>
|
<td>{{ t.created }}</td>
|
||||||
<td>{{ t.product }}</td>
|
<td>{{ t.product }}</td>
|
||||||
<td>{{ t.amount }}</td>
|
<td>{{ t.amount }}</td>
|
||||||
<td>{% if t.user.get_profile.image %}<img src="{{ t.user.get_profile.image }}" class="customer" title="{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}" />{% else %}{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}{% endif %}</td>
|
<td>{% if t.user.profile.image %}<img src="{{ t.user.profile.image }}" class="customer" title="{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}" />{% else %}{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@
|
|||||||
{% for order in orders %}
|
{% for order in orders %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ order.created }}</td>
|
<td>{{ order.created }}</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>{% if order.customer %}{% if order.customer.profile.image %}<img src="{{ order.customer.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.orderlines.all %}
|
<td>{% for line in order.orderlines.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>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
{% for t in transactions %}
|
{% for t in transactions %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ t.created }}</td>
|
<td>{{ t.created }}</td>
|
||||||
<td>{% if t.user.get_profile.image %}<img src="{{ t.user.get_profile.image }}" class="customer" title="{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}" />{% else %}{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}{% endif %}</td>
|
<td>{% if t.user.profile.image %}<img src="{{ t.user.profile.image }}" class="customer" title="{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}" />{% else %}{{ t.user.first_name }} {{ t.user.last_name|slice:":1"}}{% endif %}</td>
|
||||||
<td>{{ t.amount }}</td>
|
<td>{{ t.amount }}</td>
|
||||||
<!--<td>{% include "modal-delete-transaction.html" with t=t %}<a class="btn btn-danger" data-toggle="modal" href="#modal-trans-{{t.id}}"><i class="icon-trash icon-white"></i> Slett</a></td>-->
|
<!--<td>{% include "modal-delete-transaction.html" with t=t %}<a class="btn btn-danger" data-toggle="modal" href="#modal-trans-{{t.id}}"><i class="icon-trash icon-white"></i> Slett</a></td>-->
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<section id="user-profile" data-user-id="{{request.user.pk}}">
|
<section id="user-profile" data-user-id="{{request.user.pk}}">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<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>
|
<h1 class="profile-name"><img src="{{ request.user.profile.profile_image_url }}" class="profile-image" /> {{user.first_name}}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Saldo</div>
|
<div class="panel-heading">Saldo</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<h2>{{request.user.get_profile.balance }} kr</h2>
|
<h2>{{request.user.profile.balance }} kr</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
{% block active_register %}active{% endblock %}
|
{% block active_register %}active{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@@ -40,14 +41,14 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<ul class="well">
|
<ul class="well">
|
||||||
<li class="customer">{% spaceless %}
|
<li class="customer">{% spaceless %}
|
||||||
<img class="profile" src="{{ STATIC_URL }}dist/images/unknown_person.png" alt="Profile picture" /><br />
|
<img class="profile" src="{% static "dist/images/unknown_person.png" %}" alt="Profile picture" /><br />
|
||||||
<span class="name">Ekstern</span><br />
|
<span class="name">Ekstern</span><br />
|
||||||
<span class="balance"> </span>
|
<span class="balance"> </span>
|
||||||
{% endspaceless %}</li>
|
{% 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.profile.last_purchase_date < half_a_year_ago and not user.profile.last_purchase == None %} infrequent hidden{% endif %}">{% spaceless %}
|
||||||
<img class="profile" src="{{ user.get_profile.profile_image_url }}" alt="Profile picture" /><br />
|
<img class="profile" src="{{ user.profile.profile_image_url }}" alt="Profile picture" /><br />
|
||||||
<span class="name">{{ user.first_name }} {{ user.last_name|slice:":1"}}</span><br />
|
<span class="name">{{ user.first_name }} {{ user.last_name|slice:":1"}}</span><br />
|
||||||
<span class="balance">{{ user.get_profile.balance }}</span>
|
<span class="balance">{{ user.profile.balance }}</span>
|
||||||
<span class="id" style="display:none;">{{ user.id }}</span>
|
<span class="id" style="display:none;">{{ user.id }}</span>
|
||||||
{% endspaceless %}</li>{% endfor %}
|
{% endspaceless %}</li>{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -77,9 +78,9 @@
|
|||||||
<input type="hidden" name="form-{{ forloop.counter0 }}-unit_price_ext" value="{{product.sale_price_ext }}" />
|
<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 }}dist/images/product.png" /><br />
|
<img class="product" src="{% static "dist/images/product.png" %}" /><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<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>
|
<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>
|
||||||
|
|||||||
Reference in new issue
Block a user