Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions p0sx/p0sx/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
'rest_framework',
'rest_framework.authtoken',
'django_filters',
'django_q',
'django_q'
)

MIDDLEWARE = [
Expand Down Expand Up @@ -150,11 +150,13 @@

# SumUp affiliate key. Create one on your SumUp account with application-id com.polarparty.p0sx
SUMUP_AFFILIATE_KEY = ''
# SumUp callback hostname, must include http:// or https:// and port if required.
# SumUp callback hostname, must include https:// and port if required.
SUMUP_CALLBACK_HOSTNAME = ''
# SumUp Merchant code
SUMUP_MERCHANT_CODE = ''

SUMUP_BEARER_TOKEN = ''

# GeekEvents event id for the current party
GE_EVENT_ID = None
GE_SSO_SUCCESS_REDIRECT = None
Expand All @@ -163,7 +165,8 @@
'name': 'p0sX',
'workers': 1,
'recycle': 500,
'timeout': 60,
'timeout': 10,
'retry': 10,
'compress': True,
'save_limit': 250,
'queue_limit': 500,
Expand Down
35 changes: 6 additions & 29 deletions p0sx/p0sx/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@

from pos.views.foodtracker import active_orders, delivery_screen, delivery_station, production_station, production_station_exclude, production_station_single
from pos.views.littleadmin import (
AddUserSumupCredit,
add_credit_stats,
add_user,
add_user_credit,
check_credit,
check_sumup_status,
credit_edit,
credit_overview,
crew_report,
Expand All @@ -26,7 +24,6 @@
verify_add_credit,
verify_add_credit_cash
)
from pos.views.remotepay import pay, pay_callback, pay_success, pay_error, pay_hold
from pos.views.shift import AllShiftsViewSet, CurrentShiftViewSet, NewShiftViewSet, ShiftViewSet
from pos.views.sso import (
add_user,
Expand All @@ -40,21 +37,14 @@
OrderLineViewSet,
OrderViewSet,
PurchaseViewSet)
from pos.views.sumup import SumUpAuthView, get_pending_transactions, set_processing, sumup_callback, sumup_callbackonline
from pos.views.sumup import sumup_ordercallback, sumup_creditcallback
from pos.views.user import UserViewSet


from rest_framework import routers

sale_url = [
url(r'^$', RedirectView.as_view(url=reverse_lazy('littleadmin:sale'))),
url(r'overview', sale_overview, name='overview')
]

littleadmin_url = [
url(r'^$', RedirectView.as_view(url=reverse_lazy('littleadmin:overview'))),
url(r'sumup-init/(?P<instance_id>\d+)/$', SumUpAuthView.as_view(), name='sumup_auth', kwargs={'action': 'init'}),
url(r'sumup-return/$', SumUpAuthView.as_view(), name='sumup_return', kwargs={'action': 'sumup_return'}),
url(r'check/', check_credit, name='check'),
url(r'overview/', credit_overview, name='overview'),
url(r'edit_crew_credit/(?P<card>\w+)', credit_edit, name='edit_crew_credit'),
Expand All @@ -65,18 +55,9 @@
url(r'fetch_from_ge/', fetch_credit_from_ge, name='fetch_credit_from_ge'),
url(r'scan_user_card', scan_user_card, name='scan_user_card'),
url(r'add_user_credit/(?P<card>\w+)$', add_user_credit, name='add_user_credit'),
url(r'add_user_credit/(?P<card>\w+)/sumup$', AddUserSumupCredit.as_view(), name='add_user_credit_sumup'),
url(r'add_user_credit/(?P<card>\w+)/sumup/(?P<transaction_id>\d+)/verify$', AddUserSumupCredit.as_view(),
name='add_user_credit_sumup_verify', kwargs={'verify': True}),
url(r'add_user/(?P<card>\w+)', add_user, name='add_user'),
url(r'verify_add_credit_cash/(?P<user>\d+)/(?P<amount>\d+)', verify_add_credit_cash, name='verify_add_credit_cash'),
path('verify_add_credit/<uuid:tid>', verify_add_credit, name='verify_add_credit'),
# url(r'check_sumup_status/(?P<tid>\[a-zA-Z0-9-]+)', check_sumup_status, name='check_sumup_status'),
path('check_sumup_status/<uuid:tid>', check_sumup_status, name='check_sumup_status'),
# url(r'get_pending_transactions/', get_pending_transactions, name='get_pending_transactions'),
path('get_pending_transactions/', get_pending_transactions, name='get_pending_transactions'),
# url(r'set_processing/(?P<transaction>\[a-zA-Z0-9-]+)', set_processing, name='set_processing'),
path('set_processing/<uuid:transaction>', set_processing, name='set_processing'),
path('verify_add_credit/<int:tid>', verify_add_credit, name='verify_add_credit'),
url(r'add_credit_stats', add_credit_stats, name='add_credit_stats'),
path('update_ge_user/', update_ge_user, name='update_ge_user'),
]
Expand Down Expand Up @@ -111,14 +92,10 @@
url(r'^', include(router.urls)),
url(r'littleadmin/', include((littleadmin_url, 'pos'), namespace='littleadmin')),
url(r'sso/', include((sso_url, 'pos'), namespace='sso')),
path('pay/', pay, name='pay'),
path('pay/callback/<uuid:checkoutid>', pay_callback, name='pay_callback'),
path('pay/success/', pay_success, name='pay_success'),
path('pay/hold/', pay_hold, name='pay_hold'),
path('pay/error/', pay_error, name='pay_error'),
# url(r'callback/(?P<tid>\d+)', sumup_callback, name='sumup_callback')
path('callback/<uuid:tid>', sumup_callback, name='sumup_callback'),
path('callbackonline/<uuid:tid>', sumup_callbackonline, name='sumup_callbackonline'),

path('order-callback/<int:order_id>', sumup_ordercallback, name='sumup_ordercallback'),
path('credit-callback/<int:transaction_id>', sumup_creditcallback, name='sumup_creditcallback'),

path('foodtracker/active/', active_orders, name='active_orders'),
path('foodtracker/production_station/', production_station, name='production_station'),
path('foodtracker/production_station/<int:category>/', production_station_single, name='production_station_single'),
Expand Down
103 changes: 73 additions & 30 deletions p0sx/pos/admin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from django.contrib import admin
from django import forms
from django.urls import reverse
from django.utils.safestring import mark_safe

from pos.models.shift import Shift
from pos.models.stock import Category, Discount, FoodLog, Ingredient, Item, ItemIngredient, Order, OrderLine
from pos.models.sumup import SumUpAPIKey, SumUpCard, SumUpOnline, SumUpTerminal, SumUpTransaction
from pos.models.user import CreditUpdate, User, GeekeventsToken
from pos.models.printer import Printer

from pos.models.sumup_cloud import SumupReader, SumupTransaction
from pos.service.sumup import pair_sumup_reader

class CreditUpdateAdmin(admin.ModelAdmin):
readonly_fields = ('timestamp', 'amount', 'user', 'updated_by_user', 'geekevents_id')
Expand Down Expand Up @@ -58,12 +61,22 @@ class IngredientAdmin(admin.ModelAdmin):


class ItemAdmin(admin.ModelAdmin):
pass
list_display = ('name', 'price', 'active')


class OrderLineAdmin(admin.ModelAdmin):
readonly_fields = ('ingredients', 'item', 'price')
list_display = ('item', 'order', 'state')
list_display = ('id', 'item', 'price', 'order_link', 'state')

def order_link(self, obj):
if obj.order is None:
return '-'
return mark_safe('<a href="{}">{}</a>'.format(
reverse("admin:pos_order_change", args=(obj.order.pk,)),
obj.order
))

order_link.short_description = 'order'


class OrderLineInline(admin.TabularInline):
Expand All @@ -89,23 +102,6 @@ class ShiftAdmin(admin.ModelAdmin):
pass


class SumUpAPIKeyAdmin(admin.ModelAdmin):
pass

class SumUpOnlineAdmin(admin.ModelAdmin):
readonly_fields = ('id', 'created', 'timestamp', 'transaction_id', 'transaction_comment')
ordering = ('-created',)
list_display = ('user', 'amount', 'status', 'created', 'transaction_id', 'transaction_comment',)
pass

class SumUpTerminalAdmin(admin.ModelAdmin):
pass


class SumUpTransactionAdmin(admin.ModelAdmin):
pass


class SumUpCardAdmin(admin.ModelAdmin):
readonly_fields = ('id', 'created', 'timestamp')
ordering = ('-created',)
Expand Down Expand Up @@ -135,15 +131,65 @@ def has_add_permission(self, request, obj=None):


class OrderAdmin(admin.ModelAdmin):
readonly_fields = ('user', 'payment_method', 'cashier', 'authenticated_user')
list_display = ('id', 'user', 'date', 'sum', 'state')
search_fields = ('id', 'user__card')
readonly_fields = ('user', 'payment_method', 'cashier', 'authenticated_user', 'payment_state', 'payment_reference')
list_display = ('id', 'user_link', 'date', 'sum', 'state', 'payment_state', 'payment_method')
inlines = [OrderLineInline]

def user_link(self, obj):
if obj.user is None:
return '-'
return mark_safe('<a href="{}">{}</a>'.format(
reverse("admin:pos_user_change", args=(obj.user.pk,)),
obj.user
))

user_link.short_description = 'user'


class PrinterAdmin(admin.ModelAdmin):
pass


class SumupReaderAdminForm(forms.ModelForm):
pairing_code = forms.CharField(max_length=255, required=True)

class Meta:
model = SumupReader
fields = ('name', 'user', 'reader_id') # Include all model fields, or specify a subset

class SumupReaderAdmin(admin.ModelAdmin):
form = SumupReaderAdminForm
readonly_fields = ('reader_id',)

def get_form(self, request, obj=None, change=False, **kwargs):
form = super().get_form(request, obj, **kwargs)

if obj:
del form.base_fields['pairing_code']

return form

def save_model(self, request, obj, form, change):
if not change:
obj.reader_id = pair_sumup_reader(form.cleaned_data.get('name'), form.cleaned_data.get('pairing_code'))

super().save_model(request, obj, form, change) # Call the original save_model

class SumupTransactionAdmin(admin.ModelAdmin):
readonly_fields = ('user', 'authenticated_user', 'payment_state', 'payment_reference', 'amount', 'used')
list_display = ('id', 'user_link', 'amount', 'payment_state', 'used')

def user_link(self, obj):
if obj.user is None:
return '-'
return mark_safe('<a href="{}">{}</a>'.format(
reverse("admin:pos_user_change", args=(obj.user.pk,)),
obj.user
))

user_link.short_description = 'user'

admin.site.register(User, UserAdmin)
admin.site.register(Ingredient, IngredientAdmin)
admin.site.register(Item, ItemAdmin)
Expand All @@ -155,12 +201,9 @@ class PrinterAdmin(admin.ModelAdmin):
admin.site.register(Discount, DiscountAdmin)
admin.site.register(CreditUpdate, CreditUpdateAdmin)

admin.site.register(SumUpAPIKey, SumUpAPIKeyAdmin)
admin.site.register(SumUpTerminal, SumUpTerminalAdmin)
admin.site.register(SumUpTransaction, SumUpTransactionAdmin)
admin.site.register(SumUpCard, SumUpCardAdmin)
admin.site.register(SumUpOnline, SumUpOnlineAdmin)

admin.site.register(FoodLog, FoodLogAdmin)

admin.site.register(Printer, PrinterAdmin)
admin.site.register(Printer, PrinterAdmin)

admin.site.register(SumupReader, SumupReaderAdmin)
admin.site.register(SumupTransaction, SumupTransactionAdmin)
7 changes: 6 additions & 1 deletion p0sx/pos/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class CheckCreditForm(forms.Form):
card = forms.CharField(max_length=100, widget=forms.PasswordInput(attrs={'autofocus': 'autofocus'}))
card = forms.CharField(max_length=100, widget=forms.PasswordInput(attrs={'autofocus': 'autofocus', 'autocomplete': 'off'}))


class AddCreditForm(forms.Form):
Expand Down Expand Up @@ -38,6 +38,11 @@ class TimeFilterForm(forms.Form):
to_time = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M'], widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}), required=False)


class CsvTimeFilterForm(forms.Form):
from_time = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M'], widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}), required=True)
to_time = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M'], widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}), required=True)


class RemotePayForm(forms.Form):
phone = forms.CharField(widget=forms.TextInput(attrs={'pattern': '[49]\d{7}', 'minlength': '8', 'maxlength': '8', 'oninvalid': 'this.setCustomValidity(\'Skriv inn et gyldig mobilnummer\')', 'oninput': 'this.setCustomValidity(\'\')'}))
amount = forms.CharField(widget=forms.TextInput(attrs={'pattern': '(5[0-9]|[6-9][0-9]|[1-9][0-9]{2}|1000)', 'oninvalid': 'this.setCustomValidity(\'Skriv inn et beløp mellom kr. 50,- og kr. 1000,-\')', 'oninput': 'this.setCustomValidity(\'\')'}))
33 changes: 33 additions & 0 deletions p0sx/pos/migrations/0021_auto_20251005_0945.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.25 on 2025-10-05 09:45

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('pos', '0020_printer'),
]

