Add public refund creation endpoint and PDF generation
Introduces RefundPublicView for public refund creation via email and invoice/order ID, returning refund info and a base64-encoded PDF slip. Adds RefundCreatePublicSerializer for validation and creation, implements PDF generation in Refund model, and provides a customer-facing HTML template for the return slip. Updates URLs to expose the new endpoint.
This commit is contained in:
@@ -1,4 +1,71 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Refund, Order, Invoice
|
||||
|
||||
|
||||
class RefundCreatePublicSerializer(serializers.Serializer):
|
||||
email = serializers.EmailField()
|
||||
invoice_number = serializers.CharField(required=False, allow_blank=True)
|
||||
order_id = serializers.IntegerField(required=False)
|
||||
|
||||
# Optional reason fields
|
||||
reason_choice = serializers.ChoiceField(
|
||||
choices=Refund.Reason.choices, required=False
|
||||
)
|
||||
reason_text = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
def validate(self, attrs):
|
||||
email = attrs.get("email")
|
||||
invoice_number = (attrs.get("invoice_number") or "").strip()
|
||||
order_id = attrs.get("order_id")
|
||||
|
||||
if not invoice_number and not order_id:
|
||||
raise serializers.ValidationError(
|
||||
"Provide either invoice_number or order_id."
|
||||
)
|
||||
|
||||
order = None
|
||||
if invoice_number:
|
||||
try:
|
||||
invoice = Invoice.objects.get(invoice_number=invoice_number)
|
||||
order = invoice.order
|
||||
except Invoice.DoesNotExist:
|
||||
raise serializers.ValidationError({"invoice_number": "Invoice not found."})
|
||||
except Order.DoesNotExist:
|
||||
raise serializers.ValidationError({"invoice_number": "Order for invoice not found."})
|
||||
|
||||
if order_id and order is None:
|
||||
try:
|
||||
order = Order.objects.get(id=order_id)
|
||||
except Order.DoesNotExist:
|
||||
raise serializers.ValidationError({"order_id": "Order not found."})
|
||||
|
||||
# Verify email matches order's email or user's email
|
||||
if not order:
|
||||
raise serializers.ValidationError("Order could not be resolved.")
|
||||
|
||||
order_email = (order.email or "").strip().lower()
|
||||
user_email = (getattr(order.user, "email", "") or "").strip().lower()
|
||||
provided = email.strip().lower()
|
||||
if provided not in {order_email, user_email}:
|
||||
raise serializers.ValidationError({"email": "Email does not match the order."})
|
||||
|
||||
attrs["order"] = order
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
order = validated_data["order"]
|
||||
reason_choice = validated_data.get("reason_choice") or Refund.Reason.OTHER
|
||||
reason_text = validated_data.get("reason_text", "")
|
||||
|
||||
refund = Refund.objects.create(
|
||||
order=order,
|
||||
reason_choice=reason_choice,
|
||||
reason_text=reason_text,
|
||||
)
|
||||
return refund
|
||||
|
||||
from rest_framework import serializers
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from decimal import Decimal
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
Reference in New Issue
Block a user