generate_requirement_breakdown_excel.py
4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
生成「美业系统升级项目需求拆分表」Excel 文档
- 从 docs/美业系统升级项目需求拆分表_data.py 读取数据
- 输出 docs/美业系统升级项目需求拆分表.xlsx
- 含「需求拆分表」与「完整性核对说明」两个工作表
"""
import os
import sys
# 项目根目录
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
sys.path.insert(0, ROOT)
os.chdir(ROOT)
# 数据从同目录上一级的 docs 下读取(按项目结构)
DATA_MODULE_PATH = os.path.join(ROOT, "docs", "美业系统升级项目需求拆分表_data.py")
def load_data():
import importlib.util
spec = importlib.util.spec_from_file_location("req_data", DATA_MODULE_PATH)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod.ROWS
def main():
try:
import openpyxl
from openpyxl.styles import Font, Alignment, Border, Side
from openpyxl.utils import get_column_letter
except ImportError:
print("请先安装 openpyxl: pip install openpyxl")
sys.exit(1)
rows = load_data()
out_path = os.path.join(ROOT, "docs", "美业系统升级项目需求拆分表.xlsx")
wb = openpyxl.Workbook()
thin = Side(style="thin")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# ========== Sheet1: 需求拆分表 ==========
ws = wb.active
ws.title = "需求拆分表"
headers = ["期数", "板块", "功能模块", "具体功能", "详细说明", "预估人天"]
for col, h in enumerate(headers, 1):
c = ws.cell(row=1, column=col, value=h)
c.font = Font(bold=True)
c.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
c.border = border
ws.row_dimensions[1].height = 24
for row_idx, row_data in enumerate(rows, 2):
for col_idx, val in enumerate(row_data, 1):
c = ws.cell(row=row_idx, column=col_idx, value=val)
c.border = border
if col_idx == 6: # 预估人天
c.alignment = Alignment(horizontal="right")
# 列宽
ws.column_dimensions["A"].width = 10
ws.column_dimensions["B"].width = 18
ws.column_dimensions["C"].width = 22
ws.column_dimensions["D"].width = 24
ws.column_dimensions["E"].width = 52
ws.column_dimensions["F"].width = 10
# 合计行
total_row = len(rows) + 2
ws.cell(row=total_row, column=5, value="合计(人天)").font = Font(bold=True)
ws.cell(row=total_row, column=5).border = border
total_days = sum(r[5] for r in rows)
ws.cell(row=total_row, column=6, value=round(total_days, 1)).font = Font(bold=True)
ws.cell(row=total_row, column=6).border = border
# ========== Sheet2: 完整性核对说明 ==========
ws2 = wb.create_sheet("完整性核对说明", 1)
intro = [
"一、核对结论",
"与《客户需求梳理-一期收尾与二期规划》逐项对照,本需求拆分表已覆盖:",
"• 一期收尾:BUG 修复 2 项、功能小优化 9 项、文案注释规范 1 项;",
"• 二期规划:看板与统计(医美/科技部/教育部/事业部)、会员与客户、金三角与店长、品项与开单、大客与风控、人员与数据准确性、生日与短信、PC 工作台、其他补充、人事管理、预约管理、支付管理、萤石云监控对接。",
"",
"二、范围说明(与规划一致)",
"• 考勤打卡:不含人脸识别、二维码打卡;",
"• 人事:不含出差管理;薪资仅为人事侧结构与档案,不替代现有工资核算;",
"• 预约:不做客户在线预约,以线下预约表线上化、健康师维度为主;",
"• 支付:对接统一收款渠道(聚合支付),非分别对接微信/支付宝。",
"",
"三、人天说明",
"预估人天已按「开发+联调+自测」重新评估:一期收尾合计约 9.5 人天,二期规划合计见下表。",
]
for i, line in enumerate(intro, 1):
ws2.cell(row=i, column=1, value=line)
ws2.column_dimensions["A"].width = 90
wb.save(out_path)
print(f"已生成: {out_path}")
print(f"需求条目: {len(rows)} 条,预估总人天: {round(total_days, 1)}")
if __name__ == "__main__":
main()