报名表单
This commit is contained in:
@@ -8,7 +8,8 @@ from django.utils import timezone
|
||||
from django.db import models
|
||||
from drf_spectacular.utils import extend_schema
|
||||
|
||||
from shop.models import WeChatUser
|
||||
from shop.models import WeChatUser, Order
|
||||
from shop.views import get_wechat_pay_client
|
||||
from .models import Activity, ActivitySignup, Topic, Reply, TopicMedia, Announcement
|
||||
from .serializers import ActivitySerializer, ActivitySignupSerializer, TopicSerializer, ReplySerializer, TopicMediaSerializer, AnnouncementSerializer
|
||||
from .utils import get_current_wechat_user
|
||||
@@ -37,8 +38,9 @@ class ActivityViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
|
||||
activity = self.get_object()
|
||||
|
||||
# Check if already signed up
|
||||
if ActivitySignup.objects.filter(activity=activity, user=user).exists():
|
||||
# Check if already signed up (and not cancelled)
|
||||
existing_signup = ActivitySignup.objects.filter(activity=activity, user=user).exclude(status='cancelled').first()
|
||||
if existing_signup:
|
||||
return Response({'error': '您已报名该活动'}, status=400)
|
||||
|
||||
# Check limit (exclude cancelled)
|
||||
@@ -49,12 +51,7 @@ class ActivityViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
# Get signup info
|
||||
signup_info = request.data.get('signup_info', {})
|
||||
|
||||
# Basic validation
|
||||
# Re-fetch the config from the object method or serializer logic if needed,
|
||||
# but here we can just use the serializer's method to get the effective config.
|
||||
# However, accessing serializer method from view is tricky without instantiating.
|
||||
# Let's replicate the logic or rely on the fact that we can construct it.
|
||||
|
||||
# Validate signup info
|
||||
effective_config = activity.signup_form_config
|
||||
if not effective_config:
|
||||
effective_config = []
|
||||
@@ -70,17 +67,87 @@ class ActivityViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
if effective_config:
|
||||
required_fields = [f['name'] for f in effective_config if f.get('required')]
|
||||
for field in required_fields:
|
||||
# Simple check: field exists and is not empty string (if it's a string)
|
||||
val = signup_info.get(field)
|
||||
if val is None or (isinstance(val, str) and not val.strip()):
|
||||
# Try to find label for better error message
|
||||
label = next((f['label'] for f in effective_config if f['name'] == field), field)
|
||||
return Response({'error': f'请填写: {label}'}, status=400)
|
||||
|
||||
# Handle Payment Logic
|
||||
if activity.is_paid and activity.price > 0:
|
||||
import time
|
||||
from wechatpayv3 import WeChatPayType
|
||||
|
||||
# Create Order
|
||||
# Check if there is a pending order
|
||||
pending_order = Order.objects.filter(
|
||||
wechat_user=user,
|
||||
activity=activity,
|
||||
status='pending'
|
||||
).first()
|
||||
|
||||
if pending_order:
|
||||
order = pending_order
|
||||
# Update info if needed? Maybe not.
|
||||
else:
|
||||
order = Order.objects.create(
|
||||
wechat_user=user,
|
||||
activity=activity,
|
||||
total_price=activity.price,
|
||||
status='pending',
|
||||
quantity=1,
|
||||
customer_name=signup_info.get('name') or user.nickname or 'Activity User',
|
||||
phone_number=signup_info.get('phone') or user.phone_number or '',
|
||||
)
|
||||
|
||||
# Generate Pay Code
|
||||
out_trade_no = f"ACT{activity.id}U{user.id}T{int(time.time())}"
|
||||
order.out_trade_no = out_trade_no
|
||||
order.save()
|
||||
|
||||
wxpay, error_msg = get_wechat_pay_client(pay_type=WeChatPayType.NATIVE)
|
||||
if not wxpay:
|
||||
return Response({'error': f'支付配置错误: {error_msg}'}, status=500)
|
||||
|
||||
code, message = wxpay.pay(
|
||||
description=f"报名: {activity.title}",
|
||||
out_trade_no=out_trade_no,
|
||||
amount={
|
||||
'total': int(activity.price * 100),
|
||||
'currency': 'CNY'
|
||||
},
|
||||
notify_url=wxpay._notify_url
|
||||
)
|
||||
|
||||
import json
|
||||
result = json.loads(message)
|
||||
if code in range(200, 300):
|
||||
code_url = result.get('code_url')
|
||||
|
||||
# Create a pending signup record so we can update it later
|
||||
ActivitySignup.objects.create(
|
||||
activity=activity,
|
||||
user=user,
|
||||
signup_info=signup_info,
|
||||
status='pending',
|
||||
order=order
|
||||
)
|
||||
|
||||
return Response({
|
||||
'payment_required': True,
|
||||
'code_url': code_url,
|
||||
'order_id': order.id,
|
||||
'price': activity.price,
|
||||
'message': '请完成支付'
|
||||
}, status=200)
|
||||
else:
|
||||
return Response({'error': '支付接口调用失败', 'detail': result}, status=500)
|
||||
|
||||
# Free Activity Signup
|
||||
signup = ActivitySignup.objects.create(
|
||||
activity=activity,
|
||||
user=user,
|
||||
signup_info=signup_info
|
||||
signup_info=signup_info,
|
||||
status='confirmed'
|
||||
)
|
||||
serializer = ActivitySignupSerializer(signup)
|
||||
return Response(serializer.data, status=201)
|
||||
|
||||
Reference in New Issue
Block a user