prod_analysis.py 7.72 KB
import pyodbc

# 生产环境数据库
conn = pyodbc.connect(
    'DRIVER={ODBC Driver 17 for SQL Server};'
    'SERVER=192.168.1.168,1433;'
    'DATABASE=wms4_global;'
    'UID=sa;PWD=HHrobot123.'
)

cursor = conn.cursor()

print("=" * 80)
print("生产环境 ERP推送问题单据分析")
print("=" * 80)

# 1. 检查数据库版本确认是生产库
cursor.execute("SELECT @@VERSION")
row = cursor.fetchone()
print(f"\n数据库: {row[0][:50]}...")

# 2. 查看所有入库单状态分布
print("\n\n【一、入库单状态分布】")
print("-" * 60)

cursor.execute("""
    SELECT 
        COUNT(*) as total,
        SUM(CASE WHEN head_status = 0 THEN 1 ELSE 0 END) as 新建,
        SUM(CASE WHEN head_status = 100 THEN 1 ELSE 0 END) as 已提交,
        SUM(CASE WHEN head_status = 200 THEN 1 ELSE 0 END) as 已确认,
        SUM(CASE WHEN head_status = 300 THEN 1 ELSE 0 END) as 配货中,
        SUM(CASE WHEN head_status = 800 THEN 1 ELSE 0 END) as 已回传,
        SUM(CASE WHEN head_status = 900 THEN 1 ELSE 0 END) as 已完成
    FROM receipt_header
    WHERE del_flag = 0
""")
row = cursor.fetchone()
print(f"入库单总数: {row[0]}")
print(f"  新建(0): {row[1]}")
print(f"  已提交(100): {row[2]}")
print(f"  已确认(200): {row[3]}")
print(f"  配货中(300): {row[4]}")
print(f"  已回传(800): {row[5]}")
print(f"  已完成(900): {row[6]}")

# 3. 查看所有出库单状态分布
print("\n\n【二、出库单状态分布】")
print("-" * 60)

cursor.execute("""
    SELECT 
        COUNT(*) as total,
        SUM(CASE WHEN head_status = 0 THEN 1 ELSE 0 END) as 新建,
        SUM(CASE WHEN head_status = 100 THEN 1 ELSE 0 END) as 已提交,
        SUM(CASE WHEN head_status = 200 THEN 1 ELSE 0 END) as 已确认,
        SUM(CASE WHEN head_status = 300 THEN 1 ELSE 0 END) as 配货中,
        SUM(CASE WHEN head_status = 800 THEN 1 ELSE 0 END) as 已回传,
        SUM(CASE WHEN head_status = 900 THEN 1 ELSE 0 END) as 已完成
    FROM shipment_header
    WHERE del_flag = 0
""")
row = cursor.fetchone()
print(f"出库单总数: {row[0]}")
print(f"  新建(0): {row[1]}")
print(f"  已提交(100): {row[2]}")
print(f"  已确认(200): {row[3]}")
print(f"  配货中(300): {row[4]}")
print(f"  已回传(800): {row[5]}")
print(f"  已完成(900): {row[6]}")

# 4. 问题入库单:不是新建(0),不是已回传(800),不是已完成(900),且有任务但任务状态不是50
print("\n\n【三、问题入库单分析】")
print("-" * 60)

cursor.execute("""
    SELECT COUNT(*) FROM receipt_header 
    WHERE del_flag = 0 
    AND head_status NOT IN (0, 800, 900)
    AND bill_type NOT IN ('DBR', 'dbr', '倒扣料类型')  -- 排除调拨入库和倒扣料
""")
total_problem_receipt = cursor.fetchone()[0]
print(f"问题入库单总数(排除已回传和调拨入库): {total_problem_receipt}")

# 5. 详细列出问题入库单
print("\n问题入库单详情:")
print(f"{'入库单号':<30} {'类型':<10} {'头状态':<8} {'尾状态':<8} {'任务状态':<10} {'组盘码':<25} {'上游单号':<30}")
print("-" * 121)

cursor.execute("""
    SELECT TOP 100
        rh.bill_no,
        rh.bill_type,
        rh.head_status,
        rh.tail_status,
        ISNULL(CAST(th.status AS VARCHAR), '无任务') as task_status,
        STUFF((
            SELECT ',' + ch.container_code
            FROM task_detail td
            JOIN container_head ch ON td.container_id = ch.id
            WHERE td.receipt_id = rh.id
            FOR XML PATH('')
        ), 1, 1, '') as container_codes,
        rh.source_no
    FROM receipt_header rh
    LEFT JOIN task_header th ON rh.id = th.receipt_container_header_id
    WHERE rh.del_flag = 0 
    AND rh.head_status NOT IN (0, 800, 900)
    AND rh.bill_type NOT IN ('DBR', 'dbr')
    ORDER BY rh.create_time DESC
""")

