进行了 GVSDSDK 迁移,可能存在诸多问题

This commit is contained in:
TermiNexus committed 2026-06-17 20:37:47 +08:00
1 parent 72770ad73b
commit d00f0d08e5
132 files changed
+161593 -4827

No files matched your search

+2 -1
View File
@@ -132,12 +132,13 @@ AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
]
AUTH_USER_MODEL = 'users.UserMain'
AUTH_USER_MODEL = 'gvsdsdk.User'
# ==================== DRF 配置 ====================
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'gvsdsdk.auth.elt_auth.ELTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
+206 -296
View File
@@ -1,296 +1,206 @@
# Generated by Django 4.2.27 on 2026-04-06 23:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="AbnormalUserLog",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"account_id",
models.CharField(
db_index=True, max_length=20, verbose_name="账号ID(phone)"
),
),
(
"ip_address",
models.GenericIPAddressField(
blank=True, null=True, verbose_name="IP地址"
),
),
(
"real_ip",
models.GenericIPAddressField(
blank=True, null=True, verbose_name="真实IP(穿透代理后)"
),
),
(
"x_forwarded_for",
models.CharField(
blank=True,
default="",
max_length=255,
verbose_name="X-Forwarded-For",
),
),
(
"user_agent",
models.CharField(
blank=True,
default="",
max_length=500,
verbose_name="User-Agent",
),
),
(
"request_method",
models.CharField(
blank=True, default="", max_length=10, verbose_name="请求方法"
),
),
(
"request_path",
models.CharField(
blank=True, default="", max_length=500, verbose_name="请求路径"
),
),
(
"request_params",
models.TextField(
blank=True, default="", verbose_name="请求参数(GET/POST)"
),
),
(
"request_body",
models.TextField(
blank=True, default="", verbose_name="请求体(原始)"
),
),
(
"request_headers",
models.TextField(
blank=True, default="", verbose_name="请求头(JSON格式)"
),
),
(
"attempt_type",
models.CharField(
blank=True, default="", max_length=50, verbose_name="攻击类型"
),
),
(
"detail",
models.TextField(blank=True, default="", verbose_name="详细描述"),
),
(
"create_time",
models.DateTimeField(auto_now_add=True, verbose_name="创建时间"),
),
],
options={
"verbose_name": "异常用户日志",
"verbose_name_plural": "异常用户日志",
"db_table": "abnormal_user_log",
},
),
migrations.CreateModel(
name="Permission",
fields=[
(
"perm_id",
models.AutoField(
primary_key=True, serialize=False, verbose_name="权限ID"
),
),
(
"perm_code",
models.CharField(
db_index=True,
max_length=100,
unique=True,
verbose_name="权限编码",
),
),
(
"perm_name",
models.CharField(max_length=100, verbose_name="权限名称"),
),
(
"description",
models.CharField(
blank=True, default="", max_length=200, verbose_name="权限描述"
),
),
(
"create_time",
models.DateTimeField(auto_now_add=True, verbose_name="创建时间"),
),
(
"update_time",
models.DateTimeField(auto_now=True, verbose_name="更新时间"),
),
],
options={
"verbose_name": "权限",
"verbose_name_plural": "权限",
"db_table": "permission",
},
),
migrations.CreateModel(
name="Role",
fields=[
(
"role_id",
models.AutoField(
primary_key=True, serialize=False, verbose_name="角色ID"
),
),
(
"role_code",
models.CharField(
db_index=True,
max_length=50,
unique=True,
verbose_name="角色编码",
),
),
("role_name", models.CharField(max_length=50, verbose_name="角色名称")),
(
"description",
models.CharField(
blank=True, default="", max_length=200, verbose_name="角色描述"
),
),
(
"create_time",
models.DateTimeField(auto_now_add=True, verbose_name="创建时间"),
),
(
"update_time",
models.DateTimeField(auto_now=True, verbose_name="更新时间"),
),
],
options={
"verbose_name": "角色",
"verbose_name_plural": "角色",
"db_table": "role",
},
),
migrations.CreateModel(
name="UserRole",
fields=[
("id", models.AutoField(primary_key=True, serialize=False)),
(
"account_id",
models.CharField(
db_index=True, max_length=11, verbose_name="账号ID"
),
),
(
"create_time",
models.DateTimeField(auto_now_add=True, verbose_name="创建时间"),
),
(
"update_time",
models.DateTimeField(auto_now=True, verbose_name="更新时间"),
),
(
"role",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="backend.role",
verbose_name="角色",
),
),
],
options={
"verbose_name": "用户角色关联",
"verbose_name_plural": "用户角色关联",
"db_table": "user_role",
},
),
migrations.CreateModel(
name="RolePermission",
fields=[
("id", models.AutoField(primary_key=True, serialize=False)),
(
"create_time",
models.DateTimeField(auto_now_add=True, verbose_name="创建时间"),
),
(
"permission",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="backend.permission",
verbose_name="权限",
),
),
(
"role",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="backend.role",
verbose_name="角色",
),
),
],
options={
"verbose_name": "角色权限关联",
"verbose_name_plural": "角色权限关联",
"db_table": "role_permission",
},
),
migrations.AddIndex(
model_name="role",
index=models.Index(fields=["role_code"], name="role_role_co_b9f497_idx"),
),
migrations.AddIndex(
model_name="permission",
index=models.Index(
fields=["perm_code"], name="permission_perm_co_56cbe3_idx"
),
),
migrations.AddIndex(
model_name="abnormaluserlog",
index=models.Index(
fields=["account_id"], name="abnormal_us_account_425899_idx"
),
),
migrations.AddIndex(
model_name="abnormaluserlog",
index=models.Index(
fields=["ip_address"], name="abnormal_us_ip_addr_3d612b_idx"
),
),
migrations.AddIndex(
model_name="abnormaluserlog",
index=models.Index(
fields=["create_time"], name="abnormal_us_create__ee16da_idx"
),
),
migrations.AlterUniqueTogether(
name="userrole",
unique_together={("account_id", "role")},
),
migrations.AlterUniqueTogether(
name="rolepermission",
unique_together={("role", "permission")},
),
]
# Generated by Django 4.2.27 on 2026-06-17 17:17
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Permission',
fields=[
('perm_id', models.AutoField(primary_key=True, serialize=False, verbose_name='权限ID')),
('perm_code', models.CharField(db_index=True, max_length=100, unique=True, verbose_name='权限编码')),
('perm_name', models.CharField(max_length=100, verbose_name='权限名称')),
('description', models.CharField(blank=True, default='', max_length=200, verbose_name='权限描述')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '权限',
'verbose_name_plural': '权限',
'db_table': 'permission',
'managed': False,
},
),
migrations.CreateModel(
name='Role',
fields=[
('role_id', models.AutoField(primary_key=True, serialize=False, verbose_name='角色ID')),
('role_code', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='角色编码')),
('role_name', models.CharField(max_length=50, verbose_name='角色名称')),
('description', models.CharField(blank=True, default='', max_length=200, verbose_name='角色描述')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '角色',
'verbose_name_plural': '角色',
'db_table': 'role',
'managed': False,
},
),
migrations.CreateModel(
name='RolePermission',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '角色权限关联',
'verbose_name_plural': '角色权限关联',
'db_table': 'role_permission',
'managed': False,
},
),
migrations.CreateModel(
name='UserRole',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('account_id', models.CharField(db_index=True, max_length=11, verbose_name='账号ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '用户角色关联',
'verbose_name_plural': '用户角色关联',
'db_table': 'user_role',
'managed': False,
},
),
migrations.CreateModel(
name='ZuzhangRiTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='组长用户ID')),
('riqi', models.DateField(db_index=True, verbose_name='日期')),
('yaoqing_guanshi_shu', models.IntegerField(default=0, verbose_name='邀请管事总数')),
('shouru_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='收入总额(分佣)')),
('fenyong_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='分佣金额')),
],
options={
'verbose_name': '组长每日统计',
'db_table': 'zuzhang_ri_tongji',
'indexes': [models.Index(fields=['riqi', '-yaoqing_guanshi_shu'], name='zuzhang_ri__riqi_87169e_idx'), models.Index(fields=['riqi', '-shouru_zonge'], name='zuzhang_ri__riqi_1d7e51_idx')],
'unique_together': {('yonghuid', 'riqi')},
},
),
migrations.CreateModel(
name='TixianRiTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('riqi', models.DateField(db_index=True, verbose_name='日期')),
('leixing', models.IntegerField(choices=[(1, '打手'), (2, '管事'), (3, '组长'), (4, '考核官'), (5, '打手押金'), (6, '商家余额')], verbose_name='用户类型')),
('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='当天提现总额(元)')),
],
options={
'verbose_name': '每日提现统计',
'db_table': 'tixian_ri_tongji',
'indexes': [models.Index(fields=['riqi', 'leixing'], name='tixian_ri_t_riqi_c18bb2_idx')],
'unique_together': {('riqi', 'leixing')},
},
),
migrations.CreateModel(
name='ShangjiaRiTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='商家用户ID')),
('riqi', models.DateField(db_index=True, verbose_name='日期')),
('paifa_dingdan_shu', models.IntegerField(default=0, verbose_name='派发订单总数')),
('paifa_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='派发订单总金额')),
('jiesuan_dingdan_shu', models.IntegerField(default=0, verbose_name='结算订单总数')),
('jiesuan_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='结算总金额')),
('tuikuan_dingdan_shu', models.IntegerField(default=0, verbose_name='退款订单总数')),
('tuikuan_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='退款总金额')),
],
options={
'verbose_name': '商家每日统计',
'db_table': 'shangjia_ri_tongji',
'indexes': [models.Index(fields=['riqi', '-paifa_jine'], name='shangjia_ri_riqi_d00f7f_idx'), models.Index(fields=['riqi', '-jiesuan_jine'], name='shangjia_ri_riqi_25772a_idx'), models.Index(fields=['riqi', '-paifa_dingdan_shu'], name='shangjia_ri_riqi_e05c54_idx')],
'unique_together': {('yonghuid', 'riqi')},
},
),
migrations.CreateModel(
name='GuanshiXufeiRiTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='管事用户ID')),
('riqi', models.DateField(db_index=True, verbose_name='日期')),
('xufei_zongshu', models.IntegerField(default=0, verbose_name='今日续费总数')),
('xufei_shouyi', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='续费收益金额')),
],
options={
'verbose_name': '管事续费每日统计',
'db_table': 'guanshi_xufei_ri_tongji',
'indexes': [models.Index(fields=['riqi', '-xufei_zongshu'], name='guanshi_xuf_riqi_7c128f_idx'), models.Index(fields=['riqi', '-xufei_shouyi'], name='guanshi_xuf_riqi_8f09b5_idx')],
'unique_together': {('yonghuid', 'riqi')},
},
),
migrations.CreateModel(
name='GuanshiRiTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='管事用户ID')),
('riqi', models.DateField(db_index=True, verbose_name='日期')),
('yaoqing_dashou_shu', models.IntegerField(default=0, verbose_name='邀请打手总数')),
('chongzhi_dashou_shu', models.IntegerField(default=0, verbose_name='充值打手数量')),
('shouru_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='收入总额')),
],
options={
'verbose_name': '管事每日统计',
'db_table': 'guanshi_ri_tongji',
'indexes': [models.Index(fields=['riqi', '-yaoqing_dashou_shu'], name='guanshi_ri__riqi_075e1a_idx'), models.Index(fields=['riqi', '-chongzhi_dashou_shu'], name='guanshi_ri__riqi_78a79d_idx'), models.Index(fields=['riqi', '-shouru_zonge'], name='guanshi_ri__riqi_334f52_idx')],
'unique_together': {('yonghuid', 'riqi')},
},
),
migrations.CreateModel(
name='DashouRiTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='打手用户ID')),
('riqi', models.DateField(db_index=True, verbose_name='日期')),
('jiedan_zongliang', models.IntegerField(default=0, verbose_name='接单总量')),
('chengjiao_zongliang', models.IntegerField(default=0, verbose_name='成交单总量')),
('jiedan_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='接单总金额')),
('chengjiao_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='成交总金额')),
('tuikuan_liang', models.IntegerField(default=0, verbose_name='退款订单量')),
('tuikuan_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='退款总金额')),
],
options={
'verbose_name': '打手每日统计',
'db_table': 'dashou_ri_tongji',
'indexes': [models.Index(fields=['riqi', '-jiedan_zongliang'], name='dashou_ri_t_riqi_95a785_idx'), models.Index(fields=['riqi', '-chengjiao_zongliang'], name='dashou_ri_t_riqi_ad9c1a_idx'), models.Index(fields=['riqi', '-jiedan_zonge'], name='dashou_ri_t_riqi_5da703_idx'), models.Index(fields=['riqi', '-chengjiao_zonge'], name='dashou_ri_t_riqi_0a3156_idx')],
'unique_together': {('yonghuid', 'riqi')},
},
),
migrations.CreateModel(
name='AbnormalUserLog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('account_id', models.CharField(db_index=True, max_length=20, verbose_name='账号ID(phone)')),
('ip_address', models.GenericIPAddressField(blank=True, null=True, verbose_name='IP地址')),
('real_ip', models.GenericIPAddressField(blank=True, null=True, verbose_name='真实IP(穿透代理后)')),
('x_forwarded_for', models.CharField(blank=True, default='', max_length=255, verbose_name='X-Forwarded-For')),
('user_agent', models.CharField(blank=True, default='', max_length=500, verbose_name='User-Agent')),
('request_method', models.CharField(blank=True, default='', max_length=10, verbose_name='请求方法')),
('request_path', models.CharField(blank=True, default='', max_length=500, verbose_name='请求路径')),
('request_params', models.TextField(blank=True, default='', verbose_name='请求参数(GET/POST)')),
('request_body', models.TextField(blank=True, default='', verbose_name='请求体(原始)')),
('request_headers', models.TextField(blank=True, default='', verbose_name='请求头(JSON格式)')),
('attempt_type', models.CharField(blank=True, default='', max_length=50, verbose_name='攻击类型')),
('detail', models.TextField(blank=True, default='', verbose_name='详细描述')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '异常用户日志',
'verbose_name_plural': '异常用户日志',
'db_table': 'abnormal_user_log',
'indexes': [models.Index(fields=['account_id'], name='abnormal_us_account_425899_idx'), models.Index(fields=['ip_address'], name='abnormal_us_ip_addr_3d612b_idx'), models.Index(fields=['create_time'], name='abnormal_us_create__ee16da_idx')],
},
),
]
@@ -1,339 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-09 14:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("backend", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="ZuzhangRiTongji",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"yonghuid",
models.CharField(
db_index=True, max_length=7, verbose_name="组长用户ID"
),
),
("riqi", models.DateField(db_index=True, verbose_name="日期")),
(
"yaoqing_guanshi_shu",
models.IntegerField(default=0, verbose_name="邀请管事总数"),
),
(
"shouru_zonge",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="收入总额(分佣)",
),
),
(
"fenyong_jine",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="分佣金额",
),
),
],
options={
"verbose_name": "组长每日统计",
"db_table": "zuzhang_ri_tongji",
"indexes": [
models.Index(
fields=["riqi", "-yaoqing_guanshi_shu"],
name="zuzhang_ri__riqi_87169e_idx",
),
models.Index(
fields=["riqi", "-shouru_zonge"],
name="zuzhang_ri__riqi_1d7e51_idx",
),
],
"unique_together": {("yonghuid", "riqi")},
},
),
migrations.CreateModel(
name="ShangjiaRiTongji",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"yonghuid",
models.CharField(
db_index=True, max_length=7, verbose_name="商家用户ID"
),
),
("riqi", models.DateField(db_index=True, verbose_name="日期")),
(
"paifa_dingdan_shu",
models.IntegerField(default=0, verbose_name="派发订单总数"),
),
(
"paifa_jine",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="派发订单总金额",
),
),
(
"jiesuan_dingdan_shu",
models.IntegerField(default=0, verbose_name="结算订单总数"),
),
(
"jiesuan_jine",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="结算总金额",
),
),
(
"tuikuan_dingdan_shu",
models.IntegerField(default=0, verbose_name="退款订单总数"),
),
(
"tuikuan_jine",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="退款总金额",
),
),
],
options={
"verbose_name": "商家每日统计",
"db_table": "shangjia_ri_tongji",
"indexes": [
models.Index(
fields=["riqi", "-paifa_jine"],
name="shangjia_ri_riqi_d00f7f_idx",
),
models.Index(
fields=["riqi", "-jiesuan_jine"],
name="shangjia_ri_riqi_25772a_idx",
),
models.Index(
fields=["riqi", "-paifa_dingdan_shu"],
name="shangjia_ri_riqi_e05c54_idx",
),
],
"unique_together": {("yonghuid", "riqi")},
},
),
migrations.CreateModel(
name="GuanshiXufeiRiTongji",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"yonghuid",
models.CharField(
db_index=True, max_length=7, verbose_name="管事用户ID"
),
),
("riqi", models.DateField(db_index=True, verbose_name="日期")),
(
"xufei_zongshu",
models.IntegerField(default=0, verbose_name="今日续费总数"),
),
(
"xufei_shouyi",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="续费收益金额",
),
),
],
options={
"verbose_name": "管事续费每日统计",
"db_table": "guanshi_xufei_ri_tongji",
"indexes": [
models.Index(
fields=["riqi", "-xufei_zongshu"],
name="guanshi_xuf_riqi_7c128f_idx",
),
models.Index(
fields=["riqi", "-xufei_shouyi"],
name="guanshi_xuf_riqi_8f09b5_idx",
),
],
"unique_together": {("yonghuid", "riqi")},
},
),
migrations.CreateModel(
name="GuanshiRiTongji",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"yonghuid",
models.CharField(
db_index=True, max_length=7, verbose_name="管事用户ID"
),
),
("riqi", models.DateField(db_index=True, verbose_name="日期")),
(
"yaoqing_dashou_shu",
models.IntegerField(default=0, verbose_name="邀请打手总数"),
),
(
"chongzhi_dashou_shu",
models.IntegerField(default=0, verbose_name="充值打手数量"),
),
(
"shouru_zonge",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="收入总额",
),
),
],
options={
"verbose_name": "管事每日统计",
"db_table": "guanshi_ri_tongji",
"indexes": [
models.Index(
fields=["riqi", "-yaoqing_dashou_shu"],
name="guanshi_ri__riqi_075e1a_idx",
),
models.Index(
fields=["riqi", "-chongzhi_dashou_shu"],
name="guanshi_ri__riqi_78a79d_idx",
),
models.Index(
fields=["riqi", "-shouru_zonge"],
name="guanshi_ri__riqi_334f52_idx",
),
],
"unique_together": {("yonghuid", "riqi")},
},
),
migrations.CreateModel(
name="DashouRiTongji",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"yonghuid",
models.CharField(
db_index=True, max_length=7, verbose_name="打手用户ID"
),
),
("riqi", models.DateField(db_index=True, verbose_name="日期")),
(
"jiedan_zongliang",
models.IntegerField(default=0, verbose_name="接单总量"),
),
(
"chengjiao_zongliang",
models.IntegerField(default=0, verbose_name="成交单总量"),
),
(
"jiedan_zonge",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="接单总金额",
),
),
(
"chengjiao_zonge",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="成交总金额",
),
),
(
"tuikuan_liang",
models.IntegerField(default=0, verbose_name="退款订单量"),
),
(
"tuikuan_jine",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="退款总金额",
),
),
],
options={
"verbose_name": "打手每日统计",
"db_table": "dashou_ri_tongji",
"indexes": [
models.Index(
fields=["riqi", "-jiedan_zongliang"],
name="dashou_ri_t_riqi_95a785_idx",
),
models.Index(
fields=["riqi", "-chengjiao_zongliang"],
name="dashou_ri_t_riqi_ad9c1a_idx",
),
models.Index(
fields=["riqi", "-jiedan_zonge"],
name="dashou_ri_t_riqi_5da703_idx",
),
models.Index(
fields=["riqi", "-chengjiao_zonge"],
name="dashou_ri_t_riqi_0a3156_idx",
),
],
"unique_together": {("yonghuid", "riqi")},
},
),
]
-54
View File
@@ -1,54 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-10 18:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("backend", "0002_zuzhangritongji_shangjiaritongji_and_more"),
]
operations = [
migrations.CreateModel(
name="TixianRiTongji",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("riqi", models.DateField(db_index=True, verbose_name="日期")),
(
"leixing",
models.IntegerField(
choices=[(1, "打手"), (2, "管事"), (3, "组长")],
verbose_name="用户类型",
),
),
(
"total_amount",
models.DecimalField(
decimal_places=2,
default=0.0,
max_digits=12,
verbose_name="当天提现总额(元)",
),
),
],
options={
"verbose_name": "每日提现统计",
"db_table": "tixian_ri_tongji",
"indexes": [
models.Index(
fields=["riqi", "leixing"], name="tixian_ri_t_riqi_c18bb2_idx"
)
],
"unique_together": {("riqi", "leixing")},
},
),
]
@@ -1,34 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-15 01:42
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('backend', '0003_tixianritongji'),
]
operations = [
migrations.AlterField(
model_name='rolepermission',
name='permission',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='backend.permission', verbose_name='权限'),
),
migrations.AlterField(
model_name='rolepermission',
name='role',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='backend.role', verbose_name='角色'),
),
migrations.AlterField(
model_name='tixianritongji',
name='leixing',
field=models.IntegerField(choices=[(1, '打手'), (2, '管事'), (3, '组长'), (4, '考核官'), (5, '打手押金'), (6, '商家余额')], verbose_name='用户类型'),
),
migrations.AlterField(
model_name='userrole',
name='role',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='backend.role', verbose_name='角色'),
),
]
View File
Whitespace-only changes.
+4
View File
@@ -17,6 +17,7 @@ class Role(QModel):
db_table = 'role'
verbose_name = '角色'
verbose_name_plural = '角色'
managed = False
indexes = [
models.Index(fields=['role_code']),
]
@@ -39,6 +40,7 @@ class Permission(QModel):
db_table = 'permission'
verbose_name = '权限'
verbose_name_plural = '权限'
managed = False
indexes = [
models.Index(fields=['perm_code']),
]
@@ -59,6 +61,7 @@ class RolePermission(QModel):
db_table = 'role_permission'
verbose_name = '角色权限关联'
verbose_name_plural = '角色权限关联'
managed = False
unique_together = [['role', 'permission']] # 防止重复授权
def __str__(self):
@@ -78,6 +81,7 @@ class UserRole(QModel):
db_table = 'user_role'
verbose_name = '用户角色关联'
verbose_name_plural = '用户角色关联'
managed = False
unique_together = [['account_id', 'role']] # 同一用户同一角色只能有一条
def __str__(self):
+37 -36
View File
@@ -56,9 +56,10 @@ from backend.models import Role, Permission, RolePermission, UserRole, TixianRiT
## users
from users.models import (
UserMain, UserGuanshi, UserBoss, UserZuzhang,
UserGuanshi, UserBoss, UserZuzhang,
UserKefu, UserDashou, Xiugaijilu, UserShangjia, UserShenheguan
)
from gvsdsdk.models import User
## orders
from orders.models import (
@@ -315,7 +316,7 @@ class GetAdminUserListView(APIView):
page = int(request.data.get('page', 1))
page_size = int(request.data.get('pageSize', 20))
users = UserMain.query.filter(
users = User.query.filter(
user_type='kefu',
kefu_profile__isnull=False
).select_related('kefu_profile')
@@ -420,7 +421,7 @@ class GetAdminRolesView(APIView):
page_size = int(request.data.get('pageSize', 20))
# 基础查询:user_type='kefu' 且存在客服扩展表
users = UserMain.query.filter(user_type='kefu', kefu_profile__isnull=False).select_related('kefu_profile')
users = User.query.filter(user_type='kefu', kefu_profile__isnull=False).select_related('kefu_profile')
if phone:
users = users.filter(phone__icontains=phone)
if nicheng:
@@ -487,9 +488,9 @@ class ModifyAdminUserView(APIView):
return Response({'code': 400, 'msg': '缺少目标用户账号'})
try:
target_user = UserMain.query.get(phone=target_phone, user_type='kefu')
target_user = User.query.get(phone=target_phone, user_type='kefu')
target_kefu = target_user.kefu_profile
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '用户不存在'})
except UserKefu.DoesNotExist:
return Response({'code': 404, 'msg': '用户扩展信息缺失'})
@@ -574,25 +575,25 @@ class AddAdminUserView(APIView):
return Response({'code': 400, 'msg': '密码和二级密码至少6位'})
# 校验手机号是否已被占用(且 user_type='kefu')
if UserMain.query.filter(phone=phone, user_type='kefu').exists():
if User.query.filter(phone=phone, user_type='kefu').exists():
return Response({'code': 400, 'msg': '该账号已存在'})
# 生成唯一的 yonghuid(7位数字)
while True:
yonghuid = str(random.randint(1000000, 9999999))
if not UserMain.query.filter(yonghuid=yonghuid).exists():
if not User.query.filter(yonghuid=yonghuid).exists():
break
# 生成唯一的 openid(格式:admin_{时间戳}_{随机6位})
timestamp = str(int(time.time() * 1000))
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
while UserMain.query.filter(openid=openid).exists():
while User.query.filter(openid=openid).exists():
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
with transaction.atomic():
user_main = UserMain.query.create(
user_main = User.query.create(
yonghuid=yonghuid,
openid=openid,
phone=phone,
@@ -756,10 +757,10 @@ class KefuGetDashouDetailView(APIView):
# 4. 查询打手主表和扩展表
try:
user_main = UserMain.query.select_related('dashou_profile').get(
user_main = User.query.select_related('dashou_profile').get(
yonghuid=uid
)
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '打手不存在'})
try:
@@ -913,10 +914,10 @@ class KefuGetDashouDetailView(APIView):
# 3. 查询打手主表和扩展表
try:
# 使用 select_related 预加载 dashou_profile,减少数据库查询
user_main = UserMain.query.select_related('dashou_profile').get(
user_main = User.query.select_related('dashou_profile').get(
yonghuid=uid
)
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '打手不存在'}, status=status.HTTP_404_NOT_FOUND)
# 验证用户类型是否为打手(可选,但建议验证)
@@ -1063,9 +1064,9 @@ class KefuUpdateDashouView(APIView):
# 3. 查询打手
try:
dashou_user = UserMain.query.get(yonghuid=dashou_id)
dashou_user = User.query.get(yonghuid=dashou_id)
dashou_profile = dashou_user.dashou_profile
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '打手不存在'})
except UserDashou.DoesNotExist:
return Response({'code': 404, 'msg': '打手扩展信息缺失'})
@@ -2837,8 +2838,8 @@ class GetGuanliListView(APIView):
invite_count_value = request.data.get('invite_count_value')
status = request.data.get('status')
# 构建查询:从 UserMain 开始,关联 UserGuanshi 和 UserBoss(左连接获取昵称)
qs = UserMain.query.filter(
# 构建查询:从 User 开始,关联 UserGuanshi 和 UserBoss(左连接获取昵称)
qs = User.query.filter(
guanshi_profile__isnull=False # 确保是管事
).select_related('guanshi_profile').select_related('boss_profile')
@@ -2967,10 +2968,10 @@ class GetGuanliDetailView(APIView):
# 查询用户主表和管事扩展表
try:
user = UserMain.query.select_related('guanshi_profile', 'boss_profile').get(yonghuid=yonghuid)
user = User.query.select_related('guanshi_profile', 'boss_profile').get(yonghuid=yonghuid)
guanshi = user.guanshi_profile
boss = user.boss_profile if hasattr(user, 'boss_profile') else None
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '管事不存在'})
except UserGuanshi.DoesNotExist:
return Response({'code': 404, 'msg': '用户不是管事'})
@@ -3088,10 +3089,10 @@ class UpdateGuanliView(APIView):
# 查询管事对象(不在事务外加锁,事务内加锁)
try:
user = UserMain.query.get(yonghuid=yonghuid)
user = User.query.get(yonghuid=yonghuid)
guanshi = user.guanshi_profile
boss = user.boss_profile if hasattr(user, 'boss_profile') else None
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '用户不存在'})
except UserGuanshi.DoesNotExist:
return Response({'code': 404, 'msg': '用户不是管事'})
@@ -3099,7 +3100,7 @@ class UpdateGuanliView(APIView):
# 开始事务,内部使用 select_for_update
with transaction.atomic():
# 重新获取加锁对象
user = UserMain.objects.select_for_update().get(yonghuid=yonghuid)
user = User.objects.select_for_update().get(yonghuid=yonghuid)
guanshi = user.guanshi_profile
boss = user.boss_profile if hasattr(user, 'boss_profile') else None
@@ -3659,10 +3660,10 @@ class GetZuzhangDetailView(APIView):
# 查询组长主表、扩展表、老板扩展表(昵称)
try:
user = UserMain.query.select_related('zuzhang_profile', 'boss_profile').get(yonghuid=yonghuid)
user = User.query.select_related('zuzhang_profile', 'boss_profile').get(yonghuid=yonghuid)
zuzhang = user.zuzhang_profile
boss = user.boss_profile if hasattr(user, 'boss_profile') else None
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '组长不存在'})
except UserZuzhang.DoesNotExist:
return Response({'code': 404, 'msg': '用户不是组长'})
@@ -3672,7 +3673,7 @@ class GetZuzhangDetailView(APIView):
'yonghuid': user.yonghuid,
'nickname': boss.nickname if boss else '',
'avatar': user.avatar or '',
'dianhua': '', # 组长表无电话字段?组长扩展表没有电话/微信,但前端可能需要,可从UserMain关联?实际上组长表无电话字段,这里留空或从其他表获取
'dianhua': '', # 组长表无电话字段?组长扩展表没有电话/微信,但前端可能需要,可从User关联?实际上组长表无电话字段,这里留空或从其他表获取
'wechat': '',
'zhuangtai': zuzhang.zhuangtai,
'yaoqingma': zuzhang.yaoqingma,
@@ -3782,10 +3783,10 @@ class UpdateZuzhangView(APIView):
# 查询组长对象
try:
user = UserMain.query.get(yonghuid=yonghuid)
user = User.query.get(yonghuid=yonghuid)
zuzhang = user.zuzhang_profile
boss = user.boss_profile if hasattr(user, 'boss_profile') else None
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '用户不存在'})
except UserZuzhang.DoesNotExist:
return Response({'code': 404, 'msg': '用户不是组长'})
@@ -3820,7 +3821,7 @@ class UpdateZuzhangView(APIView):
if avatar:
user.avatar = avatar
user.save()
# 组长表没有电话/微信字段,如需存储可暂存到UserMain或忽略
# 组长表没有电话/微信字段,如需存储可暂存到User或忽略
# 这里不处理
# ---------- 2. 可提现金额修改(加:6600a;减:6600b)----------
@@ -5025,7 +5026,7 @@ class ShopModifyView(APIView):
return Response({'code': 400, 'msg': '必填字段缺失(用户ID、账号、密码、店铺名称)'})
# 检查用户是否存在
if not UserMain.query.filter(yonghuid=yonghu_id).exists():
if not User.query.filter(yonghuid=yonghu_id).exists():
return Response({'code': 404, 'msg': '用户不存在'})
# 检查凭证是否已存在
@@ -5961,11 +5962,11 @@ class FaKuanChuangJianView(APIView):
# 验证用户是否存在对应的扩展表
try:
user = UserMain.query.get(yonghuid=beichufa_id)
user = User.query.get(yonghuid=beichufa_id)
profile_attr = SHENFEN_PROFILE_MAP.get(shenfen)
if not profile_attr or not hasattr(user, profile_attr):
return Response({'code': 400, 'msg': '该用户不是所选身份'})
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '用户不存在'})
# 处理图片上传
@@ -6161,9 +6162,9 @@ class PunishDashouView(APIView):
# 查询打手
try:
dashou_user = UserMain.query.get(yonghuid=dashou_id)
dashou_user = User.query.get(yonghuid=dashou_id)
dashou = dashou_user.dashou_profile
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 404, 'msg': '打手用户不存在'})
except ObjectDoesNotExist:
return Response({'code': 400, 'msg': '该用户不是打手'})
@@ -8188,7 +8189,7 @@ class ZxkfghdsView(APIView):
shangjia_ext = old_order.shangjia_kuozhan
shangjia_id = shangjia_ext.shangjia_id
# 获取商家昵称用于新订单扩展表
shangjia_user = UserMain.query.get(yonghuid=shangjia_id)
shangjia_user = User.query.get(yonghuid=shangjia_id)
shangjia_nicheng = shangjia_user.shop_profile.nicheng or f"商家{shangjia_id}"
except (ObjectDoesNotExist, UserShangjia.DoesNotExist):
logger.error(f"商家信息缺失,订单: {dingdan_id}")
@@ -8205,12 +8206,12 @@ class ZxkfghdsView(APIView):
dashou_id = old_order.jiedan_dashou_id
if dashou_id:
try:
dashou_user = UserMain.query.get(yonghuid=dashou_id)
dashou_user = User.query.get(yonghuid=dashou_id)
dashou_profile = dashou_user.dashou_profile
dashou_profile.tuikuanliang += 1 # 退款次数+1
dashou_profile.zhuangtai = 1 # 设为空闲
dashou_profile.save()
except (UserMain.DoesNotExist, ObjectDoesNotExist):
except (User.DoesNotExist, ObjectDoesNotExist):
logger.warning(f"打手 {dashou_id} 不存在,跳过更新")
# 5.3 更新退款记录表
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""检查 user_dashou 中有 user_id 的记录"""
import re
with open('xaio_cheng_xu_backup.sql', 'r', encoding='utf-8') as f:
content = f.read()
pattern = re.compile(r"INSERT\s+INTO\s+`user_dashou`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
matches = list(pattern.finditer(content))
# 找有 user_id 的记录
has_uid = 0
no_uid = 0
uid_values = []
for m in matches:
v = m.group(1).rstrip()
if v.endswith('NULL'):
no_uid += 1
else:
has_uid += 1
# 提取最后一个值(user_id)
last_comma = v.rfind(',')
uid_val = v[last_comma+1:].strip()
uid_values.append(uid_val)
print(f"有 user_id: {has_uid}, 无 user_id: {no_uid}")
print(f"user_id 值样本: {uid_values[:10]}")
# 检查 user_main 中这些 user_id 是否存在
# user_main 的 id 字段是 vals[1]
main_pattern = re.compile(r"INSERT\s+INTO\s+`user_main`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
main_ids = set()
for m in main_pattern.finditer(content):
# 简单提取第二个字段 (id)
v = m.group(1)
# 找前几个逗号
in_q = False
commas = []
for i, ch in enumerate(v):
if ch == "'": in_q = not in_q
elif ch == ',' and not in_q:
commas.append(i)
if len(commas) >= 2: break
if len(commas) >= 2:
id_val = v[commas[0]+1:commas[1]].strip()
main_ids.add(id_val)
print(f"\nuser_main id 范围: {len(main_ids)} 个")
matched = sum(1 for uid in uid_values if uid in main_ids)
print(f"user_dashou user_id 匹配 user_main: {matched}/{len(uid_values)}")
# 也检查 user_type 分布
type_pattern = re.compile(r"INSERT\s+INTO\s+`user_main`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
type_counts = {}
for m in type_pattern.finditer(content):
v = m.group(1)
# 找第12个字段 (user_type, index 11)
in_q = False
commas = []
for i, ch in enumerate(v):
if ch == "'": in_q = not in_q
elif ch == ',' and not in_q:
commas.append(i)
if len(commas) >= 12: break
if len(commas) >= 12:
type_val = v[commas[10]+1:commas[11]].strip().strip("'")
type_counts[type_val] = type_counts.get(type_val, 0) + 1
print(f"\nuser_type 分布: {type_counts}")
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
"""检查数据库表行数"""
import MySQLdb
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
conn = MySQLdb.connect(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
database=DATABASE_NAME
)
cursor = conn.cursor()
cursor.execute(
"SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES "
"WHERE TABLE_SCHEMA = %s ORDER BY TABLE_NAME",
[DATABASE_NAME]
)
for row in cursor.fetchall():
print(f"{row[0]:40s} {row[1]}")
conn.close()
+296 -92
View File
@@ -1,92 +1,296 @@
# Generated by Django 5.2.10 on 2026-01-14 19:59
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Gonggao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('leixing', models.IntegerField(blank=True, null=True, verbose_name='公告类型')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='公告介绍')),
],
options={
'verbose_name': '公告',
'verbose_name_plural': '公告',
'db_table': 'gonggao',
},
),
migrations.CreateModel(
name='Lunbo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tupian_url', models.CharField(blank=True, max_length=500, null=True, verbose_name='轮播图片URL')),
('leixing', models.IntegerField(blank=True, null=True, verbose_name='图片类型:1:轮播2:个人中心背景')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
],
options={
'verbose_name': '轮播',
'verbose_name_plural': '轮播',
'db_table': 'lunbo',
},
),
migrations.CreateModel(
name='Qunpeizhi',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('peizhiid', models.IntegerField(blank=True, null=True, verbose_name='群类型:1.打手 2.管事')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
('neirong', models.CharField(blank=True, max_length=200, null=True, verbose_name='群介绍')),
('qunid', models.CharField(blank=True, max_length=100, null=True, verbose_name='群id')),
('jieshao', models.CharField(blank=True, max_length=200, null=True, verbose_name='介绍')),
],
options={
'db_table': 'qunpeizhi',
},
),
migrations.CreateModel(
name='Szjilu',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='记录ID')),
('zongsy', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='总收益')),
('zongls', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='总流水')),
('zongzc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='总支出')),
('jrzc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='今日支出')),
('jrls', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='今日流水')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
],
options={
'verbose_name': '收支记录',
'verbose_name_plural': '收支记录',
'db_table': 'szjilu',
},
),
migrations.CreateModel(
name='Tupianpeizhi',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='配置图片URL')),
('leixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='提现类型1:打手规则图片2:默认头像图片')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
],
options={
'verbose_name': '配置图片',
'verbose_name_plural': '配置图片',
'db_table': 'tupianpeizhi',
},
),
]
# Generated by Django 4.2.27 on 2026-06-17 16:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Gonggao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('leixing', models.IntegerField(blank=True, null=True, verbose_name='公告类型')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='公告介绍')),
],
options={
'verbose_name': '公告',
'verbose_name_plural': '公告',
'db_table': 'gonggao',
},
),
migrations.CreateModel(
name='Lunbo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tupian_url', models.CharField(blank=True, max_length=500, null=True, verbose_name='轮播图片URL')),
('leixing', models.IntegerField(blank=True, null=True, verbose_name='图片类型:1:轮播2:个人中心背景')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
],
options={
'verbose_name': '轮播',
'verbose_name_plural': '轮播',
'db_table': 'lunbo',
},
),
migrations.CreateModel(
name='PopupConfig',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('popup_id', models.CharField(max_length=50, verbose_name='弹窗唯一ID')),
('title', models.CharField(blank=True, max_length=200, verbose_name='标题(后台用)')),
('description', models.TextField(blank=True, verbose_name='描述(后台用)')),
('strategy_type', models.CharField(choices=[('once', '仅一次'), ('daily', '每日'), ('weekly', '每周'), ('monthly', '每月'), ('yearly', '每年'), ('always', '始终'), ('count', '周期内次数限制')], default='once', max_length=20)),
('max_count', models.PositiveIntegerField(default=1, verbose_name='周期内最大展示次数')),
('reset_interval', models.CharField(blank=True, choices=[('day', '天'), ('week', '周'), ('month', '月'), ('year', '年')], max_length=20, verbose_name='重置周期(count类型时使用)')),
('duration', models.PositiveIntegerField(default=0, verbose_name='强制阅读秒数(0=无强制)')),
('force_even_muted', models.BooleanField(default=False, verbose_name='强制弹出(忽略用户今日屏蔽)')),
('sort_order', models.PositiveIntegerField(default=0, verbose_name='展示顺序')),
('is_active', models.BooleanField(default=True, verbose_name='是否启用')),
('start_time', models.DateTimeField(blank=True, null=True, verbose_name='生效开始时间')),
('end_time', models.DateTimeField(blank=True, null=True, verbose_name='生效结束时间')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': '弹窗配置',
'verbose_name_plural': '弹窗配置',
'db_table': 'popup_config',
'ordering': ['sort_order', 'id'],
},
),
migrations.CreateModel(
name='PopupPage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('page_key', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='页面标识')),
('name', models.CharField(max_length=100, verbose_name='页面名称')),
('description', models.TextField(blank=True, verbose_name='描述')),
('is_active', models.BooleanField(default=True, verbose_name='是否启用')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('ignore_user_mute', models.BooleanField(default=False, verbose_name='忽略用户今日屏蔽')),
],
options={
'verbose_name': '弹窗页面',
'verbose_name_plural': '弹窗页面',
'db_table': 'popup_page',
},
),
migrations.CreateModel(
name='Qunpeizhi',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('peizhiid', models.IntegerField(blank=True, null=True, verbose_name='群类型:1.打手 2.管事')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
('neirong', models.CharField(blank=True, max_length=200, null=True, verbose_name='群介绍')),
('qunid', models.CharField(blank=True, max_length=100, null=True, verbose_name='群id')),
('jieshao', models.CharField(blank=True, max_length=200, null=True, verbose_name='介绍')),
],
options={
'db_table': 'qunpeizhi',
},
),
migrations.CreateModel(
name='Szjilu',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='记录ID')),
('zongsy', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='总收益')),
('zongls', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='总流水')),
('zongzc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='总支出')),
('jrzc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='今日支出')),
('jrls', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='今日流水')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
],
options={
'verbose_name': '收支记录',
'verbose_name_plural': '收支记录',
'db_table': 'szjilu',
},
),
migrations.CreateModel(
name='TixianQuotaDefault',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('leixing', models.IntegerField(choices=[(1, '打手'), (2, '管事'), (3, '组长'), (4, '考核官'), (5, '打手押金'), (6, '商家余额')], unique=True, verbose_name='用户类型')),
('default_quota', models.DecimalField(decimal_places=2, default=20.0, max_digits=10, verbose_name='默认每日提现限额(元)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '默认提现限额',
'verbose_name_plural': '默认提现限额',
'db_table': 'tixian_quota_default',
},
),
migrations.CreateModel(
name='Tupianpeizhi',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='配置图片URL')),
('leixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='提现类型1:打手规则图片2:默认头像图片')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
('fangwen_cishu', models.PositiveIntegerField(default=0, verbose_name='访问次数')),
],
options={
'verbose_name': '配置图片',
'verbose_name_plural': '配置图片',
'db_table': 'tupianpeizhi',
},
),
migrations.CreateModel(
name='WithdrawConfig',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('mode', models.IntegerField(choices=[(1, '自动提现'), (2, '手动提现')], default=2, verbose_name='提现模式')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '提现模式配置',
'verbose_name_plural': '提现模式配置',
'db_table': 'withdraw_config',
},
),
migrations.CreateModel(
name='ShangjiaMoban',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='模板ID')),
('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('leixing_id', models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')),
('moban_jieshao', models.CharField(max_length=500, verbose_name='模板介绍')),
('jiage', models.DecimalField(decimal_places=2, help_text='单位:元', max_digits=10, verbose_name='模板价格')),
('fabu_shuliang', models.PositiveIntegerField(default=0, verbose_name='发布数量')),
('yongjin_qiangdan', models.BooleanField(default=False, verbose_name='是否开启佣金抢单')),
('yongjin_jiage', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金价格')),
('chenghao_id', models.IntegerField(blank=True, null=True, verbose_name='关联称号ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '商家订单模板',
'verbose_name_plural': '商家订单模板',
'db_table': 'shangjia_moban',
'indexes': [models.Index(fields=['yonghu_id', 'leixing_id'], name='shangjia_mo_yonghu__bb287d_idx'), models.Index(fields=['yonghu_id', 'leixing_id', 'id'], name='shangjia_mo_yonghu__4240d0_idx')],
'unique_together': {('yonghu_id', 'leixing_id', 'moban_jieshao')},
},
),
migrations.CreateModel(
name='ShangjiaLianjie',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='链接ID')),
('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('leixing_id', models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')),
('moban_id', models.PositiveIntegerField(db_index=True, verbose_name='模板ID')),
('lianjie', models.CharField(max_length=500, unique=True, verbose_name='链接地址')),
('dingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('is_used', models.BooleanField(db_index=True, default=False, verbose_name='是否已使用')),
('shiyongzhe_ip', models.CharField(blank=True, max_length=50, null=True, verbose_name='使用者IP')),
('youxiao_shijian', models.DateTimeField(blank=True, null=True, verbose_name='有效截止时间')),
('lianjie_token', models.CharField(blank=True, db_index=True, max_length=32, null=True, unique=True, verbose_name='链接Token')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('previous_lianjie_id', models.PositiveIntegerField(blank=True, db_index=True, null=True, verbose_name='上一个链接ID')),
('previous_dingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='上一个订单ID')),
],
options={
'verbose_name': '商家链接',
'verbose_name_plural': '商家链接',
'db_table': 'shangjia_lianjie',
'indexes': [models.Index(fields=['yonghu_id', 'moban_id', 'leixing_id'], name='shangjia_li_yonghu__9f2b25_idx'), models.Index(fields=['lianjie_token'], name='shangjia_li_lianjie_99014c_idx'), models.Index(fields=['dingdan_id'], name='shangjia_li_dingdan_95b682_idx')],
},
),
migrations.CreateModel(
name='PopupImage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('image_url', models.CharField(max_length=500, verbose_name='图片相对路径')),
('text', models.TextField(blank=True, verbose_name='图片上方文字')),
('sort_order', models.PositiveIntegerField(default=0, verbose_name='展示顺序')),
('created_at', models.DateTimeField(auto_now_add=True)),
('popup_config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='config.popupconfig')),
],
options={
'verbose_name': '弹窗图片',
'verbose_name_plural': '弹窗图片',
'db_table': 'popup_image',
'ordering': ['sort_order', 'id'],
},
),
migrations.AddField(
model_name='popupconfig',
name='page',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='popups', to='config.popuppage'),
),
migrations.CreateModel(
name='DailyPayoutStat',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(db_index=True, unique=True, verbose_name='统计日期')),
('year', models.PositiveSmallIntegerField(verbose_name='年份')),
('month', models.PositiveSmallIntegerField(verbose_name='月份')),
('day', models.PositiveSmallIntegerField(verbose_name='日期')),
('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='出款总额')),
('total_count', models.PositiveIntegerField(default=0, verbose_name='出款总笔数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '每日出款统计',
'verbose_name_plural': '每日出款统计',
'db_table': 'daily_payout_stat',
'indexes': [models.Index(fields=['date'], name='daily_payou_date_b534ec_idx'), models.Index(fields=['year', 'month', 'day'], name='daily_payou_year_6376ca_idx')],
},
),
migrations.CreateModel(
name='DailyIncomeStat',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(db_index=True, unique=True, verbose_name='统计日期')),
('year', models.PositiveSmallIntegerField(verbose_name='年份')),
('month', models.PositiveSmallIntegerField(verbose_name='月份')),
('day', models.PositiveSmallIntegerField(verbose_name='日期')),
('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='总收入金额')),
('total_count', models.PositiveIntegerField(default=0, verbose_name='总收入笔数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '每日收入统计',
'verbose_name_plural': '每日收入统计',
'db_table': 'daily_income_stat',
'indexes': [models.Index(fields=['date'], name='daily_incom_date_75e6df_idx'), models.Index(fields=['year', 'month', 'day'], name='daily_incom_year_d85d10_idx')],
},
),
migrations.CreateModel(
name='AccountPermission',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('account_id', models.CharField(db_index=True, max_length=11, verbose_name='账号ID')),
('permission_code', models.IntegerField(verbose_name='权限代码')),
('is_enabled', models.BooleanField(default=False, verbose_name='是否开启')),
],
options={
'verbose_name': '账号权限',
'verbose_name_plural': '账号权限',
'db_table': 'account_permission',
'unique_together': {('account_id', 'permission_code')},
},
),
migrations.AlterUniqueTogether(
name='popupconfig',
unique_together={('page', 'popup_id')},
),
]
@@ -1,56 +0,0 @@
# Generated by Django 4.2.27 on 2026-01-27 12:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='ShangjiaMoban',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='模板ID')),
('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('leixing_id', models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')),
('moban_jieshao', models.CharField(max_length=500, verbose_name='模板介绍')),
('jiage', models.DecimalField(decimal_places=2, help_text='单位:元', max_digits=10, verbose_name='模板价格')),
('fabu_shuliang', models.PositiveIntegerField(default=0, verbose_name='发布数量')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '商家订单模板',
'verbose_name_plural': '商家订单模板',
'db_table': 'shangjia_moban',
'indexes': [models.Index(fields=['yonghu_id', 'leixing_id'], name='shangjia_mo_yonghu__bb287d_idx'), models.Index(fields=['yonghu_id', 'leixing_id', 'id'], name='shangjia_mo_yonghu__4240d0_idx')],
'unique_together': {('yonghu_id', 'leixing_id', 'moban_jieshao')},
},
),
migrations.CreateModel(
name='ShangjiaLianjie',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='链接ID')),
('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('leixing_id', models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')),
('moban_id', models.PositiveIntegerField(db_index=True, verbose_name='模板ID')),
('lianjie', models.CharField(max_length=500, unique=True, verbose_name='链接地址')),
('dingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('is_used', models.BooleanField(db_index=True, default=False, verbose_name='是否已使用')),
('shiyongzhe_ip', models.CharField(blank=True, max_length=50, null=True, verbose_name='使用者IP')),
('youxiao_shijian', models.DateTimeField(blank=True, null=True, verbose_name='有效截止时间')),
('lianjie_token', models.CharField(blank=True, db_index=True, max_length=32, null=True, unique=True, verbose_name='链接Token')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '商家链接',
'verbose_name_plural': '商家链接',
'db_table': 'shangjia_lianjie',
'indexes': [models.Index(fields=['yonghu_id', 'moban_id', 'leixing_id'], name='shangjia_li_yonghu__9f2b25_idx'), models.Index(fields=['lianjie_token'], name='shangjia_li_lianjie_99014c_idx'), models.Index(fields=['dingdan_id'], name='shangjia_li_dingdan_95b682_idx')],
},
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-16 17:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0002_shangjiamoban_shangjialianjie'),
]
operations = [
migrations.AddField(
model_name='tupianpeizhi',
name='fangwen_cishu',
field=models.PositiveIntegerField(default=0, verbose_name='访问次数'),
),
]
@@ -1,28 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-20 15:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0003_tupianpeizhi_fangwen_cishu'),
]
operations = [
migrations.CreateModel(
name='TixianQuotaDefault',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('leixing', models.IntegerField(choices=[(1, '打手'), (2, '管事')], unique=True, verbose_name='用户类型')),
('default_quota', models.DecimalField(decimal_places=2, default=20.0, max_digits=10, verbose_name='默认每日提现限额(元)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '默认提现限额',
'verbose_name_plural': '默认提现限额',
'db_table': 'tixian_quota_default',
},
),
]
@@ -1,76 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-24 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0004_tixianquotadefault'),
]
operations = [
migrations.CreateModel(
name='OrderTypeMapping',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('partner_club_id', models.CharField(db_index=True, max_length=6, verbose_name='对方俱乐部ID')),
('partner_type_id', models.PositiveIntegerField(verbose_name='对方订单类型ID')),
('partner_type_name', models.CharField(max_length=100, verbose_name='对方订单类型名称')),
('our_type_id', models.PositiveIntegerField(verbose_name='我方订单类型ID')),
('our_type_name', models.CharField(max_length=100, verbose_name='我方订单类型名称')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '订单类型映射',
'verbose_name_plural': '订单类型映射',
'db_table': 'order_type_mapping',
'unique_together': {('partner_club_id', 'partner_type_id')},
},
),
migrations.CreateModel(
name='DailyDispatchStat',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(db_index=True, verbose_name='统计日期')),
('year', models.PositiveSmallIntegerField(verbose_name='年份')),
('month', models.PositiveSmallIntegerField(verbose_name='月份')),
('day', models.PositiveSmallIntegerField(verbose_name='日期')),
('direction', models.PositiveSmallIntegerField(choices=[(1, '我方派单'), (2, '对方派单')], verbose_name='派单方向')),
('partner_club_id', models.CharField(db_index=True, max_length=6, verbose_name='对方俱乐部ID')),
('dispatch_count', models.PositiveIntegerField(default=0, verbose_name='派单数')),
('dispatch_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='派单总额')),
('success_count', models.PositiveIntegerField(default=0, verbose_name='成交订单数')),
('success_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='成交总额')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '每日派单统计',
'verbose_name_plural': '每日派单统计',
'db_table': 'daily_dispatch_stat',
'indexes': [models.Index(fields=['year', 'month', 'day', 'direction', 'partner_club_id'], name='daily_dispa_year_f98f91_idx'), models.Index(fields=['date'], name='daily_dispa_date_9ac7fe_idx')],
},
),
migrations.CreateModel(
name='Club',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('club_id', models.CharField(db_index=True, max_length=6, verbose_name='本俱乐部ID')),
('partner_club_id', models.CharField(max_length=6, unique=True, verbose_name='对方俱乐部ID')),
('is_interop_enabled', models.BooleanField(default=False, verbose_name='是否开启平台互通')),
('is_receive_enabled', models.BooleanField(default=False, verbose_name='是否同意接收对方订单')),
('dashou_rate', models.DecimalField(decimal_places=4, default=1.0, max_digits=5, verbose_name='打手分红费率')),
('partner_domain', models.URLField(blank=True, verbose_name='对方服务器域名')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '俱乐部',
'verbose_name_plural': '俱乐部',
'db_table': 'club',
'indexes': [models.Index(fields=['club_id'], name='club_club_id_e75636_idx'), models.Index(fields=['partner_club_id'], name='club_partner_b76039_idx')],
},
),
]
@@ -1,52 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-01 09:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0005_ordertypemapping_dailydispatchstat_club'),
]
operations = [
migrations.CreateModel(
name='ClubConfig',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('club_id', models.CharField(db_index=True, max_length=6, verbose_name='俱乐部ID')),
('club_nickname', models.CharField(blank=True, default='', max_length=50, verbose_name='俱乐部昵称')),
('club_avatar', models.CharField(blank=True, default='', max_length=500, verbose_name='俱乐部头像地址')),
('backend_domain', models.CharField(blank=True, default='', max_length=200, verbose_name='后台域名')),
('chat_api_key', models.CharField(blank=True, default='', max_length=200, verbose_name='聊天API密钥')),
('chat_api_id', models.CharField(blank=True, default='', max_length=200, verbose_name='聊天API ID')),
('customer_service_api_url', models.CharField(blank=True, default='', max_length=200, verbose_name='客服API URL')),
('customer_service_corp_id', models.CharField(blank=True, default='', max_length=100, verbose_name='客服企业ID')),
('storage_bucket_domain', models.CharField(blank=True, default='', max_length=500, verbose_name='存储桶域名')),
('is_self', models.SmallIntegerField(choices=[(0, '对方'), (1, '我方')], db_index=True, default=0, verbose_name='是否我方俱乐部')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '俱乐部配置',
'verbose_name_plural': '俱乐部配置',
'db_table': 'club_config',
'unique_together': {('club_id',)},
},
),
migrations.CreateModel(
name='AccountPermission',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('account_id', models.CharField(db_index=True, max_length=11, verbose_name='账号ID')),
('permission_code', models.IntegerField(verbose_name='权限代码')),
('is_enabled', models.BooleanField(default=False, verbose_name='是否开启')),
],
options={
'verbose_name': '账号权限',
'verbose_name_plural': '账号权限',
'db_table': 'account_permission',
'unique_together': {('account_id', 'permission_code')},
},
),
]
@@ -1,28 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-02 13:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0006_clubconfig_accountpermission'),
]
operations = [
migrations.AddField(
model_name='club',
name='receive_rate',
field=models.DecimalField(decimal_places=4, default=1.0, max_digits=5, verbose_name='接收打手分红费率'),
),
migrations.AddField(
model_name='dailydispatchstat',
name='claimed_amount',
field=models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='抢单总额'),
),
migrations.AddField(
model_name='dailydispatchstat',
name='claimed_count',
field=models.PositiveIntegerField(default=0, verbose_name='抢单数'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-04 18:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0007_club_receive_rate_dailydispatchstat_claimed_amount_and_more'),
]
operations = [
migrations.AddField(
model_name='clubconfig',
name='storage_bucket_name',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='存储桶名称'),
),
]
@@ -1,53 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-05 13:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0008_clubconfig_storage_bucket_name'),
]
operations = [
migrations.CreateModel(
name='DailyPayoutStat',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(db_index=True, unique=True, verbose_name='统计日期')),
('year', models.PositiveSmallIntegerField(verbose_name='年份')),
('month', models.PositiveSmallIntegerField(verbose_name='月份')),
('day', models.PositiveSmallIntegerField(verbose_name='日期')),
('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='出款总额')),
('total_count', models.PositiveIntegerField(default=0, verbose_name='出款总笔数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '每日出款统计',
'verbose_name_plural': '每日出款统计',
'db_table': 'daily_payout_stat',
'indexes': [models.Index(fields=['date'], name='daily_payou_date_b534ec_idx'), models.Index(fields=['year', 'month', 'day'], name='daily_payou_year_6376ca_idx')],
},
),
migrations.CreateModel(
name='DailyIncomeStat',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(db_index=True, unique=True, verbose_name='统计日期')),
('year', models.PositiveSmallIntegerField(verbose_name='年份')),
('month', models.PositiveSmallIntegerField(verbose_name='月份')),
('day', models.PositiveSmallIntegerField(verbose_name='日期')),
('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='总收入金额')),
('total_count', models.PositiveIntegerField(default=0, verbose_name='总收入笔数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '每日收入统计',
'verbose_name_plural': '每日收入统计',
'db_table': 'daily_income_stat',
'indexes': [models.Index(fields=['date'], name='daily_incom_date_75e6df_idx'), models.Index(fields=['year', 'month', 'day'], name='daily_incom_year_d85d10_idx')],
},
),
]
@@ -1,84 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-22 11:24
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('config', '0009_dailypayoutstat_dailyincomestat'),
]
operations = [
migrations.CreateModel(
name='PopupConfig',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('popup_id', models.CharField(max_length=50, verbose_name='弹窗唯一ID')),
('title', models.CharField(blank=True, max_length=200, verbose_name='标题(后台用)')),
('description', models.TextField(blank=True, verbose_name='描述(后台用)')),
('strategy_type', models.CharField(choices=[('once', '仅一次'), ('daily', '每日'), ('weekly', '每周'), ('monthly', '每月'), ('yearly', '每年'), ('always', '始终'), ('count', '周期内次数限制')], default='once', max_length=20)),
('max_count', models.PositiveIntegerField(default=1, verbose_name='周期内最大展示次数')),
('reset_interval', models.CharField(blank=True, choices=[('day', '天'), ('week', '周'), ('month', '月'), ('year', '年')], max_length=20, verbose_name='重置周期(count类型时使用)')),
('duration', models.PositiveIntegerField(default=0, verbose_name='强制阅读秒数(0=无强制)')),
('force_even_muted', models.BooleanField(default=False, verbose_name='强制弹出(忽略用户今日屏蔽)')),
('sort_order', models.PositiveIntegerField(default=0, verbose_name='展示顺序')),
('is_active', models.BooleanField(default=True, verbose_name='是否启用')),
('start_time', models.DateTimeField(blank=True, null=True, verbose_name='生效开始时间')),
('end_time', models.DateTimeField(blank=True, null=True, verbose_name='生效结束时间')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': '弹窗配置',
'verbose_name_plural': '弹窗配置',
'db_table': 'popup_config',
'ordering': ['sort_order', 'id'],
},
),
migrations.CreateModel(
name='PopupPage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('page_key', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='页面标识')),
('name', models.CharField(max_length=100, verbose_name='页面名称')),
('description', models.TextField(blank=True, verbose_name='描述')),
('is_active', models.BooleanField(default=True, verbose_name='是否启用')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('ignore_user_mute', models.BooleanField(default=False, verbose_name='忽略用户今日屏蔽')),
],
options={
'verbose_name': '弹窗页面',
'verbose_name_plural': '弹窗页面',
'db_table': 'popup_page',
},
),
migrations.CreateModel(
name='PopupImage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('image_url', models.CharField(max_length=500, verbose_name='图片相对路径')),
('text', models.TextField(blank=True, verbose_name='图片上方文字')),
('sort_order', models.PositiveIntegerField(default=0, verbose_name='展示顺序')),
('created_at', models.DateTimeField(auto_now_add=True)),
('popup_config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='config.popupconfig')),
],
options={
'verbose_name': '弹窗图片',
'verbose_name_plural': '弹窗图片',
'db_table': 'popup_image',
'ordering': ['sort_order', 'id'],
},
),
migrations.AddField(
model_name='popupconfig',
name='page',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='popups', to='config.popuppage'),
),
migrations.AlterUniqueTogether(
name='popupconfig',
unique_together={('page', 'popup_id')},
),
]
-27
View File
@@ -1,27 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-25 12:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0010_popupconfig_popuppage_popupimage_popupconfig_page_and_more'),
]
operations = [
migrations.CreateModel(
name='WithdrawConfig',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('mode', models.IntegerField(choices=[(1, '自动提现'), (2, '手动提现')], default=2, verbose_name='提现模式')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '提现模式配置',
'verbose_name_plural': '提现模式配置',
'db_table': 'withdraw_config',
},
),
]
@@ -1,28 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-17 18:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0011_withdrawconfig'),
]
operations = [
migrations.AddField(
model_name='shangjiamoban',
name='chenghao_id',
field=models.IntegerField(blank=True, null=True, verbose_name='关联称号ID'),
),
migrations.AddField(
model_name='shangjiamoban',
name='yongjin_jiage',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金价格'),
),
migrations.AddField(
model_name='shangjiamoban',
name='yongjin_qiangdan',
field=models.BooleanField(default=False, verbose_name='是否开启佣金抢单'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-26 03:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0012_shangjiamoban_chenghao_id_and_more'),
]
operations = [
migrations.AddField(
model_name='shangjialianjie',
name='previous_dingdan_id',
field=models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='上一个订单ID'),
),
migrations.AddField(
model_name='shangjialianjie',
name='previous_lianjie_id',
field=models.PositiveIntegerField(blank=True, db_index=True, null=True, verbose_name='上一个链接ID'),
),
]
@@ -1,30 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-15 01:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('config', '0013_shangjialianjie_previous_dingdan_id_and_more'),
]
operations = [
migrations.DeleteModel(
name='Club',
),
migrations.DeleteModel(
name='ClubConfig',
),
migrations.DeleteModel(
name='DailyDispatchStat',
),
migrations.DeleteModel(
name='OrderTypeMapping',
),
migrations.AlterField(
model_name='tixianquotadefault',
name='leixing',
field=models.IntegerField(choices=[(1, '打手'), (2, '管事'), (3, '组长'), (4, '考核官'), (5, '打手押金'), (6, '商家余额')], unique=True, verbose_name='用户类型'),
),
]
+9 -8
View File
@@ -37,9 +37,10 @@ from .models import (
)
from users.models import (
UserMain, AdminProfile, UserDashou, UserBoss,
AdminProfile, UserDashou, UserBoss,
UserShangjia, UserGuanshi, UserZuzhang
)
from gvsdsdk.models import User
from orders.models import Lilubiao, Dingdan, DingdanShangjia
from orders.notice_tasks import dingdan_guangbo
@@ -180,7 +181,7 @@ class AdminConfigQueryView(APIView):
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 获取当前用户(UserMain实例)
# 获取当前用户(User实例)
user_main = request.user
# 验证账号:比较user_main的phone与前端传递的zhanghao
@@ -2190,10 +2191,10 @@ class KehuGetDingdanLianjieView(APIView):
# 获取商家昵称
shangjia_nicheng = ''
try:
user_main = UserMain.query.get(yonghuid=lianjie_obj.yonghu_id)
user_main = User.query.get(yonghuid=lianjie_obj.yonghu_id)
shangjia_obj = user_main.shop_profile
shangjia_nicheng = shangjia_obj.nicheng
except (UserMain.DoesNotExist, UserShangjia.DoesNotExist):
except (User.DoesNotExist, UserShangjia.DoesNotExist):
logger.warning(f"商家信息不存在 - 用户ID: {lianjie_obj.yonghu_id}")
# ========== 新增:确定俱乐部配置 ==========
@@ -2472,7 +2473,7 @@ class KehuTianxieDingdanView(APIView):
# 验证打手是否存在且有效
try:
# 先查询用户主表
dashou_user = UserMain.query.get(yonghuid=zhiding_dashou)
dashou_user = User.query.get(yonghuid=zhiding_dashou)
logger.info(f"找到打手用户 - 用户ID: {zhiding_dashou}")
# 通过反向关系获取打手扩展信息
@@ -2510,7 +2511,7 @@ class KehuTianxieDingdanView(APIView):
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
except UserMain.DoesNotExist:
except User.DoesNotExist:
logger.warning(f"指定打手用户不存在 - 用户ID: {zhiding_dashou}")
return Response({
'code': 400,
@@ -2570,7 +2571,7 @@ class KehuTianxieDingdanView(APIView):
# 获取商家信息用于返回
try:
user_main = UserMain.query.get(yonghuid=lianjie_obj.yonghu_id)
user_main = User.query.get(yonghuid=lianjie_obj.yonghu_id)
shangjia_obj = user_main.shop_profile
shangjia_mingcheng = shangjia_obj.nicheng
except:
@@ -3250,7 +3251,7 @@ class CheckPhoneAuthView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
user = request.user # UserMain 实例
user = request.user # User 实例
# 已经认证过手机号,直接放行
if user.shoujihao_renzheng:
+31
View File
@@ -0,0 +1,31 @@
import MySQLdb
conn = MySQLdb.connect(
host='gvsds.com', port=50030, user='root',
password='sajksh.sdfGH3YUge.wjkd+',
database='xaio_cheng_xu', charset='utf8mb4'
)
cur = conn.cursor()
# 获取所有表
cur.execute("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='xaio_cheng_xu'")
tables = [row[0] for row in cur.fetchall()]
print(f'共 {len(tables)} 张表')
# 禁用外键检查,删除所有表
cur.execute('SET FOREIGN_KEY_CHECKS = 0')
for t in tables:
cur.execute(f'DROP TABLE IF EXISTS `{t}`')
print(f' 已删除: {t}')
cur.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit()
print(f'\n已删除全部 {len(tables)} 张表')
# 验证
cur.execute("SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='xaio_cheng_xu'")
count = cur.fetchone()[0]
print(f'剩余表数: {count}')
cur.close()
conn.close()
-35
View File
@@ -1,35 +0,0 @@
"""
修复 django_migrations 表中的旧 app 名称引用。
在服务器上执行: python manage.py shell < fix_migration_history.py
或: python manage.py shell
然后粘贴此脚本内容
"""
from django.db import connection
APP_NAME_MAPPINGS = {
'houtai': 'backend',
'yonghu': 'users',
'dingdan': 'orders',
'peizhi': 'config',
'shangpin': 'products',
'shangdian': 'shop',
'dengji': 'rank',
}
with connection.cursor() as cursor:
for old_name, new_name in APP_NAME_MAPPINGS.items():
cursor.execute(
"SELECT COUNT(*) FROM django_migrations WHERE app = %s",
[old_name]
)
count = cursor.fetchone()[0]
if count > 0:
cursor.execute(
"UPDATE django_migrations SET app = %s WHERE app = %s",
[new_name, old_name]
)
print(f"已更新 {count} 条记录: {old_name} -> {new_name}")
else:
print(f"无需更新: {old_name} (无记录)")
print("\n修复完成!请运行 python manage.py migrate")
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""修复 tixianjilu 导入 — 使用指定列名的 INSERT"""
import re, sys, time, MySQLdb
sys.path.insert(0, '.')
import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'a_long_dianjing.settings')
import django; django.setup()
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
SQL_FILE = os.path.join(os.path.dirname(__file__), 'xaio_cheng_xu_backup.sql')
with open(SQL_FILE, 'r', encoding='utf-8') as f:
sql_content = f.read()
# 旧表字段顺序(SQL INSERT VALUES 的顺序)
OLD_COLUMNS = [
'id', 'yonghuid', 'avatar', 'phone', 'nicheng', 'leixing', 'zhifu',
'skzhanghao', 'jine', 'zhuangtai', 'fangshi', 'shenheid', 'bhliyou',
'create_time', 'update_time', 'shenhe_danhao', 'shenhe_jilu_id'
]
# 新表字段顺序
NEW_COLUMNS = [
'id', 'yonghuid', 'avatar', 'phone', 'nicheng', 'leixing', 'zhifu',
'skzhanghao', 'jine', 'zhuangtai', 'fangshi', 'shenheid', 'bhliyou',
'shenhe_jilu_id', 'shenhe_danhao', 'create_time', 'update_time'
]
def parse_sql_value(val_str):
val_str = val_str.strip()
if val_str.upper() == 'NULL': return None
if val_str.startswith("'") and val_str.endswith("'"):
return val_str[1:-1].replace("\\'", "'").replace("\\\\", "\\")
try: return int(val_str)
except ValueError:
try: return float(val_str)
except ValueError: return val_str
def split_sql_values(values_str):
values, current, in_quote, escape = [], [], False, False
for ch in values_str:
if escape: current.append(ch); escape = False; continue
if ch == '\\': current.append(ch); escape = True; continue
if ch == "'": in_quote = not in_quote; current.append(ch); continue
if ch == ',' and not in_quote: values.append(''.join(current).strip()); current = []; continue
current.append(ch)
if current: values.append(''.join(current).strip())
return [parse_sql_value(v) for v in values]
pattern = re.compile(r"INSERT\s+INTO\s+`tixianjilu`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
matches = list(pattern.finditer(sql_content))
print(f"找到 {len(matches)} 条 tixianjilu 记录")
conn = MySQLdb.connect(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
database=DATABASE_NAME, charset='utf8mb4',
connect_timeout=10, read_timeout=60, write_timeout=60
)
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
success = 0
fail = 0
start = time.time()
for i, m in enumerate(matches):
vals = split_sql_values(m.group(1))
if len(vals) != len(OLD_COLUMNS):
fail += 1
continue
# 旧字段 → 值映射
old_dict = dict(zip(OLD_COLUMNS, vals))
# 按新字段顺序构建值列表
new_vals = []
for col in NEW_COLUMNS:
new_vals.append(old_dict.get(col))
# 构建 INSERT 语句(指定列名)
col_names = ', '.join(f'`{c}`' for c in NEW_COLUMNS)
val_parts = []
for v in new_vals:
if v is None:
val_parts.append('NULL')
elif isinstance(v, str):
escaped = conn.escape_string(v)
if isinstance(escaped, bytes): escaped = escaped.decode()
val_parts.append(f"'{escaped}'")
elif isinstance(v, bool):
val_parts.append('1' if v else '0')
elif isinstance(v, (int, float)):
val_parts.append(str(v))
else:
val_parts.append('NULL')
sql = f"INSERT INTO `tixianjilu` ({col_names}) VALUES ({', '.join(val_parts)})"
try:
cursor.execute(sql)
success += 1
except Exception as e:
fail += 1
if fail <= 3:
print(f" ERR: {str(e)[:100]}")
if success % 100 == 0 and success > 0:
conn.commit()
if (i + 1) % 200 == 0:
elapsed = time.time() - start
pct = (i + 1) / len(matches)
sys.stdout.write(f'\r [{pct:5.1%}] {i+1}/{len(matches)} {elapsed:.0f}s OK:{success} FAIL:{fail}')
sys.stdout.flush()
conn.commit()
cursor.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit()
conn.close()
elapsed = time.time() - start
print(f'\n完成: 成功 {success}, 失败 {fail}, 耗时 {elapsed:.0f}s')
+14 -7
View File
@@ -92,27 +92,34 @@ class RoleManager:
return User.objects.filter(UserUUID__in=user_uuids)
@staticmethod
def AssignPermission(RoleUUID, PermUUID):
"""为角色分配权限"""
def AssignPermission(RoleUUID, PermUUID, CompanyUUID):
"""为角色分配权限(指定公司)"""
rp = RolePermission(
RolePermUUID=uuid.uuid4().bytes,
RoleUUID=RoleUUID,
PermUUID=PermUUID,
CompanyUUID=CompanyUUID,
CreateTime=datetime.datetime.utcnow(),
)
rp.save()
return rp
@staticmethod
def RemovePermission(RoleUUID, PermUUID):
def RemovePermission(RoleUUID, PermUUID, CompanyUUID=None):
"""移除角色的指定权限"""
deleted, _ = RolePermission.objects.filter(RoleUUID=RoleUUID, PermUUID=PermUUID).delete()
qs = RolePermission.objects.filter(RoleUUID=RoleUUID, PermUUID=PermUUID)
if CompanyUUID is not None:
qs = qs.filter(CompanyUUID=CompanyUUID)
deleted, _ = qs.delete()
return deleted > 0
@staticmethod
def GetPermissionsForRole(RoleUUID):
"""获取角色的所有权限"""
perm_uuids = RolePermission.objects.filter(RoleUUID=RoleUUID).values_list('PermUUID', flat=True)
def GetPermissionsForRole(RoleUUID, CompanyUUID=None):
"""获取角色的所有权限(可按公司过滤)"""
qs = RolePermission.objects.filter(RoleUUID=RoleUUID)
if CompanyUUID is not None:
qs = qs.filter(CompanyUUID=CompanyUUID)
perm_uuids = qs.values_list('PermUUID', flat=True)
return Permission.objects.filter(PermUUID__in=perm_uuids, PermStatus=1)
+13 -6
View File
@@ -48,7 +48,7 @@ def PermissionVerifier(permission, attributes, user=None, request=None):
"""权限验证器——混合 ABAC + RBAC 检查
RBAC 仅检查当前角色(CurrentRoleUUID Cookie 指定的角色)的权限,
通过 RolePermission → Permission 链路查询。
通过 RolePermission → Permission 链路查询,按当前公司过滤。
超级管理员/员工直接放行。
"""
if not permission:
@@ -63,6 +63,7 @@ def PermissionVerifier(permission, attributes, user=None, request=None):
return True
current_role = getattr(request, 'current_role', None) if request else None
current_company = getattr(request, 'current_company_uuid', None) if request else None
for attr in attributes:
# ABAC 检查
@@ -73,13 +74,16 @@ def PermissionVerifier(permission, attributes, user=None, request=None):
if abac_match:
continue
# RBAC 检查:仅检查当前角色
# RBAC 检查:仅检查当前角色,按公司过滤权限
if current_role and isinstance(current_role, Role):
if current_role.RoleStatus != 1:
return False
perm_uuids = RolePermission.objects.filter(
rp_qs = RolePermission.objects.filter(
RoleUUID=current_role.RoleUUID
).values_list('PermUUID', flat=True)
)
if current_company:
rp_qs = rp_qs.filter(CompanyUUID=current_company)
perm_uuids = rp_qs.values_list('PermUUID', flat=True)
rbac_result = Permission.objects.filter(
PermUUID__in=perm_uuids,
PermCode=attr,
@@ -94,9 +98,12 @@ def PermissionVerifier(permission, attributes, user=None, request=None):
RoleUUID__in=user_role_uuids,
RoleStatus=1,
).values_list('RoleUUID', flat=True)
perm_uuids = RolePermission.objects.filter(
rp_qs = RolePermission.objects.filter(
RoleUUID__in=active_role_uuids
).values_list('PermUUID', flat=True)
)
if current_company:
rp_qs = rp_qs.filter(CompanyUUID=current_company)
perm_uuids = rp_qs.values_list('PermUUID', flat=True)
rbac_result = Permission.objects.filter(
PermUUID__in=perm_uuids,
PermCode=attr,
+205 -82
View File
@@ -1,8 +1,8 @@
# Generated by Django 6.0.5 on 2026-06-13 11:43
# Generated by Django 4.2.27 on 2026-06-17 17:07
import datetime
import gvsdsdk.models
from django.db import migrations, models
import gvsdsdk.models
class Migration(migrations.Migration):
@@ -16,9 +16,9 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='AccountActivation',
fields=[
('AccountActivationCode', gvsdsdk.models.FixedBinaryField(binary_length=6, db_column='AccountActivationCode', max_length=6, primary_key=True, serialize=False)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
('AccountActivationCode', gvsdsdk.models.FixedBinaryField(binary_length=6, db_column='AccountActivationCode', max_length=6, primary_key=True, serialize=False, verbose_name='激活码')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', verbose_name='用户UUID')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '账户激活',
@@ -30,13 +30,13 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='EphemeralToken',
fields=[
('ELTUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ELTUUID', primary_key=True, serialize=False)),
('ELTUserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ELTUserUUID', db_index=True)),
('ELTCreateTime', models.DateTimeField(db_column='ELTCreateTime', default=datetime.datetime.utcnow)),
('ELTEndTime', models.DateTimeField(db_column='ELTEndTime', default=gvsdsdk.models._elt_end_time_default)),
('ELTType', models.SmallIntegerField(db_column='ELTType', default=0)),
('ELTAllowIP', models.JSONField(db_column='ELTAllowIP', default=list)),
('ELTStatus', models.SmallIntegerField(db_column='ELTStatus', db_index=True, default=1)),
('ELTUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ELTUUID', primary_key=True, serialize=False, verbose_name='令牌UUID')),
('ELTUserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ELTUserUUID', db_index=True, verbose_name='用户UUID')),
('ELTCreateTime', models.DateTimeField(db_column='ELTCreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
('ELTEndTime', models.DateTimeField(db_column='ELTEndTime', default=gvsdsdk.models._EltEndTimeDefault, verbose_name='过期时间')),
('ELTType', models.SmallIntegerField(db_column='ELTType', default=0, verbose_name='令牌类型')),
('ELTAllowIP', models.JSONField(db_column='ELTAllowIP', default=list, verbose_name='允许IP')),
('ELTStatus', models.SmallIntegerField(db_column='ELTStatus', db_index=True, default=1, verbose_name='状态')),
],
options={
'verbose_name': '临时令牌',
@@ -48,8 +48,8 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Password',
fields=[
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', primary_key=True, serialize=False)),
('Password', models.CharField(db_column='Password', max_length=1024)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', primary_key=True, serialize=False, verbose_name='用户UUID')),
('Password', models.CharField(db_column='Password', max_length=1024, verbose_name='密码哈希')),
],
options={
'verbose_name': '密码',
@@ -61,12 +61,14 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Permission',
fields=[
('PermUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PermUUID', primary_key=True, serialize=False)),
('PermName', models.CharField(db_column='PermName', max_length=128)),
('PermCode', models.CharField(db_column='PermCode', max_length=128)),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID')),
('PermStatus', models.SmallIntegerField(db_column='PermStatus', default=1)),
('PermDesc', models.CharField(db_column='PermDesc', default='', max_length=512)),
('PermUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PermUUID', primary_key=True, serialize=False, verbose_name='权限UUID')),
('TenantUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='TenantUUID', verbose_name='租户UUID')),
('PermName', models.CharField(db_column='PermName', max_length=128, verbose_name='权限名称')),
('PermCode', models.CharField(db_column='PermCode', max_length=128, verbose_name='权限键')),
('PermCategory', models.CharField(db_column='PermCategory', default='', max_length=64, verbose_name='权限分类')),
('PermStatus', models.SmallIntegerField(db_column='PermStatus', default=1, verbose_name='是否启用')),
('PermDesc', models.CharField(db_column='PermDesc', default='', max_length=512, verbose_name='描述')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '权限',
@@ -75,16 +77,72 @@ class Migration(migrations.Migration):
'managed': True,
},
),
migrations.CreateModel(
name='Position',
fields=[
('PositionUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PositionUUID', primary_key=True, serialize=False, verbose_name='职务UUID')),
('TenantUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='TenantUUID', verbose_name='租户UUID')),
('PositionName', models.CharField(db_column='PositionName', max_length=128, verbose_name='职务名称')),
('PositionCode', models.CharField(db_column='PositionCode', default='', max_length=64, verbose_name='职务编码')),
('PositionLevel', models.SmallIntegerField(db_column='PositionLevel', default=0, verbose_name='职务级别')),
('PositionStatus', models.SmallIntegerField(db_column='PositionStatus', default=1, verbose_name='状态')),
('PositionDesc', models.CharField(db_column='PositionDesc', default='', max_length=512, verbose_name='描述')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
('UpdateTime', models.DateTimeField(db_column='UpdateTime', default=datetime.datetime.utcnow, verbose_name='更新时间')),
],
options={
'verbose_name': '人事职务标签',
'verbose_name_plural': '人事职务标签',
'db_table': 'Position',
'managed': True,
},
),
migrations.CreateModel(
name='PositionTemplate',
fields=[
('PositionTemplateUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PositionTemplateUUID', primary_key=True, serialize=False, verbose_name='岗位模板UUID')),
('TenantUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='TenantUUID', verbose_name='租户UUID')),
('TemplateName', models.CharField(db_column='TemplateName', max_length=128, verbose_name='模板名称')),
('TemplateCode', models.CharField(db_column='TemplateCode', default='', max_length=64, verbose_name='模板编码')),
('TemplateStatus', models.SmallIntegerField(db_column='TemplateStatus', default=1, verbose_name='模板状态')),
('TemplateDesc', models.CharField(db_column='TemplateDesc', default='', max_length=512, verbose_name='模板描述')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
('UpdateTime', models.DateTimeField(db_column='UpdateTime', default=datetime.datetime.utcnow, verbose_name='更新时间')),
],
options={
'verbose_name': '岗位模板',
'verbose_name_plural': '岗位模板',
'db_table': 'PositionTemplate',
'managed': True,
},
),
migrations.CreateModel(
name='PositionTemplatePermission',
fields=[
('PTPermUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PTPermUUID', primary_key=True, serialize=False, verbose_name='关联UUID')),
('PositionTemplateUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PositionTemplateUUID', verbose_name='岗位模板UUID')),
('PermUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PermUUID', verbose_name='权限UUID')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '岗位模板权限关联',
'verbose_name_plural': '岗位模板权限关联',
'db_table': 'PositionTemplatePermission',
'managed': True,
},
),
migrations.CreateModel(
name='Role',
fields=[
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID', primary_key=True, serialize=False)),
('CompanyUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='CompanyUUID')),
('DeptUUID', gvsdsdk.models.UUIDField(binary_length=16, blank=True, db_column='DeptUUID', null=True)),
('RoleName', models.CharField(db_column='RoleName', max_length=128)),
('RoleType', models.SmallIntegerField(db_column='RoleType', default=2)),
('RoleStatus', models.SmallIntegerField(db_column='RoleStatus', default=1)),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID', primary_key=True, serialize=False, verbose_name='角色UUID')),
('TenantUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='TenantUUID', verbose_name='租户UUID')),
('RoleName', models.CharField(db_column='RoleName', max_length=128, verbose_name='角色名称')),
('RoleType', models.SmallIntegerField(db_column='RoleType', default=2, verbose_name='角色类型')),
('RoleStatus', models.SmallIntegerField(db_column='RoleStatus', default=1, verbose_name='角色状态')),
('AssignScope', models.SmallIntegerField(db_column='AssignScope', default=0, verbose_name='分配可见范围')),
('AssignScopeUUID', gvsdsdk.models.UUIDField(binary_length=16, blank=True, db_column='AssignScopeUUID', null=True, verbose_name='分配范围UUID')),
('RoleDesc', models.CharField(db_column='RoleDesc', default='', max_length=512, verbose_name='角色描述')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '角色',
@@ -94,55 +152,69 @@ class Migration(migrations.Migration):
},
),
migrations.CreateModel(
name='RoleDept',
name='RolePermission',
fields=[
('RoleDeptUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleDeptUUID', primary_key=True, serialize=False)),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID')),
('DeptUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='DeptUUID')),
('IsMainDept', models.SmallIntegerField(db_column='IsMainDept', default=1)),
('RolePermUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RolePermUUID', primary_key=True, serialize=False, verbose_name='关联UUID')),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID', verbose_name='角色UUID')),
('PermUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PermUUID', verbose_name='权限UUID')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '角色部门关联',
'verbose_name_plural': '角色部门关联',
'db_table': 'RoleDept',
'verbose_name': '角色权限关联',
'verbose_name_plural': '角色权限关联',
'db_table': 'RolePermission',
'managed': True,
},
),
migrations.CreateModel(
name='User',
name='RoleShop',
fields=[
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', primary_key=True, serialize=False)),
('UserName', models.CharField(db_column='UserName', max_length=256, unique=True)),
('UserPassword', models.CharField(db_column='UserPassword', default='', max_length=60)),
('UserPositionStatus', models.SmallIntegerField(db_column='UserPositionStatus', default=0)),
('UserPersonalSignature', models.CharField(db_column='UserPersonalSignature', default='', max_length=1024)),
('UserEmail', models.CharField(db_column='UserEmail', default='', max_length=256)),
('UserEmailVerify', models.SmallIntegerField(db_column='UserEmailVerify', default=0)),
('UserAccountLicense', models.SmallIntegerField(db_column='UserAccountLicense', default=1)),
('UserGender', models.SmallIntegerField(db_column='UserGender', default=-1)),
('UserTele', models.CharField(blank=True, db_column='UserTele', max_length=16, null=True)),
('UserCreateTime', models.DateTimeField(db_column='UserCreateTime', default=datetime.datetime.utcnow)),
('UserLastLoginDate', models.DateTimeField(db_column='UserLastLoginDate', default=datetime.datetime.utcnow)),
('IsStaff', models.BooleanField(db_column='IsStaff', default=False)),
('IsSuperuser', models.BooleanField(db_column='IsSuperuser', default=False)),
('RoleShopUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleShopUUID', primary_key=True, serialize=False, verbose_name='关联UUID')),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID', verbose_name='角色UUID')),
('ShopUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ShopUUID', verbose_name='商铺UUID')),
('IsMainShop', models.SmallIntegerField(db_column='IsMainShop', default=0, verbose_name='主商铺')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '用户',
'verbose_name_plural': '用户',
'db_table': 'User',
'verbose_name': '角色商铺关联',
'verbose_name_plural': '角色商铺关联',
'db_table': 'RoleShop',
'managed': True,
},
),
migrations.CreateModel(
name='Shop',
fields=[
('ShopUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ShopUUID', primary_key=True, serialize=False, verbose_name='商铺UUID')),
('CompanyUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='CompanyUUID', verbose_name='公司UUID')),
('ShopName', models.CharField(db_column='ShopName', max_length=128, verbose_name='商铺名称')),
('ShopCode', models.CharField(db_column='ShopCode', default='', max_length=64, verbose_name='商铺编码')),
('ShopType', models.SmallIntegerField(db_column='ShopType', default=0, verbose_name='商铺类型')),
('ShopStatus', models.SmallIntegerField(db_column='ShopStatus', default=1, verbose_name='商铺状态')),
('ShopAddress', models.CharField(db_column='ShopAddress', default='', max_length=512, verbose_name='商铺地址')),
('ShopContact', models.CharField(db_column='ShopContact', default='', max_length=128, verbose_name='联系人')),
('ShopPhone', models.CharField(db_column='ShopPhone', default='', max_length=32, verbose_name='联系电话')),
('ShopDesc', models.CharField(db_column='ShopDesc', default='', max_length=512, verbose_name='描述')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
('UpdateTime', models.DateTimeField(db_column='UpdateTime', default=datetime.datetime.utcnow, verbose_name='更新时间')),
],
options={
'verbose_name': '商铺',
'verbose_name_plural': '商铺',
'db_table': 'Shop',
'managed': True,
},
),
migrations.CreateModel(
name='User2FA',
fields=[
('User2FAUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='User2FAUUID', primary_key=True, serialize=False)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', db_index=True)),
('SecretKey', models.CharField(db_column='SecretKey', max_length=64)),
('IsEnabled', models.SmallIntegerField(db_column='IsEnabled', default=0)),
('Verified', models.SmallIntegerField(db_column='Verified', default=0)),
('LastUsedAt', models.DateTimeField(blank=True, db_column='LastUsedAt', null=True)),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
('User2FAUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='User2FAUUID', primary_key=True, serialize=False, verbose_name='2FA UUID')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', db_index=True, verbose_name='用户UUID')),
('SecretKey', models.CharField(db_column='SecretKey', max_length=64, verbose_name='密钥')),
('IsEnabled', models.SmallIntegerField(db_column='IsEnabled', default=0, verbose_name='是否启用')),
('Verified', models.SmallIntegerField(db_column='Verified', default=0, verbose_name='已验证')),
('LastUsedAt', models.DateTimeField(blank=True, db_column='LastUsedAt', null=True, verbose_name='最后使用')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '双因素认证',
@@ -154,9 +226,9 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='UserABAC',
fields=[
('UserABACUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserABACUUID', primary_key=True, serialize=False)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID')),
('HierarchicalPermissionIdentifiers', models.CharField(db_column='HierarchicalPermissionIdentifiers', max_length=256)),
('UserABACUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserABACUUID', primary_key=True, serialize=False, verbose_name='ABAC UUID')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', verbose_name='用户UUID')),
('HierarchicalPermissionIdentifiers', models.CharField(db_column='HierarchicalPermissionIdentifiers', max_length=256, verbose_name='层级权限标识')),
],
options={
'verbose_name': '用户ABAC',
@@ -168,10 +240,10 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='UserAvatar',
fields=[
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', primary_key=True, serialize=False)),
('UserAvatar', models.BinaryField(db_column='UserAvatar', editable=True)),
('AvatarUploadTime', models.DateTimeField(db_column='AvatarUploadTime', default=datetime.datetime.utcnow)),
('AvatarFileType', models.CharField(db_column='AvatarFileType', default='png', max_length=16)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', primary_key=True, serialize=False, verbose_name='用户UUID')),
('UserAvatar', models.BinaryField(db_column='UserAvatar', editable=True, verbose_name='头像数据')),
('AvatarUploadTime', models.DateTimeField(db_column='AvatarUploadTime', default=datetime.datetime.utcnow, verbose_name='上传时间')),
('AvatarFileType', models.CharField(db_column='AvatarFileType', default='png', max_length=16, verbose_name='文件类型')),
],
options={
'verbose_name': '用户头像',
@@ -180,16 +252,33 @@ class Migration(migrations.Migration):
'managed': True,
},
),
migrations.CreateModel(
name='UserDept',
fields=[
('UserDeptUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserDeptUUID', primary_key=True, serialize=False, verbose_name='关联UUID')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', verbose_name='用户UUID')),
('DeptUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='DeptUUID', verbose_name='部门UUID')),
('PositionUUID', gvsdsdk.models.UUIDField(binary_length=16, blank=True, db_column='PositionUUID', null=True, verbose_name='职务标签UUID')),
('IsMainDept', models.SmallIntegerField(db_column='IsMainDept', default=1, verbose_name='是否主部门')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '员工部门关联',
'verbose_name_plural': '员工部门关联',
'db_table': 'UserDept',
'managed': True,
},
),
migrations.CreateModel(
name='UserLoginLog',
fields=[
('LogUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='LogUUID', primary_key=True, serialize=False)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', db_index=True)),
('LoginIP', models.CharField(db_column='LoginIP', max_length=39)),
('LoginPlatform', models.CharField(db_column='LoginPlatform', max_length=32)),
('LoginStatus', models.SmallIntegerField(db_column='LoginStatus')),
('LoginTime', models.DateTimeField(db_column='LoginTime', default=datetime.datetime.utcnow)),
('UserAgent', models.CharField(db_column='UserAgent', default='', max_length=512)),
('LogUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='LogUUID', primary_key=True, serialize=False, verbose_name='日志UUID')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', db_index=True, verbose_name='用户UUID')),
('LoginIP', models.CharField(db_column='LoginIP', max_length=39, verbose_name='登录IP')),
('LoginPlatform', models.CharField(db_column='LoginPlatform', max_length=32, verbose_name='登录平台')),
('LoginStatus', models.SmallIntegerField(db_column='LoginStatus', verbose_name='登录状态')),
('LoginTime', models.DateTimeField(db_column='LoginTime', default=datetime.datetime.utcnow, verbose_name='登录时间')),
('UserAgent', models.CharField(db_column='UserAgent', default='', max_length=512, verbose_name='用户代理')),
],
options={
'verbose_name': '登录日志',
@@ -201,10 +290,10 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='UserPending2FA',
fields=[
('PendingUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PendingUUID', primary_key=True, serialize=False)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', unique=True)),
('SecretKey', models.CharField(db_column='SecretKey', max_length=64)),
('ExpireAt', models.DateTimeField(db_column='ExpireAt')),
('PendingUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PendingUUID', primary_key=True, serialize=False, verbose_name='待确认UUID')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', unique=True, verbose_name='用户UUID')),
('SecretKey', models.CharField(db_column='SecretKey', max_length=64, verbose_name='密钥')),
('ExpireAt', models.DateTimeField(db_column='ExpireAt', verbose_name='过期时间')),
],
options={
'verbose_name': '2FA待确认',
@@ -216,10 +305,11 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='UserRole',
fields=[
('UserRoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserRoleUUID', primary_key=True, serialize=False)),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID')),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
('UserRoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserRoleUUID', primary_key=True, serialize=False, verbose_name='关联UUID')),
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', verbose_name='用户UUID')),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID', verbose_name='角色UUID')),
('CompanyUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='CompanyUUID', verbose_name='公司UUID')),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'verbose_name': '用户角色关联',
@@ -228,4 +318,37 @@ class Migration(migrations.Migration):
'managed': True,
},
),
migrations.CreateModel(
name='User',
fields=[
('UserUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='UserUUID', primary_key=True, serialize=False, verbose_name='用户UUID')),
('UserName', models.CharField(db_column='UserName', max_length=256, unique=True, verbose_name='用户名')),
('UserPassword', models.CharField(db_column='UserPassword', default='', max_length=60, verbose_name='密码')),
('UserPositionStatus', models.SmallIntegerField(db_column='UserPositionStatus', default=0, verbose_name='职位状态')),
('UserPersonalSignature', models.CharField(db_column='UserPersonalSignature', default='', max_length=1024, verbose_name='个人签名')),
('UserEmail', models.CharField(db_column='UserEmail', default='', max_length=256, verbose_name='邮箱')),
('UserEmailVerify', models.SmallIntegerField(db_column='UserEmailVerify', default=0, verbose_name='邮箱验证')),
('UserAccountLicense', models.SmallIntegerField(db_column='UserAccountLicense', default=1, verbose_name='账户许可')),
('UserGender', models.SmallIntegerField(db_column='UserGender', default=-1, verbose_name='性别')),
('UserTele', models.CharField(blank=True, db_column='UserTele', max_length=16, null=True, verbose_name='电话')),
('UserCreateTime', models.DateTimeField(db_column='UserCreateTime', default=datetime.datetime.utcnow, verbose_name='创建时间')),
('UserLastLoginDate', models.DateTimeField(db_column='UserLastLoginDate', default=datetime.datetime.utcnow, verbose_name='最后登录')),
('UserUID', models.CharField(blank=True, db_column='UserUID', max_length=7, null=True, unique=True, verbose_name='用户业务ID')),
('OpenID', models.CharField(blank=True, db_column='OpenID', max_length=64, null=True, unique=True, verbose_name='微信OpenID')),
('UnionID', models.CharField(blank=True, db_column='UnionID', max_length=64, null=True, verbose_name='微信UnionID')),
('Avatar', models.CharField(db_column='Avatar', default='a_long/morentouxiang.jpg', max_length=500, verbose_name='头像')),
('Phone', models.CharField(blank=True, db_column='Phone', max_length=11, null=True, verbose_name='手机号')),
('PhoneVerified', models.BooleanField(db_column='PhoneVerified', default=False, verbose_name='手机号是否已认证')),
('IP', models.CharField(blank=True, db_column='IP', max_length=50, null=True, verbose_name='来访用户IP')),
('IsStaff', models.BooleanField(db_column='IsStaff', default=False, verbose_name='是否员工')),
('IsSuperuser', models.BooleanField(db_column='IsSuperuser', default=False, verbose_name='是否超级用户')),
],
options={
'verbose_name': '用户',
'verbose_name_plural': '用户',
'db_table': 'User',
'managed': True,
'indexes': [models.Index(fields=['UserUID'], name='User_UserUID_a656ea_idx'), models.Index(fields=['OpenID'], name='User_OpenID_2a920d_idx')],
},
),
]
@@ -1,90 +0,0 @@
# Generated by Django 6.0.5 on 2026-06-13 12:29
import datetime
import gvsdsdk.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gvsdsdk', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Position',
fields=[
('PositionUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PositionUUID', primary_key=True, serialize=False)),
('CompanyUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='CompanyUUID')),
('PositionName', models.CharField(db_column='PositionName', max_length=128)),
('PositionCode', models.CharField(db_column='PositionCode', default='', max_length=64)),
('PositionLevel', models.SmallIntegerField(db_column='PositionLevel', default=0)),
('PositionStatus', models.SmallIntegerField(db_column='PositionStatus', default=1)),
('PositionDesc', models.CharField(db_column='PositionDesc', default='', max_length=512)),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
('UpdateTime', models.DateTimeField(db_column='UpdateTime', default=datetime.datetime.utcnow)),
],
options={
'verbose_name': '职务',
'verbose_name_plural': '职务',
'db_table': 'Position',
'managed': True,
},
),
migrations.CreateModel(
name='RolePosition',
fields=[
('RolePositionUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RolePositionUUID', primary_key=True, serialize=False)),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID')),
('PositionUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='PositionUUID')),
('IsMainPosition', models.SmallIntegerField(db_column='IsMainPosition', default=0)),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
],
options={
'verbose_name': '角色职务关联',
'verbose_name_plural': '角色职务关联',
'db_table': 'RolePosition',
'managed': True,
},
),
migrations.CreateModel(
name='RoleShop',
fields=[
('RoleShopUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleShopUUID', primary_key=True, serialize=False)),
('RoleUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='RoleUUID')),
('ShopUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ShopUUID')),
('IsMainShop', models.SmallIntegerField(db_column='IsMainShop', default=0)),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
],
options={
'verbose_name': '角色商铺关联',
'verbose_name_plural': '角色商铺关联',
'db_table': 'RoleShop',
'managed': True,
},
),
migrations.CreateModel(
name='Shop',
fields=[
('ShopUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='ShopUUID', primary_key=True, serialize=False)),
('CompanyUUID', gvsdsdk.models.UUIDField(binary_length=16, db_column='CompanyUUID')),
('ShopName', models.CharField(db_column='ShopName', max_length=128)),
('ShopCode', models.CharField(db_column='ShopCode', default='', max_length=64)),
('ShopType', models.SmallIntegerField(db_column='ShopType', default=0)),
('ShopStatus', models.SmallIntegerField(db_column='ShopStatus', default=1)),
('ShopAddress', models.CharField(db_column='ShopAddress', default='', max_length=512)),
('ShopContact', models.CharField(db_column='ShopContact', default='', max_length=128)),
('ShopPhone', models.CharField(db_column='ShopPhone', default='', max_length=32)),
('ShopDesc', models.CharField(db_column='ShopDesc', default='', max_length=512)),
('CreateTime', models.DateTimeField(db_column='CreateTime', default=datetime.datetime.utcnow)),
('UpdateTime', models.DateTimeField(db_column='UpdateTime', default=datetime.datetime.utcnow)),
],
options={
'verbose_name': '商铺',
'verbose_name_plural': '商铺',
'db_table': 'Shop',
'managed': True,
},
),
]
+162 -19
View File
@@ -186,17 +186,33 @@ class User(QModel):
UserTele = models.CharField(max_length=16, null=True, blank=True, db_column='UserTele', verbose_name='电话')
UserCreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='UserCreateTime', verbose_name='创建时间')
UserLastLoginDate = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='UserLastLoginDate', verbose_name='最后登录')
# === 本地业务字段(去远程化后新增) ===
UserUID = models.CharField(max_length=7, unique=True, db_column='UserUID', verbose_name='用户业务ID', null=True, blank=True)
OpenID = models.CharField(max_length=64, unique=True, db_column='OpenID', verbose_name='微信OpenID', null=True, blank=True)
UnionID = models.CharField(max_length=64, db_column='UnionID', verbose_name='微信UnionID', null=True, blank=True)
Avatar = models.CharField(max_length=500, default='a_long/morentouxiang.jpg', db_column='Avatar', verbose_name='头像')
Phone = models.CharField(max_length=11, db_column='Phone', verbose_name='手机号', null=True, blank=True)
PhoneVerified = models.BooleanField(default=False, db_column='PhoneVerified', verbose_name='手机号是否已认证')
IP = models.CharField(max_length=50, db_column='IP', verbose_name='来访用户IP', null=True, blank=True)
IsStaff = models.BooleanField(default=False, db_column='IsStaff', verbose_name='是否员工')
IsSuperuser = models.BooleanField(default=False, db_column='IsSuperuser', verbose_name='是否超级用户')
objects = UserManager()
# Django auth 框架必需
USERNAME_FIELD = 'UserName'
REQUIRED_FIELDS = ['UserUID']
class Meta:
managed = False
managed = True # 将由 QModelBase.__new__ 根据 GVSDSDK_MANAGE_TABLES 动态设置
app_label = 'gvsdsdk'
db_table = 'User'
verbose_name = '用户'
verbose_name_plural = '用户'
indexes = [
models.Index(fields=['UserUID']),
models.Index(fields=['OpenID']),
]
def __str__(self):
return self.UserName
@@ -304,6 +320,66 @@ class User(QModel):
def is_authenticated(self):
return self.IsAuthenticated
@property
def yonghuid(self):
"""兼容旧代码的 yonghuid 属性"""
return self.UserUID
@property
def openid(self):
"""兼容旧代码的 openid 属性"""
return self.OpenID
@property
def user_type(self):
"""兼容旧代码的 user_type 属性 — 通过 UserRole 推断(带实例缓存)"""
# 实例缓存:同一请求内只查一次
if hasattr(self, '_cached_user_type'):
return self._cached_user_type
try:
# 单次查询获取所有角色名
role_uuids = UserRole.objects.filter(
UserUUID=self.UserUUID
).values_list('RoleUUID', flat=True)
role_names = set(
Role.objects.filter(RoleUUID__in=role_uuids)
.values_list('RoleName', flat=True)
)
# 优先级:管理员 > 客服 > 负责人 > 组长 > 审核官 > 商家 > 打手
for rn in role_names:
if '管理员' in rn or 'admin' in rn.lower():
self._cached_user_type = 'admin'
return 'admin'
for rn in role_names:
if '客服' in rn or 'kefu' in rn.lower():
self._cached_user_type = 'kefu'
return 'kefu'
for rn in role_names:
if '负责人' in rn or '管事' in rn or 'guanshi' in rn.lower():
self._cached_user_type = 'guanshi'
return 'guanshi'
for rn in role_names:
if '组长' in rn or 'zuzhang' in rn.lower():
self._cached_user_type = 'zuzhang'
return 'zuzhang'
for rn in role_names:
if '审核' in rn or 'shenheguan' in rn.lower():
self._cached_user_type = 'shenheguan'
return 'shenheguan'
for rn in role_names:
if '商家' in rn or 'shangjia' in rn.lower():
self._cached_user_type = 'shop'
return 'shop'
for rn in role_names:
if '打手' in rn or 'dashou' in rn.lower():
self._cached_user_type = 'dashou'
return 'dashou'
self._cached_user_type = 'normal'
return 'normal'
except Exception:
self._cached_user_type = 'normal'
return 'normal'
@property
def pk(self):
return self.PK
@@ -318,6 +394,73 @@ class User(QModel):
def check_password(self, raw_password):
return self.CheckPassword(raw_password)
@property
def dashou_profile(self):
"""兼容旧代码"""
from users.models import UserDashou
return UserDashou.objects.filter(user=self).first()
@property
def shop_profile(self):
"""兼容旧代码"""
from users.models import UserShangjia
return UserShangjia.objects.filter(user=self).first()
@property
def guanshi_profile(self):
"""兼容旧代码"""
from users.models import UserGuanshi
return UserGuanshi.objects.filter(user=self).first()
@property
def boss_profile(self):
"""兼容旧代码"""
from users.models import UserBoss
return UserBoss.objects.filter(user=self).first()
@property
def admin_profile(self):
"""兼容旧代码"""
from users.models import AdminProfile
return AdminProfile.objects.filter(user=self).first()
@property
def kefu_profile(self):
"""兼容旧代码"""
from users.models import UserKefu
return UserKefu.objects.filter(user=self).first()
@property
def zuzhang_profile(self):
"""兼容旧代码"""
from users.models import UserZuzhang
return UserZuzhang.objects.filter(user=self).first()
@property
def shenheguan_profile(self):
"""兼容旧代码"""
from users.models import UserShenheguan
return UserShenheguan.objects.filter(user=self).first()
def has_role(self, role_code):
"""检查用户是否拥有指定角色(支持角色名或旧 user_type 值)"""
# 角色名映射:旧 user_type → 角色名
ROLE_CODE_MAP = {
'admin': '管理员', 'kefu': '客服', 'guanshi': '负责人',
'zuzhang': '组长', 'shenheguan': '审核官', 'shop': '商家',
'dashou': '打手', 'normal': '消费者',
}
target = ROLE_CODE_MAP.get(role_code, role_code)
try:
role_uuids = UserRole.objects.filter(
UserUUID=self.UserUUID
).values_list('RoleUUID', flat=True)
return Role.objects.filter(
RoleUUID__in=role_uuids, RoleName=target
).exists()
except Exception:
return False
# === 用户头像表 ===
@@ -330,7 +473,7 @@ class UserAvatar(QModel):
AvatarFileType = models.CharField(max_length=16, default='png', db_column='AvatarFileType', verbose_name='文件类型')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'UserAvatar'
verbose_name = '用户头像'
@@ -351,7 +494,7 @@ class User2FA(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'User2FA'
verbose_name = '双因素认证'
@@ -369,7 +512,7 @@ class UserPending2FA(QModel):
ExpireAt = models.DateTimeField(db_column='ExpireAt', verbose_name='过期时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'UserPending2FA'
verbose_name = '2FA待确认'
@@ -396,7 +539,7 @@ class EphemeralToken(QModel):
ELTStatus = models.SmallIntegerField(default=1, db_index=True, db_column='ELTStatus', verbose_name='状态')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'EphemeralToken'
verbose_name = '临时令牌'
@@ -425,7 +568,7 @@ class UserLoginLog(QModel):
UserAgent = models.CharField(max_length=512, default='', db_column='UserAgent', verbose_name='用户代理')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'UserLoginLog'
verbose_name = '登录日志'
@@ -442,7 +585,7 @@ class AccountActivation(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'AccountActivation'
verbose_name = '账户激活'
@@ -472,7 +615,7 @@ class Role(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'Role'
verbose_name = '角色'
@@ -516,7 +659,7 @@ class Permission(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'Permission'
verbose_name = '权限'
@@ -555,7 +698,7 @@ class UserRole(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'UserRole'
verbose_name = '用户角色关联'
@@ -577,7 +720,7 @@ class RolePermission(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'RolePermission'
verbose_name = '角色权限关联'
@@ -594,7 +737,7 @@ class UserABAC(QModel):
HierarchicalPermissionIdentifiers = models.CharField(max_length=256, db_column='HierarchicalPermissionIdentifiers', verbose_name='层级权限标识')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'UserABAC'
verbose_name = '用户ABAC'
@@ -610,7 +753,7 @@ class Password(QModel):
Password = models.CharField(max_length=1024, db_column='Password', verbose_name='密码哈希')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'Password'
verbose_name = '密码'
@@ -639,7 +782,7 @@ class Shop(QModel):
UpdateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='UpdateTime', verbose_name='更新时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'Shop'
verbose_name = '商铺'
@@ -671,7 +814,7 @@ class RoleShop(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'RoleShop'
verbose_name = '角色商铺关联'
@@ -700,7 +843,7 @@ class PositionTemplate(QModel):
UpdateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='UpdateTime', verbose_name='更新时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'PositionTemplate'
verbose_name = '岗位模板'
@@ -750,7 +893,7 @@ class PositionTemplatePermission(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'PositionTemplatePermission'
verbose_name = '岗位模板权限关联'
@@ -778,7 +921,7 @@ class Position(QModel):
UpdateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='UpdateTime', verbose_name='更新时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'Position'
verbose_name = '人事职务标签'
@@ -806,7 +949,7 @@ class UserDept(QModel):
CreateTime = models.DateTimeField(default=_datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
class Meta:
managed = False
managed = True
app_label = 'gvsdsdk'
db_table = 'UserDept'
verbose_name = '员工部门关联'
+532
View File
@@ -0,0 +1,532 @@
"""MSYNC ORM 中转处理器
子服务器端注册 Socket.IO 事件处理器,接收主服务器发来的 ORM 查询请求,
在本地数据库执行 SQL 并返回结果。
用法(子服务器端):
from gvsdsdk.msync.orm_handler import ORMRelayHandler
handler = ORMRelayHandler()
handler.Register(sio_client) # 注册到 MSyncSocketClient 实例
"""
import datetime
import logging
import uuid
logger = logging.getLogger(__name__)
class ORMRelayHandler:
"""ORM 中转处理器——在子服务器端执行本地 SQL 查询
通过 MSYNC Socket.IO 事件协议,主服务器将 ORM 请求转发给子服务器,
子服务器在本地数据库执行查询后返回结果。
"""
def Register(self, sio_client):
"""将 ORM 事件处理器注册到 MSyncSocketClient 实例
Args:
sio_client: MSyncSocketClient 实例,需要有 _sio 属性
"""
sio = sio_client._sio
@sio.on('msync:orm:tables', namespace='/msync')
def on_orm_tables(data):
return self.HandleTables(data)
@sio.on('msync:orm:columns', namespace='/msync')
def on_orm_columns(data):
return self.HandleColumns(data)
@sio.on('msync:orm:list', namespace='/msync')
def on_orm_list(data):
return self.HandleList(data)
@sio.on('msync:orm:add', namespace='/msync')
def on_orm_add(data):
return self.HandleAdd(data)
@sio.on('msync:orm:modify', namespace='/msync')
def on_orm_modify(data):
return self.HandleModify(data)
@sio.on('msync:orm:delete', namespace='/msync')
def on_orm_delete(data):
return self.HandleDelete(data)
logger.info('[ORM] ORM 中转处理器已注册')
def _GetConnection(self):
"""获取本地数据库连接(Django default)"""
from django.db import connections
conn = connections['default']
conn.ensure_connection()
return conn
# ─── 事件处理 ──────────────────────────────────────────────
def HandleTables(self, data):
"""列出本地数据库中所有用户表"""
try:
conn = self._GetConnection()
except Exception as e:
return {'code': 1, 'msg': f'数据库连接失败: {e}'}
try:
with conn.cursor() as cursor:
tables = self._ListTables(cursor)
return {'code': 0, 'msg': 'success', 'data': tables}
except Exception as e:
logger.error(f'[ORM] HandleTables 异常: {e}')
return {'code': 1, 'msg': f'查询失败: {e}'}
def HandleColumns(self, data):
"""列出指定表的列信息"""
table_name = (data or {}).get('Table', '')
if not table_name:
return {'code': 1, 'msg': '缺少 Table 参数'}
try:
conn = self._GetConnection()
except Exception as e:
return {'code': 1, 'msg': f'数据库连接失败: {e}'}
try:
with conn.cursor() as cursor:
columns = self._ListColumns(cursor, table_name)
return {'code': 0, 'msg': 'success', 'data': columns}
except Exception as e:
logger.error(f'[ORM] HandleColumns 异常: {e}')
return {'code': 1, 'msg': f'查询失败: {e}'}
def HandleList(self, data):
"""分页查询表数据"""
table_name = (data or {}).get('Table', '')
if not table_name:
return {'code': 1, 'msg': '缺少 Table 参数'}
try:
conn = self._GetConnection()
except Exception as e:
return {'code': 1, 'msg': f'数据库连接失败: {e}'}
try:
with conn.cursor() as cursor:
result = self._QueryTable(cursor, table_name, data or {})
if result.get('error'):
return {'code': 1, 'msg': result['error'], 'data': None}
return {'code': 0, 'msg': 'success', 'data': result}
except Exception as e:
logger.error(f'[ORM] HandleList 异常: {e}')
return {'code': 1, 'msg': f'查询失败: {e}'}
def HandleAdd(self, data):
"""新增记录"""
table_name = (data or {}).get('Table', '')
record = (data or {}).get('Record', {})
if not table_name:
return {'code': 1, 'msg': '缺少 Table 参数'}
try:
conn = self._GetConnection()
except Exception as e:
return {'code': 1, 'msg': f'数据库连接失败: {e}'}
try:
with conn.cursor() as cursor:
result = self._AddRecord(cursor, table_name, record)
return result
except Exception as e:
logger.error(f'[ORM] HandleAdd 异常: {e}')
return {'code': 1, 'msg': f'新增失败: {e}'}
def HandleModify(self, data):
"""修改记录"""
table_name = (data or {}).get('Table', '')
record = (data or {}).get('Record', {})
if not table_name:
return {'code': 1, 'msg': '缺少 Table 参数'}
try:
conn = self._GetConnection()
except Exception as e:
return {'code': 1, 'msg': f'数据库连接失败: {e}'}
try:
with conn.cursor() as cursor:
result = self._ModifyRecord(cursor, table_name, record)
return result
except Exception as e:
logger.error(f'[ORM] HandleModify 异常: {e}')
return {'code': 1, 'msg': f'修改失败: {e}'}
def HandleDelete(self, data):
"""删除记录"""
table_name = (data or {}).get('Table', '')
record = (data or {}).get('Record', {})
if not table_name:
return {'code': 1, 'msg': '缺少 Table 参数'}
try:
conn = self._GetConnection()
except Exception as e:
return {'code': 1, 'msg': f'数据库连接失败: {e}'}
try:
with conn.cursor() as cursor:
result = self._DeleteRecord(cursor, table_name, record)
return result
except Exception as e:
logger.error(f'[ORM] HandleDelete 异常: {e}')
return {'code': 1, 'msg': f'删除失败: {e}'}
# ─── SQL 执行 ──────────────────────────────────────────────
def _ListTables(self, cursor):
"""列出所有用户表,含 i18n 标题"""
cursor.execute(
"SELECT TABLE_NAME, TABLE_ROWS, TABLE_COMMENT FROM information_schema.TABLES "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' "
"ORDER BY TABLE_NAME"
)
from django.apps import apps
# 构建表名→中文标题映射
model_verbose = {}
for model in apps.get_models():
meta = model._meta
# 优先使用 table_title(自定义 Meta 属性),其次 verbose_name
table_title = getattr(meta, 'table_title', None)
title = str(table_title) if table_title else (str(meta.verbose_name) if meta.verbose_name else '')
if title:
model_verbose[meta.object_name] = title
model_verbose[meta.db_table] = title
result = []
for row in cursor.fetchall():
table_name, table_rows, table_comment = row
# 优先级:TABLE_COMMENT > table_title/verbose_name > 表名
title = table_comment or model_verbose.get(table_name) or table_name
result.append({'name': table_name, 'title': title, 'count': table_rows or 0})
return result
def _ListColumns(self, cursor, table_name):
"""列出指定表的列信息"""
cursor.execute(
"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_TYPE, COLUMN_COMMENT "
"FROM information_schema.COLUMNS "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s "
"ORDER BY ORDINAL_POSITION",
[table_name]
)
model_verbose = self._FindModelVerboseNames(table_name)
logger.info(f'[ORM] _ListColumns table={table_name} model_verbose={model_verbose}')
columns = []
for row in cursor.fetchall():
col_name, data_type, is_nullable, col_key, extra, col_type, col_comment = row
is_pk = col_key == 'PRI'
is_auto = 'auto_increment' in (extra or '').lower()
if data_type in ('int', 'bigint', 'tinyint', 'smallint', 'mediumint'):
ftype = 'number'
elif data_type in ('float', 'double', 'decimal'):
ftype = 'number'
elif data_type in ('datetime', 'timestamp'):
ftype = 'datetime'
elif data_type in ('date',):
ftype = 'date'
elif data_type in ('time',):
ftype = 'time'
elif data_type in ('json',):
ftype = 'textarea'
elif data_type in ('text', 'mediumtext', 'longtext', 'tinytext'):
ftype = 'textarea'
elif data_type in ('binary', 'varbinary', 'blob'):
ftype = 'uuid'
else:
ftype = 'text'
title = col_comment or model_verbose.get(col_name) or col_name
columns.append({
'field': col_name,
'title': title,
'type': ftype,
'editable': not is_pk and not is_auto,
'sortable': True,
'filterable': True,
'primaryKey': is_pk,
'hideInForm': is_pk,
'required': is_nullable == 'NO' and not is_auto,
'dbType': col_type,
})
return columns
def _QueryTable(self, cursor, table_name, params):
"""分页查询表数据"""
cursor.execute(
"SELECT COUNT(*) FROM information_schema.TABLES "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s",
[table_name]
)
if cursor.fetchone()[0] == 0:
return {'records': [], 'total': 0, 'error': f'表不存在: {table_name}'}
col_info = self._GetTableColumns(cursor, table_name)
pk_cols = {k: v for k, v in col_info.items() if v['is_pk']}
where_parts = []
where_values = []
for pk_name in pk_cols:
pk_val = params.get(pk_name, '')
if pk_val:
where_parts.append(f'`{pk_name}` = %s')
where_values.append(self._ConvertValueForDB(pk_val, pk_cols[pk_name]))
keyword = params.get('keyword', '')
if not where_parts and keyword:
cursor.execute(
"SELECT COLUMN_NAME FROM information_schema.COLUMNS "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s "
"AND DATA_TYPE IN ('varchar', 'char', 'text', 'mediumtext', 'longtext')",
[table_name]
)
text_cols = [row[0] for row in cursor.fetchall()]
if text_cols:
conditions = [f'`{c}` LIKE %s' for c in text_cols]
or_clause = ' OR '.join(conditions)
where_parts.append(f'({or_clause})')
where_values.extend([f'%{keyword}%'] * len(text_cols))
where_clause = (' WHERE ' + ' AND '.join(where_parts)) if where_parts else ''
if where_clause:
cursor.execute(f'SELECT COUNT(*) FROM `{table_name}`{where_clause}', where_values)
total = cursor.fetchone()[0]
else:
cursor.execute(f'SELECT COUNT(*) FROM `{table_name}`')
total = cursor.fetchone()[0]
try:
page = max(int(params.get('PageIndex', 1)), 1)
except (ValueError, TypeError):
page = 1
try:
page_size = min(max(int(params.get('PageSize', 20)), 1), 200)
except (ValueError, TypeError):
page_size = 20
offset = (page - 1) * page_size
cursor.execute(
f'SELECT * FROM `{table_name}`{where_clause} ORDER BY 1 LIMIT %s OFFSET %s',
where_values + [page_size, offset]
)
desc = [d[0] for d in cursor.description]
records = []
for row in cursor.fetchall():
record = {}
for i, val in enumerate(row):
val = self._SerializeValue(val)
record[desc[i]] = val
records.append(record)
return {'records': records, 'total': total, 'page': page, 'PageSize': page_size}
def _AddRecord(self, cursor, table_name, record):
"""新增记录"""
if not self._ValidateTableName(cursor, table_name):
return {'code': 1, 'msg': f'表 {table_name} 不存在'}
col_info = self._GetTableColumns(cursor, table_name)
fields = []
values = []
for key, val in record.items():
if key not in col_info:
continue
if col_info[key]['is_auto']:
continue
fields.append(f'`{key}`')
values.append(self._ConvertValueForDB(val, col_info[key]))
if not fields:
return {'code': 1, 'msg': '没有可插入的字段'}
placeholders = ', '.join(['%s'] * len(fields))
sql = f'INSERT INTO `{table_name}` ({", ".join(fields)}) VALUES ({placeholders})'
cursor.execute(sql, values)
return {'code': 0, 'msg': '新增成功'}
def _ModifyRecord(self, cursor, table_name, record):
"""修改记录"""
if not self._ValidateTableName(cursor, table_name):
return {'code': 1, 'msg': f'表 {table_name} 不存在'}
col_info = self._GetTableColumns(cursor, table_name)
pk_cols = {k: v for k, v in col_info.items() if v['is_pk']}
if not pk_cols:
return {'code': 1, 'msg': '表没有主键,无法定位记录'}
set_parts = []
set_values = []
for key, val in record.items():
if key not in col_info or key in pk_cols:
continue
set_parts.append(f'`{key}` = %s')
set_values.append(self._ConvertValueForDB(val, col_info[key]))
if not set_parts:
return {'code': 0, 'msg': '没有需要更新的字段'}
where_parts = []
where_values = []
for pk_name in pk_cols:
if pk_name not in record:
return {'code': 1, 'msg': f'缺少主键字段: {pk_name}'}
where_parts.append(f'`{pk_name}` = %s')
where_values.append(self._ConvertValueForDB(record[pk_name], pk_cols[pk_name]))
sql = f'UPDATE `{table_name}` SET {", ".join(set_parts)} WHERE {" AND ".join(where_parts)}'
cursor.execute(sql, set_values + where_values)
if cursor.rowcount == 0:
return {'code': 1, 'msg': '记录不存在或未变更'}
return {'code': 0, 'msg': '修改成功'}
def _DeleteRecord(self, cursor, table_name, record):
"""删除记录"""
if not self._ValidateTableName(cursor, table_name):
return {'code': 1, 'msg': f'表 {table_name} 不存在'}
col_info = self._GetTableColumns(cursor, table_name)
pk_cols = {k: v for k, v in col_info.items() if v['is_pk']}
if not pk_cols:
return {'code': 1, 'msg': '表没有主键,无法定位记录'}
where_parts = []
where_values = []
for pk_name in pk_cols:
if pk_name not in record:
return {'code': 1, 'msg': f'缺少主键字段: {pk_name}'}
where_parts.append(f'`{pk_name}` = %s')
where_values.append(self._ConvertValueForDB(record[pk_name], pk_cols[pk_name]))
sql = f'DELETE FROM `{table_name}` WHERE {" AND ".join(where_parts)}'
cursor.execute(sql, where_values)
if cursor.rowcount == 0:
return {'code': 1, 'msg': '记录不存在'}
return {'code': 0, 'msg': '删除成功'}
# ─── 工具方法 ──────────────────────────────────────────────
def _ValidateTableName(self, cursor, table_name):
"""验证表名存在"""
cursor.execute(
"SELECT COUNT(*) FROM information_schema.TABLES "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s",
[table_name]
)
return cursor.fetchone()[0] > 0
def _GetTableColumns(self, cursor, table_name):
"""获取表的列信息"""
cursor.execute(
"SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, COLUMN_KEY, EXTRA, IS_NULLABLE "
"FROM information_schema.COLUMNS "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s "
"ORDER BY ORDINAL_POSITION",
[table_name]
)
cols = {}
for row in cursor.fetchall():
col_name, data_type, column_type, col_key, extra, is_nullable = row
cols[col_name] = {
'type': data_type,
'column_type': column_type or '',
'is_pk': col_key == 'PRI',
'is_auto': 'auto_increment' in (extra or '').lower(),
'is_nullable': is_nullable == 'YES',
}
return cols
def _ConvertValueForDB(self, value, col_info):
"""将前端传来的值转换为数据库可接受的类型"""
if value is None or value == '':
if col_info['is_nullable']:
return None
return ''
data_type = col_info['type']
if data_type in ('int', 'bigint', 'tinyint', 'smallint', 'mediumint'):
return int(value)
elif data_type in ('float', 'double', 'decimal'):
return float(value)
elif data_type in ('binary', 'varbinary'):
import re
hex_str = re.sub(r'[^0-9a-fA-F]', '', str(value))
if len(hex_str) == 32:
return uuid.UUID(hex_str).bytes
return value
return value
def _SerializeValue(self, val):
"""将数据库值序列化为 JSON 安全格式"""
if isinstance(val, bytes):
if len(val) == 16:
try:
return str(uuid.UUID(bytes=val))
except ValueError:
return val.hex()
return val.hex()
elif isinstance(val, datetime.datetime):
return val.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(val, datetime.date):
return val.isoformat()
elif isinstance(val, datetime.time):
return val.strftime('%H:%M:%S')
elif isinstance(val, (bytearray, memoryview)):
return bytes(val).hex()
return val
def _FindModelVerboseNames(self, table_name):
"""从 Django 模型中获取字段的 verbose_name"""
from django.apps import apps
verbose_map = {}
try:
for model in apps.get_models():
if model._meta.db_table == table_name:
logger.info(f'[ORM] _FindModelVerboseNames matched model={model.__name__} db_table={model._meta.db_table}')
for f in model._meta.get_fields():
# 获取数据库列名
col_name = None
if hasattr(f, 'column') and f.column:
col_name = f.column
elif hasattr(f, 'db_column') and f.db_column:
col_name = f.db_column
elif hasattr(f, 'attname'):
col_name = f.attname
if not col_name:
continue
vn = getattr(f, 'verbose_name', None)
if vn and str(vn) != col_name:
verbose_map[col_name] = str(vn)
logger.debug(f'[ORM] {col_name} -> {str(vn)}')
break
else:
# 没有匹配的模型
available = [m._meta.db_table for m in apps.get_models()]
logger.warning(f'[ORM] _FindModelVerboseNames: 未找到 db_table={table_name} 的模型, 可用表: {available[:20]}...')
except Exception as e:
logger.error(f'[ORM] _FindModelVerboseNames 异常: {e}')
return verbose_map
+145
View File
@@ -0,0 +1,145 @@
#!/usr/bin/env python3
"""只导入用户迁移所需的表到临时数据库 xaio_old"""
import MySQLdb
import re
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD
# 需要导入的表(用户相关)
NEEDED_TABLES = {
'user_main', 'user_dashou', 'user_guanshi', 'user_kefu',
'user_shangjia', 'user_boss', 'admin_profile', 'user_zuzhang',
'user_shenheguan', 'user_role', 'role', 'permission',
'role_permission', 'account_permission',
}
def get_conn(db=None):
kwargs = dict(
host=DATABASE_HOST, port=int(DATABASE_PORT),
user=DATABASE_USER, password=DATABASE_PASSWORD,
charset='utf8mb4', connect_timeout=60,
read_timeout=300, write_timeout=300,
)
if db:
kwargs['database'] = db
return MySQLdb.connect(**kwargs)
# Drop and recreate
conn = get_conn()
cursor = conn.cursor()
cursor.execute('DROP DATABASE IF EXISTS xaio_old')
cursor.execute('CREATE DATABASE xaio_old CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci')
conn.commit()
conn.close()
print('临时数据库 xaio_old 已重建')
# Read the SQL file
with open('xaio_cheng_xu_backup.sql', 'r', encoding='utf-8') as f:
sql_content = f.read()
# Parse and filter statements
# We need CREATE TABLE and INSERT statements for NEEDED_TABLES only
# Also need DROP TABLE IF EXISTS for those tables
statements = []
current = []
current_table = None
in_create = False
for line in sql_content.split('\n'):
stripped = line.strip()
if not stripped or stripped.startswith('--') or stripped.startswith('/*'):
continue
# Detect table name from CREATE TABLE or DROP TABLE or INSERT INTO
create_match = re.match(r'CREATE\s+TABLE\s+`(\w+)`', stripped, re.IGNORECASE)
drop_match = re.match(r'DROP\s+TABLE\s+IF\s+EXISTS\s+`(\w+)`', stripped, re.IGNORECASE)
insert_match = re.match(r'INSERT\s+INTO\s+`(\w+)`', stripped, re.IGNORECASE)
if create_match:
current_table = create_match.group(1)
in_create = True
elif drop_match:
current_table = drop_match.group(1)
elif insert_match:
current_table = insert_match.group(1)
in_create = False
# Only include statements for needed tables
if current_table and current_table in NEEDED_TABLES:
current.append(line)
if stripped.endswith(';'):
stmt = '\n'.join(current).strip()
current = []
current_table = None
in_create = False
upper = stmt.upper()
if not upper.startswith('SET ') and not upper.startswith('USE '):
statements.append(stmt)
elif stripped.endswith(';'):
# Not a needed table, skip
current = []
current_table = None
in_create = False
elif current_table and current_table in NEEDED_TABLES:
current.append(line)
else:
# Not needed, skip but track state
if stripped.endswith(';'):
current = []
current_table = None
print(f'筛选出 {len(statements)} 条用户相关SQL语句')
# Execute
conn = get_conn(db='xaio_old')
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
executed = 0
errors = 0
for stmt in statements:
try:
cursor.execute(stmt)
executed += 1
if executed % 20 == 0:
conn.commit()
except MySQLdb.OperationalError as e:
if e.args[0] in (2006, 2013):
try:
conn.close()
except:
pass
conn = get_conn(db='xaio_old')
cursor = conn.cursor()
try:
cursor.execute(stmt)
executed += 1
except Exception as e2:
errors += 1
if errors <= 5:
print(f' ERR(retry): {str(e2)[:100]}')
else:
errors += 1
if errors <= 5:
print(f' ERR: {str(e)[:100]}')
except Exception as e:
errors += 1
if errors <= 5:
print(f' ERR: {str(e)[:100]}')
conn.commit()
cursor.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit()
print(f'\n导入完成: 成功 {executed}, 错误 {errors}')
# Check row counts
print('\n关键表行数:')
for table in sorted(NEEDED_TABLES):
try:
cursor.execute('SELECT COUNT(*) FROM `%s`' % table)
count = cursor.fetchone()[0]
print(f' {table}: {count} rows')
except Exception:
print(f' {table}: NOT FOUND')
conn.close()
+463
View File
@@ -0,0 +1,463 @@
#!/usr/bin/env python3
"""
migrate_data.py — 从 SQL 备份文件直接迁移数据到新的 gvsdsdk User + RBAC 体系
v3: 正确的字段映射 + 基于扩展表存在性分配角色 + bulk_create + 实时进度
"""
import os, sys, re, uuid, time, datetime, MySQLdb
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'a_long_dianjing.settings')
import django; django.setup()
from app_secrets import DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
TENANT_UUID = uuid.UUID('a0000000-0000-0000-0000-000000000001').bytes
COMPANY_UUID = uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes
BATCH_SIZE = 500
ROLE_MAP = {
'normal': '消费者', 'dashou': '打手', 'shop': '商家',
'guanshi': '负责人', 'admin': '管理员', 'kefu': '客服',
'zuzhang': '组长', 'shenheguan': '审核官',
}
# 角色优先级(高→低): 管理员 > 客服 > 负责人 > 组长 > 审核官 > 商家 > 打手 > 消费者
ROLE_PRIORITY = ['admin', 'kefu', 'guanshi', 'zuzhang', 'shenheguan', 'shop', 'dashou', 'normal']
# 扩展表 → 角色类型 映射
EXT_ROLE_MAP = {
'admin_profile': 'admin',
'user_kefu': 'kefu',
'user_guanshi': 'guanshi',
'user_zuzhang': 'zuzhang',
'user_shenheguan': 'shenheguan',
'user_shangjia': 'shop',
'user_dashou': 'dashou',
}
SQL_FILE = os.path.join(os.path.dirname(__file__), 'xaio_cheng_xu_backup.sql')
class Progress:
def __init__(self, total, width=35):
self.total = total; self.width = width; self.start = time.time(); self.done = 0
def update(self, n=1):
self.done += n; pct = self.done / self.total if self.total else 0
filled = int(self.width * pct); bar = '█' * filled + '░' * (self.width - filled)
elapsed = time.time() - self.start
eta = (elapsed / self.done * (self.total - self.done)) if self.done else 0
sys.stdout.write(f'\r [{bar}] {pct:5.1%} {self.done}/{self.total} {elapsed:.0f}s ETA{eta:.0f}s')
sys.stdout.flush()
def finish(self):
elapsed = time.time() - self.start
sys.stdout.write(f'\r [{"█"*self.width}] 100% {self.done}/{self.total} {elapsed:.0f}s\n')
sys.stdout.flush()
def parse_insert_values(table_name, sql_content):
pattern = re.compile(r"INSERT\s+INTO\s+`" + re.escape(table_name) + r"`\s+VALUES\s*\((.+?)\)\s*;", re.IGNORECASE | re.DOTALL)
return [m.group(1) for m in pattern.finditer(sql_content)]
def parse_sql_value(val_str):
val_str = val_str.strip()
if val_str.upper() == 'NULL': return None
if val_str.startswith("'") and val_str.endswith("'"):
return val_str[1:-1].replace("\\'", "'").replace("\\\\", "\\")
try: return int(val_str)
except ValueError:
try: return float(val_str)
except ValueError: return val_str
def split_sql_values(values_str):
values, current, in_quote, escape = [], [], False, False
for ch in values_str:
if escape: current.append(ch); escape = False; continue
if ch == '\\': current.append(ch); escape = True; continue
if ch == "'": in_quote = not in_quote; current.append(ch); continue
if ch == ',' and not in_quote: values.append(''.join(current).strip()); current = []; continue
current.append(ch)
if current: values.append(''.join(current).strip())
return [parse_sql_value(v) for v in values]
def parse_dt(v):
if isinstance(v, str) and v:
try: return datetime.datetime.fromisoformat(v.replace(' ', 'T'))
except: pass
return datetime.datetime.utcnow()
def get_raw_conn(db=None):
kwargs = dict(host=DATABASE_HOST, port=int(DATABASE_PORT), user=DATABASE_USER,
password=DATABASE_PASSWORD, charset='utf8mb4', connect_timeout=10,
read_timeout=60, write_timeout=60)
if db: kwargs['database'] = db
return MySQLdb.connect(**kwargs)
def run_migration():
from gvsdsdk.models import User, Role, UserRole
from users.models import (
UserBoss, UserDashou, UserShangjia, UserGuanshi,
UserZuzhang, UserShenheguan, AdminProfile, UserKefu,
UserSensitiveData
)
print("=" * 60)
print("开始从 SQL 备份迁移数据到 gvsdsdk.User + RBAC")
print("=" * 60)
# [0] 读取 SQL
print("\n[0/7] 读取 SQL 备份文件...", end=' ')
with open(SQL_FILE, 'r', encoding='utf-8') as f:
sql_content = f.read()
print(f"{len(sql_content)/1024/1024:.1f} MB")
# [1] 解析所有扩展表的 user_id → 建立角色映射
print("\n[1/7] 解析扩展表建立角色映射...")
# 正确的 user_id 索引位置
ext_user_id_idx = {
'user_dashou': 22,
'user_guanshi': 11,
'user_kefu': 9,
'user_shangjia': 14,
'user_boss': 6,
'admin_profile': 4,
'user_zuzhang': 17,
'user_shenheguan': 9,
}
# user_main.id → 角色集合
user_roles = {} # old_user_id -> set of role_types
for table_name, role_type in EXT_ROLE_MAP.items():
inserts = parse_insert_values(table_name, sql_content)
uid_idx = ext_user_id_idx[table_name]
count = 0
for values_str in inserts:
vals = split_sql_values(values_str)
if uid_idx < len(vals) and vals[uid_idx] is not None:
old_uid = vals[uid_idx]
if old_uid not in user_roles:
user_roles[old_uid] = set()
user_roles[old_uid].add(role_type)
count += 1
print(f" {table_name}: {count} 条有 user_id")
# [2] 解析 user_main
print("\n[2/7] 解析 user_main...")
user_main_inserts = parse_insert_values('user_main', sql_content)
total = len(user_main_inserts)
print(f" 共 {total} 条记录")
uid_map = {} # yonghuid -> UserUUID (bytes)
user_id_map = {} # old id -> yonghuid
phone_to_yonghuid = {}
# 先解析所有 user_main 记录
user_data = [] # (old_id, yonghuid, fields_dict, role_type)
prog = Progress(total)
for i, values_str in enumerate(user_main_inserts):
vals = split_sql_values(values_str)
if len(vals) < 16:
prog.update(); continue
old_id = vals[1]
yonghuid = str(vals[2]) if vals[2] else None
if not yonghuid:
prog.update(); continue
# 确定角色:基于扩展表存在性 + user_type
roles = user_roles.get(old_id, set())
user_type = str(vals[11]) if vals[11] else 'normal'
# user_type 也可能指定角色
if user_type == 'admin':
roles.add('admin')
elif user_type == 'kefu':
roles.add('kefu')
# 如果没有任何角色,默认为 normal
if not roles:
roles.add('normal')
# 选择优先级最高的角色
primary_role = 'normal'
for r in ROLE_PRIORITY:
if r in roles:
primary_role = r
break
user_data.append((old_id, yonghuid, vals, primary_role, roles))
user_id_map[old_id] = yonghuid
phone = str(vals[5]) if vals[5] else ''
if phone: phone_to_yonghuid[phone] = yonghuid
prog.update()
prog.finish()
print(f" 解析完成: {len(user_data)} 条有效记录")
# [3] 创建角色
print("\n[3/7] 创建角色...")
created_roles = {}
for user_type, role_name in ROLE_MAP.items():
role, created = Role.objects.get_or_create(
RoleName=role_name, TenantUUID=TENANT_UUID,
defaults={'RoleUUID': uuid.uuid4().bytes, 'RoleDesc': f'{role_name}角色', 'RoleStatus': 1, 'AssignScope': 0})
created_roles[user_type] = role
print(f" {role_name}: {'NEW' if created else 'EXISTS'}")
# [4] 批量创建 User + UserRole + UserSensitiveData
print("\n[4/7] 批量创建 User + UserRole + UserSensitiveData...")
user_batch, ur_batch, usd_batch = [], [], []
errors = 0
prog = Progress(len(user_data))
for old_id, yonghuid, vals, primary_role, all_roles in user_data:
openid = str(vals[3]) if vals[3] else ''
avatar = str(vals[4]) if vals[4] else 'a_long/morentouxiang.jpg'
phone = str(vals[5]) if vals[5] else ''
password = str(vals[6]) if vals[6] else ''
zhifu = str(vals[7]) if vals[7] else ''
skzhanghao = str(vals[8]) if vals[8] else ''
ip = str(vals[9]) if vals[9] else ''
last_login_time = vals[10]
create_time = vals[12]
unionid = str(vals[14]) if vals[14] else ''
shoujihao_renzheng = bool(vals[15]) if vals[15] is not None else False
user_uuid = uuid.uuid4().bytes
ct, lt = parse_dt(create_time), parse_dt(last_login_time)
user_batch.append(User(
UserUUID=user_uuid, UserName=yonghuid, UserUID=yonghuid,
OpenID=openid, UnionID=unionid, Avatar=avatar, Phone=phone,
PhoneVerified=shoujihao_renzheng, IP=ip, UserAccountLicense=1,
UserPositionStatus=0, UserCreateTime=ct, UserLastLoginDate=lt,
IsStaff=('admin' in all_roles), IsSuperuser=('admin' in all_roles)))
# 为每个角色创建 UserRole(多对多)
for role_type in all_roles:
role = created_roles.get(role_type)
if role:
ur_batch.append(UserRole(
UserRoleUUID=uuid.uuid4().bytes, UserUUID=user_uuid,
RoleUUID=role.RoleUUID, CompanyUUID=COMPANY_UUID))
usd_batch.append(UserSensitiveData(
user_uuid_id=user_uuid, password=password, zhifu=zhifu,
skzhanghao=skzhanghao, shoujihao_renzheng=shoujihao_renzheng))
uid_map[yonghuid] = user_uuid
if len(user_batch) >= BATCH_SIZE:
try:
User.objects.bulk_create(user_batch, ignore_conflicts=True)
UserRole.objects.bulk_create(ur_batch, ignore_conflicts=True)
UserSensitiveData.objects.bulk_create(usd_batch, ignore_conflicts=True)
except Exception: errors += len(user_batch)
user_batch, ur_batch, usd_batch = [], [], []
prog.update()
if user_batch:
try:
User.objects.bulk_create(user_batch, ignore_conflicts=True)
UserRole.objects.bulk_create(ur_batch, ignore_conflicts=True)
UserSensitiveData.objects.bulk_create(usd_batch, ignore_conflicts=True)
except Exception: errors += len(user_batch)
prog.finish()
print(f" 成功: {len(uid_map)}, 错误: {errors}")
# [5] 迁移扩展表 — 用 ORM bulk_create(正确字段映射)
print("\n[5/7] 迁移扩展表...")
# 正确的字段映射: (sql_index, model_field_name)
# None = 跳过, '_user_id' = FK 到新 User
ext_configs = [
('user_dashou', UserDashou, [
(0, None), (1, 'nicheng'), (2, 'chenghao'), (3, 'zhuangtai'), (4, 'zaixianzhuangtai'),
(5, 'zhanghaozhuangtai'), (6, 'jieshao'), (7, 'jiedanzongliang'), (8, 'chengjiaozongliang'),
(9, 'tuikuanliang'), (10, 'yue'), (11, 'zonge'), (12, 'dianhua'), (13, 'wechat'),
(14, 'yaoqingren'), (15, 'jinrijiedan'), (16, 'jinrishouyi'), (17, 'jinyuejiedan'),
(18, 'jinyueshouyi'), (19, 'jifen'), (20, 'yajin'), (21, None), # create_time
(22, '_user_id'), # user_id FK
(23, 'ewai_xiane'), (24, 'jinritixian_jine'), (25, 'kaioi_ewai_xiane'),
(26, 'last_tixian_date'),
]),
('user_guanshi', UserGuanshi, [
(0, None), (1, 'yaoqingma'), (2, 'dianhua'), (3, 'wechat'),
(4, 'yaogingshuliang'), (5, 'zhuangtai'), (6, 'jinrichongzhi'),
(7, 'jinyuechongzhi'), (8, 'chongzhifenrun'), (9, 'yue'), (10, None), # create_time
(11, '_user_id'),
(12, 'fenghong_erci'), (13, 'fenghong_erci_enabled'), (14, 'fenhong_yici'),
(15, 'ewai_xiane'), (16, 'jinritixian_jine'), (17, 'kaioi_ewai_xiane'),
(18, 'last_tixian_date'), (19, 'yaoqingren'), (20, 'invite_qrcode_url'),
]),
('user_kefu', UserKefu, [
(0, None), (1, 'nicheng'), (2, 'erjimima'), (3, 'zhuangtai'),
(4, 'jinrichuli'), (5, 'jinyuechuli'), (6, 'zongchuli'),
(7, None), (8, None), (9, '_user_id'),
]),
('user_shangjia', UserShangjia, [
(0, None), (1, 'nicheng'), (2, 'zhuangtai'), (3, 'dianhua'), (4, 'wechat'),
(5, 'fabu'), (6, 'tuikuan'), (7, 'yue'), (8, 'chengjiao'),
(9, 'jinridingdan'), (10, 'jinriliushui'), (11, 'jinyuedingdan'),
(12, 'jinyueliushui'), (13, None), (14, '_user_id'),
]),
('user_boss', UserBoss, [
(0, None), (1, 'nickname'), (2, 'zonge'), (3, 'alldingdan'),
(4, 'alltui'), (5, None), (6, '_user_id'),
]),
('admin_profile', AdminProfile, [
(0, None), (1, 'password'), (2, 'wechat'), (3, None),
(4, '_user_id'), (5, 'yaoqingma'),
]),
('user_zuzhang', UserZuzhang, [
(0, None), (1, 'yaoqingma'), (2, 'fenyong_zonge'), (3, 'ketixian_jine'),
(4, 'yaoqing_zongshu'), (5, 'jinri_fenyong'), (6, 'jinyue_fenyong'),
(7, 'zhuangtai'), (8, 'haibao_url'), (9, 'jinri_tixian'), (10, 'last_tixian_time'),
(11, 'ewai_tixian_xiane'), (12, 'kaioi_ewai_tixian'), (13, 'kaioi_ewai_fenhong'),
(14, 'ewai_fenhong_jine'), (15, None), (16, None), (17, '_user_id'),
]),
('user_shenheguan', UserShenheguan, [
(0, None), (1, 'zhuangtai'), (2, 'shenhe_zhuangtai'),
(3, 'shenhe_zongshu'), (4, 'tongguo_zongshu'), (5, 'yue'), (6, 'zonge'),
(7, None), (8, None), (9, '_user_id'), (10, 'is_renzheng'),
]),
]
for table_name, model, field_map in ext_configs:
inserts = parse_insert_values(table_name, sql_content)
if not inserts:
print(f" {table_name}: 0 条"); continue
user_id_sql_idx = next((idx for idx, fn in field_map if fn == '_user_id'), None)
if user_id_sql_idx is None:
print(f" {table_name}: 无法定位 user_id"); continue
batch = []
success = 0
fail = 0
prog = Progress(len(inserts))
for values_str in inserts:
vals = split_sql_values(values_str)
if not vals or user_id_sql_idx >= len(vals) or vals[user_id_sql_idx] is None:
fail += 1; prog.update(); continue
old_user_id = vals[user_id_sql_idx]
yonghuid = user_id_map.get(old_user_id)
if not yonghuid:
fail += 1; prog.update(); continue
new_uuid = uid_map.get(yonghuid)
if not new_uuid:
fail += 1; prog.update(); continue
try:
obj = model(user_id=new_uuid)
for sql_idx, field_name in field_map:
if field_name is None or field_name == '_user_id':
continue
if sql_idx < len(vals) and vals[sql_idx] is not None:
try: setattr(obj, field_name, vals[sql_idx])
except: pass
batch.append(obj)
success += 1
except Exception:
fail += 1
if len(batch) >= BATCH_SIZE:
try: model.objects.bulk_create(batch, ignore_conflicts=True)
except: pass
batch = []
prog.update()
if batch:
try: model.objects.bulk_create(batch, ignore_conflicts=True)
except: pass
prog.finish()
print(f" 成功: {success}, 失败(无user_id): {fail}")
# [6] 迁移其他引用表
print("\n[6/7] 迁移其他引用 yonghuid 的表...")
other_tables = [
'tixianjilu', 'tixian_shenhe_jilu', 'tixian_auto_record',
'xiugaijilu', 'ranking_record',
]
conn = get_raw_conn(db=DATABASE_NAME)
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
for table_name in other_tables:
inserts = parse_insert_values(table_name, sql_content)
if not inserts:
print(f" {table_name}: 0 条"); continue
success = 0
prog = Progress(len(inserts))
for values_str in inserts:
sql = f"INSERT INTO `{table_name}` VALUES ({values_str})"
try:
cursor.execute(sql)
success += 1
except Exception:
pass
if success % 100 == 0 and success > 0:
try: conn.commit()
except: pass
prog.update()
try: conn.commit()
except MySQLdb.OperationalError:
conn = get_raw_conn(db=DATABASE_NAME)
cursor = conn.cursor()
cursor.execute('SET FOREIGN_KEY_CHECKS = 0')
prog.finish()
print(f" 成功: {success}")
try:
cursor.execute('SET FOREIGN_KEY_CHECKS = 1')
conn.commit(); conn.close()
except: pass
# [7] 验证
print("\n[7/7] 验证迁移结果...")
new_user_count = User.objects.count()
new_ur_count = UserRole.objects.count()
usd_count = UserSensitiveData.objects.count()
print(f" gvsdsdk.User: {new_user_count}")
print(f" UserRole: {new_ur_count}")
print(f" UserSensitiveData: {usd_count}")
print("\n 角色分布:")
for user_type, role in created_roles.items():
ur_count = UserRole.objects.filter(RoleUUID=role.RoleUUID).count()
print(f" {ROLE_MAP[user_type]}: {ur_count} 人")
print("\n 扩展表:")
for name, model in [('user_dashou', UserDashou), ('user_guanshi', UserGuanshi),
('user_kefu', UserKefu), ('user_shangjia', UserShangjia),
('user_boss', UserBoss), ('admin_profile', AdminProfile),
('user_zuzhang', UserZuzhang), ('user_shenheguan', UserShenheguan)]:
print(f" {name}: {model.objects.count()} 条")
print("\n" + "=" * 60)
print("迁移完成!")
print(f"TENANT_UUID = {uuid.UUID(bytes=TENANT_UUID)}")
print(f"COMPANY_UUID = {uuid.UUID(bytes=COMPANY_UUID)}")
print("=" * 60)
if __name__ == '__main__':
run_migration()
+259
View File
@@ -0,0 +1,259 @@
#!/usr/bin/env python3
"""
migrate_to_gvsdsdk_user.py — 将 UserMain 用户体系迁移到 gvsdsdk.User + RBAC
使用方式:
cd /opt/.../django
python manage.py shell < migrate_to_gvsdsdk_user.py
或:
python manage.py shell
>>> exec(open('migrate_to_gvsdsdk_user.py').read())
"""
import uuid
import datetime
from django.db import transaction
from django.conf import settings
# === 配置 ===
TENANT_UUID = uuid.uuid4().bytes # 本租户 UUID(所有角色共用)
COMPANY_UUID = uuid.uuid4().bytes # 默认公司 UUID
# 角色映射:user_type → (RoleName, RoleDesc)
ROLE_MAP = {
'normal': ('消费者', '普通消费者/老板'),
'dashou': ('打手', '接单打手'),
'shop': ('商家', '发布订单的商家'),
'guanshi': ('负责人', '管事/负责人'),
'admin': ('管理员', '系统管理员'),
'kefu': ('客服', '客服人员'),
'zuzhang': ('组长', '组长'),
'shenheguan': ('审核官', '审核官'),
}
# 权限映射:每个角色拥有的权限码
PERMISSION_MAP = {
'消费者': ['view_orders', 'create_order', 'view_own_profile'],
'打手': ['view_orders', 'accept_order', 'view_own_profile', 'withdraw'],
'商家': ['view_orders', 'create_order', 'view_own_profile', 'withdraw', 'manage_own_orders'],
'负责人': ['view_orders', 'view_own_profile', 'withdraw', 'invite_dashou', 'view_dashou_stats'],
'管理员': ['admin_access', 'manage_users', 'view_all_orders', 'manage_orders', 'view_stats', 'manage_fines'],
'客服': ['kefu_access', 'view_orders', 'manage_orders', 'apply_fine', 'view_stats'],
'组长': ['view_orders', 'view_own_profile', 'withdraw', 'invite_dashou'],
'审核官': ['view_orders', 'review_orders', 'view_own_profile', 'withdraw'],
}
def run_migration():
from gvsdsdk.models import User, Role, Permission, UserRole, RolePermission
from users.models import (
UserMain, UserBoss, UserDashou, UserShangjia, UserGuanshi,
UserZuzhang, UserShenheguan, AdminProfile, UserKefu,
UserSensitiveData
)
print("=" * 60)
print("开始迁移 UserMain → gvsdsdk.User + RBAC")
print("=" * 60)
# ========== 第1步:创建租户下的角色和权限 ==========
print("\n[1/6] 创建角色和权限...")
created_roles = {}
created_perms = {}
for user_type, (role_name, role_desc) in ROLE_MAP.items():
# 创建角色
role, created = Role.objects.get_or_create(
RoleName=role_name,
TenantUUID=TENANT_UUID,
defaults={
'RoleUUID': uuid.uuid4().bytes,
'RoleDesc': role_desc,
'RoleStatus': 1,
'AssignScope': 0,
}
)
if created:
print(f" 创建角色: {role_name}")
created_roles[user_type] = role
# 创建该角色的权限
perm_codes = PERMISSION_MAP.get(role_name, [])
for perm_code in perm_codes:
perm, perm_created = Permission.objects.get_or_create(
PermCode=perm_code,
TenantUUID=TENANT_UUID,
defaults={
'PermUUID': uuid.uuid4().bytes,
'PermName': perm_code,
'PermCategory': role_name,
'PermStatus': 1,
}
)
if perm_created:
print(f" 创建权限: {perm_code}")
created_perms[perm_code] = perm
# 关联角色-权限
RolePermission.objects.get_or_create(
RoleUUID=role.RoleUUID,
PermUUID=perm.PermUUID,
defaults={
'RolePermUUID': uuid.uuid4().bytes,
}
)
# ========== 第2步:迁移用户 ==========
print("\n[2/6] 迁移用户数据...")
user_main_qs = UserMain.objects.all()
total = user_main_qs.count()
print(f" 共 {total} 个用户待迁移")
# 构建 yonghuid → UserUUID 映射
uid_map = {} # yonghuid → UserUUID (bytes)
for i, um in enumerate(user_main_qs):
if (i + 1) % 100 == 0:
print(f" 进度: {i+1}/{total}")
user_uuid = uuid.uuid4().bytes
# 创建 gvsdsdk User
user = User.objects.create(
UserUUID=user_uuid,
UserName=um.yonghuid, # 用 yonghuid 作为用户名
UserUID=um.yonghuid,
OpenID=um.openid or '',
UnionID=um.unionid or '',
Avatar=um.avatar or 'a_long/morentouxiang.jpg',
Phone=um.phone or '',
PhoneVerified=um.shoujihao_renzheng or False,
IP=um.ip or '',
UserAccountLicense=1,
UserPositionStatus=0,
UserCreateTime=um.create_time or datetime.datetime.utcnow(),
UserLastLoginDate=um.last_login_time or datetime.datetime.utcnow(),
IsStaff=(um.user_type == 'admin'),
IsSuperuser=(um.user_type == 'admin'),
)
uid_map[um.yonghuid] = user_uuid
# 创建 UserRole
user_type = um.user_type or 'normal'
role = created_roles.get(user_type)
if role:
UserRole.objects.create(
UserRoleUUID=uuid.uuid4().bytes,
UserUUID=user_uuid,
RoleUUID=role.RoleUUID,
CompanyUUID=COMPANY_UUID,
)
# 创建 UserSensitiveData
UserSensitiveData.objects.create(
user_uuid_id=user_uuid,
password=um.password or '',
zhifu=um.zhifu or '',
skzhanghao=um.skzhanghao or '',
shoujihao_renzheng=um.shoujihao_renzheng or False,
)
print(f" 用户迁移完成: {len(uid_map)} 个")
# ========== 第3步:迁移扩展表 FK ==========
print("\n[3/6] 迁移扩展表 FK...")
ext_tables = [
('UserBoss', UserBoss, 'boss_profile'),
('UserDashou', UserDashou, 'dashou_profile'),
('UserShangjia', UserShangjia, 'shop_profile'),
('UserGuanshi', UserGuanshi, 'guanshi_profile'),
('UserZuzhang', UserZuzhang, 'zuzhang_profile'),
('UserShenheguan', UserShenheguan, 'shenheguan_profile'),
('AdminProfile', AdminProfile, 'admin_profile'),
('UserKefu', UserKefu, 'kefu_profile'),
]
for table_name, model, _ in ext_tables:
count = 0
for obj in model.objects.all():
old_user_id = obj.user_id # 旧 FK (UserMain.id)
# 通过旧 UserMain 查找 yonghuid → 新 UserUUID
try:
old_user = UserMain.objects.get(id=old_user_id)
new_uuid = uid_map.get(old_user.yonghuid)
if new_uuid:
obj.user_id = new_uuid # 更新 FK 为新 UserUUID
obj.save(update_fields=['user_id'])
count += 1
except UserMain.DoesNotExist:
pass
print(f" {table_name}: 迁移 {count} 条")
# ========== 第4步:迁移其他引用 yonghuid 的表 ==========
print("\n[4/6] 迁移其他表的 yonghuid 引用...")
# Tixianjilu, TixianShenheJilu, TixianAutoRecord, Xiugaijilu, RankingRecord
# 这些表使用 yonghuid 字符串字段,不需要修改(UserUID 保留相同值)
print(" 这些表使用 yonghuid 字符串字段,值不变,无需迁移")
# ========== 第5步:迁移 backend.UserRole ==========
print("\n[5/6] 迁移 backend.UserRole...")
from backend.models import UserRole as BackendUserRole
count = 0
for bur in BackendUserRole.objects.all():
# account_id 是手机号,查找对应的 UserMain → 新 UserUUID
try:
um = UserMain.objects.get(phone=bur.account_id)
new_uuid = uid_map.get(um.yonghuid)
if new_uuid:
# 查找对应的新角色
old_role = bur.role
# 尝试匹配角色名
role_name_map = {
'客服': 'kefu', '打手': 'dashou', '商家': 'shop',
'管事': 'guanshi', '管理员': 'admin', '组长': 'zuzhang',
'审核官': 'shenheguan', '消费者': 'normal',
}
new_role = None
for ut, r in created_roles.items():
if old_role.role_name in r.RoleName or old_role.role_code in ut:
new_role = r
break
if new_role:
UserRole.objects.get_or_create(
UserUUID=new_uuid,
RoleUUID=new_role.RoleUUID,
CompanyUUID=COMPANY_UUID,
defaults={'UserRoleUUID': uuid.uuid4().bytes}
)
count += 1
except UserMain.DoesNotExist:
pass
print(f" 迁移 {count} 条 backend.UserRole")
# ========== 第6步:验证 ==========
print("\n[6/6] 验证迁移结果...")
new_user_count = User.objects.count()
new_role_count = Role.objects.filter(TenantUUID=TENANT_UUID).count()
new_perm_count = Permission.objects.filter(TenantUUID=TENANT_UUID).count()
new_ur_count = UserRole.objects.count()
print(f" gvsdsdk.User: {new_user_count}")
print(f" Role: {new_role_count}")
print(f" Permission: {new_perm_count}")
print(f" UserRole: {new_ur_count}")
print(f" UserSensitiveData: {UserSensitiveData.objects.count()}")
print("\n" + "=" * 60)
print("迁移完成!")
print(f"TENANT_UUID = {uuid.UUID(bytes=TENANT_UUID)}")
print(f"COMPANY_UUID = {uuid.UUID(bytes=COMPANY_UUID)}")
print("请将这两个 UUID 保存到 settings.py 中")
print("=" * 60)
if __name__ == '__main__':
run_migration()
+454 -205
View File
@@ -1,205 +1,454 @@
# Generated by Django 5.2.10 on 2026-01-14 19:59
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Lilubiao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lilu', models.DecimalField(decimal_places=4, max_digits=5, null=True, verbose_name='平台分成利率,1是平台,2是商家')),
('fadanpingtai', models.CharField(max_length=10, null=True, verbose_name='订单所属平台,(商家或平台)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'lilubiao',
},
),
migrations.CreateModel(
name='Ptliushui',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('zonge', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='收取总金额')),
('zhichuzonge', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='支出总金额')),
('zongshouyi', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='总收益')),
('rizonge', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='日收取')),
('rizhichu', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='日支出')),
('rishouyi', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='日收益')),
('zongshoucishu', models.IntegerField(default=0, verbose_name='总收取次数')),
('rishoucishu', models.IntegerField(default=0, verbose_name='日收取次数')),
('zongzhichucishu', models.IntegerField(default=0, verbose_name='总支出次数')),
('rizhichucishu', models.IntegerField(default=0, verbose_name='日支出次数')),
],
options={
'db_table': 'ptliushui',
},
),
migrations.CreateModel(
name='Chufajilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dashouid', models.CharField(db_index=True, max_length=7, null=True, verbose_name='被罚打手ID')),
('qingqiuid', models.CharField(db_index=True, max_length=7, null=True, verbose_name='请求处罚ID')),
('chuliid', models.CharField(db_index=True, max_length=7, null=True, verbose_name='处理处罚ID')),
('cfliyou', models.TextField(blank=True, null=True, verbose_name='处罚理由')),
('sqzhuangtai', models.IntegerField(blank=True, default=0, null=True, verbose_name='处罚申请状态:0待处理,1成功,2驳回')),
('bhliyou', models.TextField(blank=True, null=True, verbose_name='驳回处罚理由')),
('jifen', models.IntegerField(default=0, verbose_name='扣除打手积分')),
('dingdan_id', models.CharField(db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'chufajilu',
'indexes': [models.Index(fields=['dashouid'], name='chufajilu_dashoui_07aac0_idx'), models.Index(fields=['qingqiuid'], name='chufajilu_qingqiu_ac160e_idx'), models.Index(fields=['chuliid'], name='chufajilu_chuliid_cd63ac_idx'), models.Index(fields=['dingdan_id'], name='chufajilu_dingdan_b8f0c2_idx')],
},
),
migrations.CreateModel(
name='Dashoutupian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('dashou', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='接单打手ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='打手提交图片URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'dashoutupian',
'indexes': [models.Index(fields=['dashou'], name='dashoutupia_dashou_7de8bd_idx'), models.Index(fields=['dingdan_id'], name='dashoutupia_dingdan_97c685_idx')],
},
),
migrations.CreateModel(
name='Dingdan',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
('zhuangtai', models.IntegerField(blank=True, db_index=True, default=1, null=True, verbose_name='订单状态')),
('fadan_pingtai', models.IntegerField(blank=True, null=True, verbose_name='发单平台')),
('jine', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='订单金额')),
('dashou_fencheng', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='打手分成')),
('jiedan_dashou_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='接单打手ID')),
('dashou_liuyan', models.TextField(blank=True, null=True, verbose_name='打手留言')),
('zhiding_id', models.CharField(blank=True, max_length=32, null=True, verbose_name='指定ID')),
('shangpin_id', models.IntegerField(blank=True, null=True, verbose_name='商品ID')),
('leixing_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='商品类型ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='商品图片URL')),
('yaoqiuleixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='抢单要求类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('yongjin', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金要求')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='订单介绍')),
('beizhu', models.TextField(blank=True, null=True, verbose_name='订单备注')),
('nicheng', models.CharField(blank=True, max_length=50, null=True, verbose_name='游戏昵称')),
('user1_id', models.CharField(db_index=True, max_length=30, null=True, verbose_name='用户1标识')),
('user2_id', models.CharField(db_index=True, max_length=30, null=True, verbose_name='用户2打手标识')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '订单',
'verbose_name_plural': '订单',
'db_table': 'dingdan',
'indexes': [models.Index(fields=['zhuangtai'], name='dingdan_zhuangt_2febe8_idx'), models.Index(fields=['dingdan_id'], name='dingdan_dingdan_83dcb6_idx'), models.Index(fields=['jiedan_dashou_id'], name='dingdan_jiedan__921bfa_idx')],
},
),
migrations.CreateModel(
name='Liaotian',
fields=[
('id', models.BigAutoField(primary_key=True, serialize=False, verbose_name='主键ID')),
('user1_id', models.CharField(db_index=True, max_length=30, verbose_name='用户1标识')),
('user2_id', models.CharField(db_index=True, max_length=30, verbose_name='用户2标识')),
('dingdan_id', models.CharField(max_length=32, unique=True, verbose_name='订单ID')),
('zhuangtai', models.IntegerField(choices=[(1, '开启中'), (0, '已关闭')], db_index=True, default=1, verbose_name='聊天状态')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'liaotian',
'indexes': [models.Index(fields=['user1_id'], name='liaotian_user1_i_6be6cd_idx'), models.Index(fields=['user2_id'], name='liaotian_user2_i_9f61a4_idx'), models.Index(fields=['zhuangtai'], name='liaotian_zhuangt_5e8be5_idx')],
},
),
migrations.CreateModel(
name='Pingfen',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dashou', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='接单打手ID')),
('zongfen', models.PositiveIntegerField(default=0, verbose_name='总分')),
('cishu', models.PositiveIntegerField(default=0, verbose_name='评分次数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '评分表',
'db_table': 'pingfenbiao',
'indexes': [models.Index(fields=['dashou'], name='pingfenbiao_dashou_f62f10_idx')],
},
),
migrations.CreateModel(
name='Tuikuanjilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(max_length=32, unique=True, verbose_name='订单ID')),
('dashouid', models.CharField(max_length=7, null=True, verbose_name='接单打手ID')),
('qingqiuid', models.CharField(max_length=7, null=True, verbose_name='请求用户ID')),
('chuliid', models.CharField(db_index=True, max_length=7, null=True, verbose_name='处理人ID')),
('liyou', models.TextField(blank=True, null=True, verbose_name='理由')),
('sqzhuangtai', models.IntegerField(blank=True, db_index=True, default=0, null=True, verbose_name='申请状态:0待处理,1成功,2驳回')),
('bhliyou', models.TextField(blank=True, null=True, verbose_name='驳回理由')),
('jine', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='订单金额')),
('dashou_fencheng', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='打手分成')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='订单介绍')),
('beizhu', models.TextField(blank=True, null=True, verbose_name='订单备注')),
('nicheng', models.CharField(blank=True, max_length=50, null=True, verbose_name='游戏昵称')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'tuikuanjilu',
'indexes': [models.Index(fields=['chuliid'], name='tuikuanjilu_chuliid_0b0f16_idx'), models.Index(fields=['sqzhuangtai'], name='tuikuanjilu_sqzhuan_d89dc9_idx')],
},
),
migrations.CreateModel(
name='DingdanPingtai',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('laoban_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='老板ID')),
('laoban_pingjia', models.TextField(blank=True, null=True, verbose_name='老板评价')),
('dingdan', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='pingtai_kuozhan', to='orders.dingdan', verbose_name='订单')),
],
options={
'verbose_name': '平台订单扩展',
'verbose_name_plural': '平台订单扩展',
'db_table': 'dingdan_pingtai',
'indexes': [models.Index(fields=['laoban_id'], name='dingdan_pin_laoban__d55e6f_idx')],
},
),
migrations.CreateModel(
name='DingdanShangjia',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('shangjia_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='商家ID')),
('shangjia_pingjia', models.TextField(blank=True, null=True, verbose_name='商家评价')),
('cfliyou', models.TextField(blank=True, null=True, verbose_name='商家处罚理由')),
('sqzhuangtai', models.IntegerField(blank=True, default=0, null=True, verbose_name='处罚申请状态:0待处理,1成功,2驳回')),
('bhliyou', models.TextField(blank=True, null=True, verbose_name='驳回商家处罚理由')),
('sjnicheng', models.CharField(max_length=50, null=True, verbose_name='商家昵称')),
('dingdan', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='shangjia_kuozhan', to='orders.dingdan', verbose_name='订单')),
],
options={
'verbose_name': '商家订单扩展',
'verbose_name_plural': '商家订单扩展',
'db_table': 'dingdan_shangjia',
'indexes': [models.Index(fields=['shangjia_id'], name='dingdan_sha_shangji_64d28b_idx')],
},
),
]
# Generated by Django 4.2.27 on 2026-06-17 16:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Chufajilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dashouid', models.CharField(db_index=True, max_length=7, null=True, verbose_name='被罚打手ID')),
('qingqiuid', models.CharField(db_index=True, max_length=11, null=True, verbose_name='请求处罚ID')),
('chuliid', models.CharField(db_index=True, max_length=11, null=True, verbose_name='处理处罚ID')),
('cfliyou', models.TextField(blank=True, null=True, verbose_name='处罚理由')),
('ssliyou', models.TextField(blank=True, null=True, verbose_name='打手申诉理由')),
('sqzhuangtai', models.IntegerField(blank=True, default=0, null=True, verbose_name='处罚申请状态:0待处理,1成功,2驳回')),
('bhliyou', models.TextField(blank=True, null=True, verbose_name='驳回处罚理由')),
('jifen', models.IntegerField(default=0, verbose_name='扣除打手积分')),
('dingdan_id', models.CharField(db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'chufajilu',
},
),
migrations.CreateModel(
name='Chufatupian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('yonghuid', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='用户ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='证据图片URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'chufatupian',
},
),
migrations.CreateModel(
name='Dashoutupian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('dashou', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='接单打手ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='打手提交图片URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'dashoutupian',
},
),
migrations.CreateModel(
name='Dingdan',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
('zhuangtai', models.IntegerField(blank=True, db_index=True, default=1, null=True, verbose_name='订单状态')),
('fadan_pingtai', models.IntegerField(blank=True, null=True, verbose_name='发单平台')),
('jine', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='订单金额')),
('dashou_fencheng', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='打手分成')),
('guanshi_fencheng', models.DecimalField(blank=True, decimal_places=2, default=0, max_digits=10, null=True, verbose_name='管事分成')),
('jiedan_dashou_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='接单打手ID')),
('dashou_liuyan', models.TextField(blank=True, null=True, verbose_name='打手留言')),
('zhiding_id', models.CharField(blank=True, max_length=32, null=True, verbose_name='指定ID')),
('shangpin_id', models.IntegerField(blank=True, null=True, verbose_name='商品ID')),
('leixing_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='商品类型ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='商品图片URL')),
('yaoqiuleixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='抢单要求类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('yongjin', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金要求')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='订单介绍')),
('beizhu', models.TextField(blank=True, null=True, verbose_name='订单备注')),
('nicheng', models.CharField(blank=True, max_length=50, null=True, verbose_name='游戏昵称')),
('user1_id', models.CharField(db_index=True, max_length=30, null=True, verbose_name='用户1标识')),
('user2_id', models.CharField(db_index=True, max_length=30, null=True, verbose_name='用户2打手标识')),
('auto_task_id', models.CharField(blank=True, default='', max_length=255, verbose_name='延时任务ID')),
('auto_expire_at', models.DateTimeField(blank=True, null=True, verbose_name='计划过期时间')),
('pending_dispatch', models.BooleanField(db_index=True, default=False, verbose_name='待调度标记')),
('status_8_time', models.DateTimeField(blank=True, null=True, verbose_name='状态变为8的时间')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('clkf', models.CharField(db_index=True, max_length=20, null=True, verbose_name='处理客服')),
('tkly', models.CharField(blank=True, max_length=500, null=True, verbose_name='退款/拒绝理由')),
('wechat_transaction_id', models.CharField(blank=True, db_index=True, max_length=64, null=True, verbose_name='微信支付订单号')),
],
options={
'verbose_name': '订单',
'verbose_name_plural': '订单',
'db_table': 'dingdan',
},
),
migrations.CreateModel(
name='DingdanPeihu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
('zhudashou_id', models.CharField(db_index=True, max_length=32, verbose_name='主打手ID')),
('peihu1_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='陪护1打手ID')),
('peihu2_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='陪护2打手ID')),
('zhuangtai', models.IntegerField(default=1, verbose_name='陪护订单状态')),
('peihu_xuqiu_shuliang', models.IntegerField(default=1, verbose_name='陪护需求数量')),
('yongjin_yaoqiu', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='抢单佣金要求')),
('peihu1_dengji_xuqiu', models.PositiveIntegerField(blank=True, null=True, verbose_name='陪护1等级需求(称号ID)')),
('peihu2_dengji_xuqiu', models.PositiveIntegerField(blank=True, null=True, verbose_name='陪护2等级需求(称号ID)')),
('peihu1_zhadan_danze', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护1炸单担责比例')),
('peihu2_zhadan_danze', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护2炸单担责比例')),
('peihu1_fenhong', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护1分红比例')),
('peihu2_fenhong', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护2分红比例')),
('zhiding_peihu1', models.CharField(blank=True, max_length=32, null=True, verbose_name='指定陪护1 ID')),
('zhiding_peihu2', models.CharField(blank=True, max_length=32, null=True, verbose_name='指定陪护2 ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '陪护订单',
'verbose_name_plural': '陪护订单',
'db_table': 'dingdan_peihu',
},
),
migrations.CreateModel(
name='DingdanPingtai',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('laoban_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='老板ID')),
('laoban_pingjia', models.TextField(blank=True, null=True, verbose_name='老板评价')),
('jjjs_biaoshi', models.IntegerField(default=0, verbose_name='拒绝结算标记(1表示拒绝结算)')),
('pingtai_shouyi', models.DecimalField(blank=True, decimal_places=2, default=0.0, max_digits=10, null=True, verbose_name='平台收益')),
('dianpu_shouyi', models.DecimalField(blank=True, decimal_places=2, default=0.0, max_digits=10, null=True, verbose_name='店铺收益')),
('dianpu_id', models.PositiveIntegerField(blank=True, db_index=True, null=True, verbose_name='所属店铺ID')),
('shangji_dianpu_id', models.PositiveIntegerField(blank=True, db_index=True, null=True, verbose_name='该订单的上级店铺ID')),
('shangji_fenhong', models.DecimalField(blank=True, decimal_places=2, default=0.0, max_digits=10, null=True, verbose_name='上级分红金额')),
],
options={
'verbose_name': '平台订单扩展',
'verbose_name_plural': '平台订单扩展',
'db_table': 'dingdan_pingtai',
},
),
migrations.CreateModel(
name='DingdanShangjia',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('shangjia_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='商家ID')),
('shangjia_pingjia', models.TextField(blank=True, null=True, verbose_name='商家评价')),
('cfliyou', models.TextField(blank=True, null=True, verbose_name='商家处罚理由')),
('sqzhuangtai', models.IntegerField(blank=True, default=0, null=True, verbose_name='处罚申请状态:0待处理,1成功,2驳回')),
('bhliyou', models.TextField(blank=True, null=True, verbose_name='驳回商家处罚理由')),
('sjnicheng', models.CharField(max_length=50, null=True, verbose_name='商家昵称')),
('shangyige_dingdan_id', models.CharField(blank=True, max_length=32, null=True, verbose_name='上一个订单ID')),
],
options={
'verbose_name': '商家订单扩展',
'verbose_name_plural': '商家订单扩展',
'db_table': 'dingdan_shangjia',
},
),
migrations.CreateModel(
name='Fadan',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='自增主键')),
('beichufa_id', models.CharField(db_index=True, max_length=20, verbose_name='被处罚用户ID')),
('shenqing_chufa', models.CharField(blank=True, max_length=20, null=True, verbose_name='申请处罚者ID')),
('shenfen', models.IntegerField(choices=[(1, '打手'), (2, '管事'), (3, '商家'), (4, '组长')], default=1, verbose_name='被处罚者身份')),
('chufaliyou', models.TextField(blank=True, null=True, verbose_name='处罚理由')),
('fakuanjine', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='罚款金额')),
('guanliandingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='关联订单ID')),
('zhuangtai', models.IntegerField(choices=[(1, '待缴纳'), (2, '已缴纳'), (3, '申诉中'), (4, '已驳回')], db_index=True, default=1, verbose_name='罚单状态')),
('yingxiang_qiangdan', models.IntegerField(choices=[(1, '影响抢单'), (0, '不影响抢单')], db_index=True, default=1, verbose_name='是否影响抢单')),
('shensuliyou', models.TextField(blank=True, null=True, verbose_name='申诉理由')),
('tongyi_chufaliyou', models.TextField(blank=True, null=True, verbose_name='同意处罚理由')),
('bohuiliyou', models.TextField(blank=True, null=True, verbose_name='驳回理由')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('shenqingren_shenfen', models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员'), (4, '店铺'), (5, '商家')], default=1, verbose_name='申请处罚人身份')),
('chulizhe_shenfen', models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员')], default=2, verbose_name='处理者身份')),
('chulizhe', models.CharField(blank=True, max_length=20, null=True, verbose_name='处理者')),
('shenqingren_fenhong_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='申请人分红金额')),
],
options={
'verbose_name': '罚单',
'verbose_name_plural': '罚单',
'db_table': 'fadan',
},
),
migrations.CreateModel(
name='FadanFenhongLilv',
fields=[
('shenfen', models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员'), (4, '店铺'), (5, '商家')], primary_key=True, serialize=False, verbose_name='申请处罚人身份')),
('lilv', models.DecimalField(decimal_places=4, default=0.0, max_digits=5, verbose_name='分红费率')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '罚款分红费率配置',
'verbose_name_plural': '罚款分红费率配置',
'db_table': 'fadan_fenhong_lilv',
},
),
migrations.CreateModel(
name='Lilubiao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lilu', models.DecimalField(decimal_places=4, max_digits=5, null=True, verbose_name='平台分成利率,1是平台,2是商家')),
('fadanpingtai', models.CharField(max_length=10, null=True, verbose_name='订单所属平台,(商家或平台)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'lilubiao',
},
),
migrations.CreateModel(
name='Ptliushui',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('zonge', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='收取总金额')),
('zhichuzonge', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='支出总金额')),
('zongshouyi', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='总收益')),
('rizonge', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='日收取')),
('rizhichu', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='日支出')),
('rishouyi', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='日收益')),
('zongshoucishu', models.IntegerField(default=0, verbose_name='总收取次数')),
('rishoucishu', models.IntegerField(default=0, verbose_name='日收取次数')),
('zongzhichucishu', models.IntegerField(default=0, verbose_name='总支出次数')),
('rizhichucishu', models.IntegerField(default=0, verbose_name='日支出次数')),
],
options={
'db_table': 'ptliushui',
},
),
migrations.CreateModel(
name='Tuikuanjilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(max_length=32, unique=True, verbose_name='订单ID')),
('dashouid', models.CharField(max_length=7, null=True, verbose_name='接单打手ID')),
('qingqiuid', models.CharField(max_length=7, null=True, verbose_name='请求用户ID')),
('chuliid', models.CharField(db_index=True, max_length=11, null=True, verbose_name='处理人ID')),
('liyou', models.TextField(blank=True, null=True, verbose_name='理由')),
('sqzhuangtai', models.IntegerField(blank=True, db_index=True, default=0, null=True, verbose_name='申请状态:0待处理,1成功,2驳回')),
('bhliyou', models.TextField(blank=True, null=True, verbose_name='驳回理由')),
('jine', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='订单金额')),
('dashou_fencheng', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='打手分成')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='订单介绍')),
('beizhu', models.TextField(blank=True, null=True, verbose_name='订单备注')),
('nicheng', models.CharField(blank=True, max_length=50, null=True, verbose_name='游戏昵称')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'tuikuanjilu',
'indexes': [models.Index(fields=['chuliid'], name='tuikuanjilu_chuliid_0b0f16_idx'), models.Index(fields=['sqzhuangtai'], name='tuikuanjilu_sqzhuan_d89dc9_idx')],
},
),
migrations.CreateModel(
name='Pingfen',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dashou', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='接单打手ID')),
('zongfen', models.PositiveIntegerField(default=0, verbose_name='总分')),
('cishu', models.PositiveIntegerField(default=0, verbose_name='评分次数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '评分表',
'db_table': 'pingfenbiao',
'indexes': [models.Index(fields=['dashou'], name='pingfenbiao_dashou_f62f10_idx')],
},
),
migrations.CreateModel(
name='OrderDashouHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, verbose_name='订单ID')),
('dashou_id', models.CharField(db_index=True, max_length=7, verbose_name='打手ID')),
('times', models.PositiveSmallIntegerField(verbose_name='第几次接单(从1开始)')),
('operator', models.CharField(max_length=11, verbose_name='操作客服ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '订单打手变更历史',
'verbose_name_plural': '订单打手变更历史',
'db_table': 'order_dashou_history',
'indexes': [models.Index(fields=['dingdan_id'], name='order_dasho_dingdan_1e79ab_idx'), models.Index(fields=['dashou_id'], name='order_dasho_dashou__0a637c_idx')],
},
),
migrations.CreateModel(
name='Liaotian',
fields=[
('id', models.BigAutoField(primary_key=True, serialize=False, verbose_name='主键ID')),
('user1_id', models.CharField(db_index=True, max_length=30, verbose_name='用户1标识')),
('user2_id', models.CharField(db_index=True, max_length=30, verbose_name='用户2标识')),
('dingdan_id', models.CharField(max_length=32, unique=True, verbose_name='订单ID')),
('zhuangtai', models.IntegerField(choices=[(1, '开启中'), (0, '已关闭')], db_index=True, default=1, verbose_name='聊天状态')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'liaotian',
'indexes': [models.Index(fields=['user1_id'], name='liaotian_user1_i_6be6cd_idx'), models.Index(fields=['user2_id'], name='liaotian_user2_i_9f61a4_idx'), models.Index(fields=['zhuangtai'], name='liaotian_zhuangt_5e8be5_idx')],
},
),
migrations.CreateModel(
name='FadanShensuTupian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('beichufa_id', models.CharField(db_index=True, max_length=7, verbose_name='被处罚用户ID')),
('tupian_url', models.CharField(max_length=500, verbose_name='图片相对URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('yongtu', models.IntegerField(choices=[(1, '处罚证据图片'), (2, '申诉图片')], default=2, verbose_name='图片用途')),
('fadan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shensu_tupians', to='orders.fadan', verbose_name='关联罚单')),
],
options={
'verbose_name': '罚款申诉图片',
'verbose_name_plural': '罚款申诉图片',
'db_table': 'fadan_shensu_tupian',
},
),
migrations.CreateModel(
name='FadanFenhong',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='自增主键')),
('fenhongzhe_id', models.CharField(db_index=True, max_length=20, verbose_name='分红者ID')),
('zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='分红总额')),
('ketixian_fenhong', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='可提现分红')),
('shenfen', models.IntegerField(choices=[(1, '商家'), (2, '客服'), (3, '平台管理者'), (4, '店铺'), (5, '售后')], default=1, verbose_name='分红者身份')),
('fenhong_cishu', models.IntegerField(default=0, verbose_name='分红次数')),
('is_individual_rate', models.BooleanField(default=False, verbose_name='是否单独开启分红利率')),
('yingde_lilv', models.DecimalField(decimal_places=4, default=0.0, max_digits=5, verbose_name='分红应得利率')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '罚款分红',
'verbose_name_plural': '罚款分红',
'db_table': 'fadan_fenhong',
'indexes': [models.Index(fields=['fenhongzhe_id'], name='fadan_fenhong_zhe_idx'), models.Index(fields=['shenfen'], name='fadan_fenhong_sf_idx')],
},
),
migrations.AddIndex(
model_name='fadan',
index=models.Index(fields=['beichufa_id', 'yingxiang_qiangdan', 'zhuangtai'], name='fadan_qiangdan_check'),
),
migrations.AddIndex(
model_name='fadan',
index=models.Index(fields=['guanliandingdan_id'], name='fadan_dingdan_idx'),
),
migrations.AddField(
model_name='dingdanshangjia',
name='dingdan',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='shangjia_kuozhan', to='orders.dingdan', verbose_name='订单'),
),
migrations.AddField(
model_name='dingdanpingtai',
name='dingdan',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='pingtai_kuozhan', to='orders.dingdan', verbose_name='订单'),
),
migrations.AddIndex(
model_name='dingdanpeihu',
index=models.Index(fields=['zhudashou_id'], name='dingdan_pei_zhudash_583f4e_idx'),
),
migrations.AddIndex(
model_name='dingdanpeihu',
index=models.Index(fields=['peihu1_id'], name='dingdan_pei_peihu1__728279_idx'),
),
migrations.AddIndex(
model_name='dingdanpeihu',
index=models.Index(fields=['peihu2_id'], name='dingdan_pei_peihu2__77e45e_idx'),
),
migrations.AddIndex(
model_name='dingdanpeihu',
index=models.Index(fields=['zhuangtai'], name='dingdan_pei_zhuangt_22eaf6_idx'),
),
migrations.AddIndex(
model_name='dingdan',
index=models.Index(fields=['zhuangtai'], name='dingdan_zhuangt_2febe8_idx'),
),
migrations.AddIndex(
model_name='dingdan',
index=models.Index(fields=['dingdan_id'], name='dingdan_dingdan_83dcb6_idx'),
),
migrations.AddIndex(
model_name='dingdan',
index=models.Index(fields=['jiedan_dashou_id'], name='dingdan_jiedan__921bfa_idx'),
),
migrations.AddIndex(
model_name='dingdan',
index=models.Index(fields=['wechat_transaction_id'], name='dingdan_wechat__278b79_idx'),
),
migrations.AddIndex(
model_name='dashoutupian',
index=models.Index(fields=['dashou'], name='dashoutupia_dashou_7de8bd_idx'),
),
migrations.AddIndex(
model_name='dashoutupian',
index=models.Index(fields=['dingdan_id'], name='dashoutupia_dingdan_97c685_idx'),
),
migrations.AddIndex(
model_name='chufatupian',
index=models.Index(fields=['yonghuid'], name='chufatupian_yonghui_71e585_idx'),
),
migrations.AddIndex(
model_name='chufatupian',
index=models.Index(fields=['dingdan_id'], name='chufatupian_dingdan_ce0dd4_idx'),
),
migrations.AddIndex(
model_name='chufajilu',
index=models.Index(fields=['dashouid'], name='chufajilu_dashoui_07aac0_idx'),
),
migrations.AddIndex(
model_name='chufajilu',
index=models.Index(fields=['qingqiuid'], name='chufajilu_qingqiu_ac160e_idx'),
),
migrations.AddIndex(
model_name='chufajilu',
index=models.Index(fields=['chuliid'], name='chufajilu_chuliid_cd63ac_idx'),
),
migrations.AddIndex(
model_name='chufajilu',
index=models.Index(fields=['dingdan_id'], name='chufajilu_dingdan_b8f0c2_idx'),
),
migrations.AddIndex(
model_name='fadanshensutupian',
index=models.Index(fields=['fadan_id'], name='fadan_shens_fadan_i_78fab9_idx'),
),
migrations.AddIndex(
model_name='fadanshensutupian',
index=models.Index(fields=['beichufa_id'], name='fadan_shens_beichuf_59748e_idx'),
),
migrations.AddIndex(
model_name='dingdanshangjia',
index=models.Index(fields=['shangjia_id'], name='dingdan_sha_shangji_64d28b_idx'),
),
migrations.AddIndex(
model_name='dingdanpingtai',
index=models.Index(fields=['laoban_id'], name='dingdan_pin_laoban__d55e6f_idx'),
),
migrations.AddIndex(
model_name='dingdanpingtai',
index=models.Index(fields=['dianpu_id'], name='dingdan_pin_dianpu__9fbe27_idx'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-01-17 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='auto_expire_at',
field=models.DateTimeField(blank=True, null=True, verbose_name='计划过期时间'),
),
migrations.AddField(
model_name='dingdan',
name='auto_task_id',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='延时任务ID'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-01-17 16:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0002_dingdan_auto_expire_at_dingdan_auto_task_id'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='pending_dispatch',
field=models.BooleanField(db_index=True, default=False, verbose_name='待调度标记'),
),
migrations.AddField(
model_name='dingdan',
name='status_8_time',
field=models.DateTimeField(blank=True, null=True, verbose_name='状态变为8的时间'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-01-17 23:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0003_dingdan_pending_dispatch_dingdan_status_8_time'),
]
operations = [
migrations.AlterField(
model_name='tuikuanjilu',
name='chuliid',
field=models.CharField(db_index=True, max_length=11, null=True, verbose_name='处理人ID'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-01-20 19:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0004_alter_tuikuanjilu_chuliid'),
]
operations = [
migrations.AlterField(
model_name='chufajilu',
name='chuliid',
field=models.CharField(db_index=True, max_length=11, null=True, verbose_name='处理处罚ID'),
),
]
-28
View File
@@ -1,28 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-07 19:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0005_alter_chufajilu_chuliid'),
]
operations = [
migrations.CreateModel(
name='Chufatupian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, null=True, verbose_name='订单ID')),
('yonghuid', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='用户ID')),
('tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='证据图片URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'db_table': 'chufatupian',
'indexes': [models.Index(fields=['yonghuid'], name='chufatupian_yonghui_71e585_idx'), models.Index(fields=['dingdan_id'], name='chufatupian_dingdan_ce0dd4_idx')],
},
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-08 00:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0006_chufatupian'),
]
operations = [
migrations.AddField(
model_name='chufajilu',
name='ssliyou',
field=models.TextField(blank=True, null=True, verbose_name='打手申诉理由'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-14 18:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0007_chufajilu_ssliyou'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='is_cross',
field=models.IntegerField(default=0, verbose_name='是否跨平台订单(0否,1是)'),
),
migrations.AddField(
model_name='dingdan',
name='partner_order_id',
field=models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='对方平台订单ID'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-21 14:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0008_dingdan_is_cross_dingdan_partner_order_id'),
]
operations = [
migrations.AddField(
model_name='dingdanpingtai',
name='clkf',
field=models.CharField(db_index=True, max_length=20, null=True, verbose_name='处理客服'),
),
migrations.AddField(
model_name='dingdanpingtai',
name='jjjs_biaoshi',
field=models.IntegerField(default=0, verbose_name='拒绝结算标记(1表示拒绝结算)'),
),
]
@@ -1,22 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-21 16:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0009_dingdanpingtai_clkf_dingdanpingtai_jjjs_biaoshi'),
]
operations = [
migrations.RemoveField(
model_name='dingdanpingtai',
name='clkf',
),
migrations.AddField(
model_name='dingdan',
name='clkf',
field=models.CharField(db_index=True, max_length=20, null=True, verbose_name='处理客服'),
),
]
-18
View File
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-21 17:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0010_remove_dingdanpingtai_clkf_dingdan_clkf'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='tkly',
field=models.CharField(blank=True, max_length=500, null=True, verbose_name='退款/拒绝理由'),
),
]
@@ -1,22 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-22 12:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0011_dingdan_tkly'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='wechat_transaction_id',
field=models.CharField(blank=True, db_index=True, max_length=64, null=True, verbose_name='微信支付订单号'),
),
migrations.AddIndex(
model_name='dingdan',
index=models.Index(fields=['wechat_transaction_id'], name='dingdan_wechat__278b79_idx'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-22 19:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0012_dingdan_wechat_transaction_id_and_more'),
]
operations = [
migrations.AlterField(
model_name='chufajilu',
name='qingqiuid',
field=models.CharField(db_index=True, max_length=11, null=True, verbose_name='请求处罚ID'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-24 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0013_alter_chufajilu_qingqiuid'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='dispatch_type',
field=models.IntegerField(choices=[(1, '我方派单'), (2, '对方派单')], default=0, verbose_name='派发情况'),
),
migrations.AddField(
model_name='dingdan',
name='partner_club_id',
field=models.CharField(blank=True, db_index=True, max_length=6, null=True, verbose_name='对方俱乐部ID'),
),
]
@@ -1,73 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-01 09:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0014_dingdan_dispatch_type_dingdan_partner_club_id'),
]
operations = [
migrations.CreateModel(
name='PreSettlement',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='我方订单ID')),
('partner_order_id', models.CharField(db_index=True, max_length=32, verbose_name='对方订单ID')),
('partner_club_id', models.CharField(db_index=True, max_length=6, verbose_name='对方俱乐部ID')),
('dashou_id', models.CharField(db_index=True, max_length=7, verbose_name='接单打手ID')),
('amount', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='打手应分金额')),
('order_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='订单原金额')),
('status', models.SmallIntegerField(choices=[(0, '待结算'), (1, '已结算'), (2, '已拒绝')], default=0, verbose_name='结算状态')),
('process_time', models.DateTimeField(blank=True, null=True, verbose_name='处理时间')),
('operator', models.CharField(blank=True, default='', max_length=32, verbose_name='操作人')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '预结算表',
'verbose_name_plural': '预结算表',
'db_table': 'pre_settlement',
'indexes': [models.Index(fields=['dingdan_id'], name='pre_settlem_dingdan_4f3541_idx'), models.Index(fields=['partner_order_id'], name='pre_settlem_partner_45b29e_idx'), models.Index(fields=['partner_club_id'], name='pre_settlem_partner_d2c44c_idx'), models.Index(fields=['dashou_id'], name='pre_settlem_dashou__d5fe7c_idx'), models.Index(fields=['status'], name='pre_settlem_status_0aa711_idx')],
},
),
migrations.CreateModel(
name='OrderDashouHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, verbose_name='订单ID')),
('dashou_id', models.CharField(db_index=True, max_length=7, verbose_name='打手ID')),
('times', models.PositiveSmallIntegerField(verbose_name='第几次接单(从1开始)')),
('operator', models.CharField(max_length=11, verbose_name='操作客服ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '订单打手变更历史',
'verbose_name_plural': '订单打手变更历史',
'db_table': 'order_dashou_history',
'indexes': [models.Index(fields=['dingdan_id'], name='order_dasho_dingdan_1e79ab_idx'), models.Index(fields=['dashou_id'], name='order_dasho_dashou__0a637c_idx')],
},
),
migrations.CreateModel(
name='CrossPlatformOrderData',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='我方订单ID')),
('partner_order_id', models.CharField(db_index=True, max_length=32, verbose_name='对方平台订单ID')),
('partner_club_id', models.CharField(db_index=True, max_length=6, verbose_name='对方俱乐部ID')),
('partner_order_status', models.IntegerField(default=0, verbose_name='对方平台订单状态')),
('partner_dashou_id', models.CharField(blank=True, default='', max_length=32, verbose_name='对方平台接单打手ID')),
('partner_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='对方平台订单金额')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '跨平台订单扩展',
'verbose_name_plural': '跨平台订单扩展',
'db_table': 'cross_platform_order_data',
'indexes': [models.Index(fields=['dingdan_id'], name='cross_platf_dingdan_498d08_idx'), models.Index(fields=['partner_order_id'], name='cross_platf_partner_5d5615_idx'), models.Index(fields=['partner_club_id'], name='cross_platf_partner_1054e1_idx')],
},
),
]
@@ -1,22 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-04 15:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0015_presettlement_orderdashouhistory_and_more'),
]
operations = [
migrations.AlterField(
model_name='presettlement',
name='dingdan_id',
field=models.CharField(db_index=True, max_length=32, verbose_name='我方订单ID'),
),
migrations.AlterUniqueTogether(
name='presettlement',
unique_together={('dingdan_id', 'dashou_id')},
),
]
@@ -1,32 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-23 14:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0016_alter_presettlement_dingdan_id_and_more'),
]
operations = [
migrations.AddField(
model_name='dingdanpingtai',
name='dianpu_id',
field=models.PositiveIntegerField(blank=True, db_index=True, null=True, verbose_name='所属店铺ID'),
),
migrations.AddField(
model_name='dingdanpingtai',
name='dianpu_shouyi',
field=models.DecimalField(blank=True, decimal_places=2, default=0.0, max_digits=10, null=True, verbose_name='店铺收益'),
),
migrations.AddField(
model_name='dingdanpingtai',
name='pingtai_shouyi',
field=models.DecimalField(blank=True, decimal_places=2, default=0.0, max_digits=10, null=True, verbose_name='平台收益'),
),
migrations.AddIndex(
model_name='dingdanpingtai',
index=models.Index(fields=['dianpu_id'], name='dingdan_pin_dianpu__9fbe27_idx'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-30 02:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0017_dingdanpingtai_dianpu_id_and_more'),
]
operations = [
migrations.AddField(
model_name='dingdanshangjia',
name='partner_yonghu_id',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='对方平台用户ID'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-05 10:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0018_dingdanshangjia_partner_yonghu_id'),
]
operations = [
migrations.AddField(
model_name='dingdanpingtai',
name='shangji_dianpu_id',
field=models.PositiveIntegerField(blank=True, db_index=True, null=True, verbose_name='该订单的上级店铺ID'),
),
migrations.AddField(
model_name='dingdanpingtai',
name='shangji_fenhong',
field=models.DecimalField(blank=True, decimal_places=2, default=0.0, max_digits=10, null=True, verbose_name='上级分红金额'),
),
]
@@ -1,58 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-06 11:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0019_dingdanpingtai_shangji_dianpu_id_and_more'),
]
operations = [
migrations.CreateModel(
name='FadanFenhong',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='自增主键')),
('fenhongzhe_id', models.CharField(db_index=True, max_length=20, verbose_name='分红者ID')),
('zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='分红总额')),
('ketixian_fenhong', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='可提现分红')),
('shenfen', models.IntegerField(choices=[(1, '商家'), (2, '客服'), (3, '平台管理者')], default=1, verbose_name='分红者身份')),
('fenhong_cishu', models.IntegerField(default=0, verbose_name='分红次数')),
('yingde_lilv', models.DecimalField(decimal_places=4, default=0.0, max_digits=5, verbose_name='分红应得利率')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '罚款分红',
'verbose_name_plural': '罚款分红',
'db_table': 'fadan_fenhong',
'indexes': [models.Index(fields=['fenhongzhe_id'], name='fadan_fenhong_zhe_idx'), models.Index(fields=['shenfen'], name='fadan_fenhong_sf_idx')],
},
),
migrations.CreateModel(
name='Fadan',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='自增主键')),
('beichufa_id', models.CharField(db_index=True, max_length=20, verbose_name='被处罚用户ID')),
('shenqing_chufa', models.CharField(blank=True, max_length=20, null=True, verbose_name='申请处罚者ID')),
('shenfen', models.IntegerField(choices=[(1, '打手'), (2, '管事'), (3, '商家'), (4, '组长')], default=1, verbose_name='被处罚者身份')),
('chufaliyou', models.TextField(blank=True, null=True, verbose_name='处罚理由')),
('fakuanjine', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='罚款金额')),
('guanliandingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='关联订单ID')),
('zhuangtai', models.IntegerField(choices=[(1, '待缴纳'), (2, '已缴纳'), (3, '申诉中'), (4, '已驳回')], db_index=True, default=1, verbose_name='罚单状态')),
('yingxiang_qiangdan', models.IntegerField(choices=[(1, '影响抢单'), (0, '不影响抢单')], db_index=True, default=1, verbose_name='是否影响抢单')),
('shensuliyou', models.TextField(blank=True, null=True, verbose_name='申诉理由')),
('tongyi_chufaliyou', models.TextField(blank=True, null=True, verbose_name='同意处罚理由')),
('bohuiliyou', models.TextField(blank=True, null=True, verbose_name='驳回理由')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '罚单',
'verbose_name_plural': '罚单',
'db_table': 'fadan',
'indexes': [models.Index(fields=['beichufa_id', 'yingxiang_qiangdan', 'zhuangtai'], name='fadan_qiangdan_check'), models.Index(fields=['guanliandingdan_id'], name='fadan_dingdan_idx')],
},
),
]
@@ -1,30 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-07 11:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('orders', '0020_fadanfenhong_fadan'),
]
operations = [
migrations.CreateModel(
name='FadanShensuTupian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('beichufa_id', models.CharField(db_index=True, max_length=7, verbose_name='被处罚用户ID')),
('tupian_url', models.CharField(max_length=500, verbose_name='图片相对URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('fadan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shensu_tupians', to='orders.fadan', verbose_name='关联罚单')),
],
options={
'verbose_name': '罚款申诉图片',
'verbose_name_plural': '罚款申诉图片',
'db_table': 'fadan_shensu_tupian',
'indexes': [models.Index(fields=['fadan_id'], name='fadan_shens_fadan_i_78fab9_idx'), models.Index(fields=['beichufa_id'], name='fadan_shens_beichuf_59748e_idx')],
},
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-07 16:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0021_fadanshensutupian'),
]
operations = [
migrations.AddField(
model_name='fadan',
name='partner_club_id',
field=models.CharField(blank=True, db_index=True, max_length=6, null=True, verbose_name='对方俱乐部ID'),
),
migrations.AddField(
model_name='fadan',
name='shenqingren_shenfen',
field=models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员')], default=1, verbose_name='申请处罚人身份'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-07 17:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0022_fadan_partner_club_id_fadan_shenqingren_shenfen'),
]
operations = [
migrations.AddField(
model_name='fadanshensutupian',
name='yongtu',
field=models.IntegerField(choices=[(1, '处罚证据图片'), (2, '申诉图片')], default=2, verbose_name='图片用途'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-07 19:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0023_fadanshensutupian_yongtu'),
]
operations = [
migrations.AddField(
model_name='fadan',
name='chulizhe',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='处理者'),
),
migrations.AddField(
model_name='fadan',
name='chulizhe_shenfen',
field=models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员')], default=2, verbose_name='处理者身份'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-10 00:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0024_fadan_chulizhe_fadan_chulizhe_shenfen'),
]
operations = [
migrations.AlterField(
model_name='fadan',
name='shenqingren_shenfen',
field=models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员'), (4, '店铺')], default=1, verbose_name='申请处罚人身份'),
),
]
@@ -1,37 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-10 17:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0025_alter_fadan_shenqingren_shenfen'),
]
operations = [
migrations.CreateModel(
name='FadanFenhongLilv',
fields=[
('shenfen', models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员'), (4, '店铺'), (5, '商家')], primary_key=True, serialize=False, verbose_name='申请处罚人身份')),
('lilv', models.DecimalField(decimal_places=4, default=0.0, max_digits=5, verbose_name='分红费率')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '罚款分红费率配置',
'verbose_name_plural': '罚款分红费率配置',
'db_table': 'fadan_fenhong_lilv',
},
),
migrations.AlterField(
model_name='fadan',
name='shenqingren_shenfen',
field=models.IntegerField(choices=[(1, '客服'), (2, '售后'), (3, '管理员'), (4, '店铺'), (5, '商家')], default=1, verbose_name='申请处罚人身份'),
),
migrations.AlterField(
model_name='fadanfenhong',
name='shenfen',
field=models.IntegerField(choices=[(1, '商家'), (2, '客服'), (3, '平台管理者'), (4, '店铺'), (5, '售后')], default=1, verbose_name='分红者身份'),
),
]
-42
View File
@@ -1,42 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-22 15:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0026_fadanfenhonglilv_alter_fadan_shenqingren_shenfen_and_more'),
]
operations = [
migrations.CreateModel(
name='DingdanPeihu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
('zhudashou_id', models.CharField(db_index=True, max_length=32, verbose_name='主打手ID')),
('peihu1_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='陪护1打手ID')),
('peihu2_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='陪护2打手ID')),
('zhuangtai', models.IntegerField(default=1, verbose_name='陪护订单状态')),
('peihu_xuqiu_shuliang', models.IntegerField(default=1, verbose_name='陪护需求数量')),
('yongjin_yaoqiu', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='抢单佣金要求')),
('peihu1_dengji_xuqiu', models.PositiveIntegerField(blank=True, null=True, verbose_name='陪护1等级需求(称号ID)')),
('peihu2_dengji_xuqiu', models.PositiveIntegerField(blank=True, null=True, verbose_name='陪护2等级需求(称号ID)')),
('peihu1_zhadan_danze', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护1炸单担责比例')),
('peihu2_zhadan_danze', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护2炸单担责比例')),
('peihu1_fenhong', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护1分红比例')),
('peihu2_fenhong', models.CharField(blank=True, max_length=10, null=True, verbose_name='陪护2分红比例')),
('zhiding_peihu1', models.CharField(blank=True, max_length=32, null=True, verbose_name='指定陪护1 ID')),
('zhiding_peihu2', models.CharField(blank=True, max_length=32, null=True, verbose_name='指定陪护2 ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '陪护订单',
'verbose_name_plural': '陪护订单',
'db_table': 'dingdan_peihu',
'indexes': [models.Index(fields=['zhudashou_id'], name='dingdan_pei_zhudash_583f4e_idx'), models.Index(fields=['peihu1_id'], name='dingdan_pei_peihu1__728279_idx'), models.Index(fields=['peihu2_id'], name='dingdan_pei_peihu2__77e45e_idx'), models.Index(fields=['zhuangtai'], name='dingdan_pei_zhuangt_22eaf6_idx')],
},
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-29 17:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0027_dingdanpeihu'),
]
operations = [
migrations.AddField(
model_name='dingdanshangjia',
name='shangyige_dingdan_id',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='上一个订单ID'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-31 22:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0028_dingdanshangjia_shangyige_dingdan_id'),
]
operations = [
migrations.AddField(
model_name='fadanfenhong',
name='is_individual_rate',
field=models.BooleanField(default=False, verbose_name='是否单独开启分红利率'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-01 00:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0029_fadanfenhong_is_individual_rate'),
]
operations = [
migrations.AddField(
model_name='fadan',
name='shenqingren_fenhong_jine',
field=models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='申请人分红金额'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-12 01:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0030_fadan_shenqingren_fenhong_jine'),
]
operations = [
migrations.AddField(
model_name='dingdan',
name='guanshi_fencheng',
field=models.DecimalField(blank=True, decimal_places=2, default=0, max_digits=10, null=True, verbose_name='管事分成'),
),
]
@@ -1,43 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-15 01:42
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('orders', '0031_dingdan_guanshi_fencheng'),
]
operations = [
migrations.DeleteModel(
name='CrossPlatformOrderData',
),
migrations.DeleteModel(
name='PreSettlement',
),
migrations.RemoveField(
model_name='dingdan',
name='dispatch_type',
),
migrations.RemoveField(
model_name='dingdan',
name='is_cross',
),
migrations.RemoveField(
model_name='dingdan',
name='partner_club_id',
),
migrations.RemoveField(
model_name='dingdan',
name='partner_order_id',
),
migrations.RemoveField(
model_name='dingdanshangjia',
name='partner_yonghu_id',
),
migrations.RemoveField(
model_name='fadan',
name='partner_club_id',
),
]
+4 -3
View File
@@ -15,7 +15,8 @@ import logging
# 导入模型 - 确保路径正确
from orders.models import Dingdan
from users.models import UserMain, UserDashou, UserShangjia
from users.models import UserDashou, UserShangjia
from gvsdsdk.models import User
from utils.celery_utils import safe_decimal_operation, log_task_execution, rollback_on_failure
from gvsdsdk.fluent import db, func, FQ
@@ -64,7 +65,7 @@ def process_expired_order(self, dingdan_id):
if dashou_id:
try:
# 查询打手用户主表
dashou_user = UserMain.query.filter(yonghuid=dashou_id).first()
dashou_user = User.query.filter(yonghuid=dashou_id).first()
if dashou_user:
# 获取打手扩展表
dashou_profile = getattr(dashou_user, 'dashou_profile', None)
@@ -93,7 +94,7 @@ def process_expired_order(self, dingdan_id):
shangjia_id = shangjia_kuozhan.shangjia_id
if shangjia_id:
# 查询商家用户
shangjia_user = UserMain.query.filter(yonghuid=shangjia_id).first()
shangjia_user = User.query.filter(yonghuid=shangjia_id).first()
if shangjia_user:
shangjia_profile = getattr(shangjia_user, 'shop_profile', None)
if shangjia_profile:
+47 -46
View File
@@ -62,7 +62,8 @@ from orders.models import (
Lilubiao, Pingfen, Tuikuanjilu
)
from products.models import Shangpin, ShangpinLeixing, Huiyuangoumai
from users.models import UserMain, UserDashou, UserShangjia, UserBoss
from users.models import UserDashou, UserShangjia, UserBoss
from gvsdsdk.models import User
from rank.models import DashouBiaoxian, Chenghao, DingdanBiaoqian, YonghuChenghao
from config.models import (
Szjilu, ShangjiaLianjie
@@ -240,7 +241,7 @@ class WechatPayNotifyView(APIView):
if hasattr(dingdan, 'pingtai_kuozhan'):
laoban_id = dingdan.pingtai_kuozhan.laoban_id
if laoban_id:
user_main = UserMain.query.filter(yonghuid=laoban_id).first()
user_main = User.query.filter(yonghuid=laoban_id).first()
if user_main and hasattr(user_main, 'boss_profile'):
boss = user_main.boss_profile
boss.zonge = (boss.zonge or 0) + (dingdan.jine or 0)
@@ -524,7 +525,7 @@ class PaymentVerifyView(APIView):
# 更新老板扩展表
laoban_id = dingdan.pingtai_kuozhan.laoban_id if hasattr(dingdan, 'pingtai_kuozhan') else None
if laoban_id:
user_main = UserMain.query.filter(yonghuid=laoban_id).first()
user_main = User.query.filter(yonghuid=laoban_id).first()
if user_main and hasattr(user_main, 'boss_profile'):
boss = user_main.boss_profile
boss.zonge = (boss.zonge or 0) + (dingdan.jine or 0)
@@ -710,7 +711,7 @@ class CreateOrderView(APIView):
zhiding_id_value = None
if zhiding:
# 查询主表中是否存在该打手
zhiding_user = UserMain.query.filter(
zhiding_user = User.query.filter(
yonghuid=zhiding,
#user_type='dashou'
).first()
@@ -1348,7 +1349,7 @@ class JiedanView(APIView):
# 7. 更新打手扩展表(如果有打手ID和分成)
if jiedan_dashou_id and dashou_fencheng > 0:
# 查询打手用户
dashou_user = UserMain.query.filter(yonghuid=jiedan_dashou_id).first()
dashou_user = User.query.filter(yonghuid=jiedan_dashou_id).first()
if dashou_user:
# 查询打手扩展表
@@ -1511,7 +1512,7 @@ class DingdanXiangqingView2(APIView):
jiedan_time = ''
tijiao_time = ''
if jiedan_dashou_id:
dashou_user = UserMain.query.filter(yonghuid=jiedan_dashou_id).first()
dashou_user = User.query.filter(yonghuid=jiedan_dashou_id).first()
if dashou_user:
dashou_touxiang = dashou_user.avatar or ''
try:
@@ -1660,7 +1661,7 @@ class JiedanView2(APIView):
# 9. 更新打手收益与状态
if jiedan_dashou_id and dashou_fencheng > 0:
dashou_user = UserMain.query.filter(yonghuid=jiedan_dashou_id).first()
dashou_user = User.query.filter(yonghuid=jiedan_dashou_id).first()
if dashou_user:
try:
dashou_ext = dashou_user.dashou_profile
@@ -1915,11 +1916,11 @@ class ShangjiaPaifaView(APIView):
zhiding_dashou = None
if zhiding_uid:
try:
zhiding_user = UserMain.query.get(yonghuid=zhiding_uid)
zhiding_user = User.query.get(yonghuid=zhiding_uid)
zhiding_dashou = zhiding_user.dashou_profile
if zhiding_dashou.zhanghaozhuangtai != 1:
return Response({'code': 400, 'msg': '指定打手状态异常'})
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({'code': 400, 'msg': '指定用户不存在'})
except UserDashou.DoesNotExist:
return Response({'code': 400, 'msg': '指定用户不是打手'})
@@ -2221,7 +2222,7 @@ class ShangjiaDingdanXiangqingView(APIView):
dashou_nicheng = ''
dashou_avatar = ''
if dashou_yonghuid:
dashou_user = UserMain.query.filter(
dashou_user = User.query.filter(
yonghuid=dashou_yonghuid
).select_related('dashou_profile').first()
if dashou_user:
@@ -2425,9 +2426,9 @@ class ShangjiaJiesuanView(APIView):
# ========== 本地订单正常结算给打手 ==========
# 查询打手信息
try:
dashou_user = UserMain.query.get(yonghuid=jiedan_dashou_id)
dashou_user = User.query.get(yonghuid=jiedan_dashou_id)
dashou = dashou_user.dashou_profile
except (UserMain.DoesNotExist, UserDashou.DoesNotExist):
except (User.DoesNotExist, UserDashou.DoesNotExist):
return Response({
'code': 8,
'msg': '接单打手不存在或信息不完整',
@@ -2767,7 +2768,7 @@ class ShangjiaTuikuanShenqingView(APIView):
# ====== 原有功能:更新打手状态 ======
if dingdan.jiedan_dashou_id:
try:
dashou_main = UserMain.query.filter(
dashou_main = User.query.filter(
yonghuid=dingdan.jiedan_dashou_id
).first()
if dashou_main and hasattr(dashou_main, 'dashou_profile'):
@@ -2850,9 +2851,9 @@ class ShangjiaChufaShenqingView(APIView):
with transaction.atomic():
# 验证打手身份
try:
dashou_user = UserMain.query.get(yonghuid=dashou_id)
dashou_user = User.query.get(yonghuid=dashou_id)
dashou = dashou_user.dashou_profile
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response({
'code': 5,
'msg': '打手用户不存在',
@@ -3028,7 +3029,7 @@ class DashouDingdanHuoquView(APIView):
zhiding_ids = {item['zhiding_id'] for item in dingdan_list if item.get('zhiding_id')}
zhiding_info = {}
if zhiding_ids:
dashou_query = UserMain.query.filter(
dashou_query = User.query.filter(
yonghuid__in=zhiding_ids
).select_related('dashou_profile').annotate(
nicheng=F('dashou_profile__nicheng')
@@ -3078,10 +3079,10 @@ class DashouDingdanHuoquView(APIView):
if sj['shangjia_id']:
yonghuid_set.add(sj['shangjia_id'])
# 将 yonghuid 字符串转换为 UserMain 的主键 id
# 将 yonghuid 字符串转换为 User 的主键 id
user_id_map = {}
if yonghuid_set:
users = UserMain.query.filter(yonghuid__in=yonghuid_set).values('id', 'yonghuid')
users = User.query.filter(yonghuid__in=yonghuid_set).values('id', 'yonghuid')
for u in users:
user_id_map[u['yonghuid']] = u['id']
@@ -3346,8 +3347,8 @@ def send_group_message(
def check_user_permission(identity_type, uid, order):
"""验证用户身份、账号状态、以及是否属于该订单"""
try:
user = UserMain.query.get(yonghuid=uid)
except UserMain.DoesNotExist:
user = User.query.get(yonghuid=uid)
except User.DoesNotExist:
return False, '用户不存在'
if identity_type == 'dashou':
@@ -4672,11 +4673,11 @@ class AdGengHuanDaShou(APIView):
# 8. 验证新打手ID是否存在,并且是打手身份
try:
new_dashou_user = UserMain.query.get(
new_dashou_user = User.query.get(
yonghuid=new_dashou_id,
#user_type='dashou'
)
except UserMain.DoesNotExist:
except User.DoesNotExist:
return Response(
{'code': 404, 'message': '打手不存在或不是打手身份', 'data': None},
status=status.HTTP_404_NOT_FOUND
@@ -4767,7 +4768,7 @@ class AdGengHuanDaShou(APIView):
if old_dashou_id:
try:
# 查询原打手主表
old_dashou_user = UserMain.query.get(
old_dashou_user = User.query.get(
yonghuid=old_dashou_id,
#user_type='dashou'
)
@@ -4781,7 +4782,7 @@ class AdGengHuanDaShou(APIView):
old_dashou_profile.save()
logger.info(f"成功更新原打手{old_dashou_id}状态")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 原打手不存在,继续执行不影响更换
logger.warning(f"原打手{old_dashou_id}不存在,跳过更新")
except AttributeError:
@@ -4911,7 +4912,7 @@ class AdQiangZhiJieDan(APIView):
if jiedan_dashou_id:
try:
# 查询打手用户主表
dashou_user = UserMain.query.get(
dashou_user = User.query.get(
yonghuid=jiedan_dashou_id,
#user_type='dashou'
)
@@ -4938,7 +4939,7 @@ class AdQiangZhiJieDan(APIView):
dashou_profile.save()
logger.info(f"强制结单成功,打手{jiedan_dashou_id}结算分成:{dashou_fencheng}")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 打手用户不存在,记录日志但不影响强制结单
logger.warning(f"强制结单:打手{jiedan_dashou_id}不存在,跳过打手结算")
except AttributeError:
@@ -4954,7 +4955,7 @@ class AdQiangZhiJieDan(APIView):
if shangjia_id:
# 查询商家用户主表
shangjia_user = UserMain.query.get(
shangjia_user = User.query.get(
yonghuid=shangjia_id,
#user_type='shop'
)
@@ -4971,7 +4972,7 @@ class AdQiangZhiJieDan(APIView):
except DingdanShangjia.DoesNotExist:
# 商家订单扩展表不存在,跳过商家更新
logger.warning(f"强制结单:订单{dingdan_id}商家扩展表不存在,跳过商家更新")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 商家用户不存在,跳过商家更新
logger.warning(f"强制结单:商家{shangjia_id}不存在,跳过商家更新")
except AttributeError:
@@ -5087,7 +5088,7 @@ class AdJuJueTuiKuan(APIView):
if jiedan_dashou_id:
try:
# 查询打手用户主表
dashou_user = UserMain.query.get(
dashou_user = User.query.get(
yonghuid=jiedan_dashou_id,
#user_type='dashou'
)
@@ -5114,7 +5115,7 @@ class AdJuJueTuiKuan(APIView):
dashou_profile.save()
logger.info(f"拒绝退款成功,打手{jiedan_dashou_id}结算分成:{dashou_fencheng}")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 打手用户不存在,记录日志但不影响操作
logger.warning(f"拒绝退款:打手{jiedan_dashou_id}不存在,跳过打手结算")
except AttributeError:
@@ -5130,7 +5131,7 @@ class AdJuJueTuiKuan(APIView):
if shangjia_id:
# 查询商家用户主表
shangjia_user = UserMain.query.get(
shangjia_user = User.query.get(
yonghuid=shangjia_id,
#user_type='shop'
)
@@ -5147,7 +5148,7 @@ class AdJuJueTuiKuan(APIView):
except DingdanShangjia.DoesNotExist:
# 商家订单扩展表不存在,跳过商家更新
logger.warning(f"拒绝退款:订单{dingdan_id}商家扩展表不存在,跳过商家更新")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 商家用户不存在,跳过商家更新
logger.warning(f"拒绝退款:商家{shangjia_id}不存在,跳过商家更新")
except AttributeError:
@@ -5318,7 +5319,7 @@ class AdTongYiTuiKuanShangJia(APIView):
if jiedan_dashou_id:
try:
# 查询打手用户主表
dashou_user = UserMain.query.get(
dashou_user = User.query.get(
yonghuid=jiedan_dashou_id,
#user_type='dashou'
)
@@ -5332,7 +5333,7 @@ class AdTongYiTuiKuanShangJia(APIView):
dashou_profile.save()
logger.info(f"同意退款成功,打手{jiedan_dashou_id}退款订单+1")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 打手用户不存在,记录日志但不影响操作
logger.warning(f"同意退款:打手{jiedan_dashou_id}不存在,跳过打手更新")
except AttributeError:
@@ -5343,7 +5344,7 @@ class AdTongYiTuiKuanShangJia(APIView):
if shangjia_id:
try:
# 查询商家用户主表
shangjia_user = UserMain.query.get(
shangjia_user = User.query.get(
yonghuid=shangjia_id,
#user_type='shop'
)
@@ -5360,7 +5361,7 @@ class AdTongYiTuiKuanShangJia(APIView):
shangjia_profile.save()
logger.info(f"同意退款成功,商家{shangjia_id}退款订单+1,余额增加:{jine}")
except UserMain.DoesNotExist:
except User.DoesNotExist:
# 商家用户不存在,记录日志但不影响操作
logger.warning(f"同意退款:商家{shangjia_id}不存在,跳过商家更新")
except AttributeError:
@@ -5528,25 +5529,25 @@ class AdTongYiTuiKuanPingTai(APIView):
# 14. 更新打手扩展表
if jiedan_dashou_id:
try:
dashou_user = UserMain.query.get(yonghuid=jiedan_dashou_id)
dashou_user = User.query.get(yonghuid=jiedan_dashou_id)
dashou_profile = dashou_user.dashou_profile
dashou_profile.zhuangtai = 1 # 打手状态设为空闲
dashou_profile.tuikuanliang += 1
dashou_profile.save()
except (UserMain.DoesNotExist, AttributeError):
except (User.DoesNotExist, AttributeError):
logger.warning(f"平台退款:打手{jiedan_dashou_id}不存在或扩展信息缺失,跳过")
# 15. 更新老板扩展表
if laoban_id:
try:
laoban_user = UserMain.query.get(yonghuid=laoban_id)
laoban_user = User.query.get(yonghuid=laoban_id)
laoban_profile = laoban_user.boss_profile
laoban_profile.alltui += 1
laoban_profile.zonge -= jine
if laoban_profile.zonge < 0:
laoban_profile.zonge = 0
laoban_profile.save()
except (UserMain.DoesNotExist, AttributeError):
except (User.DoesNotExist, AttributeError):
logger.warning(f"平台退款:老板{laoban_id}不存在或扩展信息缺失,跳过")
# 16. 更新收支记录表(id=1)
@@ -5864,12 +5865,12 @@ class AdJuJueJieSuan(APIView):
# 8. 更新打手扩展表
try:
dashou_user = UserMain.query.get(yonghuid=jiedan_dashou_id)
dashou_user = User.query.get(yonghuid=jiedan_dashou_id)
dashou_profile = dashou_user.dashou_profile
dashou_profile.zhuangtai = 1 # 打手状态设为正常
dashou_profile.tuikuanliang += 1 # 退款订单总量+1
dashou_profile.save()
except (UserMain.DoesNotExist, AttributeError) as e:
except (User.DoesNotExist, AttributeError) as e:
logger.warning(f"拒绝结算:打手{jiedan_dashou_id}信息更新失败 - {str(e)}")
return Response({'code': 0, 'message': '拒绝结算成功', 'data': None})
@@ -5946,12 +5947,12 @@ class AdZhuanYiDaTing(APIView):
# 如果有接单打手,更新其扩展表
if jiedan_dashou_id:
try:
dashou_user = UserMain.query.get(yonghuid=jiedan_dashou_id)
dashou_user = User.query.get(yonghuid=jiedan_dashou_id)
dashou_profile = dashou_user.dashou_profile
dashou_profile.zhuangtai = 1
dashou_profile.tuikuanliang += 1
dashou_profile.save()
except (UserMain.DoesNotExist, AttributeError) as e:
except (User.DoesNotExist, AttributeError) as e:
logger.warning(f"转移大厅:打手{jiedan_dashou_id}信息更新失败 - {str(e)}")
return Response({'code': 0, 'message': '转移大厅成功', 'data': None})
@@ -6224,12 +6225,12 @@ class ZxsjghdsView(APIView):
# 6.2 释放打手
if dashou_id:
try:
dashou_user = UserMain.query.get(yonghuid=dashou_id)
dashou_user = User.query.get(yonghuid=dashou_id)
dashou_profile = dashou_user.dashou_profile
dashou_profile.tuikuanliang = (dashou_profile.tuikuanliang or 0) + 1
dashou_profile.zhuangtai = 1 # 空闲
dashou_profile.save(update_fields=['tuikuanliang', 'zhuangtai'])
except (UserMain.DoesNotExist, ObjectDoesNotExist):
except (User.DoesNotExist, ObjectDoesNotExist):
logger.warning(f"打手 {dashou_id} 不存在或扩展表缺失,跳过更新")
# 6.3 更新退款记录
+208 -149
View File
@@ -1,149 +1,208 @@
# Generated by Django 5.2.10 on 2026-01-14 19:59
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Huiyuan',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('huiyuan_id', models.CharField(max_length=6, unique=True, verbose_name='会员ID')),
('jieshao', models.CharField(max_length=30, verbose_name='会员介绍')),
('jtjieshao', models.TextField(blank=True, null=True, verbose_name='会员规则介绍')),
('jiage', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='会员价格')),
('guanshifc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='管事分成')),
('goumai_cishu', models.PositiveIntegerField(default=0, verbose_name='购买次数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '会员',
'verbose_name_plural': '会员',
'db_table': 'huiyuan',
},
),
migrations.CreateModel(
name='Huiyuangoumai',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='购买记录ID')),
('huiyuan_id', models.CharField(db_index=True, max_length=6, verbose_name='会员ID')),
('yonghu_id', models.CharField(db_index=True, max_length=32, verbose_name='用户ID')),
('huiyuan_zhuangtai', models.PositiveIntegerField(default=1, verbose_name='会员状态')),
('jieshao', models.CharField(max_length=30, null=True, verbose_name='会员介绍')),
('daoqi_time', models.DateTimeField(verbose_name='会员到期时间')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '用户购买会员',
'verbose_name_plural': '用户购买会员',
'db_table': 'huiyuangoumai',
},
),
migrations.CreateModel(
name='Shangpin',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='商品ID')),
('biaoqian', models.CharField(blank=True, max_length=45, null=True, verbose_name='商品标题')),
('jiage', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='商品价格')),
('kucun', models.PositiveIntegerField(default=0, verbose_name='商品库存')),
('leixing_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='商品类型ID')),
('zhuanqu_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='商品专区ID')),
('zhenshi_xiaoliang', models.PositiveIntegerField(default=0, verbose_name='商品真实销量')),
('duiwai_xiaoliang', models.PositiveIntegerField(default=0, verbose_name='商品对外销量')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='商品介绍')),
('xiadan_xuzhi', models.TextField(blank=True, null=True, verbose_name='下单须知')),
('guize_tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='规则图片URL')),
('yaoqiuleixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='抢单要求类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('yongjin', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金要求')),
('tupian_url', models.CharField(blank=True, max_length=500, null=True, verbose_name='商品图片URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
],
options={
'verbose_name': '商品',
'verbose_name_plural': '商品',
'db_table': 'shangpin',
},
),
migrations.CreateModel(
name='ShangpinLeixing',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='类型ID')),
('yaoqiuleixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='抢单要求类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('yongjin', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金要求')),
('jieshao', models.CharField(blank=True, max_length=45, null=True, verbose_name='类型介绍')),
('tupian_url', models.CharField(blank=True, max_length=500, null=True, verbose_name='类型图片URL')),
],
options={
'verbose_name': '商品类型',
'verbose_name_plural': '商品类型',
'db_table': 'shangpin_leixing',
},
),
migrations.CreateModel(
name='ShangpinZhuanqu',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='专区ID')),
('mingzi', models.CharField(blank=True, max_length=45, null=True, verbose_name='专区名称')),
('leixing_id', models.PositiveIntegerField(verbose_name='类型ID')),
],
options={
'verbose_name': '商品专区',
'verbose_name_plural': '商品专区',
'db_table': 'shangpin_zhuanqu',
},
),
migrations.CreateModel(
name='Czjilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('zhuangtai', models.IntegerField(blank=True, null=True, verbose_name='订单状态')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('jine', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='订单金额')),
('leixing', models.IntegerField(blank=True, null=True, verbose_name='充值类型,1:会员,2:押金,3:积分,4:商家')),
('shuoming', models.CharField(blank=True, max_length=100, null=True, verbose_name='订单说明')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '充值记录订单',
'verbose_name_plural': '充值记录订单',
'db_table': 'czjilu',
'indexes': [models.Index(fields=['dingdan_id'], name='czjilu_dingdan_39bbd0_idx'), models.Index(fields=['yonghuid'], name='czjilu_yonghui_a0555f_idx')],
},
),
migrations.CreateModel(
name='Gsfenhong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(max_length=32, unique=True, verbose_name='订单ID')),
('guanshi', models.CharField(db_index=True, max_length=7, verbose_name='管事ID')),
('dashouid', models.CharField(db_index=True, max_length=7, unique=True, verbose_name='打手ID')),
('shuoming', models.CharField(blank=True, max_length=100, null=True, verbose_name='订单说明')),
('fenhong', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='订单分红金额')),
('avatar', models.CharField(blank=True, max_length=500, null=True, verbose_name='打手头像')),
('nicheng', models.CharField(max_length=50, null=True, verbose_name='打手昵称')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '管事分红记录',
'verbose_name_plural': '管事分红记录',
'db_table': 'gsfenhong',
'indexes': [models.Index(fields=['guanshi'], name='gsfenhong_guanshi_dc440f_idx'), models.Index(fields=['dashouid'], name='gsfenhong_dashoui_5473ca_idx')],
},
),
]
# Generated by Django 4.2.27 on 2026-06-17 16:31
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Czjilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('zhuangtai', models.IntegerField(blank=True, null=True, verbose_name='订单状态')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('jine', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='订单金额')),
('leixing', models.IntegerField(blank=True, null=True, verbose_name='充值类型,1:会员,2:押金,3:积分,4:商家')),
('shuoming', models.CharField(blank=True, max_length=100, null=True, verbose_name='订单说明')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '充值记录订单',
'verbose_name_plural': '充值记录订单',
'db_table': 'czjilu',
},
),
migrations.CreateModel(
name='DuociFenhong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('huiyuan', models.CharField(max_length=10, verbose_name='会员ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='管事ID')),
('cishu', models.PositiveIntegerField(verbose_name='分红次数')),
('guanshi_fenhong', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='管事分红金额')),
('zuzhang_fenhong', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='组长分红金额')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '多次分红配置',
'verbose_name_plural': '多次分红配置',
'db_table': 'duoci_fenhong',
},
),
migrations.CreateModel(
name='Gsfenhong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(max_length=32, unique=True, verbose_name='订单ID')),
('guanshi', models.CharField(db_index=True, max_length=7, verbose_name='管事ID')),
('dashouid', models.CharField(db_index=True, max_length=7, verbose_name='打手ID')),
('shuoming', models.CharField(blank=True, max_length=100, null=True, verbose_name='订单说明')),
('fenhong', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='订单分红金额')),
('avatar', models.CharField(blank=True, max_length=500, null=True, verbose_name='打手头像')),
('nicheng', models.CharField(max_length=50, null=True, verbose_name='打手昵称')),
('zuzhang_id', models.CharField(blank=True, db_index=True, max_length=7, null=True, verbose_name='组长ID')),
('zuzhang_fenhong', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='组长分红金额')),
('fenhong_leixing', models.PositiveSmallIntegerField(choices=[(1, '会员分红'), (2, '押金分红'), (3, '商家订单分红')], default=1, verbose_name='分红类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '管事分红记录',
'verbose_name_plural': '管事分红记录',
'db_table': 'gsfenhong',
},
),
migrations.CreateModel(
name='Huiyuan',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('huiyuan_id', models.CharField(max_length=6, unique=True, verbose_name='会员ID')),
('jieshao', models.CharField(max_length=30, verbose_name='会员介绍')),
('jtjieshao', models.TextField(blank=True, null=True, verbose_name='会员规则介绍')),
('jiage', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='会员价格')),
('guanshifc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='管事分成')),
('zuzhangfc', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='组长分成')),
('goumai_cishu', models.PositiveIntegerField(default=0, verbose_name='购买次数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '会员',
'verbose_name_plural': '会员',
'db_table': 'huiyuan',
},
),
migrations.CreateModel(
name='Huiyuangoumai',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='购买记录ID')),
('huiyuan_id', models.CharField(db_index=True, max_length=6, verbose_name='会员ID')),
('yonghu_id', models.CharField(db_index=True, max_length=32, verbose_name='用户ID')),
('huiyuan_zhuangtai', models.PositiveIntegerField(default=1, verbose_name='会员状态')),
('jieshao', models.CharField(max_length=30, null=True, verbose_name='会员介绍')),
('daoqi_time', models.DateTimeField(verbose_name='会员到期时间')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '用户购买会员',
'verbose_name_plural': '用户购买会员',
'db_table': 'huiyuangoumai',
},
),
migrations.CreateModel(
name='Shangpin',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='商品ID')),
('biaoqian', models.CharField(blank=True, max_length=45, null=True, verbose_name='商品标题')),
('jiage', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='商品价格')),
('kucun', models.PositiveIntegerField(default=0, verbose_name='商品库存')),
('leixing_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='商品类型ID')),
('zhuanqu_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='商品专区ID')),
('zhenshi_xiaoliang', models.PositiveIntegerField(default=0, verbose_name='商品真实销量')),
('duiwai_xiaoliang', models.PositiveIntegerField(default=0, verbose_name='商品对外销量')),
('jieshao', models.TextField(blank=True, null=True, verbose_name='商品介绍')),
('xiadan_xuzhi', models.TextField(blank=True, null=True, verbose_name='下单须知')),
('guize_tupian', models.CharField(blank=True, max_length=500, null=True, verbose_name='规则图片URL')),
('yaoqiuleixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='抢单要求类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('yongjin', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金要求')),
('kaioi_ewai_dashou_fencheng', models.BooleanField(default=False, verbose_name='是否开启打手额外分成')),
('ewai_dashou_fencheng', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='打手额外分成金额')),
('tupian_url', models.CharField(blank=True, max_length=500, null=True, verbose_name='商品图片URL')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更改时间')),
('paixu', models.IntegerField(default=0, verbose_name='排序权重')),
('shenhezhuangtai', models.IntegerField(default=1, help_text='1=正常, 2=审核专用', verbose_name='审核状态')),
('shangjia_zhuangtai', models.BooleanField(default=True, verbose_name='是否上架')),
('fengjin_zhuangtai', models.BooleanField(default=True, verbose_name='是否封禁')),
('shenhe_zhuangtai', models.BooleanField(default=False, help_text='True=审核通过,False=未审核', verbose_name='平台审核状态')),
],
options={
'verbose_name': '商品',
'verbose_name_plural': '商品',
'db_table': 'shangpin',
},
),
migrations.CreateModel(
name='ShangpinLeixing',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='类型ID')),
('yaoqiuleixing', models.PositiveIntegerField(blank=True, null=True, verbose_name='抢单要求类型')),
('huiyuan_id', models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID')),
('yongjin', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='佣金要求')),
('jieshao', models.CharField(blank=True, max_length=45, null=True, verbose_name='类型介绍')),
('tupian_url', models.CharField(blank=True, max_length=500, null=True, verbose_name='类型图片URL')),
('paixu', models.IntegerField(default=0, verbose_name='排序权重')),
('shenhezhuangtai', models.IntegerField(default=1, help_text='1=正常, 2=审核专用', verbose_name='审核状态')),
],
options={
'verbose_name': '商品类型',
'verbose_name_plural': '商品类型',
'db_table': 'shangpin_leixing',
},
),
migrations.CreateModel(
name='ShangpinMeiriTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('riqi', models.DateField(db_index=True, verbose_name='统计日期')),
('nian', models.PositiveSmallIntegerField(verbose_name='年份')),
('yue', models.PositiveSmallIntegerField(verbose_name='月份')),
('ri', models.PositiveSmallIntegerField(verbose_name='日')),
('diandan_zongliang', models.PositiveIntegerField(default=0, verbose_name='点单总量')),
('diandan_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='点单总额')),
('chengjiao_zongliang', models.PositiveIntegerField(default=0, verbose_name='成交总量')),
('chengjiao_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='成交总额')),
('tuikuan_zongliang', models.PositiveIntegerField(default=0, verbose_name='退款总量')),
('tuikuan_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='退款总额')),
('pingtai_shouyi', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='平台收益')),
('dianpu_zongshouyi', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='店铺总收益')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
],
options={
'verbose_name': '商品每日统计',
'verbose_name_plural': '商品每日统计',
'db_table': 'shangpin_meiri_tongji',
},
),
migrations.CreateModel(
name='ShangpinZhuanqu',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='专区ID')),
('mingzi', models.CharField(blank=True, max_length=45, null=True, verbose_name='专区名称')),
('leixing_id', models.PositiveIntegerField(verbose_name='类型ID')),
('paixu', models.IntegerField(default=0, verbose_name='排序权重')),
('shenhezhuangtai', models.IntegerField(default=1, help_text='1=正常, 2=审核专用', verbose_name='审核状态')),
('shangjia_zhuangtai', models.BooleanField(default=True, verbose_name='是否上架')),
('fengjin_zhuangtai', models.BooleanField(default=True, verbose_name='是否封禁')),
],
options={
'verbose_name': '商品专区',
'verbose_name_plural': '商品专区',
'db_table': 'shangpin_zhuanqu',
},
),
]
@@ -1,29 +0,0 @@
# Generated by Django 4.2.27 on 2026-01-18 14:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0001_initial'),
]
operations = [
migrations.AlterUniqueTogether(
name='huiyuangoumai',
unique_together={('yonghu_id', 'huiyuan_id')},
),
migrations.AddIndex(
model_name='huiyuangoumai',
index=models.Index(fields=['yonghu_id'], name='huiyuangoum_yonghu__ba2138_idx'),
),
migrations.AddIndex(
model_name='huiyuangoumai',
index=models.Index(fields=['huiyuan_id'], name='huiyuangoum_huiyuan_35fe1d_idx'),
),
migrations.AddIndex(
model_name='huiyuangoumai',
index=models.Index(fields=['yonghu_id', 'huiyuan_id'], name='huiyuangoum_yonghu__21e6e1_idx'),
),
]
+2 -2
View File
@@ -1,4 +1,4 @@
# Generated by Django 4.2.27 on 2026-06-17 01:32
# Generated by Django 4.2.27 on 2026-06-17 16:31
from django.db import migrations, models
import django.db.models.deletion
@@ -9,8 +9,8 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('rank', '0001_initial'),
('products', '0001_initial'),
('rank', '0001_initial'),
('shop', '0001_initial'),
]
@@ -1,33 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-07 19:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0002_alter_huiyuangoumai_unique_together_and_more'),
]
operations = [
migrations.AddField(
model_name='shangpin',
name='paixu',
field=models.IntegerField(default=0, verbose_name='排序权重'),
),
migrations.AddField(
model_name='shangpinleixing',
name='paixu',
field=models.IntegerField(default=0, verbose_name='排序权重'),
),
migrations.AddField(
model_name='shangpinleixing',
name='shenhezhuangtai',
field=models.IntegerField(default=1, help_text='1=正常, 2=审核专用', verbose_name='审核状态'),
),
migrations.AddField(
model_name='shangpinzhuanqu',
name='paixu',
field=models.IntegerField(default=0, verbose_name='排序权重'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-09 15:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0003_shangpin_paixu_shangpinleixing_paixu_and_more'),
]
operations = [
migrations.AddField(
model_name='shangpin',
name='shenhezhuangtai',
field=models.IntegerField(default=1, help_text='1=正常, 2=审核专用', verbose_name='审核状态'),
),
migrations.AddField(
model_name='shangpinzhuanqu',
name='shenhezhuangtai',
field=models.IntegerField(default=1, help_text='1=正常, 2=审核专用', verbose_name='审核状态'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-02-27 15:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0004_shangpin_shenhezhuangtai_and_more'),
]
operations = [
migrations.AlterField(
model_name='gsfenhong',
name='dashouid',
field=models.CharField(db_index=True, max_length=7, verbose_name='打手ID'),
),
]
@@ -1,45 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-18 12:09
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('products', '0005_alter_gsfenhong_dashouid'),
]
operations = [
migrations.AddField(
model_name='gsfenhong',
name='huiyuan_id',
field=models.CharField(blank=True, max_length=6, null=True, verbose_name='会员ID'),
),
migrations.AddField(
model_name='huiyuan',
name='zuzhangfc',
field=models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='组长分成'),
),
migrations.CreateModel(
name='DuociFenhong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('guanshi', models.CharField(db_index=True, max_length=7, verbose_name='管事ID')),
('zuzhang', models.CharField(blank=True, db_index=True, max_length=7, null=True, verbose_name='组长ID')),
('cishu', models.PositiveIntegerField(verbose_name='分红次数')),
('guanshi_fenhong', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='管事分红金额')),
('zuzhang_fenhong', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='组长分红金额')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('huiyuan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.huiyuan', verbose_name='会员')),
],
options={
'verbose_name': '多次分红配置',
'verbose_name_plural': '多次分红配置',
'db_table': 'duoci_fenhong',
'indexes': [models.Index(fields=['guanshi'], name='duoci_fenho_guanshi_b3de53_idx'), models.Index(fields=['zuzhang'], name='duoci_fenho_zuzhang_69997d_idx')],
'unique_together': {('huiyuan', 'guanshi', 'cishu')},
},
),
]
@@ -1,47 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-19 13:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0006_gsfenhong_huiyuan_id_huiyuan_zuzhangfc_duocifenhong'),
]
operations = [
migrations.RemoveIndex(
model_name='duocifenhong',
name='duoci_fenho_guanshi_b3de53_idx',
),
migrations.RemoveIndex(
model_name='duocifenhong',
name='duoci_fenho_zuzhang_69997d_idx',
),
migrations.RenameField(
model_name='duocifenhong',
old_name='guanshi',
new_name='yonghuid',
),
migrations.AlterUniqueTogether(
name='duocifenhong',
unique_together=set(),
),
migrations.AlterField(
model_name='duocifenhong',
name='huiyuan',
field=models.CharField(max_length=10, verbose_name='会员ID'),
),
migrations.AlterUniqueTogether(
name='duocifenhong',
unique_together={('huiyuan', 'yonghuid', 'cishu')},
),
migrations.AddIndex(
model_name='duocifenhong',
index=models.Index(fields=['yonghuid'], name='duoci_fenho_yonghui_db6a2f_idx'),
),
migrations.RemoveField(
model_name='duocifenhong',
name='zuzhang',
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-19 13:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0007_remove_duocifenhong_duoci_fenho_guanshi_b3de53_idx_and_more'),
]
operations = [
migrations.AddField(
model_name='gsfenhong',
name='zuzhang_fenhong',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='组长分红金额'),
),
migrations.AddField(
model_name='gsfenhong',
name='zuzhang_id',
field=models.CharField(blank=True, db_index=True, max_length=7, null=True, verbose_name='组长ID'),
),
]
@@ -1,23 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-22 15:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0008_gsfenhong_zuzhang_fenhong_gsfenhong_zuzhang_id'),
]
operations = [
migrations.AddField(
model_name='shangpin',
name='ewai_dashou_fencheng',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='打手额外分成金额'),
),
migrations.AddField(
model_name='shangpin',
name='kaioi_ewai_dashou_fencheng',
field=models.BooleanField(default=False, verbose_name='是否开启打手额外分成'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-03-24 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0009_shangpin_ewai_dashou_fencheng_and_more'),
]
operations = [
migrations.AddField(
model_name='shangpinleixing',
name='is_cross_enabled',
field=models.BooleanField(default=False, verbose_name='是否开启平台互通'),
),
]
@@ -1,60 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-21 12:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('shop', '0001_initial'),
('products', '0010_shangpinleixing_is_cross_enabled'),
]
operations = [
migrations.AddField(
model_name='shangpin',
name='dianpu',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='shop.dianpu', verbose_name='所属店铺'),
),
migrations.AddField(
model_name='shangpin',
name='dianpu_leixing',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='shop.shangpinleixingdianpu', verbose_name='店铺商品类型'),
),
migrations.AddField(
model_name='shangpin',
name='fengjin_zhuangtai',
field=models.BooleanField(default=True, verbose_name='是否封禁'),
),
migrations.AddField(
model_name='shangpin',
name='shangjia_zhuangtai',
field=models.BooleanField(default=True, verbose_name='是否上架'),
),
migrations.AddField(
model_name='shangpin',
name='shenhe_zhuangtai',
field=models.BooleanField(default=False, help_text='True=审核通过,False=未审核', verbose_name='平台审核状态'),
),
migrations.AddField(
model_name='shangpinzhuanqu',
name='dianpu',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='shop.dianpu', verbose_name='所属店铺'),
),
migrations.AddField(
model_name='shangpinzhuanqu',
name='dianpu_leixing',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='shop.shangpinleixingdianpu', verbose_name='店铺商品类型'),
),
migrations.AddField(
model_name='shangpinzhuanqu',
name='fengjin_zhuangtai',
field=models.BooleanField(default=True, verbose_name='是否封禁'),
),
migrations.AddField(
model_name='shangpinzhuanqu',
name='shangjia_zhuangtai',
field=models.BooleanField(default=True, verbose_name='是否上架'),
),
]
@@ -1,42 +0,0 @@
# Generated by Django 4.2.27 on 2026-04-23 14:56
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('products', '0011_shangpin_dianpu_shangpin_dianpu_leixing_and_more'),
]
operations = [
migrations.CreateModel(
name='ShangpinMeiriTongji',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('riqi', models.DateField(db_index=True, verbose_name='统计日期')),
('nian', models.PositiveSmallIntegerField(verbose_name='年份')),
('yue', models.PositiveSmallIntegerField(verbose_name='月份')),
('ri', models.PositiveSmallIntegerField(verbose_name='日')),
('diandan_zongliang', models.PositiveIntegerField(default=0, verbose_name='点单总量')),
('diandan_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='点单总额')),
('chengjiao_zongliang', models.PositiveIntegerField(default=0, verbose_name='成交总量')),
('chengjiao_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='成交总额')),
('tuikuan_zongliang', models.PositiveIntegerField(default=0, verbose_name='退款总量')),
('tuikuan_zonge', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='退款总额')),
('pingtai_shouyi', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='平台收益')),
('dianpu_zongshouyi', models.DecimalField(decimal_places=2, default=0.0, max_digits=12, verbose_name='店铺总收益')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('shangpin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.shangpin', verbose_name='商品ID')),
],
options={
'verbose_name': '商品每日统计',
'verbose_name_plural': '商品每日统计',
'db_table': 'shangpin_meiri_tongji',
'indexes': [models.Index(fields=['shangpin', 'riqi'], name='shangpin_me_shangpi_d27e5c_idx'), models.Index(fields=['nian', 'yue', 'ri'], name='shangpin_me_nian_e3b409_idx')],
'unique_together': {('shangpin', 'riqi')},
},
),
]
@@ -1,20 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-14 04:25
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0003_alter_dashoubiaoxian_bankuai'),
('products', '0012_shangpinmeiritongji'),
]
operations = [
migrations.AddField(
model_name='shangpinleixing',
name='bankuai',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='rank.bankuai', verbose_name='所属板块'),
),
]
@@ -1,20 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-16 16:51
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0010_kaohejilufeiyong'),
('products', '0013_shangpinleixing_bankuai'),
]
operations = [
migrations.AddField(
model_name='huiyuan',
name='bankuai',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='rank.bankuai', verbose_name='所属板块'),
),
]
@@ -1,18 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-12 01:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('products', '0014_huiyuan_bankuai'),
]
operations = [
migrations.AddField(
model_name='gsfenhong',
name='fenhong_leixing',
field=models.PositiveSmallIntegerField(choices=[(1, '会员分红'), (2, '押金分红'), (3, '商家订单分红')], default=1, verbose_name='分红类型'),
),
]
@@ -1,17 +0,0 @@
# Generated by Django 4.2.27 on 2026-06-15 01:42
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('products', '0015_gsfenhong_fenhong_leixing'),
]
operations = [
migrations.RemoveField(
model_name='shangpinleixing',
name='is_cross_enabled',
),
]
+4 -3
View File
@@ -46,8 +46,9 @@ from .models import (
Czjilu, Gsfenhong, Huiyuangoumai, DuociFenhong
)
from users.models import (
UserMain, AdminProfile, UserDashou, UserGuanshi, UserZuzhang, UserShangjia
AdminProfile, UserDashou, UserGuanshi, UserZuzhang, UserShangjia
)
from gvsdsdk.models import User
from orders.models import Lilubiao
from config.models import Szjilu, Gonggao, Lunbo
@@ -5945,7 +5946,7 @@ class ZuzhangFenhongView(APIView):
return {}
# 查询用户主表,并预加载 boss_profile
users = UserMain.query.filter(yonghuid__in=guanshi_ids).select_related(
users = User.query.filter(yonghuid__in=guanshi_ids).select_related(
'boss_profile'
).only(
'yonghuid', 'avatar',
@@ -6008,7 +6009,7 @@ class CzhqdyView(APIView):
{
'id': 1,
'name': '打手佣金抵扣',
'profile_attr': 'dashou_profile', # UserMain 的反向 related_name
'profile_attr': 'dashou_profile', # User 的反向 related_name
'balance_field': 'yue',
'rate_key': '5',
'model': UserDashou,
+277 -111
View File
@@ -1,111 +1,277 @@
# Generated by Django 4.2.27 on 2026-05-12 02:17
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('orders', '0026_fadanfenhonglilv_alter_fadan_shenqingren_shenfen_and_more'),
]
operations = [
migrations.CreateModel(
name='Bankuai',
fields=[
('bankuai_id', models.AutoField(primary_key=True, serialize=False, verbose_name='板块ID')),
('mingcheng', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='板块名称')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '板块',
'verbose_name_plural': '板块',
'db_table': 'bankuai',
},
),
migrations.CreateModel(
name='Chenghao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('mingcheng', models.CharField(max_length=50, unique=True, verbose_name='称号名称')),
('leixing', models.CharField(choices=[('dashou', '打手'), ('boss', '老板'), ('shangjia', '商家'), ('guanshi', '管事'), ('zuzhang', '组长')], max_length=10, verbose_name='称号类型')),
('tubiao_url', models.CharField(blank=True, max_length=200, null=True, verbose_name='称号图标相对URL')),
('texiao_miaoshu', models.TextField(blank=True, null=True, verbose_name='特效描述(JSON)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('bankuai', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块(空=全板块通用)')),
],
options={
'verbose_name': '称号',
'verbose_name_plural': '称号',
'db_table': 'chenghao',
},
),
migrations.CreateModel(
name='YonghuChenghao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('huode_time', models.DateTimeField(auto_now_add=True, verbose_name='获得时间')),
('chenghao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.chenghao', verbose_name='称号')),
('yonghu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chenghao_list', to=settings.AUTH_USER_MODEL, verbose_name='用户')),
],
options={
'verbose_name': '用户称号关联',
'verbose_name_plural': '用户称号关联',
'db_table': 'yonghu_chenghao',
'indexes': [models.Index(fields=['yonghu', 'chenghao'], name='yonghu_chen_yonghu__cac0a1_idx')],
'unique_together': {('yonghu', 'chenghao')},
},
),
migrations.CreateModel(
name='JingyanJilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('yonghu_leixing', models.CharField(choices=[('dashou', '打手'), ('boss', '老板'), ('shangjia', '商家'), ('guanshi', '管事'), ('zuzhang', '组长')], max_length=10, verbose_name='用户类型')),
('sudu_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='上线速度经验')),
('shili_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='打手实力经验')),
('taidu_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='服务态度经验')),
('zonghe_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='综合经验')),
('dingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='关联订单ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('bankuai', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块')),
],
options={
'verbose_name': '经验变动记录',
'verbose_name_plural': '经验变动记录',
'db_table': 'jingyan_jilu',
'indexes': [models.Index(fields=['yonghu_id', 'bankuai', 'create_time'], name='jingyan_jil_yonghu__786992_idx')],
},
),
migrations.CreateModel(
name='DashouBiaoxian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dashou_id', models.CharField(db_index=True, max_length=32, verbose_name='打手ID')),
('shangxian_sudu', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='上线速度评价(1-5)')),
('fuwu_taidu', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='服务态度评价(1-5)')),
('fanche_cishu', models.PositiveIntegerField(blank=True, null=True, verbose_name='翻车次数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('jiedan_time', models.DateTimeField(blank=True, null=True, verbose_name='接单时间')),
('tijiao_time', models.DateTimeField(blank=True, null=True, verbose_name='提交时间')),
('bankuai', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块')),
('dingdan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='biaoxian', to='orders.dingdan', verbose_name='关联订单')),
],
options={
'verbose_name': '打手订单表现',
'verbose_name_plural': '打手订单表现',
'db_table': 'dashou_biaoxian',
'indexes': [models.Index(fields=['dashou_id', 'bankuai', 'create_time'], name='dashou_biao_dashou__36e1c3_idx')],
},
),
migrations.AddIndex(
model_name='chenghao',
index=models.Index(fields=['leixing', 'bankuai'], name='chenghao_leixing_8f4371_idx'),
),
]
# Generated by Django 4.2.27 on 2026-06-17 16:31
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('orders', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Bankuai',
fields=[
('bankuai_id', models.AutoField(primary_key=True, serialize=False, verbose_name='板块ID')),
('mingcheng', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='板块名称')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '板块',
'verbose_name_plural': '板块',
'db_table': 'bankuai',
},
),
migrations.CreateModel(
name='Chenghao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('mingcheng', models.CharField(max_length=50, unique=True, verbose_name='称号名称')),
('leixing', models.CharField(choices=[('dashou', '打手'), ('boss', '老板'), ('shangjia', '商家'), ('guanshi', '管事'), ('zuzhang', '组长')], max_length=10, verbose_name='称号类型')),
('tubiao_url', models.CharField(blank=True, max_length=200, null=True, verbose_name='称号图标相对URL')),
('texiao_miaoshu', models.TextField(blank=True, null=True, verbose_name='特效描述(JSON)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('kaohe_guize', models.TextField(blank=True, null=True, verbose_name='考核规则')),
('kaioi_jinpai', models.BooleanField(default=False, verbose_name='是否同时开启金牌')),
('bankuai', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块(空=全板块通用)')),
],
options={
'verbose_name': '称号',
'verbose_name_plural': '称号',
'db_table': 'chenghao',
},
),
migrations.CreateModel(
name='KaohePayTemp',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='订单ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('tag_id', models.IntegerField(verbose_name='标签ID')),
('game_nick', models.CharField(max_length=100, verbose_name='游戏昵称')),
('remark', models.TextField(blank=True, verbose_name='备注')),
('reapply', models.BooleanField(default=False, verbose_name='是否再次申请')),
('jilu_id', models.CharField(blank=True, max_length=32, null=True, verbose_name='原记录ID(再次申请时)')),
('shenheguan_id', models.CharField(blank=True, max_length=7, verbose_name='指定考核官ID')),
('cishu', models.IntegerField(verbose_name='本次考核次数(预计算)')),
('fee', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='本次费用(分账单位)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '考核支付临时表',
'verbose_name_plural': '考核支付临时表',
'db_table': 'kaohe_pay_temp',
},
),
migrations.CreateModel(
name='ShenheJilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('shenqingren_id', models.CharField(max_length=7, verbose_name='申请人用户ID')),
('shenheguan_id', models.CharField(max_length=7, null=True, verbose_name='审核官用户ID')),
('zhuangtai', models.IntegerField(choices=[(0, '审核中'), (1, '通过'), (2, '未通过'), (3, '待审核')], default=0, verbose_name='审核状态')),
('cishu', models.IntegerField(default=1, verbose_name='第几次审核')),
('jiaofei_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='缴纳费用')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('jilu_id', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='记录ID')),
('guize_neirong', models.TextField(blank=True, null=True, verbose_name='规则内容')),
('shenheguan_youxi_id', models.CharField(blank=True, max_length=50, null=True, verbose_name='审核官游戏ID')),
('dashou_youxi_id', models.CharField(blank=True, max_length=50, null=True, verbose_name='打手游戏ID')),
('dashou_beizhu', models.TextField(blank=True, null=True, verbose_name='打手备注')),
('bankuai', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='审核板块')),
('chenghao', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.chenghao', verbose_name='审核标签')),
],
options={
'verbose_name': '审核记录',
'verbose_name_plural': '审核记录',
'db_table': 'shenhe_jilu',
},
),
migrations.CreateModel(
name='KaoheJujueJilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cishu', models.IntegerField(verbose_name='对应次数')),
('shenheguan_id', models.CharField(max_length=7, verbose_name='考核官用户ID')),
('yuanyin', models.TextField(verbose_name='拒绝原因')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('jilu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.shenhejilu', to_field='jilu_id', verbose_name='审核记录')),
],
options={
'verbose_name': '拒绝原因记录',
'verbose_name_plural': '拒绝原因记录',
'db_table': 'kaohe_jujue_jilu',
},
),
migrations.CreateModel(
name='KaoheJiluFeiyong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cishu', models.IntegerField(verbose_name='第几次考核')),
('jine', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='缴纳金额')),
('jilu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.shenhejilu', to_field='jilu_id', verbose_name='考核记录')),
],
options={
'verbose_name': '考核记录费用',
'verbose_name_plural': '考核记录费用',
'db_table': 'kaohe_jilu_feiyong',
},
),
migrations.CreateModel(
name='KaoheguanBankuai',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('kaoheguan_id', models.CharField(db_index=True, max_length=7, verbose_name='考核官用户ID')),
('bankuai', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.bankuai', verbose_name='所属板块')),
],
options={
'verbose_name': '考核官板块关联',
'verbose_name_plural': '考核官板块关联',
'db_table': 'kaoheguan_bankuai',
},
),
migrations.CreateModel(
name='KaoheCishuFeiyong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cishu', models.IntegerField(verbose_name='第几次考核')),
('feiyong', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='需缴纳金额')),
('chenghao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.chenghao', verbose_name='标签')),
],
options={
'verbose_name': '考核次数费用',
'verbose_name_plural': '考核次数费用',
'db_table': 'kaohe_cishu_feiyong',
},
),
migrations.CreateModel(
name='JingyanJilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('yonghu_leixing', models.CharField(choices=[('dashou', '打手'), ('boss', '老板'), ('shangjia', '商家'), ('guanshi', '管事'), ('zuzhang', '组长')], max_length=10, verbose_name='用户类型')),
('sudu_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='上线速度经验')),
('shili_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='打手实力经验')),
('taidu_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='服务态度经验')),
('zonghe_jingyan', models.DecimalField(decimal_places=2, default=0, max_digits=8, verbose_name='综合经验')),
('dingdan_id', models.CharField(blank=True, db_index=True, max_length=32, null=True, verbose_name='关联订单ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('bankuai', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块')),
],
options={
'verbose_name': '经验变动记录',
'verbose_name_plural': '经验变动记录',
'db_table': 'jingyan_jilu',
},
),
migrations.CreateModel(
name='DingdanBiaoqian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('chenghao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.chenghao', verbose_name='标签')),
('dingdan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='orders.dingdan', to_field='dingdan_id', verbose_name='订单')),
],
options={
'verbose_name': '订单需求标签',
'verbose_name_plural': '订单需求标签',
'db_table': 'dingdan_biaoqian',
},
),
migrations.CreateModel(
name='DashouBiaoxian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dashou_id', models.CharField(db_index=True, max_length=32, verbose_name='打手ID')),
('shangxian_sudu', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='上线速度评价(1-5)')),
('fuwu_taidu', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='服务态度评价(1-5)')),
('fanche_cishu', models.PositiveIntegerField(blank=True, null=True, verbose_name='翻车次数')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('jiedan_time', models.DateTimeField(blank=True, null=True, verbose_name='接单时间')),
('tijiao_time', models.DateTimeField(blank=True, null=True, verbose_name='提交时间')),
('bankuai', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块')),
('dingdan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='biaoxian', to='orders.dingdan', to_field='dingdan_id', verbose_name='关联订单')),
],
options={
'verbose_name': '打手订单表现',
'verbose_name_plural': '打手订单表现',
'db_table': 'dashou_biaoxian',
},
),
migrations.CreateModel(
name='YonghuChenghao',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('huode_time', models.DateTimeField(auto_now_add=True, verbose_name='获得时间')),
('chenghao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.chenghao', verbose_name='称号')),
('yonghu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chenghao_list', to=settings.AUTH_USER_MODEL, verbose_name='用户')),
],
options={
'verbose_name': '用户称号关联',
'verbose_name_plural': '用户称号关联',
'db_table': 'yonghu_chenghao',
'indexes': [models.Index(fields=['yonghu', 'chenghao'], name='yonghu_chen_yonghu__cac0a1_idx')],
'unique_together': {('yonghu', 'chenghao')},
},
),
migrations.AddIndex(
model_name='shenhejilu',
index=models.Index(fields=['shenqingren_id', 'zhuangtai'], name='shenhe_jilu_shenqin_502e9b_idx'),
),
migrations.AddIndex(
model_name='shenhejilu',
index=models.Index(fields=['shenheguan_id'], name='shenhe_jilu_shenheg_5c9959_idx'),
),
migrations.AddIndex(
model_name='kaohejujuejilu',
index=models.Index(fields=['jilu_id', 'cishu'], name='kaohe_jujue_jilu_id_1f2b29_idx'),
),
migrations.AlterUniqueTogether(
name='kaohejilufeiyong',
unique_together={('jilu', 'cishu')},
),
migrations.AddIndex(
model_name='kaoheguanbankuai',
index=models.Index(fields=['kaoheguan_id'], name='kaoheguan_b_kaohegu_00f7c5_idx'),
),
migrations.AlterUniqueTogether(
name='kaoheguanbankuai',
unique_together={('kaoheguan_id', 'bankuai')},
),
migrations.AddIndex(
model_name='kaohecishufeiyong',
index=models.Index(fields=['chenghao', 'cishu'], name='kaohe_cishu_chengha_edc272_idx'),
),
migrations.AlterUniqueTogether(
name='kaohecishufeiyong',
unique_together={('chenghao', 'cishu')},
),
migrations.AddIndex(
model_name='jingyanjilu',
index=models.Index(fields=['yonghu_id', 'bankuai', 'create_time'], name='jingyan_jil_yonghu__786992_idx'),
),
migrations.AddIndex(
model_name='dingdanbiaoqian',
index=models.Index(fields=['dingdan'], name='dingdan_bia_dingdan_4d046b_idx'),
),
migrations.AlterUniqueTogether(
name='dingdanbiaoqian',
unique_together={('dingdan', 'chenghao')},
),
migrations.AddIndex(
model_name='dashoubiaoxian',
index=models.Index(fields=['dashou_id', 'bankuai', 'create_time'], name='dashou_biao_dashou__36e1c3_idx'),
),
migrations.AddIndex(
model_name='chenghao',
index=models.Index(fields=['leixing', 'bankuai'], name='chenghao_leixing_8f4371_idx'),
),
]
@@ -1,20 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-12 02:25
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('orders', '0026_fadanfenhonglilv_alter_fadan_shenqingren_shenfen_and_more'),
('rank', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='dashoubiaoxian',
name='dingdan',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='biaoxian', to='orders.dingdan', to_field='dingdan_id', verbose_name='关联订单'),
),
]
@@ -1,19 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-12 02:32
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0002_alter_dashoubiaoxian_dingdan'),
]
operations = [
migrations.AlterField(
model_name='dashoubiaoxian',
name='bankuai',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='所属板块'),
),
]
-26
View File
@@ -1,26 +0,0 @@
# dengji/migrations/0004_dingdanbiaoqian.py
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('orders', '0026_fadanfenhonglilv_alter_fadan_shenqingren_shenfen_and_more'), # 保持你之前的依赖
('rank', '0003_alter_dashoubiaoxian_bankuai'),
]
operations = [
migrations.RunSQL(
sql="""
CREATE TABLE IF NOT EXISTS dingdan_biaoqian (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
create_time DATETIME(6) NOT NULL,
chenghao_id BIGINT NOT NULL,
dingdan_id VARCHAR(32) NOT NULL,
CONSTRAINT fk_dingdanbiaoqian_chenghao FOREIGN KEY (chenghao_id) REFERENCES chenghao (id),
CONSTRAINT fk_dingdanbiaoqian_dingdan FOREIGN KEY (dingdan_id) REFERENCES dingdan (dingdan_id),
UNIQUE KEY uniq_dingdan_chenghao (dingdan_id, chenghao_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
""",
reverse_sql="DROP TABLE IF EXISTS dingdan_biaoqian;"
),
]
-36
View File
@@ -1,36 +0,0 @@
# dengji/migrations/0005_fix_state.py
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('orders', '0026_fadanfenhonglilv_alter_fadan_shenqingren_shenfen_and_more'), # 保持你之前的依赖
('rank', '0004_dingdanbiaoqian'),
]
operations = [
migrations.SeparateDatabaseAndState(
database_operations=[], # 表已存在,不做任何数据库操作
state_operations=[
migrations.CreateModel(
name='DingdanBiaoqian',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('chenghao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.chenghao', verbose_name='标签')),
('dingdan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='orders.dingdan', to_field='dingdan_id', verbose_name='订单')),
],
options={
'verbose_name': '订单需求标签',
'verbose_name_plural': '订单需求标签',
'db_table': 'dingdan_biaoqian',
'unique_together': {('dingdan', 'chenghao')},
'indexes': [
models.Index(fields=['dingdan'], name='dingdan_bia_dingdan_4d046b_idx'),
],
},
),
],
),
]
-35
View File
@@ -1,35 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-14 18:42
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0005_fix_state'),
]
operations = [
migrations.CreateModel(
name='ShenheJilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('shenqingren_id', models.CharField(max_length=7, verbose_name='申请人用户ID')),
('shenheguan_id', models.CharField(max_length=7, null=True, verbose_name='审核官用户ID')),
('zhuangtai', models.IntegerField(choices=[(0, '审核中'), (1, '通过'), (2, '未通过')], default=0, verbose_name='审核状态')),
('cishu', models.IntegerField(default=1, verbose_name='第几次审核')),
('jiaofei_jine', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='缴纳费用')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('bankuai', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.bankuai', verbose_name='审核板块')),
('chenghao', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='rank.chenghao', verbose_name='审核标签')),
],
options={
'verbose_name': '审核记录',
'verbose_name_plural': '审核记录',
'db_table': 'shenhe_jilu',
'indexes': [models.Index(fields=['shenqingren_id', 'zhuangtai'], name='shenhe_jilu_shenqin_502e9b_idx'), models.Index(fields=['shenheguan_id'], name='shenhe_jilu_shenheg_5c9959_idx')],
},
),
]
-29
View File
@@ -1,29 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-15 00:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0006_shenhejilu'),
]
operations = [
migrations.CreateModel(
name='KaoheguanBankuai',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('kaoheguan_id', models.CharField(db_index=True, max_length=7, verbose_name='考核官用户ID')),
('bankuai', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.bankuai', verbose_name='所属板块')),
],
options={
'verbose_name': '考核官板块关联',
'verbose_name_plural': '考核官板块关联',
'db_table': 'kaoheguan_bankuai',
'indexes': [models.Index(fields=['kaoheguan_id'], name='kaoheguan_b_kaohegu_00f7c5_idx')],
'unique_together': {('kaoheguan_id', 'bankuai')},
},
),
]
@@ -1,48 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-15 04:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rank', '0007_kaoheguanbankuai'),
]
operations = [
migrations.AddField(
model_name='chenghao',
name='kaohe_guize',
field=models.TextField(blank=True, null=True, verbose_name='考核规则'),
),
migrations.AddField(
model_name='shenhejilu',
name='dashou_beizhu',
field=models.TextField(blank=True, null=True, verbose_name='打手备注'),
),
migrations.AddField(
model_name='shenhejilu',
name='dashou_youxi_id',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='打手游戏ID'),
),
migrations.AddField(
model_name='shenhejilu',
name='guize_neirong',
field=models.TextField(blank=True, null=True, verbose_name='规则内容'),
),
migrations.AddField(
model_name='shenhejilu',
name='jilu_id',
field=models.CharField(db_index=True, max_length=32, null=True, verbose_name='记录ID'),
),
migrations.AddField(
model_name='shenhejilu',
name='shenheguan_youxi_id',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='审核官游戏ID'),
),
migrations.AlterField(
model_name='shenhejilu',
name='zhuangtai',
field=models.IntegerField(choices=[(0, '审核中'), (1, '通过'), (2, '未通过'), (3, '待审核')], default=0, verbose_name='审核状态'),
),
]
@@ -1,58 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-15 13:20
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0008_chenghao_kaohe_guize_shenhejilu_dashou_beizhu_and_more'),
]
operations = [
migrations.AddField(
model_name='chenghao',
name='kaioi_jinpai',
field=models.BooleanField(default=False, verbose_name='是否同时开启金牌'),
),
migrations.AlterField(
model_name='shenhejilu',
name='jilu_id',
field=models.CharField(db_index=True, default='Sh111', max_length=32, unique=True, verbose_name='记录ID'),
preserve_default=False,
),
migrations.CreateModel(
name='KaoheJujueJilu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cishu', models.IntegerField(verbose_name='对应次数')),
('shenheguan_id', models.CharField(max_length=7, verbose_name='考核官用户ID')),
('yuanyin', models.TextField(verbose_name='拒绝原因')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('jilu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.shenhejilu', to_field='jilu_id', verbose_name='审核记录')),
],
options={
'verbose_name': '拒绝原因记录',
'verbose_name_plural': '拒绝原因记录',
'db_table': 'kaohe_jujue_jilu',
'indexes': [models.Index(fields=['jilu_id', 'cishu'], name='kaohe_jujue_jilu_id_1f2b29_idx')],
},
),
migrations.CreateModel(
name='KaoheCishuFeiyong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cishu', models.IntegerField(verbose_name='第几次考核')),
('feiyong', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='需缴纳金额')),
('chenghao', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.chenghao', verbose_name='标签')),
],
options={
'verbose_name': '考核次数费用',
'verbose_name_plural': '考核次数费用',
'db_table': 'kaohe_cishu_feiyong',
'indexes': [models.Index(fields=['chenghao', 'cishu'], name='kaohe_cishu_chengha_edc272_idx')],
'unique_together': {('chenghao', 'cishu')},
},
),
]
-29
View File
@@ -1,29 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-15 16:10
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rank', '0009_chenghao_kaioi_jinpai_alter_shenhejilu_jilu_id_and_more'),
]
operations = [
migrations.CreateModel(
name='KaoheJiluFeiyong',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cishu', models.IntegerField(verbose_name='第几次考核')),
('jine', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='缴纳金额')),
('jilu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rank.shenhejilu', to_field='jilu_id', verbose_name='考核记录')),
],
options={
'verbose_name': '考核记录费用',
'verbose_name_plural': '考核记录费用',
'db_table': 'kaohe_jilu_feiyong',
'unique_together': {('jilu', 'cishu')},
},
),
]
-35
View File
@@ -1,35 +0,0 @@
# Generated by Django 4.2.27 on 2026-05-19 13:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rank', '0010_kaohejilufeiyong'),
]
operations = [
migrations.CreateModel(
name='KaohePayTemp',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dingdan_id', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='订单ID')),
('yonghuid', models.CharField(db_index=True, max_length=7, verbose_name='用户ID')),
('tag_id', models.IntegerField(verbose_name='标签ID')),
('game_nick', models.CharField(max_length=100, verbose_name='游戏昵称')),
('remark', models.TextField(blank=True, verbose_name='备注')),
('reapply', models.BooleanField(default=False, verbose_name='是否再次申请')),
('jilu_id', models.CharField(blank=True, max_length=32, null=True, verbose_name='原记录ID(再次申请时)')),
('shenheguan_id', models.CharField(blank=True, max_length=7, verbose_name='指定考核官ID')),
('cishu', models.IntegerField(verbose_name='本次考核次数(预计算)')),
('fee', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='本次费用(分账单位)')),
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
],
options={
'verbose_name': '考核支付临时表',
'verbose_name_plural': '考核支付临时表',
'db_table': 'kaohe_pay_temp',
},
),
]
Loaded 100 of 132 files, more files were not shown because too many files have changed in this diff. Show more