|
# -*- coding: utf-8 -*-
from django.db import IntegrityError, transaction
from django.utils import timezone
from django_logit import logit
from django_response import response
from django.db.models import Q
from account.models import UserInfo
from sales.models import LotteryCampaignInfo, LotteryEntryInfo
from utils.error.errno_utils import LotteryStatusCode, UserStatusCode
def join_lottery(user, serial_no, model_id='', campaign_id='', submit_pk='', phone='', model_name=''):
"""
写入抽奖名额(幂等)
返回 (entry, campaign, is_new):
· 没有进行中的活动 → (None, None, False)
· 已有名额 → (entry, campaign, False)
· 首次参与 → (entry, campaign, True)
"""
serial_no = (serial_no or '').strip()
campaign = LotteryCampaignInfo.objects.get(status=True, campaign_id=campaign_id)
if not campaign:
return None, None
# 嵌套 atomic 生成 savepoint:并发插入冲突后还能继续查询
with transaction.atomic():
entry, created = LotteryEntryInfo.objects.get_or_create(
campaign_id=campaign.campaign_id,
serial_no=serial_no,
submit_pk=submit_pk,
title=campaign.title,
phone=phone,
user_id=user.user_id,
model_id=model_id,
model_name=model_name,
)
return entry, campaign
@logit(res=True)
@transaction.atomic
def lottery_join_api(request):
"""抽奖参与接口:写入名额"""
user_id = request.POST.get('user_id', '')
serial_no = request.POST.get('serial_no')
model_id = request.POST.get('model_id')
campaign_id = request.POST.get('campaign_id', '')
submit_pk = request.POST.get('submit_pk', '')
phone = request.POST.get('phone', '')
model_name = request.POST.get('model_name', '')
try:
user = UserInfo.objects.select_for_update().get(user_id=user_id)
except UserInfo.DoesNotExist:
return response(UserStatusCode.USER_NOT_FOUND)
# TODO 安全:应校验该序列号确实绑定在当前用户名下,防止传入他人序列号刷名额
entry, campaign = join_lottery(user, serial_no, model_id, campaign_id, submit_pk, phone, model_name)
if not campaign:
return response(LotteryStatusCode.CAMPAIGN_NOT_FOUND)
return response(200, data={
'campaign': serialize_campaign(campaign),
'entry': serialize_entry(entry),
})
|