for row in cursor.fetchall():
    bill_no = row[0] or ''
    bill_type = row[1] or ''
    head_status = row[2] if row[2] is not None else '-'
    tail_status = row[3] if row[3] is not None else '-'
    task_status = row[4] or '-'
    containers = (row[5] or '')[:20]
    source_no = (row[6] or '')[:25]
    print(f"{bill_no:<30} {bill_type:<10} {str(head_status):<8} {str(tail_status):<8} {task_status:<10} {containers:<25} {source_no:<30}")

# 6. 问题出库单
print("\n\n【四、问题出库单分析】")
print("-" * 60)

cursor.execute("""
    SELECT COUNT(*) FROM shipment_header 
    WHERE del_flag = 0 
    AND head_status NOT IN (0, 800, 900)
    AND bill_type NOT IN ('DBR', 'dbr')
""")
total_problem_shipment = cursor.fetchone()[0]
print(f"问题出库单总数(排除已回传和调拨出库): {total_problem_shipment}")

print("\n问题出库单详情:")
print(f"{'出库单号':<30} {'类型':<10} {'头状态':<8} {'尾状态':<8} {'任务状态':<10} {'组盘码':<25} {'上游单号':<30}")
print("-" * 121)

cursor.execute("""
    SELECT TOP 100
        sh.bill_no,
        sh.bill_type,
        sh.head_status,
        sh.tail_status,
        ISNULL(CAST(th.status AS VARCHAR), '无任务') as task_status,
        STUFF((
            SELECT ',' + ch.container_code
            FROM task_detail td
            JOIN container_head ch ON td.container_id = ch.id
            WHERE td.shipment_id = sh.id
            FOR XML PATH('')
        ), 1, 1, '') as container_codes,
        sh.source_no
    FROM shipment_header sh
    LEFT JOIN task_header th ON sh.id = th.shipment_container_header_id
    WHERE sh.del_flag = 0 
    AND sh.head_status NOT IN (0, 800, 900)
    AND sh.bill_type NOT IN ('DBR', 'dbr')
    ORDER BY sh.create_time DESC
""")

for row in cursor.fetchall():
    bill_no = row[0] or ''
    bill_type = row[1] or ''
    head_status = row[2] if row[2] is not None else '-'
    tail_status = row[3] if row[3] is not None else '-'
    task_status = row[4] or '-'
    containers = (row[5] or '')[:20]
    source_no = (row[6] or '')[:25]
    print(f"{bill_no:<30} {bill_type:<10} {str(head_status):<8} {str(tail_status):<8} {task_status:<10} {containers:<25} {source_no:<30}")

# 7. 组盘头表 inout_status 分析
print("\n\n【五、组盘头表 inout_status 分析】")
print("-" * 60)

cursor.execute("""
    SELECT 
        inout_status,
        COUNT(*) as cnt
    FROM container_head
    WHERE del_flag = 0
    GROUP BY inout_status
    ORDER BY inout_status
""")

print("组盘状态分布:")
for row in cursor.fetchall():
    status = row[0] if row[0] is not None else 'NULL'
    cnt = row[1]
    print(f"  状态 {status}: {cnt} 条")

# 8. 组盘头表状态不是50的详细
print("\n\n【六、组盘状态不是50的单据(可能有问题)】")
print("-" * 60)

cursor.execute("""
    SELECT 
        COUNT(*) 
    FROM container_head 
    WHERE del_flag = 0 
    AND inout_status IS NOT NULL 
    AND inout_status != 50
    AND inout_status != 0
""")
not_50_count = cursor.fetchone()[0]
print(f"组盘状态不是50的单据数: {not_50_count}")

print("\n详细列表:")
print(f"{'组盘码':<20} {'类型':<10} {'inout_status':<12} {'关联入库单':<30} {'关联出库单':<30}")
print("-" * 102)

cursor.execute("""
    SELECT TOP 50
        ch.container_code,
        ch.bill_type,
        ch.inout_status,
        ISNULL(rh.bill_no, '-') as receipt_bill,
        ISNULL(sh.bill_no, '-') as shipment_bill
    FROM container_head ch
    LEFT JOIN receipt_header rh ON ch.id = rh.container_id
    LEFT JOIN shipment_header sh ON ch.id = sh.container_id
    WHERE ch.del_flag = 0 
    AND ch.inout_status IS NOT NULL 
    AND ch.inout_status NOT IN (50, 0, 800, 900)
    ORDER BY ch.create_time DESC
""")

for row in cursor.fetchall():
    code = row[0] or ''
    bill_type = row[1] or ''
    status = row[2] if row[2] is not None else '-'
    receipt = (row[3] or '-')[:25]
    shipment = (row[4] or '-')[:25]
    print(f"{code:<20} {bill_type:<10} {str(status):<12} {receipt:<30} {shipment:<30}")

conn.close()
print("\n\n分析完成!")