Browse Source

pep8

master
Fr3deric 7 years ago
parent
commit
e1598090f7
  1. 18
      cashonly/admin.py
  2. 1
      cashonly/auth.py
  3. 1
      cashonly/formfields.py
  4. 7
      cashonly/management/commands/dailydigest.py
  5. 1
      cashonly/management/commands/debtreminder.py
  6. 22
      cashonly/models.py
  7. 17
      cashonly/urls.py
  8. 2
      cashonly/version.py
  9. 45
      cashonly/views.py

18
cashonly/admin.py

@ -8,6 +8,7 @@ from django.utils.translation import ugettext as _ @@ -8,6 +8,7 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from django.utils.translation import ugettext_noop
class AccountForm(forms.ModelForm):
credit_change = forms.DecimalField(max_digits=5, decimal_places=2,
required=False,
@ -16,8 +17,6 @@ class AccountForm(forms.ModelForm): @@ -16,8 +17,6 @@ class AccountForm(forms.ModelForm):
credit_change_comment = forms.CharField(max_length=64, required=False,
label=ugettext_lazy('comment'))
#pin_change = forms.RegexField(regex='^\d{4,}$', required=False,
# label=ugettext_lazy('PIN'))
pin_change = DigitField(min_length=4, required=False,
label=ugettext_lazy('PIN'))
@ -30,6 +29,7 @@ class AccountForm(forms.ModelForm): @@ -30,6 +29,7 @@ class AccountForm(forms.ModelForm):
# Include all fields (omitting this causes a RemovedInDjango18Warning)
exclude = []
class AccountAdmin(admin.ModelAdmin):
list_display = ('user', 'card_number', 'credit', 'transaction_link')
form = AccountForm
@ -97,6 +97,7 @@ class ProductBarcodeInline(admin.TabularInline): @@ -97,6 +97,7 @@ class ProductBarcodeInline(admin.TabularInline):
model = ProductBarcode
extra = 1
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'category', 'price', 'active')
list_filter = ['category', 'active']
@ -104,15 +105,18 @@ class ProductAdmin(admin.ModelAdmin): @@ -104,15 +105,18 @@ class ProductAdmin(admin.ModelAdmin):
inlines = [ProductBarcodeInline]
fields = ('name', 'price', 'active', 'category', 'image')
class ProductCategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'comment')
class SalesLogEntryAdmin(admin.ModelAdmin):
list_display = ('account', 'timestamp', 'product', 'count', 'unit_price')
list_filter = ['account', 'timestamp', 'product']
# Make sales log entries completely read-only
readonly_fields = map(lambda f: f.name, SalesLogEntry._meta.fields)
class TransactionAdmin(admin.ModelAdmin):
list_display = ('account', 'timestamp', 'subject', 'description', 'amount')
list_filter = ['account', 'timestamp', 'subject']
@ -125,10 +129,12 @@ class TransactionAdmin(admin.ModelAdmin): @@ -125,10 +129,12 @@ class TransactionAdmin(admin.ModelAdmin):
# Disable tampering with the transactions completely.
def has_add_permission(self, request):
return False
def has_change_permission(self, request, obj=None):
if obj is None:
return True
return False
def has_delete_permission(self, request, obj=None):
return False
@ -136,13 +142,13 @@ class TransactionAdmin(admin.ModelAdmin): @@ -136,13 +142,13 @@ class TransactionAdmin(admin.ModelAdmin):
# FIXME: a bit too hacky
def changelist_view(self, request, extra_context=None):
self.list_display_links = (None, )
return super(TransactionAdmin, self).changelist_view(request,
extra_context=None)
return super(TransactionAdmin, self).changelist_view(
request,
extra_context=None,
)
admin.site.register(Account, AccountAdmin)
admin.site.register(Product, ProductAdmin)
#admin.site.register(ProductBarcode)
admin.site.register(ProductCategory, ProductCategoryAdmin)
admin.site.register(Transaction, TransactionAdmin)
admin.site.register(SalesLogEntry, SalesLogEntryAdmin)

1
cashonly/auth.py

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
from django.contrib.auth.models import User
from cashonly.models import Account
class CashBackend(object):
def authenticate(self, card_number=None, pin=None):
if not card_number.isdigit():

