models.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # coding=utf-8
  2. from django.db import models, transaction
  3. from django.utils import timezone
  4. from django.conf import settings
  5. from django.contrib.auth import get_user_model
  6. from utils.wx.wechat import WeChat
  7. from utils.exceptions import CustomError
  8. from utils.wx.WXBizDataCrypt import WXBizDataCrypt
  9. from apps.WechatApplet.models import WechatApplet
  10. User = get_user_model()
  11. class Customer(models.Model):
  12. user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u'用户', editable=False, related_name='customer_user', on_delete=models.PROTECT)
  13. is_distributor = models.BooleanField(verbose_name=u"分销商", default=False)
  14. name = models.CharField(max_length=100, verbose_name=u"姓名")
  15. tel = models.CharField(max_length=50, verbose_name=u'电话')
  16. gender = models.PositiveSmallIntegerField(choices=settings.GENDER_CHOICES, verbose_name=u'性别', null=True)
  17. face = models.CharField(max_length=200, verbose_name=u'头像', null=True)
  18. balance = models.BigIntegerField(verbose_name=u'余额', default=0, editable=False)
  19. points = models.IntegerField(verbose_name=u'积分', default=0, editable=False)
  20. success_count = models.IntegerField(verbose_name=u'成交次数', default=0, editable=False)
  21. total_amount = models.BigIntegerField(verbose_name=u'累计消费金额', default=0, editable=False)
  22. total_point = models.IntegerField(verbose_name=u'累计消费积分', default=0, editable=False)
  23. class Meta:
  24. db_table = "customer"
  25. verbose_name = u'客户管理'
  26. ordering = ['-id']
  27. index_together = (
  28. 'name',
  29. 'tel',
  30. )
  31. default_permissions = ()
  32. permissions = []
  33. @staticmethod
  34. def get_or_create_customer(user, referrer):
  35. '''
  36. :param user: 用户
  37. :param referrer: 推荐人 被推荐人是新用户的时候 要创建上级分销记录
  38. :return:
  39. '''
  40. customer = Customer.objects.filter(user=user).first()
  41. if customer:
  42. return customer
  43. with transaction.atomic():
  44. customer = Customer.objects.create(user=user, name=user.username, tel=user.username)
  45. if referrer:
  46. customer.create_distributor(referrer)
  47. return customer
  48. def create_distributor(self, re_customer):
  49. referrer = Customer.objects.filter(id=re_customer).first()
  50. if not referrer:
  51. return ''
  52. distributor = SuperiorDistributor.objects.create(customer=self, one_level=referrer)
  53. re_distributor = SuperiorDistributor.objects.filter(customer=referrer).first()
  54. if re_distributor:
  55. distributor.two_level = re_distributor.one_level
  56. distributor.three_level = re_distributor.two_level
  57. distributor.four_level = re_distributor.three_level
  58. distributor.five_level = re_distributor.four_level
  59. distributor.save()
  60. def setInfo(self, appid, openid, encryptedData, iv):
  61. wx_customer = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first()
  62. if not wx_customer:
  63. raise CustomError(u'未找到相应的微信客户!')
  64. if wx_customer.customer and wx_customer.customer.id != self.id:
  65. raise CustomError(u'该微信已同步其他客户!')
  66. if not wx_customer.customer:
  67. wx_customer.customer = self
  68. wx_customer.save()
  69. pc = WXBizDataCrypt(wx_customer.wechat_app.authorizer_appid, wx_customer.session_key)
  70. result = pc.decrypt(encryptedData, iv)
  71. self.name = result['nickName']
  72. self.gender = result['gender']
  73. self.face = result['avatarUrl']
  74. self.save()
  75. return self.face, self.name
  76. '''
  77. -------------------------------------------------分销商备注---------------------------------------
  78. A——>B
  79. 只有B是新用户的时候B才能成为A的一级分销商
  80. A——>B
  81. AB都不是分销商 B也是A的一级分销商
  82. A——>B——>C——>D——>E——>F——>G——>H 按分销商级别记录
  83. 0 1 2 3 4 5
  84. BCDEF分别是A的五级分销商
  85. F消费
  86. F是A的五级分销商 A按五级返利比例获取返利
  87. F是B的四级分销商 B按四级返利比例获取返利......
  88. 计算返利时 我要去找F分别是谁的几级分销商 不好计算
  89. A——>B——>C——>D——>E——>F——>G——>H 按各级分销商获取返利的返利级别记录(计算方便所以选择这种方式)
  90. 5 4 3 2 1 0
  91. F消费
  92. F是A的五级分销商 A按五级返利比例获取返利
  93. F是B的四级分销商 B按四级返利比例获取返利......
  94. 计算返利时 只需要找F的各级返利是谁 好计算返利
  95. A——>B——>C——>D——>E——>F——>G——>H
  96. 5 4 3 2 1 0
  97. 如果F消费 要根据系统设置比例分别给他的上级分销商(F/E/D/C/B/A)返利
  98. 如果E不是分销商那么E就不获得返利
  99. 如果E不是分销商那么D是按二级返利比例获取返利
  100. 如果E后来成为分销商后 F再消费E还能获取返利
  101. 要查看X的一级分销商都有谁 只需要查一级返利关联X的客户
  102. 查分销商Y下级分销商
  103. 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的下级分销
  104. '''
  105. class SuperiorDistributor(models.Model):
  106. customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, related_name='superior_distributor_customer', on_delete=models.PROTECT)
  107. one_level = models.ForeignKey(Customer, verbose_name=u'一级返利', related_name='superior_distributor_one_level', on_delete=models.PROTECT, null=True, blank=True)
  108. two_level = models.ForeignKey(Customer, verbose_name=u'二级返利', related_name='superior_distributor_tow_level', on_delete=models.PROTECT, null=True, blank=True)
  109. three_level = models.ForeignKey(Customer, verbose_name=u'三级返利', related_name='superior_distributor_three_level', on_delete=models.PROTECT, null=True, blank=True)
  110. four_level = models.ForeignKey(Customer, verbose_name=u'四级返利', related_name='superior_distributor_four_level', on_delete=models.PROTECT, null=True, blank=True)
  111. five_level = models.ForeignKey(Customer, verbose_name=u'五级返利', related_name='superior_distributor_five_level', on_delete=models.PROTECT, null=True, blank=True)
  112. class Meta:
  113. db_table = "superior_distributor"
  114. verbose_name = u'上级分销'
  115. ordering = ['-id']
  116. default_permissions = ()
  117. permissions = []
  118. class CustomerWechat(models.Model):
  119. wechat_app = models.ForeignKey(WechatApplet, verbose_name=u'小程序', on_delete=models.PROTECT, editable=False)
  120. customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT, editable=False, null=True)
  121. openid = models.CharField(max_length=512, verbose_name=u"openid")
  122. session_key = models.CharField(max_length=512, verbose_name=u'session_key',null=True)
  123. class Meta:
  124. db_table = "customer_wechat"
  125. verbose_name = u'微信客户'
  126. unique_together = [
  127. ('openid')
  128. ]
  129. default_permissions = ()
  130. @staticmethod
  131. def login(code, appid):
  132. '''
  133. 微信自动登录小程序
  134. :param code:
  135. :param appid:
  136. :return:
  137. '''
  138. wx = WechatApplet.getByAppid(appid)
  139. res = WeChat.code2Session(appid, wx.secret, code)
  140. instance = CustomerWechat.objects.filter(openid=res['openid'], wechat_app=wx).first()
  141. if not instance:
  142. instance = CustomerWechat.objects.create(wechat_app=wx, openid=res['openid'], session_key=res['session_key'])
  143. else:
  144. instance.session_key = res['session_key']
  145. instance.save()
  146. return instance
  147. @staticmethod
  148. def bindWechat(appid, openid, phoneEncryptedData, phoneIv, referrer):
  149. '''
  150. 微信登录小程序
  151. 判断是否有推荐人,如果有且推荐人是分销商,就要创建上级分销表,同时查询推荐人是否存在上级分销表 如果存在就要将推荐人的上级分销相应的添加到本人的上级分销表里
  152. :param appid:
  153. :param openid:
  154. :param phoneEncryptedData:
  155. :param phoneIv:
  156. :return:
  157. '''
  158. wx_customer = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first()
  159. if not wx_customer:
  160. raise CustomError(u'未找到相应的微信客户!')
  161. pc = WXBizDataCrypt(appid, wx_customer.session_key)
  162. phon_data = pc.decrypt(phoneEncryptedData, phoneIv)
  163. tel = phon_data['purePhoneNumber']
  164. if wx_customer.customer:
  165. if wx_customer.customer.user.username != tel:
  166. raise CustomError(u'微信绑定的手机号与系统记录的不符!')
  167. else:
  168. return wx_customer.customer
  169. user = User.objects.filter(username=tel).first()
  170. if not user:
  171. user = User.objects.create_customer(tel, password=tel, **{'is_active': True})
  172. customer = Customer.objects.filter(user=user).first()
  173. if not customer:
  174. customer = Customer.get_or_create_customer(user, referrer)
  175. wx_customer.customer = customer
  176. wx_customer.save()
  177. return customer
  178. class CustomerAddress(models.Model):
  179. customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT, editable=False)
  180. name = models.CharField(verbose_name=u'收货人姓名', max_length=20)
  181. tel = models.CharField(verbose_name=u'收货人电话', max_length=11)
  182. province = models.CharField(verbose_name=u'省', max_length=100, null=True)
  183. city = models.CharField(verbose_name=u'市', max_length=100, null=True)
  184. area = models.CharField(verbose_name=u'县/区', max_length=100, null=True)
  185. address = models.CharField(verbose_name=u'详细地址', max_length=500)
  186. default = models.BooleanField(verbose_name=u'默认', default=False)
  187. delete = models.BooleanField(verbose_name=u'删除', default=False, editable=False)
  188. create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now, editable=False)
  189. class Meta:
  190. db_table = 'customer_address'
  191. verbose_name = u'收货地址'
  192. ordering = ['-default', '-id']
  193. default_permissions = ()
  194. def get_address(self):
  195. return '{}{}{}{}'.format(self.province, self.city, self.area, self.address)
  196. def destory(self, queryset):
  197. if self.default:
  198. self.default = False
  199. default = queryset.first()
  200. if default:
  201. default.default = True
  202. default.save()
  203. self.delete = True
  204. self.save()