# coding=utf-8 from django.db import models from django.conf import settings from django.utils import timezone from django.db.models import F from apps.option.models import Option from apps.config.models import Config from apps.commodity.models import Commodity from apps.customer.models import Customer, CustomerAddress, SuperiorDistributor from utils.exceptions import CustomError from utils.wechatpay import WechatPay, WeChatResponse class Pay(models.Model): WAIT = 1 PAY = 2 UNDO = 3 STATUS_CHOICES = ( (WAIT, u'待付款'), (PAY, u'已付款'), (UNDO, u'已取消'), ) no = models.CharField(max_length=64, verbose_name=u"单号") status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u'状态', default=WAIT) precreate_amount = models.BigIntegerField(verbose_name=u"预支付金额") amount = models.BigIntegerField(verbose_name=u"支付金额", null=True) transaction_id = models.CharField(max_length=100, verbose_name=u"微信支付订单号", null=True) customer = models.ForeignKey(Customer, verbose_name=u'下单人', related_name='pay_customer', on_delete=models.PROTECT) create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now) class Meta: db_table = "pay" verbose_name = u"支付信息" ordering = ('-id',) index_together = ( 'create_time', 'status', ) unique_together = ( 'no', ) default_permissions = () @staticmethod def wechatPay(amount, customer, appid, openid): instance = Pay._addnew(amount, customer) return instance, instance._wechatUnifiedOrder(appid, openid) @staticmethod def _addnew(amount, customer): if amount <= 0: raise CustomError(u'无效的付款金额!') pay_no = '{}{}'.format(timezone.now().strftime('%Y%m%d%H%M%S'), str(customer.id)) pay = Pay.objects.create(no=pay_no, status=Pay.WAIT, precreate_amount=amount, customer=customer) return pay def _wechatUnifiedOrder(self, appid, openid): wechatpay = WechatPay(appid) wechatpay.unifiedOrder(self.no, self.precreate_amount, openid) data = wechatpay.getAppString() return data @staticmethod def getByNo(no): instance = Pay.objects.filter(no=no).first() if not instance: raise CustomError(u'未找到相应的支付单!') return instance def payClosed(self): if self.status != Pay.WAIT: return self.status = Pay.UNDO self.save() def payConfirm(self, amount, transaction_id): if self.status != Pay.WAIT: return self.status = Pay.PAY self.amount = amount self.transaction_id = transaction_id self.save() order = Order.objects.filter(pay=self).first() if order: order.orderPayConfirm() class ShoppingCart(models.Model): commodity_details = models.ForeignKey(Commodity, verbose_name=u'产品明细', on_delete=models.PROTECT) quantity = models.PositiveIntegerField(verbose_name=u'数量', default=1) create_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True) customer = models.ForeignKey(Customer, related_name='shopping_cart_customer', verbose_name=u"下单人", on_delete=models.PROTECT, editable=False) class Meta: db_table = 'shopping_cart' verbose_name = u'购物车' ordering = ['-id', ] default_permissions = () class Order(models.Model): WAIT_PAY = 0 WAIT_DISPATCH = 1 CONFIRM_DISPATCH = 2 CANCEL = 3 STATUS_CHOICES = ( (WAIT_PAY, u'待付款'), (WAIT_DISPATCH, u'待发货'), (CONFIRM_DISPATCH, u'已发货'), (CANCEL, u'已取消'), ) no = models.CharField(max_length=50, verbose_name=u'订单号', editable=False, null=True, blank=True) pay = models.ForeignKey(Pay, verbose_name=u'支付信息', on_delete=models.PROTECT, null=True, editable=False) total_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) status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"订单状态", default=WAIT_PAY) notes = models.CharField(max_length=500, verbose_name=u"备注", null=True, blank=True) customer = models.ForeignKey(Customer, verbose_name=u'创建人', editable=False, on_delete=models.PROTECT) create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now, editable=False) cancel_reason = models.CharField(max_length=100, verbose_name=u"取消原因", null=True, blank=True) cancel_user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='order_cancel_user', verbose_name=u"取消人", on_delete=models.PROTECT, null=True, blank=True) cancel_time = models.DateTimeField(verbose_name=u"取消时间", null=True, blank=True) address = models.ForeignKey(CustomerAddress, verbose_name=u'收货地址', related_name='order_address', null=True, blank=True, on_delete=models.PROTECT) name = models.CharField(verbose_name=u'收货人', max_length=20, null=True, blank=True) tel = models.CharField(verbose_name=u'收货电话', max_length=15, null=True, blank=True) user_address = models.CharField(verbose_name=u'详细地址', max_length=200, null=True, blank=True) express_no = models.CharField(max_length=50, verbose_name=u'快递单号', null=True, blank=True) express_company = models.ForeignKey(Option, verbose_name=u'快递公司', on_delete=models.PROTECT, null=True, blank=True) dispatch_time = models.DateTimeField(verbose_name=u'发货时间', null=True, blank=True) dispatch_user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='order_dispatch_user', verbose_name=u"发货人", on_delete=models.PROTECT, null=True, blank=True) class Meta: db_table = "order" verbose_name = u"客户订单" ordering = ('-id',) index_together = ('status', 'create_time', 'no', ) default_permissions = () permissions = [] def generateNo(self): ''' 生成订单的订单号(注意:该函数最后没有 save 要在调用该函数后save ) :return: ''' no = '{}{:0>4}'.format(timezone.now().strftime('%Y%m%d'), self.id) self.no = no def set_order_adderss(self, address_id): ''' 下单时保存用户选择的收货地址(注意:该函数最后没有 save 要在调用该函数后save ) :param address_id: 收货地址id :return: ''' address = CustomerAddress.objects.filter(id=address_id).first() if not address: raise CustomError(u'请选择正确的收货地址!') if address.delete: raise CustomError(u'该收货地址已删除,请选择重新选择收货地址!') self.address = address self.name = address.name self.tel = address.tel self.user_address = address.get_address() def set_order_detail(self, details): ''' 下单时保存选择的商品明细(注意:该函数最后没有 save 要在调用该函数后save ) :param details: 商品明细 :return: ''' total_count = total_amount = total_point = 0 create_data = [] for item in details: commodity = Commodity.objects.filter(id=item['id']).first() if not commodity: raise CustomError(u'您选择的商品不存在,请刷新后重新选择!') if commodity.delete: raise CustomError(u'商品【{}】已下架!'.format(commodity.name)) if commodity.status != settings.ONLINE: raise CustomError(u'商品【{}】已下架!'.format(commodity.name)) try: count = int(item['count']) except: raise CustomError(u'商品数量错误,请重新选择!') if count <= 0: raise CustomError(u'商品数量错误,请重新选择!') amount = point_amount = 0 if commodity.type == Commodity.POINT: point_amount = commodity.point_price * count elif commodity.type == Commodity.CASH: amount = commodity.price * count else: continue d = OrderDetails( order=self, commodity=commodity, price=commodity.price, point=commodity.point_price, count=count, amount=amount, point_amount=point_amount ) create_data.append(d) total_point += point_amount total_amount += amount total_count += count OrderDetails.objects.bulk_create(create_data) self.total_count = total_count self.total_amount = total_amount self.total_point = total_point def pointConfirm(self): ''' 积分兑换 确认兑换成功 当只购买了积分商品的时候 使用本函数确认 有现金商品的时候使用pay下边的确认函数确认 注意 order最后没有save() 在调用该函数后order要save() :return: ''' if self.status != Order.WAIT_PAY: return self.status = Order.WAIT_DISPATCH commodity_id = Config.get_commodity() # 这一点儿不能用这个 不然 数据customer数据重新保存了 积分那一块儿的就不行了 customer = Customer.objects.filter(id=self.customer.id).first() detail = OrderDetails.objects.filter(order=self) for item in detail: commodity = item.commodity commodity.total_sales += item.count commodity.save() if not commodity_id: continue if commodity.id != commodity_id: continue if customer.is_distributor: continue customer.is_distributor = True customer.total_point += self.total_point customer.success_count += 1 customer.save() def orderPay(self, openid, appid): if self.status != Order.WAIT_PAY: raise CustomError(u'订单非待付款状态,禁止付款!') if self.pay: pay_no = self.pay.no # 先查询订单状态 checkRexponse = WeChatResponse(appid) total_fee = checkRexponse.OrderQuery(pay_no) if int(total_fee) == int(self.total_amount): wechatpay = WechatPay(appid) wechatpay.unifiedOrder(pay_no, self.total_amount, openid) data = wechatpay.getAppString() return data self.pay.payClosed() def orderPayConfirm(self): self.status = Order.WAIT_DISPATCH self.save() # 购买指定的商品 成为分销商 commodity_id = Config.get_commodity() point_rule = Config.get_value(Config.KEY_POINT_RULE) customer = Customer.objects.filter(id=self.customer.id).first() detail = OrderDetails.objects.filter(order=self) for item in detail: commodity = item.commodity commodity.total_sales += item.count commodity.save() if not commodity_id: continue if commodity.id != commodity_id: continue if customer.is_distributor: continue customer.is_distributor = True customer.success_count += 1 customer.total_amount += self.total_amount customer.total_point += self.total_point customer.save() class OrderDetails(models.Model): order = models.ForeignKey(Order, verbose_name=u'订单', on_delete=models.PROTECT) commodity = models.ForeignKey(Commodity, verbose_name=u'商品', on_delete=models.PROTECT) price = models.BigIntegerField(verbose_name=u'价格', null=True, default=0) point = models.IntegerField(verbose_name=u'积分', null=True, default=0) count = models.IntegerField(verbose_name=u'数量', null=True, default=0) amount = models.BigIntegerField(verbose_name=u'总金额', null=True, default=0) point_amount = models.IntegerField(verbose_name=u'总积分', null=True, default=0) class Meta: db_table = u'order_details' verbose_name = u'订单明细' ordering = ('-id', ) default_permissions = () permissions = []