def _homeview(request, invoice_objects, unpaid=False, pending=False, deleted=False, paid=False, searchterm=None): # Utility function for all main invoice views, so make the shared permissions # check here. authenticate_backend_group(request, 'Invoice managers') # Add info about refunds to all invoices invoice_objects = invoice_objects.extra(select={ 'has_refund': 'EXISTS (SELECT 1 FROM invoices_invoicerefund r WHERE r.invoice_id=invoices_invoice.id)', }) # Render a list of all invoices (invoices, paginator, page_range) = simple_pagination(request, invoice_objects, 50) has_pending = Invoice.objects.filter(finalized=False).exists() has_unpaid = Invoice.objects.filter(finalized=True, paidat__isnull=False).exists() return render(request, 'invoices/home.html', { 'invoices': invoices, 'paid': paid, 'unpaid': unpaid, 'pending': pending, 'deleted': deleted, 'has_pending': has_pending, 'has_unpaid': has_unpaid, 'searchterm': searchterm, 'page_range': page_range, 'breadcrumbs': [('/invoiceadmin/', 'Invoices'), ], 'helplink': 'payment', })
def bankfile_transactions(request, methodid): authenticate_backend_group(request, 'Invoice managers') method = get_object_or_404(InvoicePaymentMethod, pk=methodid) # Needed for backlinks methodcount = InvoicePaymentMethod.objects.filter( config__has_key='file_upload_interval').count() backbutton = "../" breadlabel = "Bank transactions" if methodcount == 1: # If there is only one method, we have to return all the way back to the index page, or we'll # just get redirected back to ourselves. backbutton = "/admin/" q = Q(method=method) if 'file' in request.GET: q = q & Q(fromfile=get_int_or_error(request.GET, 'file')) backbutton = "../../" breadlabel = "Bankfiles" allrows = BankStatementRow.objects.filter(q).order_by('-date', 'id') (rows, paginator, page_range) = simple_pagination(request, allrows, 50) extrakeys = set() hasvaluefor = { 'uniqueid': False, 'balance': False, } for r in rows: extrakeys.update(r.other.keys()) for k in hasvaluefor.keys(): if getattr(r, k, None): hasvaluefor[k] = True params = request.GET.copy() if 'page' in params: del params['page'] return render( request, 'invoices/bankfile_transactions.html', { 'rows': rows, 'extrakeys': extrakeys, 'hasvaluefor': hasvaluefor, 'page_range': page_range, 'topadmin': 'Invoices', 'helplink': 'payment', 'requestparams': params.urlencode(), 'breadcrumbs': [ (backbutton, breadlabel), ], 'backbutton': backbutton, })
def bankfiles(request): authenticate_backend_group(request, 'Invoice managers') if request.method == 'POST': # Uploading a file! method = get_object_or_404(InvoicePaymentMethod, active=True, config__has_key='file_upload_interval', id=get_int_or_error(request.POST, 'id')) if 'f' not in request.FILES: messages.error(request, "No file included in upload") elif request.FILES['f'].size < 1: messages.error(request, "Uploaded file is empty") else: f = request.FILES['f'] impl = method.get_implementation() try: (contents, numrows, numtrans, numpending) = impl.parse_uploaded_file(f) BankFileUpload( method=method, uploadby=request.user.username, name=f.name, textcontents=contents, parsedrows=numrows, newtrans=numtrans, newpending=numpending, ).save() messages.info( request, "File uploaded. {} rows parsed, {} transactions stored, resulting in {} pending transactions." .format(numrows, numtrans, numpending)) return HttpResponseRedirect('.') except Exception as e: messages.error(request, "Error uploading file: {}".format(e)) methods = InvoicePaymentMethod.objects.filter( active=True, config__has_key='file_upload_interval').annotate( latest_file=Max('bankfileupload__created')) file_objects = BankFileUpload.objects.select_related( 'method').all().order_by('-created')[:1000] (files, paginator, page_range) = simple_pagination(request, file_objects, 50) return render( request, 'invoices/bankfiles.html', { 'files': files, 'page_range': page_range, 'methods': methods, 'topadmin': 'Invoices', 'helplink': 'payment', })
def job(request, jobid): if not request.user.is_superuser: raise PermissionDenied("Access denied") job = get_object_or_404(ScheduledJob, id=jobid) if request.method == 'POST': if request.POST.get('schedule-now', '') == '1': job.nextrun = timezone.now() job.save() notify_job_change() messages.info( request, "Scheduled immediate run of '{0}'".format(job.description)) return HttpResponseRedirect('../') elif request.POST.get('reset-failure', '') == '1': job.lastrun = None job.lastrunsuccess = False job.save() messages.info( request, "Reset last run failure state of '{0}'".format( job.description)) return HttpResponseRedirect('../') form = ScheduledJobForm(request, conference=None, instance=job, data=request.POST) if form.is_valid(): form.save() reschedule_job(job, notify=True) return HttpResponseRedirect("../") else: form = ScheduledJobForm(request, conference=None, instance=job) history_objects = JobHistory.objects.filter(job=job).order_by('-time') (history, paginator, page_range) = simple_pagination(request, history_objects, 15) return render( request, 'scheduler/job.html', { 'job': job, 'history': history, 'form': form, 'page_range': page_range, 'breadcrumbs': [ ('/admin/jobs/', 'Scheduled jobs'), ], 'helplink': 'jobs', })
def refunds(request): authenticate_backend_group(request, 'Invoice managers') refund_objects = InvoiceRefund.objects.\ select_related('invoice', 'invoice__paidusing').\ only('id', 'invoice_id', 'completed', 'issued', 'registered', 'reason', 'invoice__paidusing__internaldescription').\ order_by(F('completed').desc(nulls_first=True), F('issued').desc(nulls_first=True), F('registered').desc()) (refunds, paginator, page_range) = simple_pagination(request, refund_objects, 20) return render(request, 'invoices/refunds.html', { 'refunds': refunds, 'page_range': page_range, 'breadcrumbs': [('/admin/invoices/refunds/', 'Refunds'), ], 'helplink': 'payment', })
def history(request): if not request.user.is_superuser: raise PermissionDenied("Access denied") history_objects = JobHistory.objects.only( 'time', 'job__description', 'success', 'runtime').select_related('job').order_by('-time') (history, paginator, page_range) = simple_pagination(request, history_objects, 50) return render( request, 'scheduler/history.html', { 'history': history, 'page_range': page_range, 'breadcrumbs': [ ('/admin/jobs/', 'Scheduled jobs'), ], 'helplink': 'jobs', })
def bankfiles(request): authenticate_backend_group(request, 'Invoice managers') if request.method == 'POST': # Uploading a file! method = get_object_or_404(InvoicePaymentMethod, active=True, config__has_key='file_upload_interval', id=get_int_or_error(request.POST, 'id')) impl = method.get_implementation() # Stage 1 upload has the file in request.FILES. Stage 2 has it in a hidden field in the form instead, # because we can't make it upload th file twice. if 'fc' in request.POST: # In stage 2 the file is included ase base64 txt = impl.convert_uploaded_file_to_utf8( BytesIO(base64.b64decode(request.POST['fc']))) try: rows = impl.parse_uploaded_file_to_rows(txt) (anyerror, extrakeys, hasvaluefor) = impl.process_loaded_rows(rows) numrows = len(rows) numtrans = 0 numpending = 0 numerrors = 0 with transaction.atomic(): # Store thef file itself bankfile = BankFileUpload( method=method, parsedrows=numrows, newtrans=0, newpending=0, errors=0, uploadby=request.user.username, name=request.POST['name'], textcontents=txt, ) bankfile.save() # To get an id we can use for r in rows: if r['row_already_exists']: continue if r.get('row_errors', []): numerrors += 1 continue # Insert the row b = BankStatementRow( method=method, fromfile=bankfile, uniqueid=r.get('uniqueid', None), date=r['date'], amount=r['amount'], description=r['text'], balance=r.get('balance', None), other=r['other'], ) b.save() numtrans += 1 if not register_bank_transaction( b.method, b.id, b.amount, b.description, ''): # This means the transaction wasn't directly matched and has been # registered as a pending transaction. numpending += 1 bankfile.newtrans = numtrans bankfile.newpending = numpending bankfile.errors = numerrors bankfile.save() except Exception as e: messages.error(request, "Error uploading file: {}".format(e)) return HttpResponseRedirect(".") if 'f' not in request.FILES: messages.error(request, "No file included in upload") elif request.FILES['f'].size < 1: messages.error(request, "Uploaded file is empty") else: f = request.FILES['f'] try: # Stage 1, mean we parse it and render a second form to confirm rows = impl.parse_uploaded_file_to_rows( impl.convert_uploaded_file_to_utf8(f)) (anyerror, extrakeys, hasvaluefor) = impl.process_loaded_rows(rows) f.seek(0) return render( request, 'invoices/bankfile_uploaded.html', { 'method': method, 'rows': rows, 'extrakeys': sorted(extrakeys), 'hasvaluefor': hasvaluefor, 'anyerror': anyerror, 'filename': f.name, 'fc': base64.b64encode(f.read()).decode('ascii'), 'topadmin': 'Invoices', 'helplink': 'payment', 'breadcrumbs': [ ('../../', 'Bank files'), ], }) except Exception as e: messages.error(request, "Error uploading file: {}".format(e)) methods = InvoicePaymentMethod.objects.filter( active=True, config__has_key='file_upload_interval').annotate( latest_file=Max('bankfileupload__created')) file_objects = BankFileUpload.objects.select_related( 'method').all().order_by('-created')[:1000] (files, paginator, page_range) = simple_pagination(request, file_objects, 50) return render( request, 'invoices/bankfiles.html', { 'files': files, 'page_range': page_range, 'methods': methods, 'topadmin': 'Invoices', 'helplink': 'payment', })