models.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #coding=utf-8
  2. import datetime
  3. from django.db import models
  4. from django.utils import timezone
  5. from django.conf import settings
  6. from apps.exceptions import CustomError
  7. from apps.account.models import Branch
  8. from apps.customer.models import Customer
  9. from util.wechatpay import WechatPay, WeChatResponse
  10. class Activity(models.Model):
  11. branch = models.ForeignKey(Branch, verbose_name=u"门店", on_delete=models.PROTECT)
  12. title = models.CharField(max_length=200, verbose_name=u"标题")
  13. describe = models.TextField(verbose_name=u'活动介绍')
  14. end_date = models.DateField(verbose_name=u"截止日期")
  15. amount = models.FloatField(verbose_name=u"费用", default=0)
  16. rebate = models.FloatField(verbose_name=u"返利", default=0)
  17. check_status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, verbose_name=u"审核", editable=False, default=settings.DEFAULT)
  18. branch_name = models.CharField(max_length=200, verbose_name=u"门店名称", null=True, blank=True)
  19. branch_tel = models.CharField(max_length=50, verbose_name=u"门店电话", null=True, blank=True)
  20. branch_address = models.CharField(max_length=200, verbose_name=u"门店地址", null=True, blank=True)
  21. required_signs = models.CharField(verbose_name=u'必填项', max_length=300, null=True, editable=False)
  22. create_time = models.DateTimeField(verbose_name=u"添加时间", auto_now_add=True, editable=False)
  23. enabled = models.BooleanField(verbose_name=u"在用", default=True)
  24. delete = models.BooleanField(verbose_name=u"删除", default=False)
  25. @staticmethod
  26. def getById1(id):
  27. try:
  28. id = int(id)
  29. except:
  30. raise CustomError(u'无效的活动')
  31. instance = Activity.objects.filter(pk=id).first()
  32. if not instance:
  33. raise CustomError(u'未找到相应的活动')
  34. return instance
  35. class Meta:
  36. db_table = "activity"
  37. ordering = ['-id']
  38. verbose_name = u"活动管理"
  39. def checkStatus(self):
  40. if not self.enabled:
  41. raise CustomError(u'该活动已禁用!')
  42. if self.delete:
  43. raise CustomError(u'该活动已删除!')
  44. if self.check_status != settings.PASS:
  45. raise CustomError(u'该活动尚未生效!')
  46. now = datetime.datetime.date(timezone.now())
  47. if self.end_date and now > self.end_date:
  48. raise CustomError(u'该活动已过期!')
  49. @staticmethod
  50. def getById(id):
  51. try:
  52. id = int(id)
  53. except:
  54. raise CustomError(u'无效的活动ID')
  55. instance = Activity.objects.filter(pk=id, delete=False, enabled=True).first()
  56. if not instance:
  57. raise CustomError(u'未找到相应的活动')
  58. return instance
  59. class Pay(models.Model):
  60. WAIT = 1
  61. CONFIRM = 2
  62. CLOSED = 3
  63. STATUS_CHOICES = (
  64. (WAIT, u'待付款'),
  65. (CONFIRM, u'已付款'),
  66. (CLOSED, u'已关闭'),
  67. )
  68. branch = models.ForeignKey(Branch, verbose_name=u"门店", on_delete=models.PROTECT, editable=False)
  69. no = models.CharField(max_length=64, verbose_name=u"单号")
  70. create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
  71. customer = models.ForeignKey(Customer, verbose_name=u'客户', on_delete=models.PROTECT)
  72. status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"支付状态")
  73. precreate_amount = models.BigIntegerField(verbose_name=u"预支付金额")
  74. amount = models.BigIntegerField(verbose_name=u"实际支付金额", null=True)
  75. class Meta:
  76. db_table = "pay"
  77. verbose_name = u"支付"
  78. ordering = ('-id',)
  79. index_together = (
  80. 'create_time',
  81. 'status',
  82. )
  83. unique_together = (
  84. 'no',
  85. )
  86. default_permissions = ()
  87. def payClosed(self):
  88. if self.status != Pay.WAIT:
  89. return
  90. self.status = Pay.CLOSED
  91. self.save()
  92. def payConfirm(self, amount):
  93. if self.status != Pay.WAIT:
  94. return
  95. self.status = Pay.CONFIRM
  96. self.amount = amount
  97. self.save()
  98. order = Order.objects.filter(pay=self).first()
  99. if order:
  100. order.status = Order.FINISH
  101. order.amount = self.amount
  102. order.save()
  103. @staticmethod
  104. def getByNo(no):
  105. instance = Pay.objects.filter(no=no).first()
  106. if not instance:
  107. raise CustomError(u'未找到相应的支付单!')
  108. return instance
  109. @staticmethod
  110. def wechatPay(app, branch, customer, amount, openid):
  111. instance = Pay._addnew(branch, customer, amount)
  112. return instance, instance._wechatUnifiedOrder(app, openid)
  113. @staticmethod
  114. def _addnew(branch, customer, amount):
  115. if amount <= 0:
  116. raise CustomError(u'无效的付款金额!')
  117. no = timezone.now().strftime('%y%m%d%H%M%S') + str(customer.id)
  118. instance = Pay.objects.create(
  119. branch=branch,
  120. no=no,
  121. customer=customer,
  122. type=type,
  123. status=Pay.WAIT,
  124. precreate_amount=amount
  125. )
  126. return instance
  127. def _wechatUnifiedOrder(self, app, openid):
  128. wechatpay = WechatPay(app.authorizer_appid, app.agent_num, app.agent_key)
  129. wechatpay.unifiedOrder(self.no, self.precreate_amount, openid)
  130. data = wechatpay.getAppString()
  131. return data
  132. class Order(models.Model):
  133. DEFAULT = 0
  134. FINISH = 1
  135. FAIL = 2
  136. STATUS_CHOICES = (
  137. (DEFAULT, u'待付款'),
  138. (FINISH, u'已完成'),
  139. (FAIL, u'失败'),
  140. )
  141. branch = models.ForeignKey(Branch, verbose_name=u"门店", on_delete=models.PROTECT, editable=False)
  142. activity = models.ForeignKey(Activity, verbose_name=u"活动", on_delete=models.PROTECT)
  143. pay = models.ForeignKey(Pay, verbose_name='支付信息', on_delete=models.PROTECT, null=True)
  144. member = models.ForeignKey(Customer, verbose_name=u"会员", on_delete=models.PROTECT, editable=False)
  145. amount = models.FloatField(verbose_name=u"费用", default=0)
  146. status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", default=DEFAULT, editable=False)
  147. model = models.CharField(max_length=200, verbose_name=u"车型", null=True, blank=True)
  148. tel = models.CharField(max_length=100, verbose_name=u"电话", null=True, blank=True)
  149. number = models.CharField(max_length=50, verbose_name=u"车牌号", null=True, blank=True)
  150. name = models.CharField(max_length=50, verbose_name=u"姓名", null=True, blank=True)
  151. create_time = models.DateTimeField(verbose_name=u"添加时间", auto_now_add=True, editable=False)
  152. delete = models.BooleanField(verbose_name=u"删除", default=False)
  153. class Meta:
  154. db_table = "order"
  155. ordering = ['-id']
  156. verbose_name = u"订单管理"
  157. def payOrder(self, openid, app):
  158. # 如果订单上的金额不等于活动金额 (比如下单没有支付,后来活动金额修改,现在活动金额不等于订单上活动金额) 还按下单时保存到额金额支付
  159. if self.status != Order.DEFAULT:
  160. raise CustomError(u'订单非代付款状态,禁止付款')
  161. if self.pay:
  162. pay_no = self.pay.no
  163. # 先查询订单状态
  164. checkRexponse = WeChatResponse(app.authorizer_appid, app.agent_num, app.agent_key)
  165. total_fee = checkRexponse.orderquery(pay_no)
  166. if int(total_fee) == int(self.amount):
  167. wechatpay = WechatPay(app.authorizer_appid, app.agent_num, app.agent_key)
  168. data = wechatpay.unifiedOrder(openid, pay_no, self.amount)
  169. return data
  170. self.pay.payClosed()
  171. pay, data = Pay.wechatPay(app, self.branch, self.member, self.amount, openid)
  172. self.pay = pay
  173. self.save()
  174. return data
  175. class Coupon(models.Model):
  176. FIXED_DATE = 0
  177. RECEIVE_TIMING = 1
  178. OFF_TYPE_CHOICES = (
  179. (FIXED_DATE, u'固定日期'),
  180. (RECEIVE_TIMING, u'领取计时'),
  181. )
  182. branch = models.ForeignKey(Branch, verbose_name=u"门店", on_delete=models.PROTECT)
  183. name = models.CharField(max_length=200, verbose_name=u"名称")
  184. off_type = models.PositiveSmallIntegerField(choices=OFF_TYPE_CHOICES, verbose_name=u"核销方式", default=FIXED_DATE)
  185. end_date = models.DateField(verbose_name=u"截止日期", null=True, blank=True)
  186. end_days = models.IntegerField(verbose_name=u"截止天数", null=True, blank=True)
  187. create_time = models.DateTimeField(verbose_name=u"添加时间", auto_now_add=True, editable=False)
  188. enabled = models.BooleanField(verbose_name=u"在用", default=True)
  189. class Meta:
  190. db_table = "coupon"
  191. ordering = ['-id']
  192. verbose_name = u"优惠券"
  193. @staticmethod
  194. def getById(id):
  195. try:
  196. id = int(id)
  197. except:
  198. raise CustomError(u'无效的优惠券')
  199. instance = Coupon.objects.filter(pk=id).first()
  200. if not instance:
  201. raise CustomError(u'未找到相应的优惠券')
  202. return instance
  203. class MemberCoupon(models.Model):
  204. activity = models.ForeignKey(Activity, verbose_name=u"活动", on_delete=models.PROTECT)
  205. member = models.ForeignKey(Customer, verbose_name=u"会员", on_delete=models.PROTECT)
  206. coupon = models.ForeignKey(Coupon, verbose_name=u"优惠券", on_delete=models.PROTECT)
  207. receive_date = models.DateField(verbose_name=u"领取日期", null=True, blank=True)
  208. end_date = models.DateField(verbose_name=u"有效期至", null=True, blank=True)
  209. write_off = models.BooleanField(verbose_name=u"核销", default=False)
  210. write_off_time = models.DateTimeField(verbose_name=u"核销时间", editable=False, null=True, blank=True)
  211. class Meta:
  212. db_table = "member_coupon"
  213. ordering = ['-id']
  214. verbose_name = u"会员优惠券"
  215. def writeOff(self):
  216. now = datetime.datetime.date(timezone.now())
  217. if self.write_off:
  218. raise CustomError(u'该优惠券已核销,禁止重复使用!')
  219. if self.end_date and now > self.end_date:
  220. raise CustomError(u'该优惠券已过有效期,禁止使用!')
  221. self.write_off = True
  222. self.write_off_time = timezone.now()
  223. self.save()
  224. def cancelWriteOff(self):
  225. if not self.write_off:
  226. raise CustomError(u'该优惠券尚未核销,禁止撤销!')
  227. self.write_off = False
  228. self.write_off_time = None
  229. self.save()
  230. @staticmethod
  231. def getById(id):
  232. try:
  233. id = int(id)
  234. except:
  235. raise CustomError(u'无效的会员优惠券ID')
  236. instance = MemberCoupon.objects.filter(pk=id).first()
  237. if not instance:
  238. raise CustomError(u'未找到相应的会员优惠券')
  239. return instance
  240. class ActivityCoupon(models.Model):
  241. activity = models.ForeignKey(Activity, verbose_name=u"活动", on_delete=models.PROTECT)
  242. coupon = models.ForeignKey(Coupon, verbose_name=u"优惠券", on_delete=models.PROTECT)
  243. class Meta:
  244. db_table = "activity_coupon"
  245. ordering = ['-id']
  246. verbose_name = u"活动优惠券"