"""集团多俱乐部数据模型(新建表,不修改 gvsdsdk)。""" import uuid from decimal import Decimal from django.db import models from gvsdsdk.model_base import QModel class Club(QModel): """子公司 / 俱乐部主表。""" club_id = models.CharField(max_length=16, primary_key=True, verbose_name='俱乐部ID') name = models.CharField(max_length=64, verbose_name='展示名') status = models.IntegerField(default=1, verbose_name='1启用0停用') wx_appid = models.CharField(max_length=32, blank=True, default='') wx_secret = models.CharField(max_length=128, blank=True, default='') # —— 点单/会员等收款商户(V2 JSAPI;退款也应对齐这套)—— mch_id = models.CharField(max_length=32, blank=True, default='', verbose_name='收款商户号') pay_app_id = models.CharField(max_length=32, blank=True, default='', verbose_name='收款AppID') mch_key = models.CharField(max_length=128, blank=True, default='', verbose_name='收款APIv2密钥') pay_cert_path = models.CharField( max_length=512, blank=True, default='', verbose_name='收款商户证书路径', help_text='apiclient_cert.pem,退款/V2 证书用', ) pay_key_path = models.CharField( max_length=512, blank=True, default='', verbose_name='收款商户私钥路径', help_text='apiclient_key.pem,退款/V2 证书用', ) # —— 提现/转账商户(V3;可与收款商户号不同)—— withdraw_mch_id = models.CharField( max_length=32, blank=True, default='', verbose_name='提现商户号', help_text='空则回落收款商户号 mch_id', ) api_v3_key = models.CharField(max_length=128, blank=True, default='', verbose_name='提现APIv3密钥') cert_serial_no = models.CharField(max_length=64, blank=True, default='', verbose_name='提现证书序列号') private_key_path = models.CharField( max_length=512, blank=True, default='', verbose_name='提现商户私钥路径', ) platform_cert_dir = models.CharField( max_length=512, blank=True, default='', verbose_name='提现平台证书目录', ) official_appid = models.CharField(max_length=32, blank=True, default='') official_secret = models.CharField(max_length=128, blank=True, default='') official_token = models.CharField(max_length=64, blank=True, default='') encoding_aes_key = models.CharField(max_length=64, blank=True, default='') template_id = models.CharField(max_length=64, blank=True, default='') template_max_per_minute = models.IntegerField(default=950) h5_domain = models.CharField(max_length=128, blank=True, default='') oss_prefix = models.CharField(max_length=128, blank=True, default='') goeasy_appkey = models.CharField(max_length=64, blank=True, default='') goeasy_secret = models.CharField(max_length=128, blank=True, default='') config_json = models.JSONField(default=dict, blank=True) company_uuid = models.BinaryField(max_length=16, null=True, blank=True) sort_order = models.IntegerField(default=0) CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club' verbose_name = '俱乐部' class UserWxOpenid(QModel): """微信 openid 与俱乐部用户绑定(club_id + openid 唯一)。""" club_id = models.CharField(max_length=16, db_index=True) openid = models.CharField(max_length=64, db_index=True) yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID') unionid = models.CharField(max_length=64, null=True, blank=True) CreateTime = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'user_wx_openid' unique_together = [['club_id', 'openid']] class AdminAssignment(QModel): """管理任职:集团或子公司后台权限范围。""" yonghuid = models.CharField(max_length=7, db_index=True) club_id = models.CharField(max_length=16, null=True, blank=True, db_index=True, verbose_name='NULL=集团任职') role_code = models.CharField(max_length=50, default='CLUB_ADMIN') data_scope = models.CharField(max_length=20, default='SINGLE_CLUB') is_primary = models.BooleanField(default=False) granted_by = models.CharField(max_length=7, blank=True, default='') status = models.IntegerField(default=1, verbose_name='1有效0停用') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'admin_assignment' unique_together = [['yonghuid', 'club_id', 'role_code']] class AdminAuditLog(QModel): """后台敏感操作审计(改余额等)。""" club_id = models.CharField(max_length=16, null=True, blank=True, db_index=True) operator_yonghuid = models.CharField(max_length=16, db_index=True) operator_role_code = models.CharField(max_length=50, blank=True, default='') target_yonghuid = models.CharField(max_length=7, null=True, blank=True) action = models.CharField(max_length=64, db_index=True) resource_type = models.CharField(max_length=32, blank=True, default='') resource_id = models.CharField(max_length=64, blank=True, default='') field_name = models.CharField(max_length=64, blank=True, default='') value_before = models.TextField(null=True, blank=True) value_after = models.TextField(null=True, blank=True) request_ip = models.CharField(max_length=64, blank=True, default='') remark = models.CharField(max_length=500, blank=True, default='') CreateTime = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'admin_audit_log' indexes = [models.Index(fields=['club_id', '-CreateTime'])] class ClubHuiyuanPrice(QModel): """各俱乐部会员售价/分成(全局 huiyuan_id 定义不变)。""" club_id = models.CharField(max_length=16, db_index=True) huiyuan_id = models.CharField(max_length=6, db_index=True) jiage = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0.00')) guanshifc = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0.00')) zuzhangfc = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0.00')) formal_days = models.PositiveIntegerField(default=30, verbose_name='正式会员有效天数') trial_enabled = models.BooleanField(default=False, verbose_name='是否开启体验会员') trial_price = models.DecimalField( max_digits=10, decimal_places=2, default=Decimal('0.00'), verbose_name='体验会员价格', ) trial_days = models.PositiveIntegerField(default=0, verbose_name='体验会员有效天数') trial_guanshifc = models.DecimalField( max_digits=10, decimal_places=2, default=Decimal('0.00'), verbose_name='体验管事分成', ) trial_zuzhangfc = models.DecimalField( max_digits=10, decimal_places=2, default=Decimal('0.00'), verbose_name='体验组长分成', ) card_image = models.CharField( max_length=500, blank=True, default='', verbose_name='充值页会员卡片装饰图(相对URL)', ) card_bg = models.CharField( max_length=500, blank=True, default='', verbose_name='充值页会员卡片背景图(相对URL,可选)', ) is_enabled = models.BooleanField(default=True) bankuai_id = models.IntegerField(null=True, blank=True) CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_huiyuan_price' unique_together = [['club_id', 'huiyuan_id']] class ClubHuiyuanBundleInclude(QModel): """俱乐部总会员包含的子会员类型(仅 is_bundle 会员使用)。""" club_id = models.CharField(max_length=16, db_index=True) bundle_huiyuan_id = models.CharField(max_length=6, db_index=True, verbose_name='总会员ID') included_huiyuan_id = models.CharField(max_length=6, db_index=True, verbose_name='包含的子会员ID') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_huiyuan_bundle_include' unique_together = [['club_id', 'bundle_huiyuan_id', 'included_huiyuan_id']] class ClubShangpinLeixingConfig(QModel): """各俱乐部小程序商品类型上架与图标(全局 ShangpinLeixing 由集团定义)。""" club_id = models.CharField(max_length=16, db_index=True) leixing_id = models.IntegerField(db_index=True, verbose_name='全局商品类型ID') is_enabled = models.BooleanField(default=True, verbose_name='是否上架') tupian_url = models.CharField(max_length=500, blank=True, default='', verbose_name='俱乐部专属图标') paixu = models.IntegerField(default=0, verbose_name='排序权重') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_shangpin_leixing_config' unique_together = [['club_id', 'leixing_id']] class ClubKaoheChenghaoConfig(QModel): """各俱乐部抢单池标签筛选区上架配置(全局 Chenghao 由集团定义)。""" club_id = models.CharField(max_length=16, db_index=True) chenghao_id = models.IntegerField(db_index=True, verbose_name='全局称号ID') is_enabled = models.BooleanField(default=True, verbose_name='是否在抢单池筛选区展示') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_kaohe_chenghao_config' unique_together = [['club_id', 'chenghao_id']] class ClubLilubiao(QModel): """各俱乐部分红/手续费配置(对应 lilubiao.fadanpingtai)。""" club_id = models.CharField(max_length=16, db_index=True) config_type = models.IntegerField(db_index=True, verbose_name='同 lilubiao.fadanpingtai') lilv = models.DecimalField(max_digits=10, decimal_places=4, default=Decimal('0.0000')) remark = models.CharField(max_length=255, blank=True, default='') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_lilubiao' unique_together = [['club_id', 'config_type']] class ClubWithdrawConfig(QModel): club_id = models.CharField(max_length=16, primary_key=True) mode = models.IntegerField(default=1, verbose_name='1自动2手动') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_withdraw_config' class ClubTixianQuota(QModel): club_id = models.CharField(max_length=16, db_index=True) leixing = models.IntegerField(db_index=True) daily_limit = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00')) CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_tixian_quota' unique_together = [['club_id', 'leixing']] class ClubFadanFenhongLilv(QModel): club_id = models.CharField(max_length=16, db_index=True) shenfen = models.IntegerField(db_index=True) lilv = models.DecimalField(max_digits=10, decimal_places=4, default=Decimal('0.0000')) CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_fadan_fenhong_lilv' unique_together = [['club_id', 'shenfen']] class IdentityTag(QModel): """身份装饰标签定义(与考核称号、订单需求标签分离)。""" club_id = models.CharField(max_length=16, db_index=True) name = models.CharField(max_length=64, verbose_name='标签名') color = models.CharField(max_length=32, default='#000000', verbose_name='主色') flash_enabled = models.BooleanField(default=False, verbose_name='闪光特效') texiao_json = models.TextField(blank=True, default='', verbose_name='特效JSON') sort_order = models.IntegerField(default=0) status = models.IntegerField(default=1, verbose_name='1启用0停用') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'identity_tag' ordering = ['sort_order', 'id'] class IdentityTagBind(QModel): """用户身份与装饰标签绑定。""" club_id = models.CharField(max_length=16, db_index=True) yonghuid = models.CharField(max_length=7, db_index=True) shenfen = models.IntegerField(verbose_name='1打手2管事3商家4组长') tag = models.ForeignKey(IdentityTag, on_delete=models.CASCADE, related_name='binds') CreateTime = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'identity_tag_bind' unique_together = [['club_id', 'yonghuid', 'shenfen', 'tag']] indexes = [ models.Index(fields=['club_id', 'yonghuid', 'shenfen']), ] class ClubDashouExamConfig(QModel): """各俱乐部打手抢单前考试配置(互不影响)。""" club_id = models.CharField(max_length=16, primary_key=True) is_enabled = models.BooleanField(default=False, verbose_name='是否开启考试') draw_count = models.PositiveIntegerField(default=10, verbose_name='每次抽题数量') pass_count = models.PositiveIntegerField(default=10, verbose_name='至少答对题数') require_member = models.BooleanField(default=True, verbose_name='须开通会员方可考试') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_dashou_exam_config' class ClubDashouExamQuestion(QModel): """俱乐部考试题库(题干+最多6选项)。""" club_id = models.CharField(max_length=16, db_index=True) stem = models.TextField(verbose_name='题干文字') question_type = models.IntegerField(default=1, verbose_name='1单选2多选') option_1 = models.CharField(max_length=500, blank=True, default='') option_2 = models.CharField(max_length=500, blank=True, default='') option_3 = models.CharField(max_length=500, blank=True, default='') option_4 = models.CharField(max_length=500, blank=True, default='') option_5 = models.CharField(max_length=500, blank=True, default='') option_6 = models.CharField(max_length=500, blank=True, default='') correct_1 = models.BooleanField(default=False) correct_2 = models.BooleanField(default=False) correct_3 = models.BooleanField(default=False) correct_4 = models.BooleanField(default=False) correct_5 = models.BooleanField(default=False) correct_6 = models.BooleanField(default=False) explanation = models.TextField(blank=True, default='', verbose_name='错题解析') is_enabled = models.BooleanField(default=True, verbose_name='是否上架') sort_order = models.IntegerField(default=0) CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'club_dashou_exam_question' indexes = [models.Index(fields=['club_id', 'is_enabled'])] class ClubDashouExamQuestionImage(QModel): """题目配图(题干下方,可多张)。""" club_id = models.CharField(max_length=16, db_index=True) question_id = models.IntegerField(db_index=True) image_url = models.CharField(max_length=500) sort_order = models.IntegerField(default=0) CreateTime = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'club_dashou_exam_question_image' indexes = [models.Index(fields=['club_id', 'question_id'])] class ClubDashouExamPass(QModel): """打手在本俱乐部是否已通过考试。""" club_id = models.CharField(max_length=16, db_index=True) yonghuid = models.CharField(max_length=7, db_index=True) passed_at = models.DateTimeField(auto_now_add=True) CreateTime = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'club_dashou_exam_pass' unique_together = [['club_id', 'yonghuid']] class KefuMenuPage(QModel): """客服后台左侧菜单页(固定 page_id,与前端路由对应)。""" page_id = models.CharField(max_length=64, primary_key=True, verbose_name='页面ID') name = models.CharField(max_length=64, verbose_name='展示名') path = models.CharField(max_length=128, blank=True, default='', verbose_name='路由路径,分组为空') parent_id = models.CharField(max_length=64, blank=True, default='', db_index=True) sort_order = models.IntegerField(default=0) perm_codes = models.JSONField(default=list, blank=True, verbose_name='拥有任一权限即可见') require_super = models.BooleanField(default=False, verbose_name='仅超级管理000001') require_group_manage = models.BooleanField(default=False, verbose_name='仅集团超管任职') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'kefu_menu_page' ordering = ['sort_order', 'page_id']