You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
depot_django/payments/views.py

264 lines
9.2 KiB
Python

from datetime import datetime
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.db.models import Sum
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import Table, TableStyle, Spacer, Paragraph, SimpleDocTemplate
from common.models import CompanyModel
from common.utils.utils import send_test_email, filter_queryset_by_user
from containers.models import Container
from payments.forms import PaymentCreateForm
from payments.models import Payment, PaymentItem
from payments.services import EPay
from payments.utils import calculate_charges
import io
from django.http import FileResponse, HttpResponse, response
from reportlab.pdfgen import canvas
# Create your views here.
class PaymentCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = Payment
form_class = PaymentCreateForm
template_name = 'employee/payment-create.html'
success_url = reverse_lazy('not_paid')
def test_func(self):
return self.request.user.has_employee_perm('can_manage_payments') or self.request.user.is_superuser
def form_valid(self, form):
last_payment = Payment.objects.order_by('-invoice_number').first()
today = datetime.now().strftime('%Y%m%d')
if last_payment and last_payment.invoice_number.startswith(f'INV-{today}'):
last_number = int(last_payment.invoice_number.split('-')[-1])
new_number = str(last_number + 1).zfill(4)
else:
new_number = '0001'
invoice_number = f'INV-{today}-{new_number}'
payment = form.save(commit=False)
payment.invoice_number = invoice_number
payment.created_by = self.request.user
payment.updated_by = self.request.user
payment.total_amount = 0
payment.save()
container_ids = self.request.POST.getlist('containers')
containers = Container.objects.filter(id__in=container_ids)
for container in containers:
charges = calculate_charges(container)
payment.total_amount += charges['total']
PaymentItem.objects.create(
payment=payment,
container=container,
amount=charges['total'] # Using total charge for the container
)
# 0000000000000000000000000000000000#
urls = EPay.generate_urls(payment.invoice_number, payment.total_amount)
print("Generated URLs:", urls)
payment.save()
send_test_email('kikimor@gmail.com', urls) # invoice and
# 0000000000000000000000000000000000#
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
container_ids = self.request.GET.get('containers', '').split(',')
# Filter only valid IDs (non-empty strings that can be converted to int)
container_ids = [int(id) for id in container_ids if id.strip().isdigit()]
if container_ids:
# Get selected containers
context['containers'] = Container.objects.filter(
id__in=container_ids,
expedited=True,
payment_containers__isnull=True
).order_by('-expedited_on')
return context
def get_form(self, form_class=None):
form = super().get_form(form_class)
company_pk = self.request.GET.get('company', '')
form.fields['company'].initial = company_pk
container_ids = self.request.GET.get('containers', '').split(',')
container_ids = [int(_id) for _id in container_ids if _id.strip().isdigit()]
total_charges = {}
if container_ids:
containers = Container.objects.filter(
id__in=container_ids,
expedited=True,
payment_containers__isnull=True
)
for container in containers:
charges = calculate_charges(container)
total_charges['days'] = total_charges.get('days', 0) + charges.get('days', 0)
total_charges['storage_charge'] = total_charges.get('storage_charge', 0) + charges.get('storage_charge', 0)
total_charges['services_charge'] = total_charges.get('services_charge', 0) + charges.get('services_charge', 0)
total_charges['total'] = total_charges.get('total', 0) + charges.get('total', 0)
form.fields['total_amount'].initial = total_charges['total']
return form
class PaymentListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
model = Payment
template_name = 'common/payment-list.html'
context_object_name = 'objects'
paginate_by = 20
def test_func(self):
return (self.request.user.is_superuser or
self.request.user.user_type == 'CA' or
self.request.user.has_employee_perm('can_view_payments') or
self.request.user.has_company_perm('can_view_payment')
)
def get_queryset(self):
queryset = super().get_queryset()
user = self.request.user
queryset = filter_queryset_by_user(queryset, user)
data_filter = self.request.GET.get('filter')
if data_filter != 'all':
queryset = queryset.filter(paid=False)
queryset = queryset.order_by('-created_on')
return queryset
def some_view(request): # test create pdf invoice
buffer = io.BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=A4)
story = []
styles = getSampleStyleSheet()
# Custom styles
styles.add(ParagraphStyle(
name='RightAlign',
parent=styles['Normal'],
alignment=2 # right alignment
))
# Header data
depot_data = [
['ABC Depot Ltd.'],
['123 Depot Street'],
['Sofia, Bulgaria'],
['VAT: BG123456789'],
['Phone: +359 2 123 4567']
]
customer_data = [
['Customer Company Ltd.'],
['456 Customer Ave.'],
['London, UK'],
['VAT: GB987654321'],
['Contact: John Doe']
]
# Create header table
header_data = [[
Table(depot_data, colWidths=[200]),
Table(customer_data, colWidths=[200])
]]
header_table = Table(header_data, colWidths=[250, 250])
header_table.setStyle(TableStyle([
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('VALIGN', (0, 0), (-1, -1), 'TOP'),
]))
story.append(header_table)
story.append(Spacer(1, 30))
# Invoice title and number
story.append(Paragraph('INVOICE', styles['Heading1']))
story.append(Paragraph('Invoice No: INV-20240220-0001', styles['Normal']))
story.append(Paragraph('Date: 20.02.2024', styles['Normal']))
story.append(Spacer(1, 20))
# Invoice table data
table_data = [
['Container Type', 'Days', 'Swept', 'Washed', 'Amount'],
['20\' Container', '15', 'Yes', 'No', '€450.00'],
['40\' Container', '10', 'Yes', 'Yes', '€750.00'],
]
# Create invoice table
invoice_table = Table(table_data, colWidths=[120, 80, 80, 80, 100])
invoice_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('GRID', (0, 0), (-1, -1), 1, colors.black),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
]))
story.append(invoice_table)
story.append(Spacer(1, 20))
# Total amount
total_text = f'Total Amount: €1,200.00'
story.append(Paragraph(total_text, styles['RightAlign']))
# Build PDF
doc.build(story, onFirstPage=add_watermark)
pdf = buffer.getvalue()
buffer.close()
# Create response
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'inline; filename="invoice.pdf"'
response.write(pdf)
return response
def add_watermark(canvas, doc):
canvas.saveState()
canvas.setFillColorRGB(0.9, 0.9, 0.9)
canvas.setFont('Helvetica', 80)
canvas.rotate(45)
canvas.drawString(200, 000, 'ORIGINAL')
canvas.restoreState()
return response
def on_payment_result(encoded, checksum):
fields_dict, checksum_result = EPay.payment_result(encoded, checksum)
status = fields_dict["STATUS"]
invoice = fields_dict["INVOICE"]
if not checksum_result:
return f"INVOICE={invoice}:STATUS=ERR"
payment = Payment.objects.get(invoice_number=invoice)
if not payment:
return f"INVOICE={invoice}:STATUS=NO"
match status:
case "PAID":
payment.status = "paid"
payment.paid_on = datetime.now()
payment.pay_time = fields_dict["PAY_TIME"]
payment.pay_stan = fields_dict["STAN"]
payment.pay_bcode = fields_dict["BCODE"]
case "DENIED":
payment.status = "denied"
case "EXPIRED":
payment.status = "expired"
payment.save()
return f"INVOICE={invoice}:STATUS=OK"