# -*- coding: utf-8 -*-
r"""B187: portal KPH tuần 3 — (1) chèn 5 khối MỚI, (2) 5 panel 'Bổ sung 14/10' vào khối đã có,
(3) cập nhật số vụ 42->47 ở 3 chỗ, (4) cập nhật portal_map.json. Atomic + verify BeautifulSoup.
KHÔNG dùng %-format (tránh bẫy '%' trong HTML)."""
import io, json, os, re, shutil, datetime

GOC = r'C:\Claw 2\Bao cao - Hanh chinh\BAOCAOTONGHOP\HTML\KPH_TongHop_0508'
PORTAL = os.path.join(GOC, 'index.html')
MAP = r'C:\claw\Khieu Nai KHach Hang\portal_map.json'   # cạnh server_kph.py (theo skill)
TS = datetime.datetime.now().strftime('%Y%m%d_%H%M')

b = io.open(PORTAL, encoding='utf-8').read()
print('  portal truoc: %d byte | khoi=%d | LF=%d CRLF=%d' % (len(b.encode()), b.count('class="inc"'), b.count('\n'), b.count('\r\n')))
shutil.copy2(PORTAL, PORTAL + '.bak_' + TS + '_truoc_kph_tuan3')
shutil.copy2(MAP, MAP + '.bak_' + TS)
h = b

SRC_BGĐ = 'Bảng theo dõi sự cố BGĐ tuần 3 tháng 10/2026 (12-14/10/2026)'


def khoi(no, slug, tieu, phu, nm, mau, ls, st, src, mo_tieude=''):
    L = ['    <!-- ============ ' + str(no) + '. ' + slug + ' ============ -->',
         '    <div class="inc" id="' + slug + '" data-st="' + st + '">',
         '      <div class="inc-head"><span class="no">' + str(no) + '</span><div class="tt"><h3>' + tieu + '</h3><span>' + phu + '</span></div><span class="chev">▾</span></div>',
         '      <div class="inc-body">',
         '        <div class="kv">',
         '          <div><b>Nhà máy:</b> ' + nm + '</div>',
         '          <div><b>Sản phẩm/màu:</b> ' + mau + '</div>',
         '        </div>']
    if mo_tieude:
        L.append('        <div class="sub">' + mo_tieude + '</div>')
    L.append('        <div class="txt"><ul>')
    for x in ls:
        L.append('          <li>' + x + '</li>')
    L.append('        </ul></div>')
    L.append('        <p class="src">' + src + '</p>')
    L.append('      </div>')
    L.append('    </div>')
    return '\n'.join(L) + '\n'


