from django.db import models from utils.models import CoreModel,BaseModel,SimpleCoreModel from apps.address.models import Address,Area from mysystem.models import Users # Create your models here. # ================================================= # # ************** 商品分类 model ************** # # ================================================= # class GoodsCategory(CoreModel): """商品类别""" name = models.CharField(max_length=20, verbose_name='名称') desc = models.CharField(max_length=255, null=True, blank=True,verbose_name='描述') # level = models.SmallIntegerField(default=1, verbose_name="分类层级(1:一级 2:二级)", help_text="分类层级(1:一级 2:二级)") default_image = models.CharField(max_length=255, null=True, blank=True, verbose_name='默认图片') # 类别图片(单个图片) sort = models.PositiveSmallIntegerField(default=0, verbose_name="排序", help_text="显示顺序") status = models.BooleanField(default=True, verbose_name="商品类别状态", help_text="商品类别状态") is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除") parent = models.ForeignKey('self', related_name='goodscategorysubs',db_constraint=False, null=True, blank=True, on_delete=models.CASCADE, verbose_name='父类别') class Meta: db_table = 'tb_goods_category' verbose_name = '商品类别' verbose_name_plural = verbose_name def __str__(self): return self.name # ================================================= # # ************** 优惠券 model ************** # # ================================================= # GOODSCOUPON_RECEIVE_TYPE = ( (0, ""), (1, "手动领取"), (2, "新人劵"), (3, "后台发放"), (4, "邀请劵"), ) GOODSCOUPON_COUPONTYPE = ( (0, "通用券"), (1, "商城类通用券"), (2, "服务类通用券"), ) # 通用:服务类商品+商城类商品 # 服务:仅能用于服务类商品 # 商城:仅能用于商城内商品 class GoodsCoupon(CoreModel): """商品优惠券(管理员创建)""" name = models.CharField(max_length=50, verbose_name='优惠券名称') caption = models.CharField(max_length=256, verbose_name='优惠券副标题', null=True, blank=True) # 副标题 desc = models.CharField(max_length=150, null=True, blank=True, verbose_name='描述') sort = models.IntegerField(default=0, verbose_name="排序", help_text="显示顺序") total_num = models.IntegerField(default=0, verbose_name="优惠券总数量", help_text="优惠券总数量") received_num = models.IntegerField(default=0, verbose_name="优惠券已领取数量", help_text="优惠券已领取数量") used_num = models.IntegerField(default=0, verbose_name="已被使用的数量", help_text="已被使用的数量") is_permanent = models.BooleanField(default=True, verbose_name="是否无限张数", help_text="是否无限张数") price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='优惠券面值',default=0) is_condition = models.BooleanField(default=False, verbose_name="有无门槛", help_text="有无门槛")#0无门槛 1有门槛 use_min_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='最低消费多少金额可用优惠券',default=0)#有无门槛,0表示无门槛 start_time = models.DateField(null=True, blank=True, help_text="优惠券领取开启时间", verbose_name="优惠券领取开启时间") end_time = models.DateField(null=True, blank=True, help_text="优惠券领取结束时间",verbose_name="优惠券领取结束时间") valid_begin_date = models.DateField(verbose_name="有效期开始时间", blank=True, null=True) valid_end_date = models.DateField(verbose_name="有效结束时间", blank=True, null=True) coupon_expiretime = models.IntegerField(default=0, verbose_name="优惠券有效期限(单位:天)", help_text="优惠券有效期限(单位:天)")#领取后几天有效,自券被领时开始算起 receive_type = models.SmallIntegerField(choices=GOODSCOUPON_RECEIVE_TYPE, default=0, verbose_name="优惠券发送方式",help_text="优惠券发送方式") coupon_type = models.SmallIntegerField(choices=GOODSCOUPON_COUPONTYPE,default=0, verbose_name="优惠券类型(2)", help_text="优惠券类型(2)") is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除") status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")#0关闭 1正常 class Meta: db_table = 'tb_goods_coupon' verbose_name = '商品优惠券' verbose_name_plural = verbose_name def __str__(self): return self.name class CouponRecord(CoreModel): """优惠券发放、消费纪录 - 面向用户(用户领取卷)""" # 跟优惠券生成规则是一对多的关系 - 一种优惠券有30张,则发放记录就有30条 coupon = models.ForeignKey("GoodsCoupon",db_constraint=False, on_delete=models.CASCADE,verbose_name="关联优惠券") number = models.CharField(max_length=64,verbose_name="用来计数",null=True,blank=True) # 一对多,一个用户有多张优惠券,一张优惠券只能给一个用户 user = models.ForeignKey(Users,verbose_name="拥有者", on_delete=models.CASCADE,db_constraint=False,related_name='couponuser1') status_choices = ((0, '未领取'),(1, '未使用'), (2, '已使用'), (3, '已过期'), (4, '已撤回')) status = models.SmallIntegerField(choices=status_choices, default=0) used_time = models.DateTimeField(blank=True, null=True, verbose_name="使用时间") receive_time = models.DateTimeField(blank=True, null=True, verbose_name="领取时间") is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除") class Meta: db_table = 'tb_goods_coupon_record' verbose_name = '用户持券表' verbose_name_plural = verbose_name def __str__(self): return '%s-%s-%s'%(self.user,self.coupon,self.get_status_display()) # ================================================= # # ************** 商品品牌 model ************** # # ================================================= # class GoodsBrand(CoreModel): """ 商品所属品牌 """ category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE,related_name="brands",db_constraint=False, verbose_name="所属分类", help_text="所属分类") name = models.CharField(max_length=30, verbose_name="品牌名", help_text="品牌名") desc = models.TextField(blank=True, max_length=200,default="", verbose_name="品牌描述", help_text="品牌描述") default_image = models.CharField(max_length=255, null=True, blank=True, verbose_name='品牌logo') #(单个图片) sort = models.PositiveSmallIntegerField(default=0, verbose_name="排序") class Meta: db_table = "tb_goods_brand" ordering = ["-sort"] verbose_name = "商品品牌" verbose_name_plural = verbose_name def __str__(self): return self.name # ================================================= # # ************** 商品 model ************** # # ================================================= # class SPU(CoreModel): """商品SPU""" SPU_SPEC_TYPE = ( (0, "单规格"), (1, "多规格") ) name = models.CharField(max_length=60, verbose_name='标题') sub_name = models.CharField(max_length=60, blank=True,null=True, default="", verbose_name="副标题")#副标题 category1 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat1_spu',db_constraint=False, verbose_name='一级类别') # category2 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat2_spu',null=True, blank=True, verbose_name='二级类别') # category3 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat3_spu', null=True, blank=True, verbose_name='三级类别') brand = models.ForeignKey(GoodsBrand, on_delete=models.PROTECT, related_name="brands",db_constraint=False, blank=True, null=True,verbose_name="品牌") spec_type = models.PositiveIntegerField(choices=SPU_SPEC_TYPE, default=0, verbose_name="规格类型")#默认单规格 default_image = models.CharField(max_length=255, null=True, blank=True, verbose_name='商品主图') #(单个图片) image_list = models.CharField(max_length=2000, null=True, blank=True, verbose_name='商品轮播图') # (多个图片) price = models.DecimalField(max_digits=10, decimal_places=2,default=0, verbose_name="售价")#sku中选择一个最低的售价写入 # market_price = models.DecimalField(max_digits=10, decimal_places=2,default=0, verbose_name="市场价") # cost_price = models.DecimalField(max_digits=10, decimal_places=2,default=0, verbose_name="成本价") sales = models.IntegerField(default=0, verbose_name='销量') stock = models.IntegerField(default=0, verbose_name="库存") unit = models.CharField(max_length=30, default="", blank=True,null=True,verbose_name="商品单位") comments = models.IntegerField(default=0, verbose_name='评论量',null=True, blank=True) desc_detail = models.TextField(default='', verbose_name='详细介绍',null=True, blank=True)#商品详情 desc_pack = models.TextField(default='', verbose_name='包装信息',null=True, blank=True) desc_service = models.TextField(default='', verbose_name='售后服务',null=True, blank=True) is_launched = models.BooleanField(default=True, verbose_name='是否上架销售') is_tuijian = models.BooleanField(default=False, verbose_name='是否推荐')#自定义字段,可删掉 sort = models.PositiveSmallIntegerField(default=0, verbose_name="排序") is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除") class Meta: db_table = 'tb_goods_spu' verbose_name = '商品SPU' verbose_name_plural = verbose_name def __str__(self): return self.name class SKU(CoreModel): """商品SKU""" name = models.CharField(max_length=60, verbose_name='标题',null=True, blank=True) spu = models.ForeignKey(SPU, on_delete=models.CASCADE, verbose_name='商品SPU',db_constraint=False,related_name='skus') price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='商品单价') shop_price = models.DecimalField(max_digits=10, decimal_places=2, default=0,null=True, blank=True, verbose_name="售价") market_price = models.DecimalField(max_digits=10, decimal_places=2, default=0,null=True, blank=True, verbose_name="市场价") cost_price = models.DecimalField(max_digits=10, decimal_places=2, default=0,null=True, blank=True, verbose_name="成本价") stock = models.IntegerField(default=0, verbose_name='商品库存') unite = models.CharField(max_length=20, verbose_name='商品单位',null=True, blank=True) sales = models.IntegerField(default=0, verbose_name='商品销量',null=True, blank=True) default_image = models.CharField(max_length=255, null=True, blank=True, verbose_name='默认图片')#商品主图(单张) is_launched = models.BooleanField(default=True, verbose_name='是否上架销售') is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除") class Meta: ordering = ["create_datetime"] db_table = 'tb_goods_sku' verbose_name = '商品SKU' verbose_name_plural = verbose_name def __str__(self): return f'{self.spu.name}的SKU' class SKUImage(CoreModel): """SKU图片""" sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='商品sku',db_constraint=False,related_name='goods_imagelist') image = models.CharField(max_length=255,verbose_name='图片') sort = models.PositiveSmallIntegerField(default=0, verbose_name="排序") class Meta: ordering= ["sort"] db_table = 'tb_goods_sku_image' verbose_name = 'SKU图片' verbose_name_plural = verbose_name class SPUSpecification(CoreModel): """商品SPU规格名""" spu = models.ForeignKey(SPU, on_delete=models.CASCADE, related_name='spu_specs',db_constraint=False, verbose_name='商品SPU') name = models.CharField(max_length=20, verbose_name='规格名称') class Meta: ordering = ["create_datetime"] db_table = 'tb_goods_spu_specification' verbose_name = '商品SPU规格' verbose_name_plural = verbose_name def __str__(self): return self.name class SPUSpecificationOption(CoreModel): """商品SPU规格选项值""" spec = models.ForeignKey(SPUSpecification, related_name='options', on_delete=models.CASCADE,db_constraint=False, verbose_name='规格') value = models.CharField(max_length=20, verbose_name='选项值') class Meta: ordering = ["create_datetime"] db_table = 'tb_goods_spu_specification_option' verbose_name = '规格选项' verbose_name_plural = verbose_name def __str__(self): return self.value class SKUSpecification(CoreModel): """SKU具体规格""" sku = models.ForeignKey(SKU, related_name='specs', on_delete=models.CASCADE, verbose_name='sku',db_constraint=False) spec = models.ForeignKey(SPUSpecification, on_delete=models.CASCADE, verbose_name='规格名称',db_constraint=False) option = models.ForeignKey(SPUSpecificationOption, on_delete=models.CASCADE, verbose_name='规格值',db_constraint=False) class Meta: ordering = ["create_datetime"] db_table = 'tb_goods_sku_specification' verbose_name = 'SKU规格' verbose_name_plural = verbose_name def __str__(self): return '%s: %s - %s' % (self.sku, self.spec.name, self.option.value) class GoodsSpecTemplate(CoreModel): """商品规格模板(供添加商品时选择使用)""" spec = models.CharField(max_length=100, verbose_name='规格名称') option = models.CharField(max_length=255, verbose_name='规格值') class Meta: db_table = 'tb_goods_spec_template' verbose_name = '商品规格模板' verbose_name_plural = verbose_name class FreightConfigManage(SimpleCoreModel): area = models.ManyToManyField(Area, verbose_name='关联区域', db_constraint=False, help_text="关联区域") region_name = models.TextField(verbose_name="选择的区域名称",null=True,blank=True)#多个名称用、号分割(如省内所有市区都选择则 仅显示省名称如市内所有区都选择则 仅显示市名称) sz = models.FloatField(default=0,verbose_name="首重kg") yf = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='运费(元)',default=0) xz = models.FloatField(default=0,verbose_name="续重kg") xf = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='续费(元)',default=0) is_default = models.BooleanField(default=False, verbose_name="是否全国默认区域") def save(self, *args, **kwargs): # 在保存前对浮点数进行处理,保留两位小数 self.sz = round(self.sz, 2) self.xz = round(self.xz, 2) super(FreightConfigManage, self).save(*args, **kwargs) class Meta: db_table = 'tb_freight_config' verbose_name = "运费配置" verbose_name_plural = verbose_name # ================================================= # # ************** 商品订单model ************** # # ================================================= # class OrderInfo(CoreModel): """订单信息""" PAY_METHOD_CHOICES = ( (0, ""), (1, "货到付款"), (2, "微信"), (3, "支付宝"), ) ORDER_STATUS_CHOICES = ( (1, "待支付"), (2, "待发货"), (3, "待收货"), (4, "待评价"), (5, "已完成"), (6, "已取消"), ) ORDER_PAY_STATUS_CHOICES = ( (0, "待支付"), (1, "已支付"), (2, "退款中"), (3, "退款失败"), (4, "已退款"), ) order_id = models.CharField(max_length=64, verbose_name="订单号",unique=True)#内部 trade_id = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name="支付编号")#外部 user = models.ForeignKey(Users, on_delete=models.PROTECT,related_name='createorderuser1' ,db_constraint=False,verbose_name="下单用户") address_name = models.CharField(max_length=50, null=True, blank=True, verbose_name="收货人姓名") address_mobile = models.CharField(max_length=20, null=True, blank=True, verbose_name="收货人手机号") address_place = models.CharField(max_length=100, null=True, blank=True, verbose_name="收货详细地址") couponrecord_id = models.CharField(max_length=60, unique=True, null=True, blank=True, verbose_name="用户优惠券id") couponrecord_price = models.DecimalField(max_digits=10, decimal_places=2, default=0,null=True, blank=True, verbose_name="优惠券面值") total_count = models.IntegerField(default=1, verbose_name="商品总数") total_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="实付商品总金额",default=0) total_amount_pay = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="订单总金额",default=0) freight = models.DecimalField(max_digits=10, decimal_places=2,null=True, blank=True,verbose_name="运费",default=0) logistics_id = models.CharField(max_length=100, verbose_name="物流单号",null=True, blank=True)#该商城项目特有,其他项目可去掉 send_time = models.DateTimeField(null=True, blank=True, help_text="发货时间", verbose_name="发货时间")#该商城项目特有,其他项目可去掉 logistics_company = models.CharField(max_length=90, verbose_name="物流公司", null=True, blank=True)#该商城项目特有,其他项目可去掉 pay_method = models.SmallIntegerField(choices=PAY_METHOD_CHOICES, default=0, verbose_name="支付方式") pay_time = models.CharField(max_length=64,null=True, blank=True, verbose_name="支付时间", help_text="支付时间") remark = models.CharField(max_length=100, verbose_name="订单备注",null=True,blank=True) cancel_reason = models.CharField(max_length=100, verbose_name="订单取消原因", null=True, blank=True) status = models.SmallIntegerField(choices=ORDER_STATUS_CHOICES, default=1, verbose_name="订单状态") pay_status = models.SmallIntegerField(choices=ORDER_PAY_STATUS_CHOICES, default=0, verbose_name="支付状态") is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除") class Meta: db_table = "tb_mall_order_info" verbose_name = '订单基本信息' verbose_name_plural = verbose_name def __str__(self): return self.order_id class OrderGoods(CoreModel): """订单商品""" SCORE_CHOICES = ( (0, '0分'), (1, '20分'), (2, '40分'), (3, '60分'), (4, '80分'), (5, '100分'), ) order = models.ForeignKey(OrderInfo, related_name='ordergoodsskus', on_delete=models.CASCADE,db_constraint=False, verbose_name="订单") spu = models.ForeignKey(SPU, on_delete=models.PROTECT,db_constraint=False,blank=True, null=True, verbose_name="订单商品") sku = models.ForeignKey(SKU, on_delete=models.PROTECT,db_constraint=False,blank=True, null=True, verbose_name="订单规格") count = models.IntegerField(default=1, verbose_name="数量") price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="sku单价") comment = models.TextField(verbose_name="评价信息",null=True,blank=True) score = models.SmallIntegerField(choices=SCORE_CHOICES, default=5, verbose_name='满意度评分') is_anonymous = models.BooleanField(default=False, verbose_name='是否匿名评价') is_commented = models.BooleanField(default=False, verbose_name='是否评价了') class Meta: db_table = "tb_mall_order_goods" verbose_name = '订单商品' verbose_name_plural = verbose_name def __str__(self): return self.spu.name class OrderRefunds(CoreModel): """订单退款""" ORDER_STATUS_CHOICES = ( (0, "待支付"), (1, "已支付"), (2, "退款中"), (3, "退款失败"), (4, "已退款"), ) order_no= models.CharField(max_length=64, verbose_name="订单号", unique=True) # 内部 order = models.ForeignKey(OrderInfo, related_name='orderrefunds',db_constraint=False, on_delete=models.CASCADE, verbose_name="要退款的订单") refund_id = models.CharField(max_length=64, verbose_name="退款单号", unique=True) # 外部返回 amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="退款金额") reason = models.CharField(max_length=64, verbose_name="退款失败原因", null=True,blank=True) # 失败原因 status = models.SmallIntegerField(choices=ORDER_STATUS_CHOICES, default=2, verbose_name="退款状态") class Meta: db_table = "tb_mall_order_refunds" verbose_name = '商城订单退款' verbose_name_plural = verbose_name