operations = [
migrations.AddField(
model_name='order',
name='payment_reference',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='order',
name='payment_state',
field=models.SmallIntegerField(choices=[(0, 'PAID'), (1, 'PENDING'), (2, 'FAILED'), (3, 'CANCELLED')], db_index=True, default=0),
),
migrations.AlterField(
model_name='discount',
name='payment_method',
field=models.SmallIntegerField(choices=[(0, 'CASH'), (1, 'CREDIT'), (2, 'CARD'), (3, 'VIPPS'), (4, 'PREPAID'), (7, 'UNDO')], default=0),
),
migrations.AlterField(
model_name='order',
name='payment_method',
field=models.SmallIntegerField(choices=[(0, 'CASH'), (1, 'CREDIT'), (2, 'CARD'), (3, 'VIPPS'), (4, 'PREPAID'), (7, 'UNDO')], db_index=True, default=0),
),
]
29 changes: 29 additions & 0 deletions p0sx/pos/migrations/0022_sumupreader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 3.2.25 on 2025-10-05 10:16

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('pos', '0021_auto_20251005_0945'),
]

operations = [
migrations.CreateModel(
name='SumupReader',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('reader_id', models.CharField(max_length=255, unique=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'SumUp Card Reader',
'verbose_name_plural': 'SumUp Card Readers',
},
),
]
Loading
Loading