# coding=utf-8 from django.db import models, transaction from django.utils import timezone from django.conf import settings from django.contrib.auth import get_user_model from utils.wx.wechat import WeChat from utils.exceptions import CustomError from utils.wx.WXBizDataCrypt import WXBizDataCrypt from apps.WechatApplet.models import WechatApplet User = get_user_model() class Customer(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'用户', editable=False, related_name='customer_user', on_delete=models.PROTECT) is_distributor = models.BooleanField(verbose_name=u"分销商", default=False) name = models.CharField(max_length=100, verbose_name=u"姓名") tel = models.CharField(max_length=50, verbose_name=u'电话') gender = models.PositiveSmallIntegerField(choices=settings.GENDER_CHOICES, verbose_name=u'性别', null=True) face = models.CharField(max_length=200, verbose_name=u'头像', null=True) balance = models.BigIntegerField(verbose_name=u'余额', default=0, editable=False) points = models.IntegerField(verbose_name=u'积分', default=0, editable=False) success_count = models.IntegerField(verbose_name=u'成交次数', default=0, editable=False) total_amount = models.BigIntegerField(verbose_name=u'累计消费金额', default=0, editable=False) total_point = models.IntegerField(verbose_name=u'累计消费积分', default=0, editable=False) class Meta: db_table = "customer" verbose_name = u'客户管理' ordering = ['-id'] index_together = ( 'name', 'tel', ) default_permissions = () permissions = [] @staticmethod def get_or_create_customer(user, referrer): ''' :param user: 用户 :param referrer: 推荐人 被推荐人是新用户的时候 要创建上级分销记录 :return: ''' customer = Customer.objects.filter(user=user).first() if customer: return customer with transaction.atomic(): customer = Customer.objects.create(user=user, name=user.username, tel=user.username) if referrer: customer.create_distributor(referrer) return customer def create_distributor(self, re_customer): referrer = Customer.objects.filter(id=re_customer).first() if not referrer: return '' distributor = SuperiorDistributor.objects.create(customer=self, one_level=referrer) re_distributor = SuperiorDistributor.objects.filter(customer=referrer).first() if re_distributor: distributor.two_level = re_distributor.one_level distributor.three_level = re_distributor.two_level distributor.four_level = re_distributor.three_level distributor.five_level = re_distributor.four_level distributor.save() def setInfo(self, appid, openid, encryptedData, iv): wx_customer = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first() if not wx_customer: raise CustomError(u'未找到相应的微信客户!') if wx_customer.customer and wx_customer.customer.id != self.id: raise CustomError(u'该微信已同步其他客户!') if not wx_customer.customer: wx_customer.customer = self wx_customer.save() pc = WXBizDataCrypt(wx_customer.wechat_app.authorizer_appid, wx_customer.session_key) result = pc.decrypt(encryptedData, iv) self.name = result['nickName'] self.gender = result['gender'] self.face = result['avatarUrl'] self.save() return self.face, self.name ''' -------------------------------------------------分销商备注--------------------------------------- A——>B 只有B是新用户的时候B才能成为A的一级分销商 A——>B AB都不是分销商 B也是A的一级分销商 A——>B——>C——>D——>E——>F——>G——>H 按分销商级别记录 0 1 2 3 4 5 BCDEF分别是A的五级分销商 F消费 F是A的五级分销商 A按五级返利比例获取返利 F是B的四级分销商 B按四级返利比例获取返利...... 计算返利时 我要去找F分别是谁的几级分销商 不好计算 A——>B——>C——>D——>E——>F——>G——>H 按各级分销商获取返利的返利级别记录(计算方便所以选择这种方式) 5 4 3 2 1 0 F消费 F是A的五级分销商 A按五级返利比例获取返利 F是B的四级分销商 B按四级返利比例获取返利...... 计算返利时 只需要找F的各级返利是谁 好计算返利 A——>B——>C——>D——>E——>F——>G——>H 5 4 3 2 1 0 如果F消费 要根据系统设置比例分别给他的上级分销商(F/E/D/C/B/A)返利 如果E不是分销商那么E就不获得返利 如果E不是分销商那么D是按二级返利比例获取返利 如果E后来成为分销商后 F再消费E还能获取返利 要查看X的一级分销商都有谁 只需要查一级返利关联X的客户 查分销商Y下级分销商 SuperiorDistributor.objects.filter(Q(one_level=Y) | Q(two_level=Y) | Q(three_level=Y) | Q(four_level=Y) | Q(five_level=Y))的customer就是Y的下级分销 ''' class SuperiorDistributor(models.Model): customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, related_name='superior_distributor_customer', on_delete=models.PROTECT) one_level = models.ForeignKey(Customer, verbose_name=u'一级返利', related_name='superior_distributor_one_level', on_delete=models.PROTECT, null=True, blank=True) two_level = models.ForeignKey(Customer, verbose_name=u'二级返利', related_name='superior_distributor_tow_level', on_delete=models.PROTECT, null=True, blank=True) three_level = models.ForeignKey(Customer, verbose_name=u'三级返利', related_name='superior_distributor_three_level', on_delete=models.PROTECT, null=True, blank=True) four_level = models.ForeignKey(Customer, verbose_name=u'四级返利', related_name='superior_distributor_four_level', on_delete=models.PROTECT, null=True, blank=True) five_level = models.ForeignKey(Customer, verbose_name=u'五级返利', related_name='superior_distributor_five_level', on_delete=models.PROTECT, null=True, blank=True) class Meta: db_table = "superior_distributor" verbose_name = u'上级分销' ordering = ['-id'] default_permissions = () permissions = [] class CustomerWechat(models.Model): wechat_app = models.ForeignKey(WechatApplet, verbose_name=u'小程序', on_delete=models.PROTECT, editable=False) customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT, editable=False, null=True) openid = models.CharField(max_length=512, verbose_name=u"openid") session_key = models.CharField(max_length=512, verbose_name=u'session_key',null=True) class Meta: db_table = "customer_wechat" verbose_name = u'微信客户' unique_together = [ ('openid') ] default_permissions = () @staticmethod def login(code, appid): ''' 微信自动登录小程序 :param code: :param appid: :return: ''' wx = WechatApplet.getByAppid(appid) res = WeChat.code2Session(appid, wx.secret, code) instance = CustomerWechat.objects.filter(openid=res['openid'], wechat_app=wx).first() if not instance: instance = CustomerWechat.objects.create(wechat_app=wx, openid=res['openid'], session_key=res['session_key']) else: instance.session_key = res['session_key'] instance.save() return instance @staticmethod def bindWechat(appid, openid, phoneEncryptedData, phoneIv, referrer): ''' 微信登录小程序 判断是否有推荐人,如果有且推荐人是分销商,就要创建上级分销表,同时查询推荐人是否存在上级分销表 如果存在就要将推荐人的上级分销相应的添加到本人的上级分销表里 :param appid: :param openid: :param phoneEncryptedData: :param phoneIv: :return: ''' wx_customer = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first() if not wx_customer: raise CustomError(u'未找到相应的微信客户!') pc = WXBizDataCrypt(appid, wx_customer.session_key) phon_data = pc.decrypt(phoneEncryptedData, phoneIv) tel = phon_data['purePhoneNumber'] if wx_customer.customer: if wx_customer.customer.user.username != tel: raise CustomError(u'微信绑定的手机号与系统记录的不符!') else: return wx_customer.customer user = User.objects.filter(username=tel).first() if not user: user = User.objects.create_customer(tel, password=tel, **{'is_active': True}) customer = Customer.objects.filter(user=user).first() if not customer: customer = Customer.get_or_create_customer(user, referrer) wx_customer.customer = customer wx_customer.save() return customer class CustomerAddress(models.Model): customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT, editable=False) name = models.CharField(verbose_name=u'收货人姓名', max_length=20) tel = models.CharField(verbose_name=u'收货人电话', max_length=11) province = models.CharField(verbose_name=u'省', max_length=100, null=True) city = models.CharField(verbose_name=u'市', max_length=100, null=True) area = models.CharField(verbose_name=u'县/区', max_length=100, null=True) address = models.CharField(verbose_name=u'详细地址', max_length=500) default = models.BooleanField(verbose_name=u'默认', default=False) delete = models.BooleanField(verbose_name=u'删除', default=False, editable=False) create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now, editable=False) class Meta: db_table = 'customer_address' verbose_name = u'收货地址' ordering = ['-default', '-id'] default_permissions = () def get_address(self): return '{}{}{}{}'.format(self.province, self.city, self.area, self.address) def destory(self, queryset): if self.default: self.default = False default = queryset.first() if default: default.default = True default.save() self.delete = True self.save()