MOI = [
    khoi(43, 'tanviettien-tvtwhite', 'Tân Việt Tiến — Màu TVT White ngả vàng (đơn sản xuất 13/08/26)',
         'KPH mới 12/10 · QC đã có số đo màu · chưa có báo cáo xử lý của Kỹ thuật',
         'Tân Việt Tiến', 'Màu TVT White',
         ['<b>Mail phản ánh:</b> đơn hàng sản xuất ngày <b>13/08/26</b> khách hàng phản ánh bị <b>ngả vàng</b>.',
          '<b>QC báo:</b> quy trình sau khi tái chế phun <b>1 path</b> và tái chế phun <b>2 paths</b> sơn màu so với quy trình chuẩn — <b>“màu sắc có sự chênh lệch nhưng không khác biệt nhiều”</b>.',
          '<b>Kết quả đo màu</b> (máy X-Rite, sau 18 giờ — Báo cáo kiểm tra số <b>01-1026</b> ngày 14/10/2026): sản xuất thực tế <b>L 95,70 · a -0,18 · b 7,97</b>; tái chế 1 path <b>L 95,55 · a -0,16 · b 7,71 · ΔE 0,30</b>; tái chế 2 paths <b>L 95,34 · a -0,28 · b 7,28 · ΔE 0,70</b>.',
          '⚠️ <b>Chưa có báo cáo xử lý của Kỹ thuật</b>; chưa chốt ngưỡng ΔE nội bộ cho màu trắng/trắng ngà.'],
         'new', SRC_BGĐ + ' · Báo cáo kiểm tra 01-1026 (QC, 14/10/2026)',
         'Phản ánh: khách hàng gửi mail — đơn sản xuất ngày 13/08/26 bị ngả vàng (12/10/2026)'),
    khoi(44, 'hanhphuc-hp269', 'Hạnh Phúc — Màu HP 269 độ nhớt thấp',
         'KPH 14/09 · Kỹ thuật chưa cập nhật thông tin mới (14/10)',
         'Hạnh Phúc', 'HP 269',
         ['<b>Nội dung:</b> độ nhớt thấp (KPH <b>14/09/2026</b>).',
          '<b>KPPN:</b> KT cập nhật lại tỉ lệ pha của lót <b>NC T 2012 là 1:1.5</b> và báo cáo lại cho sếp Tâm.',
          '<b>Tiến độ 14/10:</b> KT <b>chưa cập nhật thông tin mới</b>.'],
         'watch', SRC_BGĐ),
    khoi(45, 'hanhmy-bex032402', 'Hành Mỹ — Bóng Bex 03-2402 H 25% (BC) sai độ bóng so với mẫu gốc',
         'KPH mới 12/10 · QC đang kiểm tra · chưa có báo cáo xử lý',
         'Hành Mỹ', 'Bóng Bex 03-2402 H 25% (BC) — Tumbling BC',
         ['<b>Mail phản ánh + KT báo:</b> độ bóng láng bề mặt sản phẩm <b>không đạt so với mẫu gốc</b>.',
          '<b>Vật tư liên quan:</b> Bóng <b>Bex 03-2402 H 25% Tumbling BC</b> (nsx: <b>19/09</b>, <b>30/09</b>) — SL: <b>140 kg</b>.',
          '<b>Tiến độ 14/10:</b> QC đang kiểm tra; chưa có báo cáo xử lý.',
          '🔗 <b>Liên hệ nội bộ:</b> cùng sản phẩm Bóng Bex 03-2402 H 25% BC với hồ sơ <b>KPH 59-26</b> (lỗi khác: lỗi sản phẩm sau ~50 ngày lưu kho) — <b>không gộp vụ</b>.'],
         'new', SRC_BGĐ),
    khoi(46, 'mekong3-mk1217h', 'Mekong 3 — Màu MK 12/17 H: sản phẩm hoàn thiện không đều màu giữa các nền phôi',
         'KPH 06/10 · KT đã sơn thử 10 chi tiết hàng rời (14/10)',
         'Mekong 3', 'MK 12/17 H',
         ['<b>Phản ánh:</b> sản phẩm hoàn thiện <b>không đều màu</b> (KPH <b>06/10/2026</b>).',
          '<b>Số đo màu (máy X-Rite, 07 nền, 09/10):</b> primer trắng chênh lệch nhiều, nhiều nhất <b>ΔE 6,96</b>; hoàn thiện quy trình <b>ΔE 1,61</b>; giữa các nền MDF primer <b>ΔE 1,25 → 3,98</b>, hoàn thiện <b>0,16 → 1,37</b> ⇒ <b>có sự chênh lệch màu sắc khi thực hiện quy trình trên các nền với nhau</b>.',
          '<b>Nội dung cần bổ sung:</b> báo cáo tổng hợp.',
          '<b>BGĐ chỉ đạo:</b> thử thêm <b>5% paste trắng 3012 H</b> vào <b>Primer BT 02-2203 H (white)</b>.',
          '<b>Tiến độ 14/10:</b> KT đã sơn thử nghiệm lên <b>10 chi tiết hàng rời</b> — kết quả <b>tương đối đồng màu</b> khi ráp lại trên cùng 1 sản phẩm tủ.'],
         'watch', SRC_BGĐ + ' · QC Lộc (số đo màu 09/10/2026)'),
    khoi(47, 'minhhungtien-mht02', 'Minh Hưng Tiến — Màu MHT 02 (AX 123) dính vết giấy tổ ong',
         'KPH 09/05 (hồ sơ KPH 35-26) · Kỹ thuật chưa cập nhật thông tin mới (14/10)',
         'Minh Hưng Tiến', 'MHT 02 (AX 123)',
         ['<b>KPH 09/05/2026</b> — dính vết giấy tổ ong (hồ sơ <b>KPH 35-26</b>).',
          '<b>Nội dung cần bổ sung:</b> cập nhật quy trình đóng gói; cập nhật và theo dõi lại quy trình màu MHT 02 (KT).',
          '<b>KPPN:</b> KT phải kết luận cho BGĐ — chốt với khách hàng, thử theo quy trình mới kết quả có làm được hay không?',
          '<b>Tiến độ 14/10:</b> KT <b>chưa cập nhật thông tin mới</b>.'],
         'watch', SRC_BGĐ),
]

i_sec = h.rfind('</section>')
assert i_sec > 0, 'khong thay </section>'
them = '\n'.join(MOI)
h = h[:i_sec] + them + h[i_sec:]
print('  da chen %d khoi moi truoc </section> (vi tri %d)' % (len(MOI), i_sec))

