new invoice design
This commit is contained in:
@@ -46,6 +46,13 @@ def generate_order_invoice(order_id):
|
||||
'final_price': item.price_after_special_discount(),
|
||||
})
|
||||
|
||||
# Resolve image paths for the template (absolute file paths for WeasyPrint)
|
||||
import os
|
||||
template_dir = os.path.join(settings.BASE_DIR, 'templates', 'order')
|
||||
logo_path = os.path.join(template_dir, 'logo2.png')
|
||||
logo_pattern_path = os.path.join(template_dir, 'logo-pattern.png')
|
||||
qr_code_path = os.path.join(template_dir, 'qr-code.png')
|
||||
|
||||
# Use stored model fields for accuracy and consistency
|
||||
context = {
|
||||
'order': order,
|
||||
@@ -66,13 +73,16 @@ def generate_order_invoice(order_id):
|
||||
'final_price': order.final_price or 0, # Stored field: final price after all calculations
|
||||
'is_paid': order.is_paid,
|
||||
'status': order.get_status_display(),
|
||||
'logo_path': logo_path,
|
||||
'logo_pattern_path': logo_pattern_path,
|
||||
'qr_code_path': qr_code_path,
|
||||
}
|
||||
|
||||
# Render HTML template
|
||||
html_string = render_to_string('order/invoice_order.html', context)
|
||||
html_string = render_to_string('order/invoice_order2.html', context)
|
||||
|
||||
# Generate PDF
|
||||
html = HTML(string=html_string, base_url=settings.STATIC_URL)
|
||||
# Generate PDF - use template directory as base_url so images resolve correctly
|
||||
html = HTML(string=html_string, base_url=template_dir)
|
||||
pdf_file = BytesIO()
|
||||
html.write_pdf(pdf_file)
|
||||
pdf_file.seek(0)
|
||||
@@ -146,6 +156,13 @@ def generate_shop_order_invoice(shop_order_id):
|
||||
# Calculate subtotal (cart total before discounts)
|
||||
subtotal = shop_order.subtotal or 0
|
||||
|
||||
# Resolve image paths for the template (absolute file paths for WeasyPrint)
|
||||
import os
|
||||
template_dir = os.path.join(settings.BASE_DIR, 'templates', 'order')
|
||||
logo_path = os.path.join(template_dir, 'logo2.png')
|
||||
logo_pattern_path = os.path.join(template_dir, 'logo-pattern.png')
|
||||
qr_code_path = os.path.join(template_dir, 'qr-code.png')
|
||||
|
||||
# Prepare context for the template
|
||||
context = {
|
||||
'shop_order': shop_order,
|
||||
@@ -175,13 +192,16 @@ def generate_shop_order_invoice(shop_order_id):
|
||||
'is_paid': shop_order.is_paid,
|
||||
'status': shop_order.get_status_display(),
|
||||
'is_settled': shop_order.is_settled,
|
||||
'logo_path': logo_path,
|
||||
'logo_pattern_path': logo_pattern_path,
|
||||
'qr_code_path': qr_code_path,
|
||||
}
|
||||
|
||||
# Render HTML template
|
||||
html_string = render_to_string('order/invoice_shop_order.html', context)
|
||||
html_string = render_to_string('order/invoice_shop_order2.html', context)
|
||||
|
||||
# Generate PDF
|
||||
html = HTML(string=html_string, base_url=settings.STATIC_URL)
|
||||
# Generate PDF - use template directory as base_url so images resolve correctly
|
||||
html = HTML(string=html_string, base_url=template_dir)
|
||||
pdf_file = BytesIO()
|
||||
html.write_pdf(pdf_file)
|
||||
pdf_file.seek(0)
|
||||
|
||||
@@ -16,7 +16,10 @@ urlpatterns = [
|
||||
CallbackView.as_view(), name='callback-gateway'),
|
||||
path('<int:pk>', OrderGetView.as_view(), name='order-get'),
|
||||
|
||||
# Invoice download endpoints
|
||||
# User invoice download endpoint (DRF APIView)
|
||||
path('invoice/<int:order_id>', UserOrderInvoiceView.as_view(), name='user-order-invoice'),
|
||||
|
||||
# Admin invoice download endpoints
|
||||
path('invoice/order/<int:order_id>/download', download_order_invoice, name='download-order-invoice'),
|
||||
path('invoice/shop-order/<int:shop_order_id>/download', download_shop_order_invoice, name='download-shop-order-invoice'),
|
||||
]
|
||||
|
||||
+48
-1
@@ -517,6 +517,53 @@ from django.contrib.auth.decorators import login_required
|
||||
from .invoice_generator import generate_order_invoice, generate_shop_order_invoice
|
||||
|
||||
|
||||
class UserOrderInvoiceView(APIView):
|
||||
"""
|
||||
API endpoint for authenticated users to download their own order invoice PDF.
|
||||
Users can only download invoices for orders that belong to them.
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@extend_schema(
|
||||
tags=["order invoice"],
|
||||
description="Download PDF invoice for the authenticated user's order.",
|
||||
responses={200: OpenApiTypes.BINARY},
|
||||
)
|
||||
def get(self, request, order_id):
|
||||
from .models import OrderModel
|
||||
|
||||
try:
|
||||
order = OrderModel.objects.get(pk=order_id)
|
||||
except OrderModel.DoesNotExist:
|
||||
return Response(
|
||||
{'detail': 'سفارش مورد نظر یافت نشد'},
|
||||
status=status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
|
||||
if order.user != request.user:
|
||||
return Response(
|
||||
{'detail': 'شما اجازه دسترسی به این فاکتور را ندارید'},
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
|
||||
if not order.is_paid:
|
||||
return Response(
|
||||
{'detail': 'فاکتور فقط برای سفارشهای پرداخت شده قابل دانلود است'},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
try:
|
||||
pdf_file = generate_order_invoice(order_id)
|
||||
response = HttpResponse(pdf_file.read(), content_type='application/pdf')
|
||||
response['Content-Disposition'] = f'attachment; filename="invoice_{order_id}.pdf"'
|
||||
return response
|
||||
except Exception as e:
|
||||
return Response(
|
||||
{'detail': f'خطا در ایجاد فاکتور: {str(e)}'},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def download_order_invoice(request, order_id):
|
||||
"""
|
||||
@@ -530,7 +577,7 @@ def download_order_invoice(request, order_id):
|
||||
pdf_file = generate_order_invoice(order_id)
|
||||
|
||||
response = HttpResponse(pdf_file.read(), content_type='application/pdf')
|
||||
response['Content-Disposition'] = f'attachment; filename="order_invoice_{order_id + 1000}.pdf"'
|
||||
response['Content-Disposition'] = f'attachment; filename="order_invoice_{order_id}.pdf"'
|
||||
|
||||
return response
|
||||
except ValueError as e:
|
||||
|
||||
Reference in New Issue
Block a user