|  | # -*- coding: utf-8 -*-
from __future__ import division
from django.conf import settings
from django.db import transaction
from django.db.models import Sum
from django_logit import logit
from django_query import get_query_value
from django_response import response
from paginator import pagination
from pywe_miniapp import get_shareinfo
from pywe_storage import RedisStorage
from TimeConvert import TimeConvert as tc
from account.models import UserInfo
from coupon.models import UserCouponInfo
from member.models import (GoodsInfo, GoodsOrderInfo, MemberActivityGroupShareInfo, MemberActivityInfo,
                           MemberActivitySigninInfo, MemberActivitySignupInfo, RightInfo)
from utils.error.errno_utils import (MemberActivityStatusCode, MemberCouponStatusCode, MemberGoodStatusCode,
                                     MemberRightStatusCode, UserStatusCode)
from utils.redis.connect import r
from utils.redis.rkeys import MEMBER_SEND_COUPON_LIST, MEMBER_UPGRADE_INFO
from utils.redis.rshot import get_member_shot_data
WECHAT = settings.WECHAT
@logit
def member(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    # 校验用户是否存在
    try:
        user = UserInfo.objects.get(user_id=user_id)
    except UserInfo.DoesNotExist:
        return response(UserStatusCode.USER_NOT_FOUND)
    rights = RightInfo.objects.filter(status=True).order_by('position')
    rights = [right.data for right in rights]
    goods = GoodsInfo.objects.filter(only_for_member=False, left_num__gt=0, status=True).order_by('position')
    goods = [good.data(user_id) for good in goods][:2]
    member_goods = GoodsInfo.objects.filter(only_for_member=True, left_num__gt=0, minlevel__lte=user.level, status=True).order_by('position')
    member_goods = [good.data(user_id) for good in member_goods]
    member_goods = [good for good in member_goods if not good['has_member_exchange']]
    upgrade_info, _ = r.getdel(MEMBER_UPGRADE_INFO % (brand_id, user_id))
    return response(data={
        'nickname': user.final_nickname,
        'avatar': user.avatar,
        'integral': user.integral,
        'freeze_integral': user.freeze_integral,
        'final_integral': user.final_integral,
        'shots_num': user.shots_num,
        'level': user.level,
        'rights': rights,
        'goods': goods,
        'member_goods': member_goods,
        'has_upgrade': bool(upgrade_info),
    })
@logit
def rights(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    level = request.POST.get('level', '')
    # 校验用户是否存在
    try:
        user = UserInfo.objects.get(user_id=user_id)
    except UserInfo.DoesNotExist:
        return response(UserStatusCode.USER_NOT_FOUND)
    rights = RightInfo.objects.filter(status=True).order_by('position')
    rights = [right.data for right in rights]
    return response(data={
        'nickname': user.final_nickname,
        'avatar': user.avatar,
        'integral': user.integral,
        'freeze_integral': user.freeze_integral,
        'final_integral': user.final_integral,
        'shots_num': user.shots_num,
        'level': user.level,
        'rights': rights,
    })
@logit
def right_detail(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    right_id = request.POST.get('right_id', '')
    try:
        right = RightInfo.objects.get(right_id=right_id)
    except RightInfo.DoesNotExist:
        return response(MemberRightStatusCode.RIGHT_NOT_FOUND)
    return response(data={
        'right': right.data,
    })
@logit
def goods(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    # 校验用户是否存在
    try:
        user = UserInfo.objects.get(user_id=user_id)
    except UserInfo.DoesNotExist:
        return response(UserStatusCode.USER_NOT_FOUND)
    raw_goods = GoodsInfo.objects.filter(only_for_member=False, left_num__gt=0, status=True).order_by('position', '-pk')
    banners = goods = []
    for good in raw_goods:
        if good.is_slider:
            banners.append(good.data(user_id))
        else:
            goods.append(good.data(user_id))
    return response(data={
        'nickname': user.final_nickname,
        'avatar': user.avatar,
        'integral': user.integral,
        'freeze_integral': user.freeze_integral,
        'final_integral': user.final_integral,
        'shots_num': user.shots_num,
        'level': user.level,
        'banners': banners,
        'goods': goods,
    })
@logit
def good_detail(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    good_id = request.POST.get('good_id', '')
    # 校验用户是否存在
    try:
        user = UserInfo.objects.get(user_id=user_id)
    except UserInfo.DoesNotExist:
        return response(UserStatusCode.USER_NOT_FOUND)
    try:
        good = GoodsInfo.objects.get(good_id=good_id)
    except GoodsInfo.DoesNotExist:
        return response(MemberGoodStatusCode.GOOD_NOT_FOUND)
    return response(data={
        'nickname': user.final_nickname,
        'avatar': user.avatar,
        'integral': user.integral,
        'freeze_integral': user.freeze_integral,
        'final_integral': user.final_integral,
        'shots_num': user.shots_num,
        'level': user.level,
        'good': good.details(user_id),
    })
@logit
@transaction.atomic
def good_exchange(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    good_id = request.POST.get('good_id', '')
    good_ids = get_query_value(request, 'good_ids', val_cast_type='listjson')
    name = request.POST.get('name', '')
    phone = request.POST.get('phone', '')
    address = request.POST.get('address', '')
    # 校验用户是否存在
    try:
        user = UserInfo.objects.select_for_update().get(user_id=user_id)
    except UserInfo.DoesNotExist:
        return response(UserStatusCode.USER_NOT_FOUND)
    if good_id:
        good_ids.append(good_id)
    goods = []
    for good_id in good_ids:
        try:
            good = GoodsInfo.objects.select_for_update().get(good_id=good_id)
        except GoodsInfo.DoesNotExist:
            return response(MemberGoodStatusCode.GOOD_NOT_FOUND)
        if good.left_num <= 0:
            return response(MemberGoodStatusCode.GOOD_STOCK_NOT_ENOUGH)
        if user.level < good.minlevel:
            return response(MemberGoodStatusCode.GOOD_NO_EXCHANGE_PERMISSION)
        if user.integral < good.integral:
            return response(MemberGoodStatusCode.GOOD_INTEGRAL_NOT_ENOUGH)
        user.integral -= good.integral
        user.save()
        good.left_num -= 1
        good.save()
        GoodsOrderInfo.objects.create(
            user_id=user_id,
            good_id=good_id,
            good_type=good.good_type,
            title=good.title,
            name=name,
            phone=phone,
            address=address,
            integral=good.integral,
        )
        if good.good_type == GoodsInfo.PHYSICAL:
            # TODO: 通知客服发快递
            pass
        else:
            # TODO: 发放虚拟商品
            if good.coupon_id:
                # 发放券
                r.rpushjson(MEMBER_SEND_COUPON_LIST, {
                    'brand_id': brand_id,
                    'user_id': user_id,
                    'coupon_id': good.coupon_id,
                })
            else:
                pass
        goods.append(good.data(user_id))
    return response(data={
        'nickname': user.final_nickname,
        'avatar': user.avatar,
        'integral': user.integral,
        'freeze_integral': user.freeze_integral,
        'final_integral': user.final_integral,
        'shots_num': user.shots_num,
        'level': user.level,
        'goods': goods,
    })
@logit
def coupons(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    page = request.POST.get('page', 1)
    num = request.POST.get('num', 20)
    coupons = UserCouponInfo.objects.filter(user_id=user_id, has_used=False, status=True).order_by('-pk')
    coupons, left = pagination(coupons, page, num)
    coupons = [coupon.data for coupon in coupons if not coupon.has_used]
    return response(data={
        'coupons': coupons,
        'left': left,
    })
@logit
def user_coupon_detail(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_coupon_id = request.POST.get('user_coupon_id', '')
    try:
        coupon = UserCouponInfo.objects.get(user_coupon_id=user_coupon_id, status=True)
    except UserCouponInfo.DoesNotExist:
        return response(MemberCouponStatusCode.USER_COUPON_NOT_FOUND)
    return response(data=coupon.data)
@logit
@transaction.atomic
def user_coupon_use(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    admin_id = request.POST.get('admin_id', '')
    user_coupon_id = request.POST.get('user_coupon_id', '')
    try:
        coupon = UserCouponInfo.objects.select_for_update().get(user_coupon_id=user_coupon_id, status=True)
    except UserCouponInfo.DoesNotExist:
        return response(MemberCouponStatusCode.USER_COUPON_NOT_FOUND)
    if not coupon.has_actived:
        return response(MemberCouponStatusCode.USER_COUPON_NOT_ACTIVED)
    if coupon.has_expired:
        return response(MemberCouponStatusCode.USER_COUPON_HAS_EXPIRED)
    if coupon.has_used:
        return response(MemberCouponStatusCode.USER_COUPON_HAS_USED)
    coupon.has_used = True
    coupon.admin_id = admin_id
    coupon.used_at = tc.utc_datetime()
    coupon.save()
    return response(data=coupon.data)
@logit
def integrals(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    return response(data={
        'shots_types': get_member_shot_data(),
        'enable_photo_upvote_integral': True,
        'mp_url': 'https://mp.weixin.qq.com/s/2K6PAnf3KrxtrP40-DBuww',
        'photo_upvote_integrals': {
            'headers': [u'排名', u'日', u'周', u'月'],
            'ranks': [
                [u'第1名', '10', '20', '30'],
                [u'第2名', '5', '10', '15'],
                [u'第3名', '3', '6', '9'],
                [u'第4-10名', '1', '2', '3'],
            ]
        },
        'enable_activity_integral': True,
    })
@logit
def activity_list(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    raw_activitys = MemberActivityInfo.objects.filter(activity_state=1, status=True).order_by('-date')
    banners = []
    activitys = []
    for act in raw_activitys:
        if act.is_slider:
            banners.append(act.data(user_id))
        else:
            activitys.append(act.data(user_id))
    return response(data={
        'banners': banners,
        'activitys': activitys,
    })
@logit
def activity_detail(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    activity_id = request.POST.get('activity_id')
    try:
        act = MemberActivityInfo.objects.get(activity_id=activity_id, status=True)
    except MemberActivityInfo.DoesNotExist:
        return response(MemberActivityStatusCode.ACTIVITY_NOT_FOUND)
    return response(data={
        'activity': act.details(user_id),
    })
@logit
def activity_signup(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    activity_id = request.POST.get('activity_id')
    name = request.POST.get('name', '')
    phone = request.POST.get('phone', '')
    try:
        act = MemberActivityInfo.objects.get(activity_id=activity_id, status=True)
    except MemberActivityInfo.DoesNotExist:
        return response(MemberActivityStatusCode.ACTIVITY_NOT_FOUND)
    MemberActivitySignupInfo.objects.update_or_create(user_id=user_id, activity_id=activity_id, defaults={
        'title': act.title,
        'name': name,
        'phone': phone,
    })
    # TODO: 立即推送模版消息(报名成功,时间,地点)
    # TODO: 延迟(活动当天)推送模版消息(时间,地点)
    return response(data={
        'activity': act.data(user_id),
    })
@logit
@transaction.atomic
def activity_signin(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    user_id = request.POST.get('user_id', '')
    activity_id = request.POST.get('activity_id')
    # 校验用户是否存在
    try:
        user = UserInfo.objects.select_for_update().get(user_id=user_id)
    except UserInfo.DoesNotExist:
        return response(UserStatusCode.USER_NOT_FOUND)
    try:
        act = MemberActivityInfo.objects.get(activity_id=activity_id, status=True)
    except MemberActivityInfo.DoesNotExist:
        return response(MemberActivityStatusCode.ACTIVITY_NOT_FOUND)
    MemberActivitySigninInfo.objects.update_or_create(user_id=user_id, activity_id=activity_id, defaults={
        'title': act.title,
    })
    user.integral += act.integral
    user.save()
    # TODO: 立即推送模版消息(感谢您参加活动,获得的积分)
    return response(data={
        'activity': act.data(user_id),
    })
def get_group_share_info_integral(activity_id, share_user_id, open_gid, group_share_integral, group_share_max_integral):
    # 校验该分享人是否已领取该群积分
    has_integral = MemberActivityGroupShareInfo.objects.filter(activity_id=activity_id, share_user_id=share_user_id, open_gid=open_gid, is_integral=True).exists()
    if has_integral:
        return False, 0
    # 校验该分享人是否已领取该活动积分上限
    total_integral = MemberActivityGroupShareInfo.objects.filter(activity_id=activity_id, share_user_id=share_user_id).aggregate(Sum('integral')).get('integral__sum', 0) or 0
    if total_integral + group_share_integral > group_share_max_integral:
        return False, 0
    return True, group_share_integral
@logit
@transaction.atomic
def activity_group_share(request):
    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    share_user_id = request.POST.get('share_user_id', '')
    click_user_id = request.POST.get('click_user_id', '')
    activity_id = request.POST.get('activity_id')
    iv = request.POST.get('iv', '')
    encryptedData = request.POST.get('encryptedData', '')
    wxcfg = WECHAT.get('MINIAPP', {})
    appid = wxcfg.get('appID')
    secret = wxcfg.get('appsecret')
    # {
    #     "openGId": "OPENGID"
    # }
    shareinfo = get_shareinfo(appid=appid, secret=secret, unid=click_user_id, session_key=None, encryptedData=encryptedData, iv=iv, storage=RedisStorage(r))
    open_gid = shareinfo.get('openGId')
    if not open_gid:
        return response()
    
    try:
        user = UserInfo.objects.get(user_id=share_user_id, status=True)
    except:
        return response(UserStatusCode.USER_NOT_FOUND)
    try:
        act = MemberActivityInfo.objects.select_for_update().get(activity_id=activity_id, status=True)
    except MemberActivityInfo.DoesNotExist:
        return response(MemberActivityStatusCode.ACTIVITY_NOT_FOUND)
    
    isOffline = act.activity_state != 1 or act.final_state == '已结束'
    # 判断是否给积分 & 给多少积分
    is_integral, integral = get_group_share_info_integral(act.activity_id, share_user_id, open_gid, act.group_share_integral, act.group_share_max_integral)
    # 活动未结束,则给用户加积分
        
    if is_integral:
        MemberActivityGroupShareInfo.objects.create(**{
            'brand_id': act.brand_id,
            'brand_name': act.brand_name,
            'share_user_id': share_user_id,
            'click_user_id': click_user_id,
            'open_gid': open_gid,
            'activity_id': activity_id,
            'title': act.title,
            'is_integral': is_integral,
            'integral': 0 if isOffline else integral,
        })
        if not isOffline:
            user.integral += integral
            user.save()
    if isOffline:
        return response(400002, 'Activity has been offline', '会员活动已下线')
    return response()
 |