diff --git a/osinaweb/billing/add/urls.py b/osinaweb/billing/add/urls.py new file mode 100644 index 00000000..860eb6fe --- /dev/null +++ b/osinaweb/billing/add/urls.py @@ -0,0 +1,20 @@ +from django.urls import path +from billing.add import views + + +urlpatterns = [ + path('product', views.add_product, name='addproduct'), + path('service', views.add_service, name='addservice'), + path('order//', views.add_order, name='addorder'), + + path('invoice-pdf//', views.add_invoice_pdf, name='addinvoice'), + path('payment-pdf//', views.add_payment_pdf, name='addpayment'), + + path('service///', views.add_service_in_order, name='addserviceinorder'), + + path('payment_method_modal/', views.add_payment_method_modal, name='add_payment_method_modal'), + path('payment//', views.add_payment_modal, name='add_payment_modal'), + path('payment_comment/', views.add_payment_comment_modal, name='add_payment_comment_modal'), + + +] diff --git a/osinaweb/billing/add/views.py b/osinaweb/billing/add/views.py new file mode 100644 index 00000000..c1b41a70 --- /dev/null +++ b/osinaweb/billing/add/views.py @@ -0,0 +1,349 @@ +from django.shortcuts import render, get_object_or_404, redirect +from osinacore.models import * +from billing.models import * +from django.http import JsonResponse, HttpResponse +from django.template.loader import get_template +from django.conf import settings +import os +from osinacore.decorators import * +from django.core.files.base import ContentFile +from django.db.models import Q +from weasyprint import HTML, CSS + + +@staff_login_required +def add_product(request, *args, **kwargs): + item_types = ProjectType.objects.all().order_by('name') + if request.method == 'POST': + title = request.POST.get('title') + description = request.POST.get('description') + + item_type_id = request.POST.get('item_type') + item_type = get_object_or_404(ProjectType, id=item_type_id) + + amount = request.POST.get('amount') + recurring = request.POST.get('recurring') + + Item.objects.create( + type='Product', + title=title, + description = description, + item_type = item_type, + amount = amount, + recurring = recurring, + ) + return redirect('items') + context = { + 'item_types' : item_types, + + } + return render(request, 'add_templates/add-product.html', context) + + +@staff_login_required +def add_service (request, *args, **kwargs): + item_types = ProjectType.objects.all().order_by('name') + customers = CustomerProfile.objects.all().order_by('user__first_name') + if request.method == 'POST': + title = request.POST.get('title') + description = request.POST.get('description') + + customer_id = request.POST.get('customer') + customer = get_object_or_404(CustomerProfile, id=customer_id) + + item_type_id = request.POST.get('item_type') + item_type = get_object_or_404(ProjectType, id=item_type_id) + + amount = request.POST.get('amount') + recurring = request.POST.get('recurring') + + Item.objects.create( + type='Service', + title=title, + description = description, + customer = customer, + item_type = item_type, + amount = amount, + recurring = recurring, + ) + return redirect('items') + context = { + 'item_types' : item_types, + 'customers' : customers + } + return render(request, 'add_templates/add-service.html', context) + + +@staff_login_required +def add_order(request, customer_id): + customer= get_object_or_404(CustomerProfile, id=customer_id) + businesses = Business.objects.filter(customer=customer) + services = Item.objects.filter(Q(type='Service') & (Q(customer=customer) | Q(customer__isnull=True))) + + if request.method == 'POST': + business_id = request.POST.get('business') + date = request.POST.get('date') + if business_id: + business = get_object_or_404(Business, id=business_id) + else: + business = None + + + order = Order.objects.create( + customer=customer, + business=business, + date=date + ) + + selected_services_ids = request.POST.getlist('service') + for service_id in selected_services_ids: + service = get_object_or_404(Item, id=service_id) + order_item = OrderItem.objects.create( + order=order, + item=service, + purchased_at=datetime.now() + ) + + return redirect('orderdetails', order_id=order.order_id) + + context = { + 'customer' : customer, + 'businesses' : businesses, + 'services' : services, + } + + return render(request, 'add_templates/add-order.html', context) + + + +@staff_login_required +def add_service_in_order(request, service_id, order_id): + service =get_object_or_404(Item, id=service_id) + order= get_object_or_404(Order, id=order_id) + + order_item = OrderItem.objects.create( + order = order, + item = service, + purchased_at = datetime.now() + ) + order_item.save() + return redirect('orderdetails', order_id=order.order_id) + + + + +@staff_login_required +def add_payment_method_modal(request, *args, **kwargs): + if request.method == 'POST': + name = request.POST.get('name') + description = request.POST.get('description') + image = request.FILES.get('image') + + payment_method = PaymentType( + name = name, + description = description, + image = image + ) + payment_method.save() + + # Reload the parent page + return HttpResponse('') + return render(request, 'add_templates/add-payment-method-modal.html') + + + + +@staff_login_required +def add_payment_modal(request, order_id): + order = get_object_or_404(Order, id=order_id) + methods = PaymentType.objects.all().order_by('name') + if request.method == 'POST': + amount = request.POST.get('amount') + + if request.POST.get('date_paid'): + date_paid = request.POST.get('date_paid') + else: + date_paid = None + + if request.POST.get('date_due'): + date_due = request.POST.get('date_due') + else: + date_due = None + + comment = request.POST.get('comment') + selected_methods = request.POST.getlist('methods') + + payment = OrderPayment( + order = order, + amount = amount, + date_paid = date_paid, + date_due = date_due, + comment = comment + ) + payment.save() + + for method_id in selected_methods: + method = get_object_or_404(PaymentType, id=method_id) + payment.type.add(method) + + + # Reload the parent page + return HttpResponse('') + + context = { + 'methods': methods, + 'order': order + } + + return render(request, 'add_templates/add-payment-modal.html', context) + + + + +@staff_login_required +def add_payment_comment_modal(request): + + context = { + + } + + return render(request, 'add_templates/add-payment-comment-modal.html', context) + + + +def add_invoice_pdf(request, order_id): + order = get_object_or_404(Order, id=order_id) + + current_year = str(timezone.now().year)[-2:] + last_invoice = Invoice.objects.all().last() + if last_invoice: + last_invoice_number = int(last_invoice.invoice_number.split('-')[1].split('+')[0]) + new_invoice_number = f"$0{current_year}-{last_invoice_number + 1}" + else: + new_invoice_number = f"$0{current_year}-1425" + + + + invoice = Invoice.objects.create( + invoice_number = new_invoice_number, + order=order, + date_created=datetime.now(), + ) + + template = get_template('details_templates/invoice-details.html') + context = {'order': order} + html_string = template.render(context) + + # Define the CSS string with Poppins font + css_string = ''' + @font-face { + font-family: 'Poppins'; + src: url('path_to_poppins_font_file.ttf') format('truetype'); /* Update the path to the font file */ + } + + body { + font-family: 'Poppins', sans-serif; /* Use Poppins font for the entire document */ + } + + /* Your existing CSS styles */ + /* Add or modify styles as needed */ + ''' + + # Generate PDF + pdf = HTML(string=html_string).write_pdf( + stylesheets=[ + CSS(string=css_string), + CSS(string='@page { margin: 30px; }') + ], + presentational_hints=True + ) + + filename = f'invoice_{invoice.invoice_number}.pdf' + pdf_content = ContentFile(pdf) + invoice.pdf.save(filename, pdf_content, save=True) + + + # Return PDF + response = HttpResponse(pdf, content_type='application/pdf') + response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"' + return response + + + + + + + +def add_payment_pdf(request, order_id): + order = get_object_or_404(Order, id=order_id) + payments = OrderPayment.objects.filter(order = order) + paid_amount = OrderPayment.objects.filter(order=order, date_paid__isnull=False).aggregate(total_paid=Sum('amount'))['total_paid'] or 0 + cart_total = order.get_cart_total + remaining_amount = cart_total - paid_amount + + + invoice = order.invoice + + # Render both invoice and payment details templates to HTML + invoice_template = get_template('details_templates/invoice-details.html') + payment_template = get_template('details_templates/payment-details.html') + invoice_html = invoice_template.render({'order': order}) + payment_html = payment_template.render({'order': order, 'payments':payments, 'remaining_amount':remaining_amount,}) + + # Combine the HTML content of both templates + combined_html = f"{invoice_html}
{payment_html}" + + # Define CSS + css_string = ''' + @font-face { + font-family: 'Poppins'; + src: url('path_to_poppins_font_file.ttf') format('truetype'); /* Update the path to the font file */ + } + + body { + font-family: 'Poppins', sans-serif; /* Use Poppins font for the entire document */ + } + + /* Your existing CSS styles */ + /* Add or modify styles as needed */ + ''' + + # Generate PDF + pdf = HTML(string=combined_html).write_pdf( + stylesheets=[ + CSS(string=css_string), + CSS(string='@page { margin: 30px; }') + ], + presentational_hints=True + ) + + # Return PDF + response = HttpResponse(pdf, content_type='application/pdf') + response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"' + return response + + + + + + + + + + + + + + + + + + + + + + + + + +