1
cashonly/formfields.py

@ -3,6 +3,7 @@ from django.core.exceptions import ValidationError @@ -3,6 +3,7 @@ from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.core.validators import EMPTY_VALUES
class DigitField(CharField):
def clean(self, value):
super(DigitField, self).clean(value)

7
cashonly/management/commands/dailydigest.py

@ -13,6 +13,7 @@ import datetime @@ -13,6 +13,7 @@ import datetime
RANGE = 24
USERSETTINGS_URL = 'https://cypher/kasse/usersettings/'
class Command(NoArgsCommand):
help = 'Sends out the daily digest to all users with transactions' + \
'in the last %dh' % RANGE
@ -31,8 +32,8 @@ class Command(NoArgsCommand): @@ -31,8 +32,8 @@ class Command(NoArgsCommand):
'url': USERSETTINGS_URL}
transactions = Transaction.objects.filter(account=a) \
.filter(timestamp__gte=(datetime.datetime.now()
- datetime.timedelta(hours = RANGE)))
.filter(timestamp__gte=(datetime.datetime.now() -
datetime.timedelta(hours=RANGE)))
if transactions.count() > 0:
lengths = {'timestamp': len(_('date')),
@ -42,7 +43,7 @@ class Command(NoArgsCommand): @@ -42,7 +43,7 @@ class Command(NoArgsCommand):
sum = 0
for t in transactions:
lengths['timestamp'] = \
max(lengths['timestamp'], len(DateFormat(t.timestamp) \
max(lengths['timestamp'], len(DateFormat(t.timestamp)
.format(get_format('SHORT_DATETIME_FORMAT'))))
lengths['description'] = \
max(lengths['description'], len(t.description))

1
cashonly/management/commands/debtreminder.py

@ -8,6 +8,7 @@ from django.template.loader import get_template @@ -8,6 +8,7 @@ from django.template.loader import get_template
from django.utils import translation
from django.utils.translation import ugettext as _
class Command(NoArgsCommand):
help = 'Sends a reminder mail to every with a negative credit'

22
cashonly/models.py

@ -11,12 +11,14 @@ from django.db import transaction @@ -11,12 +11,14 @@ from django.db import transaction
import PIL.Image
import StringIO
class Account(models.Model):
user = models.OneToOneField(User)
card_number = models.CharField(max_length=32, unique=True, blank=True,
null=True, verbose_name=_('card number'))
pin = models.CharField(max_length=32, blank=True, verbose_name=_('PIN'))
daily_digest = models.BooleanField(verbose_name = _('daily digest'), default=True)
daily_digest = models.BooleanField(verbose_name=_('daily digest'),
default=True)
credit = models.DecimalField(max_digits=5, decimal_places=2, default=0,
verbose_name=_('credit'))
@ -36,8 +38,8 @@ class Account(models.Model): @@ -36,8 +38,8 @@ class Account(models.Model):
else:
# When we already have an account,
# we can add the number form LDAP (mongo shit)
if hasattr(instance, 'ldap_user') \
and instance.ldap_user.attrs.has_key('employeenumber'):
if (hasattr(instance, 'ldap_user') and
'employeenumber' in instance.ldap_user.attrs):
instance.account.card_number = \
instance.ldap_user.attrs['employeenumber'][0]
instance.account.save()
@ -61,7 +63,8 @@ class Account(models.Model): @@ -61,7 +63,8 @@ class Account(models.Model):
if min(products.values()) <= 0:
raise ValueError('Non-positive amount in products dict.')
total_value = sum(map(lambda p: p.price * products[p], products.keys()))
total_value = sum(map(lambda p: p.price * products[p],
products.keys()))
if self.credit - total_value >= MAX_DEBIT:
desc = ''
for product in products.keys():
@ -70,7 +73,8 @@ class Account(models.Model): @@ -70,7 +73,8 @@ class Account(models.Model):
amount = products[product]
logentry = SalesLogEntry(account=self, product=product,
count=amount, unit_price=product.price)
count=amount,
unit_price=product.price)
logentry.save()
desc += '%d x %s\n' % (amount, product.name)
@ -95,6 +99,7 @@ class Account(models.Model): @@ -95,6 +99,7 @@ class Account(models.Model):
def check_pin(self, pin):
return pin == self.pin
class ProductCategory(models.Model):
name = models.CharField(max_length=32, unique=True,
verbose_name=_('name'))
@ -108,6 +113,7 @@ class ProductCategory(models.Model): @@ -108,6 +113,7 @@ class ProductCategory(models.Model):
verbose_name = _('product category')
verbose_name_plural = _('product categories')
class Product(models.Model):
name = models.CharField(max_length=32, unique=True,
verbose_name=_('name'))
@ -129,6 +135,7 @@ class Product(models.Model): @@ -129,6 +135,7 @@ class Product(models.Model):
verbose_name = _('product')
verbose_name_plural = _('products')
@receiver(pre_save, sender=Product)
def product_post_save_handler(sender, instance, **kwargs):
img = instance.image
@ -159,6 +166,7 @@ class ProductBarcode(models.Model): @@ -159,6 +166,7 @@ class ProductBarcode(models.Model):
verbose_name = _('barcode')
verbose_name_plural = _('barcodes')
class Transaction(models.Model):
account = models.ForeignKey(Account, verbose_name=_('account'))
timestamp = models.DateTimeField(auto_now_add=True,
@ -172,6 +180,7 @@ class Transaction(models.Model): @@ -172,6 +180,7 @@ class Transaction(models.Model):
verbose_name = _('transaction')
verbose_name_plural = _('transactions')
class SalesLogEntry(models.Model):
account = models.ForeignKey(Account, verbose_name=_('account'))
product = models.ForeignKey(Product, verbose_name=_('product'))
@ -183,10 +192,12 @@ class SalesLogEntry(models.Model): @@ -183,10 +192,12 @@ class SalesLogEntry(models.Model):
def __unicode__(self):
return '%dx %s - %s' % (self.count, self.product, self.account)
class Meta:
verbose_name = _('sales log entry')
verbose_name_plural = _('sales log entries')
@receiver(pre_delete, sender=SalesLogEntry)
def logentry_pre_delete_handler(sender, instance, **kwargs):
SUBJECT = ugettext_noop('Cancellation')
@ -196,4 +207,3 @@ def logentry_pre_delete_handler(sender, instance, **kwargs): @@ -196,4 +207,3 @@ def logentry_pre_delete_handler(sender, instance, **kwargs):
instance.unit_price * instance.count,
SUBJECT, DESC % (instance.count, instance.product.name)
)

17
cashonly/urls.py

@ -4,16 +4,20 @@ from cashonly import views @@ -4,16 +4,20 @@ from cashonly import views
urlpatterns = [
url(r'^$', views.overview, name='overview'),
url(r'^product/(?P<pk>\d+)/$', views.ProductView.as_view(), name='product'),
url(r'^product/(?P<pk>\d+)/$', views.ProductView.as_view(),
name='product'),
url(r'transactions/$', views.transactions, {'detailed': False, 'page':1}, name='transactions'),
url(r'transactions/$', views.transactions, {'detailed': False, 'page': 1},
name='transactions'),
url(r'transactions/(?P<page>\d+)/$', views.transactions, {'detailed': False}, name='transactions'),
url(r'transactions/(?P<page>\d+)/$', views.transactions,
{'detailed': False}, name='transactions'),
url(r'transactions/(?P<page>\d+)/detailed/$', views.transactions, {'detailed': True},
name='transactions_detailed'),
url(r'transactions/(?P<page>\d+)/detailed/$', views.transactions,
{'detailed': True}, name='transactions_detailed'),
url(r'products/((?P<category_id>\d+)/)?$', views.products, name='products'),
url(r'products/((?P<category_id>\d+)/)?$', views.products,
name='products'),
url(r'buy/(?P<product_id>\d+)/$', views.buy, name='buy'),
@ -27,4 +31,3 @@ urlpatterns = [ @@ -27,4 +31,3 @@ urlpatterns = [
url(r'usersettings(/(?P<submit>\w+))?/$', views.usersettings,
name='usersettings'),
]

2
cashonly/version.py

@ -1,3 +1 @@ @@ -1,3 +1 @@
CASHONLY_VERSION = '2.1.2'

45
cashonly/views.py

@ -9,22 +9,27 @@ from django.utils.translation import ugettext_lazy @@ -9,22 +9,27 @@ from django.utils.translation import ugettext_lazy
import cashonly.version
import datetime
def version_number_context_processor(request):
return {'version_number': cashonly.version.CASHONLY_VERSION}
@login_required
def overview(request):
a = request.user.account
time = datetime.datetime.now() - datetime.timedelta(hours=12)
transactions = Transaction.objects.filter(account=a).filter(timestamp__gte=time).order_by('-timestamp')
transactions = Transaction.objects.filter(account=a) \
.filter(timestamp__gte=time).order_by('-timestamp')
# FIXME: distinct doesn't work as expected, so fetch 20 rows and hope that there are 3 distinct products
purchases = Product.objects.filter(saleslogentry__account=a).order_by('-saleslogentry__timestamp').distinct()[:20]
# FIXME: distinct doesn't work as expected, so fetch 20 rows and hope that
# there are 3 distinct products
purchases = Product.objects.filter(saleslogentry__account=a) \
.order_by('-saleslogentry__timestamp').distinct()[:20]
products = []
# Find 3 products
for p in purchases:
if not p in products:
if p not in products:
products.append(p)
if len(products) == 3:
@ -53,23 +58,27 @@ def transactions(request, detailed, page): @@ -53,23 +58,27 @@ def transactions(request, detailed, page):
except paginator.EmptyPage:
transaction_list = paginator.page(paginator.num_pages)
return render(request, 'cashonly/transaction_list.html', { 'transaction_list': transaction_list,
return render(request, 'cashonly/transaction_list.html',
{'transaction_list': transaction_list,
'detailed': detailed})
def products(request, category_id=None):
if category_id is None:
category = None
products = Product.objects.filter(active=True)
else:
category = get_object_or_404(ProductCategory, id=category_id)
products = Product.objects.filter(active=True).filter(category=category)
products = Product.objects.filter(active=True) \
.filter(category=category)
categories = ProductCategory.objects.all()
return render(request, 'cashonly/product_list.html', { 'product_list': products,
'category': category,
return render(request, 'cashonly/product_list.html',
{'product_list': products, 'category': category,
'categories': categories})
@login_required
def buy(request, product_id, confirm=False):
product = get_object_or_404(Product, id=product_id)
@ -80,20 +89,25 @@ def buy(request, product_id, confirm=False): @@ -80,20 +89,25 @@ def buy(request, product_id, confirm=False):
else:
return redirect('buy_error')
else:
return render(request, 'cashonly/buy_confirm.html', {'product': product})
return render(request, 'cashonly/buy_confirm.html',
{'product': product})
@login_required
def buy_thanks(request):
return render(request, 'cashonly/buy_thanks.html')
@login_required
def buy_error(request):
return render(request, 'cashonly/buy_error.html')
class UserSettingsForm(forms.Form):
daily_digest = forms.BooleanField(required=False,
label=ugettext_lazy('daily digest'))
class UserPinForm(forms.Form):
pin = forms.CharField(max_length=32, widget=forms.PasswordInput,
label=ugettext_lazy('PIN'), required=False)
@ -104,14 +118,14 @@ class UserPinForm(forms.Form): @@ -104,14 +118,14 @@ class UserPinForm(forms.Form):
def clean(self):
cleaned_data = super(UserPinForm, self).clean()
if not (cleaned_data.has_key('pin') or
cleaned_data.has_key('pin_confirm')):
if 'pin' not in cleaned_data and 'pin_confirm' not in cleaned_data:
return cleaned_data
if cleaned_data['pin'] != cleaned_data['pin_confirm']:
raise forms.ValidationError(_('PINs do not match.'))
return cleaned_data
@login_required
def usersettings(request, submit=None):
daily_digest = request.user.account.daily_digest
@ -137,10 +151,5 @@ def usersettings(request, submit=None): @@ -137,10 +151,5 @@ def usersettings(request, submit=None):
request.user.account.save()
return render(request, 'cashonly/usersettings_saved.html')
return render(request, 'cashonly/usersettings.html', { 'settings_form': settings_form,
'pin_form': pin_form})
return render(request, 'cashonly/usersettings.html',
{'settings_form': settings_form, 'pin_form': pin_form})

Loading…
Cancel
Save