#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Build a standalone Excel summary for the 2026-10 monthly report.

Source data (updated 2026-10 department workbooks):
  /Users/liuxinyuan/Desktop/hermas输入-工作台数据库/2026年10月月报/
本脚本只做提炼，不写回源文件。
"""
import os
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
from openpyxl.drawing.image import Image

OUT = '/Users/liuxinyuan/Desktop/Hermes输出-工作类/经营分析/月报/2026年10月月报_部门数据提炼_20261109.xlsx'
LOGO = '/Users/liuxinyuan/work/公司资料/logo_white_transparent.png'

# ---------- 10月部门数据（元） ----------
# 年度表：1）年度指标达成情况 / 二、实际完成 D-M
D = {
    '大客户部': {
        'target': 26500000.0,
        'actual': 11999295.04,
        'months': [981488.4, 906532.1, 2741487.6, 915418.0, 583785.0,
                   1737136.2, 886687.4, 863582.8, 1344203.34, 1038974.2],
        'oct_target': 5289989.47,
        'y25_ytd': 12282851.471,
        'y25_oct': 1990578.8,
    },
    '销售拓展部': {
        'target': 34000000.0,
        'actual': 24511312.858,
        'months': [3437599.3, 921263.4, 1956623.0, 2262177.96, 2415638.4,
                   2543097.0, 2598193.1, 2979228.6, 2728444.098, 2669048.0],
        'oct_target': 4441778.14733333,
        'y25_ytd': 18105468.909,
        'y25_oct': 2222552.84,
    },
    '生命科学部': {
        'target': 9000000.0,
        'actual': 408359.64,
        'months': [39448.34, 16777.0, 49818.5, 25941.0, 60308.1,
                   45741.3, 19074.5, 29881.0, 78500.1, 42869.8],
        'oct_target': 4158333.972,
        'y25_ytd': None,
        'y25_oct': None,
    },
}
DEPT_ORDER = ['大客户部', '销售拓展部', '生命科学部']
for v in D.values():
    assert abs(sum(v['months']) - v['actual']) < 0.01, (v['actual'], sum(v['months']))

TOTAL_TARGET = sum(v['target'] for v in D.values())
TOTAL_ACTUAL = sum(v['actual'] for v in D.values())
TOTAL_OCT = sum(v['months'][-1] for v in D.values())
TOTAL_OCT_TARGET = sum(v['oct_target'] for v in D.values())
TOTAL_25_YTD = sum(v['y25_ytd'] for v in D.values() if v['y25_ytd'])
TOTAL_25_OCT = sum(v['y25_oct'] for v in D.values() if v['y25_oct'])
TOTAL_MONTHS = [sum(D[k]['months'][i] for k in DEPT_ORDER) for i in range(10)]
# 大客户+拓展同口径（生命科学部无2025年同期）
TWO_TARGET = D['大客户部']['target'] + D['销售拓展部']['target']
TWO_ACTUAL = D['大客户部']['actual'] + D['销售拓展部']['actual']
TWO_OCT = D['大客户部']['months'][-1] + D['销售拓展部']['months'][-1]
TWO_OCT_TARGET = D['大客户部']['oct_target'] + D['销售拓展部']['oct_target']
TWO_25_YTD = D['大客户部']['y25_ytd'] + D['销售拓展部']['y25_ytd']
TWO_25_OCT = D['大客户部']['y25_oct'] + D['销售拓展部']['y25_oct']

# ---------- 过程指标（10月，原表） ----------
PROC = {
    '大客户部': dict(visits=82, ngs_visits=0, tests=34, sku_sent=None, feedback=37,
                    feedback_rate=37/34, ngs_tests=0, ngs_orders=0, orders=55,
                    proc_amount=1037934.2, annual_amount=1038974.2, new_dev=None, new_deal=None),
    '销售拓展部': dict(visits=336, ngs_visits=42, tests=181, sku_sent=None, feedback=147,
                    feedback_rate=147/181, ngs_tests=14, ngs_orders=4, orders=171,
                    proc_amount=2669048.0, annual_amount=2669048.0, new_dev=None, new_deal=None),
    '生命科学部': dict(visits=733, ngs_visits=0, tests=119, sku_sent=180, feedback=61,
                    feedback_rate=61/180, ngs_tests=0, ngs_orders=0, orders=36,
                    proc_amount=43669.8, annual_amount=42869.8, new_dev=1, new_deal=29),
}

# ---------- 绩效（10月） ----------
PERF = [
    ('大客户部', '刘子研', '销售工程师', 94.7, ''),
    ('大客户部', '赵云浩', '销售工程师', 88.0, ''),
    ('生命科学部', '黄建华', '销售工程师', 73.0, ''),
    ('生命科学部', '陈彩红', '销售工程师', 57.0, ''),
    ('生命科学部', '王诗香', '销售工程师', 81.0, ''),
    ('生命科学部', '侯海瑜', '销售工程师', 36.0, ''),
    ('生命科学部', '叶信福', '销售工程师', 68.0, ''),
    ('生命科学部', '袁殿果', '销售工程师', 91.0, ''),
    ('生命科学部', '韩远怀', '区域销售经理', 64.0, '广州区域'),
    ('生命科学部', '吴云', '区域销售经理', 64.0, '杭州区域'),
]

# ---------- 2026 1-10月 TOP10 ----------
TOP = {
    '大客户部': [
        (1, '丽珠集团', '珠海丽珠试剂股份有限公司', '刘子研', 2388359.6),
        (2, '万孚集团', '广州万孚生物技术股份有限公司', '赵云浩', 1409720.0),
        (3, '天隆集团', '西安华伟科技有限公司', '刘子研', 848150.0),
        (4, '圣湘集团', '圣湘（上海）基因科技有限公司', '赵云浩', 806333.8),
        (5, '', '苏州华益美生物科技有限公司', '刘子研', 699500.0),
        (6, '圣湘集团', '圣湘生物科技股份有限公司', '赵云浩', 670997.94),
        (7, '', '北京明日达科技发展有限责任公司', '赵云浩', 660500.0),
        (8, '东方基因集团', '杭州丹威生物科技有限公司', '刘子研', 620116.6),
        (9, '复星集团', '复星诊断科技（上海）有限公司', '刘子研', 511025.3),
        (10, '天隆集团', '苏州天隆生物科技有限公司', '刘子研', 501610.0),
    ],
    '销售拓展部': [
        (1, '', '保密客户', '路要峰', 2127050.0),
        (2, '深圳生科原集团', '深圳生科原技术有限公司', '陈溪子', 1419000.0),
        (3, '广州生凌集团', '广州生凌智造科技有限公司', '陈溪子', 1211480.0),
        (4, '', '湖南圣测生物科技有限公司', '李江辉', 1158650.0),
        (5, '', '青岛嘉智生物技术有限公司', '刘虹晶', 1050525.0),
        (6, '英科新创集团', '英科新创（苏州）生物科技有限公司', '宋学伟', 868696.0),
        (7, '伯杰医疗', '上海伯杰医疗科技股份有限公司', '路要峰', 757300.0),
        (8, '冠牧集团', '湖南冠牧生物科技有限公司', '李江辉', 748500.0),
        (9, '知因集团', '天津知因生物科技有限公司', '刘虹晶', 707235.0),
        (10, '广州易安', '广州易安生物技术有限公司', '陈溪子', 690853.6),
    ],
}

# ---------- 样式 ----------
NAVY = '0B2A4A'
BLUE = '1F6FEB'
PALE = 'F3F7FC'
LINE = 'D9E2EE'
GREY = '5B6B7F'
RED = 'C00000'
GREEN = '16803C'
ORANGE = 'B26A00'
FONT_CN = '宋体'
thin = Side(style='thin', color=LINE)
BORDER = Border(left=thin, right=thin, top=thin, bottom=thin)


def fill(c):
    return PatternFill('solid', fgColor=c)


def font(size=10, bold=False, color='1F2937', name=FONT_CN):
    return Font(name=name, size=size, bold=bold, color=color)


def title(ws, text, sub=None, ncol=10):
    ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=ncol)
    c = ws.cell(1, 1, text)
    c.font = font(17, True, NAVY)
    c.alignment = Alignment(horizontal='left', vertical='center')
    ws.row_dimensions[1].height = 30
    if sub:
        ws.merge_cells(start_row=2, start_column=1, end_row=2, end_column=ncol)
        c = ws.cell(2, 1, sub)
        c.font = font(9, False, GREY)
        c.alignment = Alignment(horizontal='left', vertical='center', wrap_text=True)
        ws.row_dimensions[2].height = 22


def header(ws, row, vals, widths=None, height=32):
    for j, v in enumerate(vals, 1):
        c = ws.cell(row, j, v)
        c.font = font(9, True, 'FFFFFF')
        c.fill = fill(NAVY)
        c.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        c.border = BORDER
    ws.row_dimensions[row].height = height
    if widths:
        for i, w in enumerate(widths, 1):
            ws.column_dimensions[get_column_letter(i)].width = w


def body_row(ws, row, vals, fmt=None, bold=False, fill_color=None, height=24):
    for j, v in enumerate(vals, 1):
        c = ws.cell(row, j, v)
        c.font = font(9.5, bold, '1F2937')
        c.border = BORDER
        c.alignment = Alignment(horizontal='center' if j != 2 else 'left',
                                vertical='center', wrap_text=True)
        if fill_color:
            c.fill = fill(fill_color)
    ws.row_dimensions[row].height = height


def fmt_num(c, decimals=2):
    c.number_format = f'#,##0.{("0" * decimals)}'


def fmt_pct(c, decimals=1):
    c.number_format = f'0.{("0" * decimals)}%'


def note(ws, row, text, ncol=10, color=GREY, size=8.5, height=30):
    ws.merge_cells(start_row=row, start_column=1, end_row=row, end_column=ncol)
    c = ws.cell(row, 1, text)
    c.font = font(size, False, color)
    c.alignment = Alignment(horizontal='left', vertical='top', wrap_text=True)
    ws.row_dimensions[row].height = height


wb = Workbook()

# ================= 00 封面 =================
ws = wb.active
ws.title = '00_封面'
for col in range(1, 11):
    ws.column_dimensions[get_column_letter(col)].width = 12
for r in range(1, 24):
    ws.row_dimensions[r].height = 24
    for c in range(1, 11):
        ws.cell(r, c).fill = fill(NAVY)
# logo
if os.path.exists(LOGO):
    img = Image(LOGO)
    img.width = 180
    img.height = 61
    ws.add_image(img, 'B2')
ws['D4'] = '2026年10月月报'
ws['D4'].font = font(30, True, 'FFFFFF')
ws['D5'] = '部门经营数据提炼'
ws['D5'].font = font(20, True, 'D9E9FF')
ws['D7'] = '数据截止：2026年10月31日'
ws['D7'].font = font(11, False, 'D9E9FF')
ws['D8'] = '口径：诊断原料大客户部 / 诊断原料销售拓展部 / 生命科学销售部 月度数据看板（更新版）'
ws['D8'].font = font(9.5, False, 'B7C9DE')
ws.merge_cells('D8:J8')
ws['D10'] = '本册用于 10 月月报引用，包含：总览、月度趋势、过程指标、绩效、重点客户、口径与数据源。'
ws['D10'].font = font(10, False, 'FFFFFF')
ws.merge_cells('D10:J10')
# 三张提示卡
cards = [
    ('D12:E15', '10月销售', '375.09 万元'),
    ('F12:H15', '1-10月累计', '3,691.90 万元'),
    ('I12:J15', '年度达成', '53.1%'),
]
for rng, label, value in cards:
    ws.merge_cells(rng)
    first = rng.split(':')[0]
    c = ws[first]
    c.value = f'{label}\n{value}'
    c.font = font(12, True, 'FFFFFF')
    c.fill = fill('123B63')
    c.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
    # 给合并区所有单元格填充，避免白边
    for row in ws[rng]:
        for cell in row:
            cell.fill = fill('123B63')
ws['D17'] = '注：封面数字为三部门合计；年度目标采用本次部门更新文件的 6,950 万元口径。'
ws['D17'].font = font(8.5, False, 'B7C9DE')
ws.merge_cells('D17:J17')
ws['D19'] = '宝锐生物  BIORI BIOTECH'
ws['D19'].font = font(11, True, 'FFFFFF')
ws['D20'] = '守护生命健康，缔造美好生活'
ws['D20'].font = font(14, True, 'FFFFFF')
ws['D22'] = '内部资料 · 2026-11-09'
ws['D22'].font = font(8.5, False, 'B7C9DE')

# ================= 01 总览 =================
ws = wb.create_sheet('01_总览')
title(ws, '一、三部门年度目标与10月达成',
      '金额单位：万元；年度目标与10月目标取自部门月度数据看板；同比为2026年对2025年同口径。', 10)
header(ws, 4, ['部门', '年度目标', '1-10月实际', '年度达成率', '年度缺口',
               '10月实际', '10月目标', '10月达成率', '10月同比', '1-10月同比'],
       [16, 12, 13, 11, 12, 11, 11, 11, 11, 12])
r = 5
for k in DEPT_ORDER:
    v = D[k]
    ytd_rate = v['actual'] / v['target']
    oct_rate = v['months'][-1] / v['oct_target']
    oct_yoy = (v['months'][-1] / v['y25_oct'] - 1) if v['y25_oct'] else None
    ytd_yoy = (v['actual'] / v['y25_ytd'] - 1) if v['y25_ytd'] else None
    vals = [k, v['target']/1e4, v['actual']/1e4, ytd_rate, (v['target']-v['actual'])/1e4,
            v['months'][-1]/1e4, v['oct_target']/1e4, oct_rate,
            oct_yoy if oct_yoy is not None else '—',
            ytd_yoy if ytd_yoy is not None else '—']
    body_row(ws, r, vals, height=27)
    for c in (2, 3, 5, 6, 7):
        fmt_num(ws.cell(r, c))
    for c in (4, 8):
        fmt_pct(ws.cell(r, c))
    for c in (9, 10):
        if isinstance(ws.cell(r, c).value, (int, float)):
            fmt_pct(ws.cell(r, c))
            if ws.cell(r, c).value < 0:
                ws.cell(r, c).font = font(9.5, True, RED)
    # 达成率低于50%标红
    if ytd_rate < 0.5:
        ws.cell(r, 4).font = font(9.5, True, RED)
    r += 1
# 两部门同口径（生命科学部无2025同期）
vals = ['两部门同口径（大客户+拓展）', TWO_TARGET/1e4, TWO_ACTUAL/1e4, TWO_ACTUAL/TWO_TARGET,
        (TWO_TARGET-TWO_ACTUAL)/1e4, TWO_OCT/1e4, TWO_OCT_TARGET/1e4,
        TWO_OCT/TWO_OCT_TARGET, TWO_OCT/TWO_25_OCT-1, TWO_ACTUAL/TWO_25_YTD-1]
body_row(ws, r, vals, bold=False, fill_color='F8FBFF', height=26)
for c in (2, 3, 5, 6, 7):
    fmt_num(ws.cell(r, c))
for c in (4, 8, 9, 10):
    fmt_pct(ws.cell(r, c))
ws.cell(r, 1).font = font(9.5, True, BLUE)
r += 1
# 合计
vals = ['三部门合计', TOTAL_TARGET/1e4, TOTAL_ACTUAL/1e4, TOTAL_ACTUAL/TOTAL_TARGET,
        (TOTAL_TARGET-TOTAL_ACTUAL)/1e4, TOTAL_OCT/1e4, TOTAL_OCT_TARGET/1e4,
        TOTAL_OCT/TOTAL_OCT_TARGET, '—', '—']
body_row(ws, r, vals, bold=True, fill_color='E8F1FC', height=28)
for c in (2, 3, 5, 6, 7):
    fmt_num(ws.cell(r, c), 2)
for c in (4, 8):
    fmt_pct(ws.cell(r, c))
r += 2

# 关键观察
ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=10)
c = ws.cell(r, 1, '关键观察（数据事实）')
c.font = font(11, True, NAVY)
c.fill = fill('E8F1FC')
c.alignment = Alignment(vertical='center')
ws.row_dimensions[r].height = 24
r += 1
observations = [
    '10月两部门同口径（大客户+拓展）370.80 万元，同比 -12.0%；三部门合计 375.09 万元，生命科学部无2025年同期，不计算三部门合计同比。',
    '1-10月累计 3,691.90 万元；两部门同口径同比 +20.1%；三部门合计目标 6,950.00 万元，达成 53.1%，缺口 3,258.10 万元。',
    '部门年度达成分化：销售拓展部 72.1%、大客户部 45.3%、生命科学部 4.5%。',
    '10月目标达成：销售拓展部 60.1%、大客户部 19.6%、生命科学部 1.0%；三部门合计 27.0%。',
    '10月同比：大客户部 -47.8%，销售拓展部 +20.1%；生命科学部无2025年同月数据，不计算同比。',
]
for text in observations:
    ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=10)
    c = ws.cell(r, 1, '• ' + text)
    c.font = font(9.5, False, '1F2937')
    c.alignment = Alignment(vertical='center', wrap_text=True)
    ws.row_dimensions[r].height = 22
    r += 1

ws.merge_cells(start_row=r+1, start_column=1, end_row=r+1, end_column=10)
c = ws.cell(r+1, 1, '口径提示：年度目标合计 6,950 万元（2026 年度目标责任书确认：诊断原料 6,050 万元 + 生命科学 900 万元）；既有 6,650 万元为主数据未同步的旧口径，详见 06_口径与数据源。')
c.font = font(8.8, True, RED)
c.fill = fill('FDE9E7')
c.alignment = Alignment(vertical='center', wrap_text=True)
ws.row_dimensions[r+1].height = 34

# ================= 02 月度趋势 =================
ws = wb.create_sheet('02_月度趋势')
title(ws, '二、2026年1-10月销售额月度趋势',
      '金额单位：万元；取各部门年度表“实际完成”行；合计=三部门加总。', 6)
header(ws, 4, ['月份', '大客户部', '销售拓展部', '生命科学部', '三部门合计', '合计环比'],
       [10, 15, 15, 15, 15, 12])
for i in range(10):
    m = f'{i+1}月'
    mom = (TOTAL_MONTHS[i] / TOTAL_MONTHS[i-1] - 1) if i > 0 and TOTAL_MONTHS[i-1] else None
    vals = [m, D['大客户部']['months'][i]/1e4, D['销售拓展部']['months'][i]/1e4,
            D['生命科学部']['months'][i]/1e4, TOTAL_MONTHS[i]/1e4,
            mom if mom is not None else '—']
    body_row(ws, 5+i, vals, height=23)
    for c in (2, 3, 4, 5):
        fmt_num(ws.cell(5+i, c))
    if mom is not None:
        fmt_pct(ws.cell(5+i, 6))
        if mom < 0:
            ws.cell(5+i, 6).font = font(9.5, True, RED)
# 10月环比 row
m = '10月环比'
body_row(ws, 15, [m, D['大客户部']['months'][-1]/D['大客户部']['months'][-2]-1,
                  D['销售拓展部']['months'][-1]/D['销售拓展部']['months'][-2]-1,
                  D['生命科学部']['months'][-1]/D['生命科学部']['months'][-2]-1,
                  TOTAL_MONTHS[-1]/TOTAL_MONTHS[-2]-1, '—'],
         bold=True, fill_color='E8F1FC', height=23)
for c in (2, 3, 4, 5):
    fmt_pct(ws.cell(15, c))
    if ws.cell(15, c).value < 0:
        ws.cell(15, c).font = font(9.5, True, RED)
note(ws, 17, '注：生命科学部2025年同期数据未随本次部门数据提供，因此不计算该部门同比；三部门合计同比仅按大客户部+销售拓展部的2025年同期计算，生命科学部未纳入同比分母。', 6, height=34)

# ================= 03 过程指标 =================
ws = wb.create_sheet('03_过程指标')
title(ws, '三、10月过程指标',
      '数据取自三部门“过程指标（月度绩效）达成情况”表；过程表与年度表金额存在原表差异，本表同时列示。', 15)
header(ws, 4, ['部门', '客户拜访数', 'NGS客户拜访', '测试单发放（订单数）', '发放货号数',
               '反馈数', '反馈率', 'NGS测试单数', 'NGS订单数', '销售订单数',
               '过程表订单金额', '年度表10月金额', '差异(元)', '新客户开发', '新客户成交'],
       [16, 10, 10, 12, 10, 8, 9, 11, 10, 10, 14, 14, 10, 10, 10], height=42)
r = 5
for k in DEPT_ORDER:
    p = PROC[k]
    vals = [k, p['visits'], p['ngs_visits'] if p['ngs_visits'] else '—',
            p['tests'], p['sku_sent'] if p['sku_sent'] else '—', p['feedback'],
            p['feedback_rate'], p['ngs_tests'] if p['ngs_tests'] else '—',
            p['ngs_orders'] if p['ngs_orders'] else '—', p['orders'],
            p['proc_amount']/1e4, p['annual_amount']/1e4,
            round(p['proc_amount'] - p['annual_amount'], 2),
            p['new_dev'] if p['new_dev'] is not None else '—',
            p['new_deal'] if p['new_deal'] is not None else '—']
    body_row(ws, r, vals, height=28)
    for c in (11, 12):
        fmt_num(ws.cell(r, c))
    fmt_num(ws.cell(r, 13), 2)
    fmt_pct(ws.cell(r, 7))
    if isinstance(ws.cell(r, 13).value, (int, float)) and ws.cell(r, 13).value != 0:
        ws.cell(r, 13).font = font(9.5, True, ORANGE)
    r += 1
note(ws, 9, '注1：大客户部反馈数37大于测试单发放34，反馈率108.8%，为原表口径；未做截断。', 15, height=22)
note(ws, 10, '注2：生命科学部反馈率按发放货号数180计算（原表口径），不是按测试单订单数119计算。', 15, height=22)
note(ws, 11, '注3：过程表订单金额与年度表10月金额差：大客户部 -1,040 元，生命科学部 +800 元，销售拓展部一致；原表未对平，月报引用时建议以年度表金额为准。', 15, color=ORANGE, height=34)

# ================= 04 绩效 =================
ws = wb.create_sheet('04_绩效')
title(ws, '四、10月绩效得分',
      '数据取自各部门“销售工程师/区域销售经理考核分数通报（2026年10月）”；仅列已结算得分。', 6)
header(ws, 4, ['部门', '姓名', '岗位', '10月绩效得分', '备注'], [16, 12, 16, 14, 38])
r = 5
for dept, name, role, score, remark in PERF:
    vals = [dept, name, role, score, remark]
    body_row(ws, r, vals, height=23)
    ws.cell(r, 4).number_format = '0.0'
    r += 1
# 拓展备注行
body_row(ws, r, ['销售拓展部', '—', '销售工程师（11人）', 90.1,
                 '10月总得分列全部为90.1，疑似模板占位/未结算，未纳入部门均分；建议向部门确认'],
         height=32)
ws.cell(r, 4).number_format = '0.0'
ws.cell(r, 4).font = font(9.5, True, ORANGE)
r += 2
ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=5)
ws.cell(r, 1, '已结算均分：大客户部 91.4 分；生命科学部销售工程师 67.7 分；生命科学部区域经理 64.0 分。').font = font(9.5, True, NAVY)
ws.cell(r, 1).fill = fill('E8F1FC')
ws.cell(r, 1).alignment = Alignment(vertical='center')
ws.row_dimensions[r].height = 24

# ================= 05 重点客户 =================
ws = wb.create_sheet('05_重点客户')
title(ws, '五、2026年1-10月重点客户TOP10',
      '金额单位：万元；按客户名称口径；集团列为空表示源表未填集团。', 7)
r = 4
for dept in ['大客户部', '销售拓展部']:
    ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=7)
    c = ws.cell(r, 1, f'{dept}｜2026年1-10月销售额TOP10')
    c.font = font(11, True, NAVY)
    c.fill = fill('E8F1FC')
    c.alignment = Alignment(vertical='center')
    ws.row_dimensions[r].height = 24
    r += 1
    header(ws, r, ['排名', '集团', '客户名称', '销售员', '2026 1-10月销售额', '占部门累计', '备注'],
           [8, 16, 38, 10, 16, 12, 18])
    r += 1
    total = D[dept]['actual']
    for rank, group, customer, sales, amount in TOP[dept]:
        vals = [rank, group or '—', customer, sales, amount/1e4, amount/total, '']
        body_row(ws, r, vals, height=23)
        fmt_num(ws.cell(r, 5))
        fmt_pct(ws.cell(r, 6))
        ws.cell(r, 2).alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        r += 1
    top_sum = sum(x[4] for x in TOP[dept])
    vals = ['TOP10合计', '', '', '', top_sum/1e4, top_sum/total, f'占部门累计 {top_sum/total:.1%}']
    body_row(ws, r, vals, bold=True, fill_color='F3F7FC', height=24)
    fmt_num(ws.cell(r, 5)); fmt_pct(ws.cell(r, 6))
    r += 2
note(ws, r, '生命科学部本次数据未提供客户级2026年1-10月销售额排名，暂不列TOP10。', 7, height=22)

# ================= 06 口径与数据源 =================
ws = wb.create_sheet('06_口径与数据源')
title(ws, '六、口径、数据源与待确认事项', '本表只提炼，不修改源数据；月报引用时建议同时标注数据源与口径。', 3)
header(ws, 4, ['项目', '内容', '处理建议'], [22, 70, 34])
rows = [
    ('统计期间', '2026年1月1日—2026年10月31日；10月数据截止10月31日。', '月报统一使用该期间。'),
    ('金额口径', '部门数据看板“实际完成”行，单位为元；本册换算为万元，保留2位小数。', '引用时注明“部门数据看板口径”。'),
    ('年度目标', '大客户部 2,650 万；销售拓展部 3,400 万；生命科学部 900 万；合计 6,950 万。', '2026 年度目标责任书确认的正式口径。'),
    ('目标口径差异', '2026 责任书确认：诊断原料 6,050 万 + 生命科学 900 万 = 6,950 万；数据/目标基础数据_2026.json 仍为生命科学 600 万、合计 6,650 万。', '6,650 为未同步旧口径；是否统一更新主数据，需确认后再改看板与KPI。'),
    ('10月合计', '三部门合计 375.09 万元。', '与旧月度数据 386.48 万元相差 -11.39 万元，本册采用本次更新版部门数据。'),
    ('10月同比', '大客户部 -47.8%；销售拓展部 +20.1%；两部门同口径 -12.0%。', '生命科学部无2025年同期，不计算三部门合计同比。'),
    ('1-10月同比', '大客户部 -2.3%；销售拓展部 +35.4%；两部门同口径 +20.1%。', '三部门合计不计算同比，生命科学部无2025年同期。'),
    ('过程表差异', '大客户部过程金额 1,037,934.20，年度表 1,038,974.20，差 -1,040 元；生命科学部过程金额 43,669.80，年度表 42,869.80，差 +800 元；销售拓展部一致。', '月报金额以年度表为准；过程金额只用于过程指标。'),
    ('绩效口径', '大客户部、生命科学部10月得分已结算；销售拓展部10月总得分列全部90.1，疑似模板占位。', '拓展部绩效得分不纳入部门均分，需向部门确认。'),
    ('生命科学部历史', '本次未提供2025年同期客户/销售数据，无法计算同比。', '如需同比，补2025年1-10月生命科学部数据。'),
    ('数据源1', '10月大客户及科研/1、2026月度数据-诊断原料大客户销售部.xlsx', '年度指标、近三年、过程指标、TOP客户。'),
    ('数据源2', '10月销售拓展部数据/10月份/2、2026月度数据-诊断原料销售拓展部.xlsx', '年度指标、近三年、过程指标、TOP客户。'),
    ('数据源3', '10月大客户及科研/3、2026月度数据-生命科学销售部.xlsx', '年度指标、区域/个人、过程指标。'),
    ('数据源4', '绩效/大客户销售部-销售工程师考核分数通报（2026年10月）.xlsx', '10月绩效得分。'),
    ('数据源5', '绩效/生命科学销售部-各区域销售工程师考核分数通报（2026年10月）.xlsx', '10月销售工程师绩效得分。'),
    ('数据源6', '绩效/生命科学销售部-区域销售经理考核分数通报（2026年10月）.xlsx', '10月区域经理绩效得分。'),
    ('数据源7', '绩效/销售拓展部销售工程师考核分数通报（2026年10月）(1).xlsx', '10月绩效；总得分列疑似占位。'),
]
r = 5
for item, content, suggestion in rows:
    vals = [item, content, suggestion]
    body_row(ws, r, vals, height=34)
    ws.cell(r, 1).font = font(9.5, True, NAVY)
    ws.cell(r, 2).alignment = Alignment(horizontal='left', vertical='center', wrap_text=True)
    ws.cell(r, 3).alignment = Alignment(horizontal='left', vertical='center', wrap_text=True)
    if item in ('目标口径差异', '过程表差异', '绩效口径'):
        for c in range(1, 4):
            ws.cell(r, c).fill = fill('FDE9E7')
    r += 1

# 页面设置 / 打印
for ws in wb.worksheets:
    ws.sheet_view.showGridLines = False
    ws.page_setup.orientation = 'landscape'
    ws.page_setup.fitToWidth = 1
    ws.page_setup.fitToHeight = 0
    ws.sheet_properties.pageSetUpPr.fitToPage = True

os.makedirs(os.path.dirname(OUT), exist_ok=True)
wb.save(OUT)
print(OUT)
print('total target', TOTAL_TARGET, 'total actual', TOTAL_ACTUAL, 'oct', TOTAL_OCT)
