combo/combo/apps/lingo/manager_views.py

193 lines
6.8 KiB
Python

# lingo - basket and payment system
# Copyright (C) 2015 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import csv
import datetime
from dateutil import parser as date_parser
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.db.models import Q
from django.db.models.expressions import RawSQL
from django.utils import six
from django.utils.timezone import make_aware, now
from django.views.generic import CreateView, UpdateView, ListView, DeleteView, View
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template.response import TemplateResponse
import eopayment
from .forms import RegieForm
from .forms import TransactionExportForm
from .models import BasketItem, PaymentBackend, Regie, Transaction
class RegieListView(ListView):
model = Regie
class RegieCreateView(CreateView):
model = Regie
fields = ['label', 'slug', 'description', 'payment_backend']
success_url = reverse_lazy('lingo-manager-regie-list')
class RegieUpdateView(UpdateView):
model = Regie
form_class = RegieForm
success_url = reverse_lazy('lingo-manager-regie-list')
class RegieDeleteView(DeleteView):
model = Regie
success_url = reverse_lazy('lingo-manager-regie-list')
class PaymentBackendListView(ListView):
model = PaymentBackend
class PaymentBackendCreateView(CreateView):
model = PaymentBackend
fields = '__all__'
success_url = reverse_lazy('lingo-manager-paymentbackend-list')
class PaymentBackendUpdateView(UpdateView):
model = PaymentBackend
fields = '__all__'
success_url = reverse_lazy('lingo-manager-paymentbackend-list')
class PaymentBackendDeleteView(DeleteView):
model = PaymentBackend
success_url = reverse_lazy('lingo-manager-paymentbackend-list')
class TransactionListView(ListView):
model = Transaction
paginate_by = 10
def get_context_data(self, **kwargs):
context = super(TransactionListView, self).get_context_data(**kwargs)
context['query'] = self.request.GET.get('q') or ''
return context
def get_queryset(self):
qs = Transaction.objects.filter(
status__in=(eopayment.PAID, eopayment.ACCEPTED)).order_by('-start_date')
query = self.request.GET.get('q')
if query:
try:
date = date_parser.parse(query, dayfirst=True)
except:
qs = qs.filter(
Q(order_id=query) |
Q(bank_transaction_id=query) |
Q(items__subject__icontains=query)
)
else:
date = make_aware(date)
qs = qs.filter(start_date__gte=date, start_date__lt=date + datetime.timedelta(days=1))
return qs
class BasketItemErrorListView(ListView):
model = BasketItem
template_name = 'lingo/basketitem_error_list.html'
paginate_by = 10
def get_context_data(self, **kwargs):
context = super(BasketItemErrorListView, self).get_context_data(**kwargs)
context['query'] = self.request.GET.get('q') or ''
return context
def get_queryset(self):
raw = (
'SELECT %s FROM lingo_transaction '
'INNER JOIN lingo_transaction_items '
'ON "lingo_transaction"."id" = "lingo_transaction_items"."transaction_id" '
'AND "lingo_transaction_items"."basketitem_id"="lingo_basketitem"."id" '
'ORDER BY start_date DESC LIMIT 1')
queryset = (
BasketItem.objects
.annotate(bank_transaction_id=RawSQL(raw % 'bank_transaction_id', []))
.annotate(transaction_status=RawSQL(raw % 'status', []))
.filter(regie__webservice_url='')
.order_by())
terms = self.request.GET.get('q')
if terms:
queryset = queryset.filter(subject__icontains=terms)
queryset1 = (
queryset
.filter(
notification_date__isnull=True,
cancellation_date__isnull=True,
payment_date__lt=now() - datetime.timedelta(minutes=300)))
queryset2 = queryset.filter(transaction_status=eopayment.ERROR)
return queryset1.union(queryset2).order_by('-creation_date')
class BasketItemMarkAsNotifiedView(View):
def get(self, request, *args, **kwargs):
item = get_object_or_404(
BasketItem.objects.exclude(source_url=''),
pk=kwargs['item_id'],
regie__webservice_url='',
notification_date__isnull=True,
cancellation_date__isnull=True,
payment_date__lt=now() - datetime.timedelta(minutes=300))
item.notify_payment(notify_origin=False)
return HttpResponseRedirect(reverse('lingo-manager-payment-error-list'))
def download_transactions_csv(request):
if request.method == 'POST':
form = TransactionExportForm(data=request.POST)
if form.is_valid():
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="transactions.csv"'
writer = csv.writer(response)
transactions = (
Transaction.objects
.filter(
status__in=(eopayment.PAID, eopayment.ACCEPTED),
start_date__gte=form.cleaned_data['start_date'],
start_date__lte=form.cleaned_data['end_date'],
).order_by('-start_date'))
for transaction in transactions:
row = [transaction.order_id,
transaction.bank_transaction_id,
transaction.start_date.strftime('%Y-%m-%d %H:%M:%S'),
transaction.get_user_name(),
str(transaction.amount)]
for item in transaction.items.all():
row.extend([item.subject, str(item.amount)])
if six.PY3:
writer.writerow([x for x in row])
else:
writer.writerow([unicode(x).encode('utf-8') for x in row])
return response
else:
form = TransactionExportForm()
return TemplateResponse(request, 'lingo/transaction_export.html', {'form': form})