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.
264 lines
9.2 KiB
Python
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" |