| @@ -206,25 +206,26 @@ def good_exchange(request): | ||
| 206 | 206 | if user.integral < good.integral: | 
| 207 | 207 | return response(MemberGoodStatusCode.GOOD_INTEGRAL_NOT_ENOUGH) | 
| 208 | 208 |  | 
| 209 | + # 校验重复兑换 | |
| 210 | + if good.only_once and GoodsOrderInfo.objects.filter(user_id=user_id, good_id=good_id, status=True).exists(): | |
| 211 | + return response(MemberGoodStatusCode.GOOD_EXCHANGE_ONLY_ONCE) | |
| 212 | + | |
| 209 | 213 | user.integral -= good.integral | 
| 210 | 214 | user.save() | 
| 211 | 215 |  | 
| 212 | 216 | good.left_num -= 1 | 
| 213 | 217 | good.save() | 
| 214 | 218 |  | 
| 215 | - # 校验重复兑换 | |
| 216 | - is_exists = GoodsOrderInfo.objects.filter(user_id=user_id, good_id=good_id, status=True).exists() | |
| 217 | - if not is_exists: | |
| 218 | - GoodsOrderInfo.objects.create( | |
| 219 | - user_id=user_id, | |
| 220 | - good_id=good_id, | |
| 221 | - good_type=good.good_type, | |
| 222 | - title=good.title, | |
| 223 | - name=name, | |
| 224 | - phone=phone, | |
| 225 | - address=address, | |
| 226 | - integral=good.integral, | |
| 227 | - ) | |
| 219 | + GoodsOrderInfo.objects.create( | |
| 220 | + user_id=user_id, | |
| 221 | + good_id=good_id, | |
| 222 | + good_type=good.good_type, | |
| 223 | + title=good.title, | |
| 224 | + name=name, | |
| 225 | + phone=phone, | |
| 226 | + address=address, | |
| 227 | + integral=good.integral, | |
| 228 | + ) | |
| 228 | 229 |  | 
| 229 | 230 | if good.good_type == GoodsInfo.PHYSICAL: | 
| 230 | 231 | # TODO: 通知客服发快递 | 
| @@ -0,0 +1,20 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.11.29 on 2021-04-25 07:01 | |
| 3 | +from __future__ import unicode_literals | |
| 4 | + | |
| 5 | +from django.db import migrations, models | |
| 6 | + | |
| 7 | + | |
| 8 | +class Migration(migrations.Migration): | |
| 9 | + | |
| 10 | + dependencies = [ | |
| 11 | +        ('member', '0028_auto_20210115_1108'), | |
| 12 | + ] | |
| 13 | + | |
| 14 | + operations = [ | |
| 15 | + migrations.AddField( | |
| 16 | + model_name='goodsinfo', | |
| 17 | + name='only_once', | |
| 18 | + field=models.BooleanField(default=False, help_text='\u4ec5\u652f\u6301\u5151\u6362\u4e00\u6b21', verbose_name='only_once'), | |
| 19 | + ), | |
| 20 | + ] | 
| @@ -47,6 +47,7 @@ class GoodsInfo(BaseModelMixin): | ||
| 47 | 47 | minlevel = models.IntegerField(_(u'minlevel'), default=0, help_text=u'兑换最低会员级别', db_index=True) | 
| 48 | 48 |  | 
| 49 | 49 | only_for_member = models.BooleanField(_(u'only_for_member'), default=False, help_text=u'会员专属') | 
| 50 | + only_once = models.BooleanField(_(u'only_once'), default=False, help_text=u'仅支持兑换一次') | |
| 50 | 51 |  | 
| 51 | 52 | position = models.IntegerField(_(u'position'), default=1, help_text=u'排序', db_index=True) | 
| 52 | 53 |  | 
| @@ -81,6 +81,7 @@ class MemberGoodStatusCode(BaseStatusCode): | ||
| 81 | 81 | GOOD_NO_EXCHANGE_PERMISSION = StatusCodeField(503502, 'Good No Exchange Permission', description=u'商品无兑换权限') | 
| 82 | 82 | GOOD_INTEGRAL_NOT_ENOUGH = StatusCodeField(503503, 'Good Integral Not Enough', description=u'商品兑换积分不足') | 
| 83 | 83 | GOOD_STOCK_NOT_ENOUGH = StatusCodeField(503504, 'Good Integral Not Enough', description=u'商品库存不足') | 
| 84 | + GOOD_EXCHANGE_ONLY_ONCE = StatusCodeField(503505, 'Good Exchange Only Once', description=u'商品仅可兑换一次') | |
| 84 | 85 |  | 
| 85 | 86 |  | 
| 86 | 87 | class MemberRightStatusCode(BaseStatusCode): |