# -*- coding: utf-8 -*- import io, sys, pymysql sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') conn = pymysql.connect(host='192.168.1.161', user='devgps', password='dev@2021GPS', database='zentao_dev_2026', charset='utf8mb4') cur = conn.cursor() def q(sql): cur.execute(sql); return cur.fetchall() print("### 1. Bug密度(开发者维度):6月done任务,分子=挂任务的Bug数,分母=Σestimate") rows = q(""" SELECT t.assignedTo, u.realname, COUNT(DISTINCT t.id) tasks, SUM(t.estimate) est FROM zt_task t LEFT JOIN zt_user u ON u.account=t.assignedTo WHERE t.status='done' AND t.finishedDate>='2026-06-01' AND t.finishedDate<'2026-07-01' AND t.deleted='0' AND t.assignedTo NOT IN ('','closed') GROUP BY t.assignedTo ORDER BY est DESC """) print("name | done任务 | Σest(h) | Bug数 | ×100(%) | ×1000(‰)") for r in rows: est = float(r[3] or 0) bugs = q(f"SELECT COUNT(*) FROM zt_bug b JOIN zt_task t2 ON b.task=t2.id WHERE t2.assignedTo='{r[0]}' AND t2.status='done' AND t2.finishedDate>='2026-06-01' AND t2.finishedDate<'2026-07-01' AND t2.deleted='0' AND b.deleted='0'")[0][0] if est: print(f"{r[1] or r[0]} | {r[2]} | {est:.1f} | {bugs} | {bugs/est*100:.2f}% | {bugs/est*1000:.1f}‰") print("\n### 2. 线上Bug率(产品维度):6月上线需求 prod Bug / devel工时") rows = q(""" SELECT s.product, COUNT(DISTINCT s.id) stories FROM zt_story s WHERE s.releaseddate>='2026-06-01' AND s.releaseddate<'2026-07-01' AND s.deleted='0' GROUP BY s.product ORDER BY stories DESC LIMIT 6 """) for r in rows: pid = r[0] dev = q(f"""SELECT SUM(t.estimate) FROM zt_task t JOIN zt_story s ON t.story=s.id WHERE s.product={pid} AND s.releaseddate>='2026-06-01' AND s.releaseddate<'2026-07-01' AND s.deleted='0' AND t.type='devel' AND t.deleted='0'""")[0][0] bugs = q(f"""SELECT b.severity, COUNT(*) FROM zt_bug b JOIN zt_story s ON b.story=s.id WHERE s.product={pid} AND s.releaseddate>='2026-06-01' AND s.releaseddate<'2026-07-01' AND s.deleted='0' AND b.deleted='0' GROUP BY b.severity""") dev = float(dev or 0) tot = sum(c for _, c in bugs) rate = tot/dev*1000 if dev else None print(f"product {pid}: 上线需求={r[1]} devel工时={dev:.1f} Bug={bugs} → {'%.2f‰'%rate if rate is not None else 'NA(分母0)'}") print("\n### 3. 缺陷检出率(全量):6月上线需求 (普通×1+重大×5)/devel工时") rows = q(""" SELECT (SELECT SUM(t.estimate) FROM zt_task t WHERE t.story=s.id AND t.type='devel' AND t.deleted='0') dev_est, (SELECT COUNT(*) FROM zt_bug b WHERE b.story=s.id AND b.deleted='0' AND b.severity IN (3,4)) nb, (SELECT COUNT(*) FROM zt_bug b WHERE b.story=s.id AND b.deleted='0' AND b.severity IN (1,2)) mb FROM zt_story s WHERE s.releaseddate>='2026-06-01' AND s.releaseddate<'2026-07-01' AND s.deleted='0' """) tot_dev = sum(float(r[0] or 0) for r in rows) tot_w = sum((r[1] or 0)*1 + (r[2] or 0)*5 for r in rows) n_dev0 = sum(1 for r in rows if not r[0]) print(f"需求数={len(rows)}(其中devel工时为空 {n_dev0}) Σdevel工时={tot_dev:.1f} Σ加权Bug={tot_w}") if tot_dev: print(f"检出率 ×100={tot_w/tot_dev*100:.2f}% ×1000={tot_w/tot_dev*1000:.1f}‰") print("\n### 4. 版本计划:6月发布需求 工时 vs 指数覆盖") rows = q(""" SELECT s.id, s.estimate, e.workload_index, (SELECT SUM(t.estimate) FROM zt_task t WHERE t.story=s.id AND t.deleted='0') task_est FROM zt_story s LEFT JOIN zt_story_expand e ON e.story_id=s.id WHERE s.releaseddate>='2026-06-01' AND s.releaseddate<'2026-07-01' AND s.deleted='0' """) n=len(rows); wi=[r for r in rows if r[2] not in (None,'','0')] sum_task=sum(float(r[3] or 0) for r in rows); sum_sest=sum(float(r[1] or 0) for r in rows) print(f"发布需求={n} 有工作量指数={len(wi)}(覆盖率 {len(wi)/n*100:.0f}%) Σ任务工时={sum_task:.1f} Σstory.estimate={sum_sest:.1f}") print("\n### 5. 检出率口径交叉:严重度分布(6月所有Bug)") for r in q("SELECT severity, COUNT(*) FROM zt_bug WHERE deleted='0' AND openeddate>='2026-06-01' AND openeddate<'2026-07-01' GROUP BY severity"): print("severity", r[0], "=", r[1])