# ── PANEL bổ sung 14/10 vào khối đã có (neo: p.src CUỐI của khối) ────────
PANEL = {
    'tienhung-tth270': ['<b>Nội dung cần bổ sung:</b> kết quả kiểm tra lần sản xuất thứ nhất sau quy định được thống nhất (KT); QC xác nhận đã nhận thẻ màu theo nội dung đã thống nhất với khách hàng.',
                        '<b>KPPN:</b> kỹ thuật up thẻ mẫu đầu chuyền có các giá trị Lab và chữ ký khách hàng; mang thẻ mẫu về cho QC ghi nhận và theo dõi.',
                        '<b>Tiến độ 14/10:</b> KT <b>chưa cập nhật thông tin mới</b>.'],
    'thanhthang-thth91': ['<b>KPPN:</b> RD điều chỉnh lại công thức; QC2 điều chỉnh lại phương pháp kiểm tra.',
                          '<b>Tiến độ 14/10:</b> QC2 kiểm tra bóng <b>NC Mod 1106 30%</b> — kết quả màng sơn <b>bị đục</b>; chuyển RD xem lại và điều chỉnh.'],
    'danglong-dlo11': ['<b>Nội dung cần bổ sung:</b> điều chỉnh lại quy trình và công thức glaze màu (KT); báo cáo sản xuất các lô tiếp theo.',
                       '<b>BGĐ chỉ đạo:</b> QC xuống nhà máy kiểm tra thực tế sản xuất và lấy mẫu về công ty kiểm tra.',
                       '<b>Tiến độ 14/10:</b> khi nào nhà máy chạy đơn hàng màu này trên gỗ MDF, QC sẽ xuống kiểm tra.'],
    'mekong3': ['<b>Nội dung cần bổ sung (KPH 13/08 — lót SW2-2108 H trắng, màu 17/17 H):</b> RD điều chỉnh lại lớp lót; KT điều chỉnh lại quy trình.',
                '<b>Tiến độ 14/10:</b> RD làm mẫu và đưa KT thử nhưng <b>chưa chốt được kết quả</b>.'],
    'tv': ['<b>Nội dung cần bổ sung (KPH 23/07 — TVIET 246 / TVIET 299A dính foam):</b> làm lại quy trình các màu đang bị khiếu nại dính mặt (KT).',
           '<b>KPPN:</b> quy trình mới màu <b>TVIET 299A chưa có</b>.',
           '<b>Tiến độ 14/10:</b> KT <b>chưa cập nhật thông tin mới</b>.'],
}
for slug, ls in PANEL.items():
    i_blk = h.find('id="' + slug + '"')
    assert i_blk > 0, 'khong thay khoi ' + slug
    i_end = h.find('<!-- ============', i_blk + 10)
    if i_end < 0:
        i_end = len(h)
    srcs, pos = [], i_blk
    while True:
        k = h.find('<p class="src">', pos)
        if k == -1 or k > i_end:
            break
        srcs.append(k); pos = k + 15
    assert srcs, 'khoi ' + slug + ' khong co p.src'
    i_ins = srcs[-1]
    P = ('        <div class="sub">📎 Bổ sung 14/10/2026 — bảng theo dõi sự cố BGĐ tuần 3 tháng 10/2026</div>\n'
         '        <div class="txt"><ul>\n'
         + ''.join('          <li>' + x + '</li>\n' for x in ls)
         + '        </ul></div>\n'
         '        <p class="src">' + SRC_BGĐ + '</p>\n')
    h = h[:i_ins] + P + h[i_ins:]
    print('  da chen panel vao khoi %-20s (%d p.src trong khoi)' % (slug, len(srcs)))

# ── số vụ 42 -> 47 ở 3 chỗ ───────────────────────────────────────────────
n_khoi = h.count('class="inc"')
print('  so khoi sau khi chen: %d' % n_khoi)
for cu, moi_, n in (('<small>42 vụ việc</small>', '<small>' + str(n_khoi) + ' vụ việc</small>', 1),
                    ('badge">🏭 42 vụ việc / khách hàng', 'badge">🏭 ' + str(n_khoi) + ' vụ việc / khách hàng', 1),
                    ('42 vụ — ', str(n_khoi) + ' vụ — ', 1)):
    cnt = h.count(cu)
    assert cnt == n, 'so vu: %r xuat hien %d lan (mong %d)' % (cu, cnt, n)
    h = h.replace(cu, moi_)
    print('  so vu: %r -> %r' % (cu[:40], moi_[:40]))

io.open(PORTAL + '.tmp_ghi', 'w', encoding='utf-8', newline='').write(h)
os.replace(PORTAL + '.tmp_ghi', PORTAL)
print('  da ghi portal: %d byte (tang %d)' % (len(h.encode()), len(h.encode()) - len(b.encode())))

# ── portal_map.json ─────────────────────────────────────────────────────
m = json.load(io.open(MAP, encoding='utf-8'))
print('  portal_map keys:', list(m.keys()))
for kk in ('by_hoso', 'by_kph'):
    if isinstance(m.get(kk), dict):
        m[kk].update({'829': 'tanviettien-tvtwhite', '830': 'hanhphuc-hp269', '831': 'hanhmy-bex032402'}) if kk == 'by_hoso' else None
io.open(MAP + '.tmp_ghi', 'w', encoding='utf-8').write(json.dumps(m, ensure_ascii=False, indent=1))
os.replace(MAP + '.tmp_ghi', MAP)
print('  da cap nhat portal_map.json')
