一次性脚本,将多余分类的产品迁移到工业品/日用品,然后软删除多余分类。 运行方式: python -m backend.scripts.cleanup_categories Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
158 lines
5.3 KiB
Python
158 lines
5.3 KiB
Python
"""清理多余产品分类脚本。
|
|
|
|
将数据库中多余的分类迁移到工业品(1)或日用品(2),然后软删除多余分类。
|
|
|
|
运行方式: python -m backend.scripts.cleanup_categories
|
|
"""
|
|
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from sqlalchemy import select, func
|
|
|
|
from backend.app.db import SessionLocal
|
|
from backend.app.models.business import Product, ProductCategory
|
|
|
|
# 保留的分类 ID
|
|
KEEP_IDS = {1, 2}
|
|
|
|
# 工业关键词:产品名包含这些词的归入工业品
|
|
INDUSTRY_KEYWORDS = ["布", "带", "胶", "板", "管", "钢", "铁", "铝", "铜", "塑", "膜", "网", "绳", "线", "丝", "棉", "纱"]
|
|
|
|
|
|
def classify_product(product_name: str) -> int:
|
|
"""根据产品名判断归入工业品(1)还是日用品(2)"""
|
|
for kw in INDUSTRY_KEYWORDS:
|
|
if kw in product_name:
|
|
return 1
|
|
return 2
|
|
|
|
|
|
def main():
|
|
session = SessionLocal()
|
|
try:
|
|
# ========== Step 1: 查询当前状态 ==========
|
|
print("=" * 60)
|
|
print("产品分类清理脚本")
|
|
print("=" * 60)
|
|
|
|
categories = session.execute(
|
|
select(ProductCategory).where(ProductCategory.deleted == 0).order_by(ProductCategory.id)
|
|
).scalars().all()
|
|
|
|
print(f"\n当前分类列表(共 {len(categories)} 个):")
|
|
print("-" * 50)
|
|
|
|
extra_categories = []
|
|
for cat in categories:
|
|
product_count = session.execute(
|
|
select(func.count(Product.id)).where(
|
|
Product.category_id == cat.id,
|
|
Product.deleted == 0,
|
|
)
|
|
).scalar() or 0
|
|
|
|
tag = "✓ 保留" if cat.id in KEEP_IDS else "✗ 待删除"
|
|
print(f" ID={cat.id} {cat.category_name:<12} ({cat.category_code}) 产品数: {product_count} [{tag}]")
|
|
|
|
if cat.id not in KEEP_IDS:
|
|
extra_categories.append((cat, product_count))
|
|
|
|
if not extra_categories:
|
|
print("\n没有需要清理的多余分类。")
|
|
return
|
|
|
|
# 统计需要迁移的产品
|
|
total_products_to_migrate = sum(count for _, count in extra_categories)
|
|
print(f"\n需要迁移的产品总数: {total_products_to_migrate}")
|
|
print(f"需要删除的分类数: {len(extra_categories)}")
|
|
|
|
# 显示迁移计划
|
|
print("\n迁移计划:")
|
|
print("-" * 50)
|
|
for cat, count in extra_categories:
|
|
products = session.execute(
|
|
select(Product).where(
|
|
Product.category_id == cat.id,
|
|
Product.deleted == 0,
|
|
)
|
|
).scalars().all()
|
|
|
|
industry_count = sum(1 for p in products if classify_product(p.product_name) == 1)
|
|
daily_count = count - industry_count
|
|
|
|
print(f" 分类「{cat.category_name}」({count}个产品):")
|
|
print(f" → 工业品: {industry_count} 个")
|
|
print(f" → 日用品: {daily_count} 个")
|
|
|
|
for p in products:
|
|
target = "工业品" if classify_product(p.product_name) == 1 else "日用品"
|
|
print(f" - {p.product_name} ({p.specification}) → {target}")
|
|
|
|
# ========== Step 2: 确认 ==========
|
|
print("\n" + "=" * 60)
|
|
confirm = input("确认执行清理?(输入 yes 继续): ").strip()
|
|
if confirm.lower() != "yes":
|
|
print("已取消。")
|
|
return
|
|
|
|
# ========== Step 3: 执行迁移 ==========
|
|
print("\n执行迁移...")
|
|
migrated = 0
|
|
for cat, count in extra_categories:
|
|
products = session.execute(
|
|
select(Product).where(
|
|
Product.category_id == cat.id,
|
|
Product.deleted == 0,
|
|
)
|
|
).scalars().all()
|
|
|
|
for p in products:
|
|
target_id = classify_product(p.product_name)
|
|
target_name = "工业品" if target_id == 1 else "日用品"
|
|
p.category_id = target_id
|
|
p.category = target_name
|
|
migrated += 1
|
|
print(f" 迁移: {p.product_name} → {target_name}")
|
|
|
|
# ========== Step 4: 软删除多余分类 ==========
|
|
print("\n删除多余分类...")
|
|
deleted = 0
|
|
for cat, _ in extra_categories:
|
|
cat.deleted = 1
|
|
deleted += 1
|
|
print(f" 删除: {cat.category_name}")
|
|
|
|
session.commit()
|
|
|
|
# ========== Step 5: 验证 ==========
|
|
print("\n" + "=" * 60)
|
|
print("清理完成!验证结果:")
|
|
|
|
remaining = session.execute(
|
|
select(ProductCategory).where(ProductCategory.deleted == 0).order_by(ProductCategory.id)
|
|
).scalars().all()
|
|
|
|
print(f"剩余分类数: {len(remaining)}")
|
|
for cat in remaining:
|
|
product_count = session.execute(
|
|
select(func.count(Product.id)).where(
|
|
Product.category_id == cat.id,
|
|
Product.deleted == 0,
|
|
)
|
|
).scalar() or 0
|
|
print(f" ID={cat.id} {cat.category_name} 产品数: {product_count}")
|
|
|
|
print(f"\n共迁移 {migrated} 个产品,删除 {deleted} 个分类。")
|
|
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|