diff --git a/backend/migrations/0003_withdrawaldailystats_club_id.py b/backend/migrations/0003_withdrawaldailystats_club_id.py index f4c0a7f..2fa6e22 100644 --- a/backend/migrations/0003_withdrawaldailystats_club_id.py +++ b/backend/migrations/0003_withdrawaldailystats_club_id.py @@ -1,4 +1,15 @@ from django.db import migrations, models +from django.db.models import Max + + +def _dedupe_withdrawal_daily(apps, schema_editor): + Model = apps.get_model('backend', 'WithdrawalDailyStats') + for row in Model.objects.values('club_id', 'Date', 'WithdrawalType').annotate(max_id=Max('id')): + Model.objects.filter( + club_id=row['club_id'], + Date=row['Date'], + WithdrawalType=row['WithdrawalType'], + ).exclude(id=row['max_id']).delete() class Migration(migrations.Migration): @@ -17,6 +28,7 @@ class Migration(migrations.Migration): name='withdrawaldailystats', unique_together=set(), ), + migrations.RunPython(_dedupe_withdrawal_daily, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='withdrawaldailystats', unique_together={('club_id', 'Date', 'WithdrawalType')}, diff --git a/backend/migrations/0004_role_daily_club_id.py b/backend/migrations/0004_role_daily_club_id.py index ccf689e..c0a9aac 100644 --- a/backend/migrations/0004_role_daily_club_id.py +++ b/backend/migrations/0004_role_daily_club_id.py @@ -1,4 +1,34 @@ from django.db import migrations, models +from django.db.models import Max + + +def _dedupe_role_daily(apps, schema_editor, model_name, user_field): + Model = apps.get_model('backend', model_name) + for row in Model.objects.values('club_id', user_field, 'Date').annotate(max_id=Max('id')): + Model.objects.filter( + club_id=row['club_id'], + **{user_field: row[user_field], 'Date': row['Date']}, + ).exclude(id=row['max_id']).delete() + + +def _dedupe_merchant(apps, schema_editor): + _dedupe_role_daily(apps, schema_editor, 'MerchantDailyStats', 'MerchantID') + + +def _dedupe_player(apps, schema_editor): + _dedupe_role_daily(apps, schema_editor, 'PlayerDailyStats', 'PlayerID') + + +def _dedupe_leader(apps, schema_editor): + _dedupe_role_daily(apps, schema_editor, 'LeaderDailyStats', 'LeaderID') + + +def _dedupe_manager(apps, schema_editor): + _dedupe_role_daily(apps, schema_editor, 'ManagerDailyStats', 'ManagerID') + + +def _dedupe_manager_renewal(apps, schema_editor): + _dedupe_role_daily(apps, schema_editor, 'ManagerRenewalDailyStats', 'ManagerID') class Migration(migrations.Migration): @@ -33,22 +63,27 @@ class Migration(migrations.Migration): name='club_id', field=models.CharField(db_index=True, default='xq', max_length=16, verbose_name='俱乐部ID'), ), + migrations.RunPython(_dedupe_merchant, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='merchantdailystats', unique_together={('club_id', 'MerchantID', 'Date')}, ), + migrations.RunPython(_dedupe_player, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='playerdailystats', unique_together={('club_id', 'PlayerID', 'Date')}, ), + migrations.RunPython(_dedupe_leader, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='leaderdailystats', unique_together={('club_id', 'LeaderID', 'Date')}, ), + migrations.RunPython(_dedupe_manager, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='managerdailystats', unique_together={('club_id', 'ManagerID', 'Date')}, ), + migrations.RunPython(_dedupe_manager_renewal, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='managerrenewaldailystats', unique_together={('club_id', 'ManagerID', 'Date')}, diff --git a/config/migrations/0006_display_club_id.py b/config/migrations/0006_display_club_id.py index 28c80f1..02241be 100644 --- a/config/migrations/0006_display_club_id.py +++ b/config/migrations/0006_display_club_id.py @@ -1,4 +1,23 @@ from django.db import migrations, models +from django.db.models import Max + + +def _dedupe_popuppage(apps, schema_editor): + PopupPage = apps.get_model('config', 'PopupPage') + for row in PopupPage.objects.values('club_id', 'page_key').annotate(max_id=Max('id')): + PopupPage.objects.filter( + club_id=row['club_id'], + page_key=row['page_key'], + ).exclude(id=row['max_id']).delete() + + +def _dedupe_tupianpeizhi(apps, schema_editor): + Tupianpeizhi = apps.get_model('config', 'Tupianpeizhi') + for row in Tupianpeizhi.objects.values('club_id', 'ImageType').annotate(max_id=Max('id')): + Tupianpeizhi.objects.filter( + club_id=row['club_id'], + ImageType=row['ImageType'], + ).exclude(id=row['max_id']).delete() class Migration(migrations.Migration): @@ -45,10 +64,12 @@ class Migration(migrations.Migration): name='page_key', field=models.CharField(db_index=True, max_length=50, verbose_name='页面标识'), ), + migrations.RunPython(_dedupe_popuppage, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='popuppage', unique_together={('club_id', 'page_key')}, ), + migrations.RunPython(_dedupe_tupianpeizhi, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='tupianpeizhi', unique_together={('club_id', 'ImageType')}, diff --git a/deploy/pre_migrate_dedupe.sql b/deploy/pre_migrate_dedupe.sql new file mode 100644 index 0000000..c039dfd --- /dev/null +++ b/deploy/pre_migrate_dedupe.sql @@ -0,0 +1,68 @@ +-- 部署 jituan 前若 migrate 报 Duplicate entry 唯一约束冲突,在 dbshell 执行。 +-- 每种组合只保留 id 最大的一条;不影响订单/资金主表。 + +-- config.0006 tupianpeizhi +DELETE FROM tupianpeizhi +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM tupianpeizhi GROUP BY club_id, ImageType + ) AS t +); + +-- config.0006 popup_page +DELETE FROM popup_page +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM popup_page GROUP BY club_id, page_key + ) AS t +); + +-- products.0005 duoci_fenhong +DELETE FROM duoci_fenhong +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM duoci_fenhong GROUP BY club_id, huiyuan, yonghuid, cishu + ) AS t +); + +-- backend.0003 提现日统计 +DELETE FROM tixian_ri_tongji +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM tixian_ri_tongji GROUP BY club_id, Date, WithdrawalType + ) AS t +); + +-- backend.0004 角色日统计 +DELETE FROM shangjia_ri_tongji +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM shangjia_ri_tongji GROUP BY club_id, MerchantID, Date + ) AS t +); +DELETE FROM dashou_ri_tongji +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM dashou_ri_tongji GROUP BY club_id, PlayerID, Date + ) AS t +); +DELETE FROM zuzhang_ri_tongji +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM zuzhang_ri_tongji GROUP BY club_id, LeaderID, Date + ) AS t +); +DELETE FROM guanshi_ri_tongji +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM guanshi_ri_tongji GROUP BY club_id, ManagerID, Date + ) AS t +); +DELETE FROM guanshi_xufei_ri_tongji +WHERE id NOT IN ( + SELECT keep_id FROM ( + SELECT MAX(id) AS keep_id FROM guanshi_xufei_ri_tongji GROUP BY club_id, ManagerID, Date + ) AS t +); + +-- szjilu 应只有 1 行;多行时勿自动删,需人工核对 TotalIncome 后处理 diff --git a/products/migrations/0005_duoci_fenhong_club_id.py b/products/migrations/0005_duoci_fenhong_club_id.py index f399413..b640962 100644 --- a/products/migrations/0005_duoci_fenhong_club_id.py +++ b/products/migrations/0005_duoci_fenhong_club_id.py @@ -1,4 +1,18 @@ from django.db import migrations, models +from django.db.models import Max + + +def _dedupe_duoci_fenhong(apps, schema_editor): + DuociFenhong = apps.get_model('products', 'DuociFenhong') + for row in DuociFenhong.objects.values( + 'club_id', 'huiyuan', 'yonghuid', 'cishu', + ).annotate(max_id=Max('id')): + DuociFenhong.objects.filter( + club_id=row['club_id'], + huiyuan=row['huiyuan'], + yonghuid=row['yonghuid'], + cishu=row['cishu'], + ).exclude(id=row['max_id']).delete() class Migration(migrations.Migration): @@ -13,6 +27,7 @@ class Migration(migrations.Migration): name='club_id', field=models.CharField(db_index=True, default='xq', max_length=16, verbose_name='所属俱乐部'), ), + migrations.RunPython(_dedupe_duoci_fenhong, migrations.RunPython.noop), migrations.AlterUniqueTogether( name='duocifenhong', unique_together={('club_id', 'huiyuan', 'yonghuid', 'cishu')},