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"