ข้ามไปที่เนื้อหา

แผน Q5 — roots_hemms_ha_report (Final 1.0)

เวอร์ชันแผน: Final 1.0 — อนุมัติแล้ว, พร้อมดำเนินการ อนุมัติ: 2026-05-22 Module ID: roots_hemms_ha_report Layer: 3 (เลนส์โรงพยาบาล) — depends on Q1 (PM), Q3 (สัญญา, ทางอ้อมผ่าน signature), Q4 (roots_hemms_signature) การ implement: Q5.1–Q5.12 ship ตามลำดับ, ไม่มี blocker ภายนอก (Q3 + Q4 ship แล้ว)

0. บทสรุปผู้บริหาร

สิ่งที่เราสร้าง: โมดูล Layer 3 ใหม่ roots_hemms_ha_report ที่ ผลิต PDF รายงานการบำรุงรักษาเชิงป้องกันประจำปี ซึ่งกำหนดโดย HA Thailand และมาตรฐาน MoPH มาตรฐานระบบบริการสุขภาพ ด้านที่ 6 รายงานรวมข้อมูล PM ที่ Q1 จับไว้แล้ว, จัดประเภทเครื่องมือแพทย์ทุกชิ้น ตามโมเดลความเสี่ยง 3 ระดับของ MoPH (สูง / กลาง / ต่ำ), แสดง PM ตามแผน vs ทำจริง ต่อเครื่องมือแพทย์สำหรับหนึ่งปีงบประมาณไทย (ปีงบประมาณ), ล็อกผ่านสแน็ปช็อต JSON เมื่อ submit, และวิ่งผ่านสะพาน sign_oca ของ Q4 สำหรับการลงนามของหัวหน้า BME + หัวหน้าวิศวกรรม + ผู้อำนวยการ

ทำไม: วันนี้วิศวกร BME สร้างรายงานนี้ใหม่ด้วยมือใน Excel ทุกปี — งาน 2–4 สัปดาห์ที่มีโอกาสผิดพลาดและเปราะต่อการตรวจสอบ ผู้สำรวจขอเอกสารนี้ในวันแรกของการเยี่ยม HA Thailand; การผลิตไม่ได้ทำให้การรับรองล่าช้า Q5 เปลี่ยนข้อมูล PM ของ Q1 เป็น ผลผลิตการปฏิบัติตามข้อกำหนดในคลิกเดียว, จับคู่กับการตรวจสอบทรัพย์สิน ประจำปี ปจป. ที่มีอยู่ (roots_hemms_asset_inspection) เพื่อให้ HEMMS ครอบคลุม ทั้งสอง รายงานการปฏิบัติตามข้อกำหนดสิ้นปีที่โรงพยาบาลรัฐไทยต้องผลิต

ความพยายาม: 12 commit / ~2 เซสชันพัฒนา, เป้าหมายการทดสอบ 20 รายการ, เอกสาร 5 หน้า, สาธิต 1 ปีงบประมาณ (30 เครื่องมือแพทย์ × 3 แผนก, ~78% การปฏิบัติตามแผน พร้อม 3 ข้อยกเว้นที่บันทึกไว้)

ชัยชนะหลัก (จัดลำดับตามผลกระทบ):

  1. รายงานประจำปีในคลิกเดียว (Q5.7 + Q5.8) — วิซาร์ดสร้าง สร้าง line จากข้อมูล PM, QWeb render PDF รูปแบบราชการ 7-section เต็มรูปแบบ
  2. seed ระดับความเสี่ยง 83 อุปกรณ์ของ MoPH (Q5.2) — ทุกโรงพยาบาลได้ ตารางการจัดประเภทอย่างเป็นทางการมาทันที; แก้ไขได้สำหรับ การเพิ่มเติมในพื้นที่
  3. คะแนน EM แบบ WHO Fennigkoh-Smith บนฟอร์มเครื่องมือแพทย์ (Q5.3) — 4 slider + คะแนนสดให้วิศวกร BME จัดประเภทเครื่องมือแพทย์ นอกรายการได้ในไม่กี่วินาที, พร้อมเก็บแผ่นงานคะแนนไว้ใน ภาคผนวก ข เป็นหลักฐานสำหรับผู้ตรวจสอบ
  4. การลงนามผ่านสะพาน Q4 (Q5.9) — หัวหน้า BME + หัวหน้าวิศวกรรม
  5. ผู้อำนวยการ ลงนามในแอปหรือผ่านอีเมล portal; PDF ที่เซ็นแล้วแนบ อัตโนมัติไปยัง chatter; ไม่มี state แยก, ป้ายแสดง 🟡 รอลงนาม / 🟢 ลงนามครบ
  6. สแน็ปช็อต lock-on-submit (Q5.6) — การพิมพ์ซ้ำ byte เหมือนกัน แม้ข้อมูลเครื่องมือแพทย์ที่อยู่เบื้องหลังจะเปลี่ยน; ป้องกันได้ในการตรวจสอบ

License: LGPL-3 (wrapper) เหนือ dependency แบบ AGPL-3 แบบ transitive (sign_oca ผ่าน Q4) รูปแบบเขตแดนเดียวกับ Q2.1 / Q3 / Q4

สถานะของคำถามที่ยังเปิด: ทั้ง 6 ข้อแก้ไขแล้ว 2026-05-22 — OQ-A สะพานต่อโมเดล (ไม่มี mixin); OQ-B baseline noupdate="1"; OQ-C 4 slider บนฟอร์มเครื่องมือแพทย์; OQ-D ไม่จำกัดการลงนามซ้ำ; OQ-E ใช้ fixture Q4.6 ซ้ำ; OQ-F Q5 = HA Report, รายการสัญญาตามต่อ → Q6 ดู §8


1. วัตถุประสงค์

โรงพยาบาลรัฐไทยถูกกำหนดโดย ประกาศกระทรวงสาธารณสุข เรื่อง การกำหนดลักษณะของสถานพยาบาลและมาตรฐานมาตรฐานระบบบริการสุขภาพ ด้านที่ 6 ข้อ 6.1.4 ให้คงทะเบียนเครื่องมือแพทย์ปัจจุบัน AND ทำการบำรุงรักษาเชิงป้องกันตามความเสี่ยงพร้อมหลักฐานที่บันทึกไว้ ผู้สำรวจ HA Thailand ขอหลักฐานประจำปีในวันแรก

มาตรฐานที่ผูกพัน:

"แนวทางประเมินระดับความเสี่ยงของเครื่องมือแพทย์ที่ต้องการการบำรุงรักษา และกำหนดความถี่ในการตรวจสอบและบำรุงรักษาเชิงป้องกันตามรอบเวลา (พ.ศ. 2564)" — กองวิศวกรรมการแพทย์, กรมสนับสนุนบริการสุขภาพ, กระทรวงสาธารณสุข, co-developed with บริษัท อาร์เอฟเอส (รามาธิบดี/ม.มหิดล) and ECRI APAC.

ไม่มี PDF แบบฟอร์ม อย่างเป็นทางการเดียว — โรงพยาบาลสร้างเลย์เอาต์ของตนเอง ที่พิสูจน์จุดข้อมูลเหล่านี้ Q5 implement เลย์เอาต์นั้นใน QWeb, สไตล์ราชการไทยสอดคล้องกับรายงาน ปจป. ที่มีอยู่

ขอบเขต — ที่รวม

  • Q5.1: โครงโมดูล, manifest, ir.sequence (HA/%(year)s/00001), paperformat (A4, TH Sarabun, ระยะขอบราชการไทย)
  • Q5.2: โมเดลคำศัพท์ hemms.ha.device.class + seed 83 อุปกรณ์ของ MoPH (ระดับต่ำ/กลาง/สูง, freq เดือน, duration ชั่วโมง), noupdate="1"
  • Q5.3: ส่วนขยาย maintenance.equipment:
  • roots_risk_tier (Selection high/medium/low)
  • roots_pm_freq_months (Integer)
  • device_class_id (M2O hemms.ha.device.class)
  • roots_em_function / roots_em_application / roots_em_maintenance / roots_em_history (Integer slider)
  • roots_em_score (Integer, computed/stored)
  • Waterfall compute: roots_risk_tier ชัดเจน → lookup device_class_id → คะแนน EM
  • section "Risk Assessment (HA)" แบบยุบได้บนฟอร์มเครื่องมือแพทย์
  • Q5.4: โมเดล header hemms.ha.report:
  • name, fiscal_year, department_id, date_from/to, state
  • author_id, bme_head_id, engineering_head_id, director_id
  • Computed: total_equipment, pm_plan_count, pm_actual_count, compliance_pct, tier_high_count, tier_mid_count, tier_low_count
  • mail.thread + mail.activity.mixin, มุมมอง list/form, เมนู
  • Q5.5: โมเดล hemms.ha.report.line:
  • equipment_id + ชื่อสองภาษาที่ related + equipment_ref + serial_no + model + department_id
  • risk_tier, pm_freq_months (จาก waterfall ของเครื่องมือแพทย์)
  • pm_planned_count (derived 12 / freq), pm_actual_count, pm_compliance_pct
  • result (pass/conditional/fail/not_done), exception_reason, responsible_id
  • Q5.6: โมเดล JSON hemms.ha.report.snapshot + ล็อก action_submit() — สแน็ปช็อตเก็บข้อมูล line + เวอร์ชัน device-class + metadata paperformat; การพิมพ์ซ้ำ render จากสแน็ปช็อตเสมอ
  • Q5.7: วิซาร์ด hemms.ha.report.generate:
  • ปีงบประมาณ (พ.ศ. ไทย) + ตัวเลือกแผนก
  • ใช้ roots_hemms_asset_inspection._get_fiscal_year_dates() ซ้ำ
  • กรองเครื่องมือแพทย์ที่ active ตามแผนก + นับ PM ที่เสร็จแล้ว maintenance.request (kind = PM) ในช่วง
  • Q5.8: รายงาน QWeb 7-section:
  • ปก — ฟิลด์ส่วนหัว
  • บทสรุปผู้บริหาร — ยอดรวม + จำนวนตามระดับ + การปฏิบัติตามแผน %
  • ตารางครุภัณฑ์ + ผลการบำรุงรักษา — รายละเอียดต่อเครื่องมือแพทย์
  • รายการครุภัณฑ์ที่ไม่ได้ทำตามแผน — ข้อยกเว้นพร้อมเหตุผล
  • ภาคผนวก ก — ตาราง 83 อุปกรณ์ของ MoPH
  • ภาคผนวก ข — แผ่นงานคะแนน EM (เฉพาะ line ที่ใช้เส้นทาง EM)
  • หน้าลงนาม — บล็อกลายเซ็น 3 บล็อก (หัวหน้า BME / หัวหน้าวิศวกรรม / ผู้อำนวยการ)
  • Q5.9: สะพาน sign_oca (รูปแบบต่อโมเดล, ไม่แก้ Q4):
  • sign.oca.request._inherit เพิ่ม hemms_ha_report_id (M2O คำนวณจาก record_ref)
  • super-extension _check_signed เขียน roots_signed_pdf เมื่อ record_ref._name == 'hemms.ha.report'
  • action_send_for_signature() บนรายงานพร้อมผู้ลงนาม 3 คน Command.create() (หัวหน้า BME / หัวหน้าวิศวกรรม / ผู้อำนวยการ)
  • guard ตรวจก่อน _check_ha_signers_resolvable()
  • role seed ใหม่ 2 ตัว (role_bme_head, role_engineering_head); ใช้ roots_hemms_signature.role_hospital_signer ของ Q4 ซ้ำสำหรับผู้อำนวยการ
  • XML เทมเพลตสาธิต (demo/sign_oca_template_ha_report.xml)
  • หน้าลายเซ็น QWeb: กล่องว่างสไตล์กระดาษเมื่อ roots_signed_pdf ว่าง; ฝังรูป PDF ที่เซ็นแล้วเมื่อตั้งค่า
  • ปุ่มสถิติ + ป้าย 🟡 รอลงนาม / 🟢 ลงนามครบ บนฟอร์ม header
  • Q5.10: การทดสอบ — 8 unit + 12 integration = เป้าหมาย 20 การทดสอบ, เขียวบน hemms_demo AND hemms_private
  • Q5.11: เอกสาร 5 หน้าใต้ docs/modules/ha-report/ + แผนนี้
  • Q5.12: ข้อมูลสาธิต — โรงพยาบาล 1 FY (2569 พ.ศ.) พร้อม 30 เครื่องมือแพทย์ × 3 แผนก, ระดับผสม, ~78% การปฏิบัติตามแผน, 3 ข้อยกเว้นพร้อมพิมพ์

ขอบเขต — ที่ตัดออก (เลื่อนออกไป)

  • ❌ รายงานเปรียบเทียบหลายปีงบประมาณ — Q6+
  • ❌ ส่งออก Excel (XLSX) ควบคู่ PDF — Q6+
  • ❌ widget dashboard การปฏิบัติตามแผมแบบ real-time — Q6+
  • ❌ สร้างอัตโนมัติเมื่อสิ้นปีงบประมาณ (cron) — Q6+ (วิซาร์ดด้วยมือสำหรับ V1)
  • ❌ รายงานย่อยต่อแผนกภายในรายงานหลักเดียว — Q6+
  • ❌ เครื่องมือแพทย์ที่มี sub-location หลายแห่ง / การติดตามเครื่องมือเคลื่อนที่ — Q6+
  • ❌ scorecard ผลงาน vendor ภายในรายงาน — Q6 (เคยเป็น "Q5+" ของ Q4)
  • ❌ การแจ้งเตือนการต่ออายุหลายขั้น / การละเมิด SLA / วิซาร์ดเทมเพลตสัญญา / การกั้น workflow — Q6 (สัญญาตามต่อ; เคยเป็น "Q5+" ของ Q4)
  • ❌ คำนวณ % การปฏิบัติตามแผนใหม่อัตโนมัติเมื่อ backdate เหตุการณ์ PM — โดยการออกแบบ; สแน็ปช็อตไม่เปลี่ยนแปลงหลัง submit
  • ❌ รายงานหลายภาษา (เวอร์ชัน EN-primary) — Q6+ (TH primary สำหรับ V1)
  • ❌ OTP / 2FA ตอนลงนาม — Q6+ (roadmap ของ sign_oca)
  • ❌ ลายเซ็นรับรอง PKI / ETDA Level 2 — Q6+ (roadmap ของ sign_oca)

2. การตัดสินใจด้านการออกแบบ (ล็อกแล้ว)

# การตัดสินใจ ตัวเลือก
D1 แมป roots_hemms_criticality (Value × Risk → R/Y/G) เข้ากับ MoPH (สูง/กลาง/ต่ำ)? ไม่แมป — ฟิลด์ roots_risk_tier แยกต่างหาก ความวิกฤตขับเคลื่อนการ triage ปฏิบัติการ; risk_tier คือการจัดประเภทของหน่วยกำกับ semantics ต่างกัน, แหล่งความจริงต่างกัน การรวมกันสร้าง abstraction ที่รั่ว
D2 seed ตาราง 83 อุปกรณ์ของ MoPH เป็นข้อมูล? ใช่ — hemms.ha.device.class พร้อม noupdate="1" โรงพยาบาลเพิ่ม/แก้ entry ในพื้นที่หลังติดตั้งได้โดยไม่เสีย baseline เมื่ออัปเกรด สะท้อนรูปแบบคำศัพท์ชนิดสัญญาของ Q3
D3 การจัดการปีงบประมาณ ใช้ roots_hemms_asset_inspection._get_fiscal_year_dates() ซ้ำ (ปีงบประมาณไทย ต.ค.–ก.ย.) ยกขึ้นเป็น helper สาธารณะหากปัจจุบันเป็น private
D4 กลไกสแน็ปช็อต JSON blob บน hemms.ha.report.snapshot (สะท้อน Q2/asset-inspection) ไม่ใช่โมเดล read-only ที่ clone
D5 flow ลายเซ็น OCA sign_oca ผ่าน Q4 (dep roots_hemms_signature)
D6 การ integrate การลงนามอยู่ที่ใด? ภายใน roots_hemms_ha_report — Q5 เป็นเจ้าของส่วนขยาย sign.oca.request ของตนเอง (เพิ่ม hemms_ha_report_id + _check_signed เพิ่ม) ไม่ แก้ roots_hemms_signature Q5 ใช้ helper ของ Q4 ซ้ำ (_roots_attach_signed_pdf_to_parent) ผ่านห่วงโซ่ inheritance
D7 แหล่ง risk-tier บนเครื่องมือแพทย์ waterfall สามขั้น: (1) roots_risk_tier ชัดเจน → ใช้มัน; (2) ไม่งั้น lookup device_class_id → ตาราง MoPH; (3) ไม่งั้นคำนวณจากคะแนน EM วิซาร์ดแสดงว่าใช้เส้นทางใดต่อ line ตรวจสอบได้
D8 การ render สองภาษา TH หลัก, EN ในวงเล็บ สำหรับชื่อเครื่องมือแพทย์; หัวข้อ section เป็น TH เท่านั้น (สอดคล้องกับรายงาน ปจป.)
D9 การเลื่อน state เมื่อลงนาม ไม่เลื่อน state — การมี roots_signed_pdf คือสถานะที่เซ็นแล้ว header คงอยู่ใน submitted ตรงกับ Q4 OQ3 state machine ง่ายกว่า, การทดสอบการเปลี่ยนน้อยกว่า, สอดคล้องกับรูปแบบของบ้าน
D10 Lock-on-submit action_submit() สร้างสแน็ปช็อต JSON, แช่แข็ง line ผ่านการตรวจ state บน field readonly ข้อมูลเครื่องมือแพทย์ที่เปลี่ยนหลัง submit ไม่ เปลี่ยนรายงาน การพิมพ์ซ้ำจากสแน็ปช็อตเสมอ, byte เหมือนกัน
D11 เส้นทางการปฏิเสธ ปฏิเสธผ่าน portal การลงนาม → ล้าง roots_signed_pdf, archive sign.oca.request เก่า, อนุญาตให้สร้างใหม่ รายงานคงอยู่ใน submitted ตลอด audit เห็นได้ใน chatter ไม่จำกัดรอบ (ตรงกับรูปแบบ Q3 + Q4)
D12 การกำหนดขอบเขต security department_id บน header + record rules: เจ้าหน้าที่ BME แผนกของตน; หัวหน้า BME ทั้งหมด; หัวหน้าวิศวกรรม / ผู้อำนวยการ / แผนก Quality อ่านได้ทั้งหมด
D13 สูตรคะแนน EM EM = Function + Application + Maintenance + History ตาม WHO Fennigkoh-Smith ช่วง History −2..+2 (ลดคะแนนได้; ไม่ทำ abs) Buckets: ≤12 ตัด / 12–14 → 1×/ปี / 15–18 → 2×/ปี / ≥19 → 3×/ปี การตีความขอบเขตบันทึกใน code comment (12 = ตัด; 14 = 1×/ปี; 18 = 2×/ปี; 19 = 3×/ปี — ขอบบนรวม)
D14 UX ตัวแก้ EM 4 slider บนฟอร์มเครื่องมือแพทย์ ภายใน section "Risk Assessment (HA)" แบบยุบได้ roots_em_score สดข้าง input ไม่ต้องใช้วิซาร์ด
D15 License / สถานะ LGPL-3, Alpha, maintainer jakapolr

3. โมเดลข้อมูล

3.1 โมเดลใหม่

hemms.ha.device.class                      (Q5.2 — MoPH 83-device vocab)
  ├─ name_en               Char         e.g. "Anesthesia Units"
  ├─ name_th               Char         e.g. "เครื่องดมยาสลบ"
  ├─ risk_tier             Selection    high/medium/low
  ├─ pm_freq_months        Integer      e.g. 6
  ├─ pm_duration_hours     Float        e.g. 2.4
  ├─ sequence              Integer      display order
  └─ active                Boolean

hemms.ha.report                            (Q5.4 — header)
  ├─ name                  Char         readonly, ir.sequence
  ├─ fiscal_year           Integer      Thai พ.ศ.
  ├─ department_id         M2O hr.department  (null = whole hospital)
  ├─ date_from / date_to   Date         auto from fiscal_year
  ├─ state                 Selection    draft / in_progress / submitted / archived
  ├─ author_id             M2O res.users
  ├─ bme_head_id           M2O res.users
  ├─ engineering_head_id   M2O res.users
  ├─ director_id           M2O res.users
  ├─ line_ids              O2M hemms.ha.report.line
  ├─ snapshot_id           M2O hemms.ha.report.snapshot
  ├─ sign_request_ids      O2M sign.oca.request  (via hemms_ha_report_id inverse)
  ├─ sign_request_count    Integer      computed, stored, sudo
  ├─ roots_signed_pdf      Binary       written by Q4 helper via _check_signed
  ├─ roots_signed_pdf_filename Char
  ├─ total_equipment       Integer      computed, stored
  ├─ pm_plan_count         Integer      computed, stored
  ├─ pm_actual_count       Integer      computed, stored
  ├─ compliance_pct        Float        computed, stored
  ├─ tier_high_count       Integer      computed, stored
  ├─ tier_mid_count        Integer      computed, stored
  ├─ tier_low_count        Integer      computed, stored
  ├─ signed_badge          Char         computed (🟡 รอลงนาม / 🟢 ลงนามครบ)
  └─ active                Boolean
  + mail.thread + mail.activity.mixin

hemms.ha.report.line                       (Q5.5 — per-equipment row)
  ├─ report_id             M2O parent, required, ondelete cascade
  ├─ equipment_id          M2O maintenance.equipment, required
  ├─ equipment_name_th     Char         related, store=True
  ├─ equipment_name_en     Char         related, store=True
  ├─ equipment_ref         Char         related (roots_ref_no), gov asset no.
  ├─ serial_no             Char         related
  ├─ model                 Char         related
  ├─ department_id         M2O          related
  ├─ risk_tier             Selection    high/medium/low (from equipment waterfall)
  ├─ risk_tier_source      Selection    explicit / device_class / em_score  (D7 audit)
  ├─ pm_freq_months        Integer      from equipment
  ├─ pm_planned_count      Integer      derived: 12 / pm_freq_months
  ├─ pm_actual_count       Integer      count of done PM events in window
  ├─ pm_compliance_pct     Float        computed
  ├─ result                Selection    pass / conditional / fail / not_done
  ├─ exception_reason      Text         required if not_done or fail
  └─ responsible_id        M2O res.users

hemms.ha.report.snapshot                   (Q5.6 — immutable JSON freeze)
  ├─ report_id             M2O hemms.ha.report (1:1)
  ├─ data                  Json          full line data + device_class versions
  ├─ frozen_at             Datetime
  ├─ frozen_by_id          M2O res.users
  └─ paperformat_hash      Char          guards against paperformat edits silently changing reprints

3.2 โมเดลที่ inherit

maintenance.equipment (INHERIT, Q5.3)
  ├─ device_class_id           M2O hemms.ha.device.class
  ├─ roots_risk_tier           Selection high/medium/low  (explicit override)
  ├─ roots_pm_freq_months      Integer                    (waterfall computed/stored)
  ├─ roots_em_function         Integer  (range 2..10, slider)
  ├─ roots_em_application      Integer  (range 1..5, slider)
  ├─ roots_em_maintenance      Integer  (range 1..5, slider)
  ├─ roots_em_history          Integer  (range -2..+2, slider)
  └─ roots_em_score            Integer  computed, stored

sign.oca.request (INHERIT, Q5.9)
  └─ hemms_ha_report_id        M2O hemms.ha.report  (compute from record_ref, store=True, index=True)
  + _check_signed() super-extension:
      super()  # ← Q4's chain handles inspection + contract
      for request in self:
          if request.state != "2_signed":
              continue
          record = request.record_ref
          if not record or record._name != "hemms.ha.report":
              continue
          try:
              self._roots_attach_signed_pdf_to_parent(request, record)   # Q4 helper, reused
          except Exception:
              _logger.exception(...)

4. เลย์เอาต์โมดูล

addons/roots/roots_hemms_ha_report/
  __init__.py
  __manifest__.py
  README.rst
  data/
    ir_sequence_data.xml                  # HA-YYYY-#####
    ha_device_class_data.xml              # MoPH 83-device seed (noupdate=1)
    sign_oca_role_data.xml                # role_bme_head + role_engineering_head (noupdate=1)
    paperformat_data.xml                  # A4 TH Sarabun (may reuse asset_inspection's)
  demo/
    sign_oca_template_ha_report.xml       # demo PDF template + field placements
    hemms_ha_report_demo.xml              # Q5.12 — 1 FY hospital scenario
  models/
    __init__.py
    hemms_ha_device_class.py              # Q5.2 — MoPH vocab
    maintenance_equipment.py              # Q5.3 — risk-tier + EM-score fields
    hemms_ha_report.py                    # Q5.4 — header
    hemms_ha_report_line.py               # Q5.5 — per-equipment
    hemms_ha_report_snapshot.py           # Q5.6 — JSON freeze
    sign_oca_request.py                   # Q5.9 — _check_signed super-extension
  wizard/
    __init__.py
    hemms_ha_report_generate.py           # Q5.7
    hemms_ha_report_generate_views.xml
  report/
    hemms_ha_report_templates.xml         # Q5.8 — 7-section QWeb
    hemms_ha_report_paperformat.xml       # may inherit from asset_inspection
  views/
    hemms_ha_device_class_views.xml
    maintenance_equipment_views.xml       # collapsible "Risk Assessment (HA)" section
    hemms_ha_report_views.xml             # list/form + stat button + badge
    menus.xml
  security/
    ir.model.access.csv
    ha_report_security.xml                # record rules (own-dept vs all)
  tests/
    __init__.py
    test_device_class.py                  # Q5.10 — U1
    test_em_score.py                      # Q5.10 — U2, U3
    test_risk_tier_waterfall.py           # Q5.10 — U4, U5, U6
    test_line_compute.py                  # Q5.10 — U7, U8
    test_generate_wizard.py               # Q5.10 — I1, I2, I3
    test_lock_on_submit.py                # Q5.10 — I4, I5, I6
    test_sign_bridge.py                   # Q5.10 — I7, I8, I9, I10
    test_security.py                      # Q5.10 — I11
    test_report_render.py                 # Q5.10 — I12
  i18n/
    th.po                                 # wrapper UI strings

5. จุดสัมผัส UX

5.1 ฟอร์ม maintenance.equipment (Q5.3)

[ Existing tabs ]
  General / Inventory / Maintenance / …

[ NEW collapsible section: 🇹🇭 Risk Assessment (HA) ]
  Device Class (MoPH)   [ Anesthesia Units ▼ ]   ← lookup hemms.ha.device.class
  Risk Tier             [ High / Medium / Low ] ⓘ Auto-filled from class; override here
  PM Frequency (months) [ 6 ]                    ⓘ Auto-filled from class
  Source                ▶ device_class           ← read-only badge (D7 waterfall audit)

  ▼ EM Score Worksheet (if no Device Class)
    Function        [——●———————] 9
    Application     [—————●—————] 4
    Maintenance     [——●————————] 3
    History         [————●——————] 0
    Score           = 16 → Medium tier, 2× PM per year

5.2 มุมมองรายการ hemms.ha.report

| Reference     | FY (พ.ศ.) | Dept       | State        | 🚦 | Compliance |
| HA-2569-00001 | 2569      | BME        | Submitted    | 🟢 | 78%        |
| HA-2569-00002 | 2569      | Radiology  | In Progress  | —  | —          |
| HA-2568-00001 | 2568      | BME        | Archived     | 🟢 | 82%        |

5.3 ฟอร์ม hemms.ha.report

[ Header ]
  HA-2569-00001                            [ 🟡 รอลงนาม / 🟢 ลงนามครบ ]
  Fiscal Year (พ.ศ.)  2569
  Department          BME
  State               submitted

[ Header buttons ]
  [ Send for Signature ]  ← visible if state=='submitted' AND sign_request_count==0
  [ Print Report ]
  [ Archive ]             ← visible if state=='submitted'

[ Statbox ]
  [ 30 Equipment ] [ 78% Compliance ] [ 📝 1 Sign Request ]
                                       ↑ visible if sign_request_count > 0

[ Notebook tabs ]
  - Equipment Lines (o2m)
  - Exceptions (filtered domain on lines)
  - Signers (BME head / Eng head / Director m2o pickers)
  - Snapshot Info (read-only, post-submit)

[ Chatter ]
  Standard mail.thread — sign events post here

5.4 วิซาร์ดสร้าง (Q5.7)

┌─ Generate HA Annual PM Report ──────────────────────────┐
│ Fiscal Year (พ.ศ.)   [ 2569 ▼ ]                         │
│ Department           [ BME ▼ ]   (blank = whole hospital) │
│                                                          │
│ Period:  1 ต.ค. 2568 – 30 ก.ย. 2569                      │
│ Equipment found: 30 (estimated)                          │
│                                                          │
│ [ Cancel ]                          [ Generate Report ]  │
└──────────────────────────────────────────────────────────┘

5.5 QWeb PDF (Q5.8) — 7 sections

┌─────────────────────────────────────────────────────────┐
│ ปก                                                       │
│  รายงานการบำรุงรักษาเชิงป้องกันประจำปี                    │
│  หน่วยงาน BME, รพ. ตัวอย่าง                             │
│  ปีงบประมาณ พ.ศ. 2569                                    │
│  เลขที่: HA-2569-00001                                   │
│  จัดทำโดย: [ผู้จัดทำ]                                    │
├─────────────────────────────────────────────────────────┤
│ บทสรุปผู้บริหาร                                          │
│  ครุภัณฑ์ทั้งหมด: 30                                     │
│  สูง: 5 | กลาง: 12 | ต่ำ: 13                             │
│  PM ตามแผน: 64 ครั้ง | ทำจริง: 50 | เป็นไปตามแผน: 78%   │
├─────────────────────────────────────────────────────────┤
│ ตารางครุภัณฑ์ + ผลการบำรุงรักษา                          │
│  | ลำดับ | ชื่อเครื่อง | รุ่น | S/N | เลขครุภัณฑ์ | ระดับ │
│  |       | (TH/EN)     |     |     |              | ความ │
│  |       |             |     |     |              | เสี่ยง| ความถี่ | แผน | จริง | % | ผล |
├─────────────────────────────────────────────────────────┤
│ รายการครุภัณฑ์ที่ไม่ได้ทำตามแผน                          │
│  3 รายการ พร้อมเหตุผล                                    │
├─────────────────────────────────────────────────────────┤
│ ภาคผนวก ก — ตาราง MoPH 83 ประเภท (อ้างอิง)              │
├─────────────────────────────────────────────────────────┤
│ ภาคผนวก ข — EM Score Worksheet (เฉพาะรายการที่ใช้)      │
├─────────────────────────────────────────────────────────┤
│ หน้าลงนาม                                                │
│  [ ☐ หัวหน้างานวิศวกรรมการแพทย์ ]                        │
│  [ ☐ หัวหน้าฝ่ายเทคนิค ]                                 │
│  [ ☐ ผู้อำนวยการ รพ. ]                                  │
│  ↑ paper-style boxes when roots_signed_pdf blank        │
│  ↑ embed signed PDF image when set                       │
└─────────────────────────────────────────────────────────┘

6. ฟีเจอร์ UX ที่บันทึกไว้

ฟีเจอร์ จากการวิเคราะห์ อยู่ในขั้นตอน Q5 ใด
ir.sequence HA-YYYY-##### รูปแบบ Q3 D3 Q5.1
paperformat ราชการไทย (A4, TH Sarabun) ใช้ asset_inspection ซ้ำ Q5.1
คำศัพท์ 83 อุปกรณ์ของ MoPH + seed แหล่งที่เชื่อถือได้หน้า 2–7 Q5.2
waterfall risk-tier (D7) แหล่งที่เชื่อถือได้ + การออกแบบ Q5.3
แผ่นงานคะแนน EM (Function + Application + Maintenance + History) WHO Fennigkoh-Smith + แหล่งที่เชื่อถือได้หน้า 8–9 Q5.3
4 slider + คะแนนสดบนฟอร์มเครื่องมือแพทย์ คำตอบ OQ-C Q5.3
state machine 3 สถานะ (ไม่มี signed) D9 + สอดคล้อง Q4 OQ3 Q5.4
ยอดรวม + จำนวนตามระดับที่คำนวณ บทสรุปผู้บริหารของแหล่งที่เชื่อถือได้ Q5.4
ป้ายเซ็นแล้ว 🟡/🟢 การมองเห็นของ D9 Q5.4
PM ตามแผน/ทำจริง/การปฏิบัติตามแผนต่อเครื่องมือแพทย์ ตารางรายละเอียดของแหล่งที่เชื่อถือได้ Q5.5
ฟิลด์ audit แหล่ง risk-tier การสืบย้อนของ D7 Q5.5
สแน็ปช็อต JSON + lock-on-submit D4 + D10 (สะท้อน asset_inspection) Q5.6
วิซาร์ดปีงบประมาณด้วย พ.ศ. ไทย ใช้ D3 ซ้ำ Q5.7
การรวมเหตุการณ์ PM จาก Q1 ข้อมูล Q1 maintenance.request Q5.7
PDF QWeb 7-section เลย์เอาต์ของแหล่งที่เชื่อถือได้ Q5.8
fallback กล่องลายเซ็นว่างสไตล์กระดาษ รูปแบบ Q4 D11 Q5.8
ปุ่มสถิติ + ฟิลด์สะพาน รูปแบบสะพานต่อโมเดล Q4 Q5.9
super-extension _check_signed ใช้ helper Q4 ซ้ำ inheritance ของ helper Q4.5 Q5.9
ผู้ลงนาม 3 คน (หัวหน้า BME / หัวหน้าวิศวกรรม / ผู้อำนวยการ) บล็อกลายเซ็นของแหล่งที่เชื่อถือได้ Q5.9
role seed ใหม่ 2 ตัว + ใช้ผู้ลงนามโรงพยาบาล Q4 ซ้ำ ส่วนขยาย Q4 D12 Q5.9
ตรวจก่อน _check_ha_signers_resolvable รูปแบบ Q4 Q5.9
เทมเพลตสาธิตสำหรับรายงาน HA รูปแบบ Q4 D8 Q5.9
20 การทดสอบบน DB คู่ รูปแบบ Q3 Q5.10
.po สองภาษา (TH) มาตรฐาน Q5.11
เอกสาร 5 หน้า มาตรฐาน Q3 / Q4 Q5.11
โรงพยาบาลสาธิต 1 FY มาตรฐาน Q5.12

7. กรณีทดสอบ (20)

Unit tests (8)

# ไฟล์ การทดสอบ ตรวจสอบ
U1 test_device_class.py test_83_devices_seeded โหลด 83 ระเบียน; แสดงทั้ง 3 ระดับ; จำนวนตรงกับแหล่งที่เชื่อถือได้ (13 low / 17 mid / 53 high)
U2 test_em_score.py test_em_score_formula_boundaries F+A+M+H ที่แต่ละขอบเขต (≤12, 12–14, 15–18, ≥19) → ระดับ + freq ถูกต้องตาม D13
U3 test_em_score.py test_em_history_negative_allowed History=−2 ลดคะแนน; ไม่ถูกบังคับเป็น abs (D13)
U4 test_risk_tier_waterfall.py test_explicit_wins roots_risk_tier ชัดเจน override device_class AND คะแนน EM (D7 ขั้น 1)
U5 test_risk_tier_waterfall.py test_device_class_fallback ไม่มีชัดเจน + มี device_class → device_class ชนะ EM (D7 ขั้น 2)
U6 test_risk_tier_waterfall.py test_em_score_last_resort ไม่มีชัดเจน + ไม่มี device_class → ใช้ระดับ EM (D7 ขั้น 3); risk_tier_source == 'em_score'
U7 test_line_compute.py test_pm_planned_count_derivation คณิต 12 / pm_freq_months สำหรับ freq 3-เดือน / 6-เดือน / 12-เดือน (4 / 2 / 1)
U8 test_line_compute.py test_compliance_pct_handles_zero_plan planned=0 → compliance_pct=0.0 (ไม่หารด้วยศูนย์); planned=4 / actual=3 → 75%

Integration tests (12)

# ไฟล์ การทดสอบ ตรวจสอบ
I1 test_generate_wizard.py test_generate_builds_lines_for_dept วิซาร์ด dept=BME สร้าง N line สำหรับเครื่องมือแพทย์ BME ที่ active เท่านั้น; total_equipment ตรงกัน
I2 test_generate_wizard.py test_fiscal_year_window_filters_pm_events เฉพาะ PM maintenance.request ที่ปิดในช่วง FY มีส่วนต่อ pm_actual_count
I3 test_generate_wizard.py test_stale_stage_pm_excluded คำขอ PM ที่ไม่ Done ถูกตัดออก; นับเฉพาะ stage=Done
I4 test_lock_on_submit.py test_submit_freezes_lines หลัง action_submit(), เขียน line_ids raise UserError; state เลื่อนเป็น submitted
I5 test_lock_on_submit.py test_snapshot_preserves_device_class_version แก้ MoPH device_class หลัง submit ไม่ เปลี่ยนการ render ภาคผนวก ก ของรายงานที่ submit แล้ว
I6 test_lock_on_submit.py test_reprint_byte_identical byte PDF จากการพิมพ์ซ้ำ hash เท่ากับการพิมพ์ครั้งแรก
I7 test_sign_bridge.py test_action_send_for_signature_creates_request สร้าง sign.oca.request ที่ record_ref ชี้กลับ, ผู้ลงนาม 3 คนพร้อมการกำหนด role ถูกต้อง (หัวหน้า BME / หัวหน้าวิศวกรรม / ผู้อำนวยการ)
I8 test_sign_bridge.py test_pre_flight_guard_missing_signer ขาดหัวหน้า BME / หัวหน้าวิศวกรรม / ผู้อำนวยการ → UserError, ไม่สร้าง sign.oca.request
I9 test_sign_bridge.py test_check_signed_writes_pdf Stub request.state='2_signed' ผ่าน helper Q4.6 → roots_signed_pdf ถูกเติม, โพสต์ chatter, state ไม่เปลี่ยน (คงเป็น submitted — D9)
I10 test_sign_bridge.py test_rejection_clears_and_respawns ปฏิเสธ → ล้าง roots_signed_pdf, archive คำขอเก่า, action_send_for_signature() ครั้งที่สองสำเร็จ
I11 test_security.py test_bme_staff_own_dept_only เจ้าหน้าที่ BME แผนก A อ่าน/เขียนรายงานแผนก B ไม่ได้ (record rule D12)
I12 test_report_render.py test_qweb_pdf_renders_signed_and_unsigned PDF render ได้ทั้งกรณีกล่องว่าง (ยังไม่เซ็น) และรูปฝัง (เซ็นแล้ว); ไม่มี QWeb error; ความยาว byte PDF > 0

โครงสร้างพื้นฐานการทดสอบ

  • ทั้งหมด TransactionCase, ไม่มี HttpCase
  • การลงนามเสร็จ stub ผ่าน roots_hemms_signature.tests.common._helper_sign_request_complete() จาก Q4.6
  • Fixtures: 1 โรงพยาบาล, 3 แผนก, 24 เครื่องมือแพทย์ (8 ต่อระดับ), ช่วง FY 1 ช่วง, ผู้ใช้สาธิตหัวหน้า BME + หัวหน้าวิศวกรรม + ผู้อำนวยการ (แต่ละคนมี res.users และ res.partner ที่ลิงก์)
  • Green gate: รันบน hemms_demo AND hemms_private (พร้อมติดตั้ง Q2 + Q3 + Q4 + ข้อมูลสาธิต) — gate DB คู่เดียวกับ Q3/Q4

เป้าหมายความครอบคลุม

ระบบย่อย ความครอบคลุม
ความถูกต้องของ MoPH seed (Q5.2) U1
คณิตคะแนน EM (Q5.3) U2 + U3
waterfall risk-tier (Q5.3) U4 + U5 + U6
คณิต line (Q5.5) U7 + U8
วิซาร์ดสร้าง (Q5.7) I1 + I2 + I3
Lock-on-submit (Q5.6) I4 + I5 + I6
สะพานการลงนาม (Q5.9) I7 + I8 + I9 + I10
Security ACL (Q5.4) I11
การ render QWeb (Q5.8) I12

8. คำถามที่ยังเปิด — แก้ไขแล้ว

# คำถาม การแก้ไข
OQ-A รูปแบบ mixin ของ Q4 — Q5 ใช้ mixin หรือสะพานต่อโมเดล? สะพานต่อโมเดล Q4 ไม่ได้ ship mixin (แต่ละโมเดลที่เชื่อมมีไฟล์เฉพาะรูปแบบ copy-paste ของตน) Q5 สะท้อนรูปแบบในโมดูลของตน — ไม่แก้ roots_hemms_signature
OQ-B seed 83 อุปกรณ์ของ MoPH — noupdate=0 หรือ =1? baseline noupdate="1" โรงพยาบาลเพิ่ม/แก้หลังติดตั้งได้โดยไม่เสียการเปลี่ยนแปลงเมื่ออัปเกรดโมดูล เหมือนคำศัพท์ชนิดสัญญาของ Q3
OQ-C UX ตัวแก้คะแนน EM — slider vs วิซาร์ด? 4 slider + คะแนนคำนวณสดบนฟอร์มเครื่องมือแพทย์, ภายใน section "Risk Assessment (HA)" แบบยุบได้ ค้นพบได้, ไม่มีคลิกเพิ่ม, คะแนนคำนวณใหม่สด
OQ-D จำกัดรอบการลงนามซ้ำ (D11)? ไม่จำกัด ตรงกับรูปแบบ Q3 + Q4 แต่ละการปฏิเสธสร้าง sign.oca.request ใหม่; เก่าถูก archive
OQ-E fixture ทดสอบจาก Q4 ใช้ซ้ำได้? ได้ Q4.6 ship _helper_sign_request_complete() ใน roots_hemms_signature/tests/common.py Q5 import และใช้ซ้ำสำหรับ I9/I10 stub completion
OQ-F ลำดับความสำคัญของขอบเขต — Q5 = HA Report หรือสัญญาตามต่อ? Q5 = HA Report สัญญาตามต่อ (การแจ้งเตือนการต่ออายุหลายขั้น, การละเมิด SLA, scorecard vendor, RFQ spare-only, วิซาร์ดเทมเพลตสัญญา, การกั้น workflow) → Q6 HA Report มีค่าการสาธิตสูงกว่า (ผลผลิตการปฏิบัติตามข้อกำหนดใหม่) มากกว่าการขัดเกลาโมดูลสัญญาที่ ship แล้ว

9. ข้อควรระวังในการดำเนินแผน

  • Q5.2 ชื่อ MoPH seed หลายบรรทัด — แหล่งที่เชื่อถือได้มีชื่อเครื่องมือแพทย์อย่าง "Patient Warming Units, Air" และ "Defibrillators and Noninvasive Pacemaker" แยกข้ามบรรทัดใน PDF ต่อกันอย่างระมัดระวังเมื่อ seed; คงทั้งคอลัมน์ EN และ TH; รักษาการสะกดเดิม (อย่าแก้อัตโนมัติ)
  • Q5.3 การจัดเก็บคะแนน EMroots_em_score เป็น computed=True, store=True Depends on ฟิลด์ input 4 ตัว ตรวจให้ store invalidate เมื่อ input ใดเปลี่ยน (ตรวจผ่านการทดสอบ)
  • Q5.3 ความกำกวมของกรณีขอบเขต — PDF แหล่งที่เชื่อถือได้แสดงขอบเขต bucket (≤12, 12–14, 15–18, ≥19) โดยไม่ระบุการรวมชัดเจน Q5 กำหนดเป็น: 12 = ตัด, 13/14 = 1×/ปี, 15/16/17/18 = 2×/ปี, 19+ = 3×/ปี (ตาม D13) บันทึกใน code comment + configuration.md
  • Q5.5 pm_actual_count ต้องกรองตาม stage=Done — PM maintenance.request ใน In Progress หรือ stage ค้าง ต้อง ไม่ นับเข้า actual มิฉะนั้น % การปฏิบัติตามแผนจะพอง
  • Q5.5 ตัวกรอง PM kind — นับเฉพาะ maintenance.request ที่ roots_kind_id.code == 'PM' (รหัส Q1 maintenance.kind) ชนิด Repair/Calibration อยู่นอกขอบเขตรายงานนี้
  • Q5.6 สแน็ปช็อตต้องรวม device_class_id.write_date ต่อ line — เพื่อให้การแก้ตาราง MoPH ภายหลังไม่เปลี่ยนการพิมพ์ซ้ำเงียบ ๆ สแน็ปช็อตเก็บค่าที่ resolve แล้ว, ไม่ใช่แค่ id ของ FK
  • Q5.6 ลายนิ้วมือ paperformat — สแน็ปช็อตยังเก็บ hash ของ paperformat format, margin_*, header_* เพื่อให้การแก้ paperformat เตือนเมื่อพิมพ์ซ้ำ (อย่าเปลี่ยนเงียบ ๆ)
  • Q5.7 helper ปีงบประมาณ — ถ้า roots_hemms_asset_inspection._get_fiscal_year_dates() ปัจจุบันเป็นเมธอด private (_method), ยกขึ้นเป็น _get_thai_fiscal_year_dates() เป็น utility สาธารณะก่อน Q5.7 (ใน Q5.1 หรือเป็นส่วนหนึ่งของ Q5.7)
  • Q5.8 QWeb ภาคผนวก ข — render เฉพาะ line ที่ risk_tier_source == 'em_score' ซ่อน section ทั้งหมดถ้าไม่มี line เช่นนั้น
  • Q5.9 ลำดับ super-chain ของ _check_signed — ต้องเรียก super()._check_signed() ก่อน ให้ Q4 จัดการ inspection/contract สาขา HA-only ของ Q5 ต้อง ไม่ raise ถ้า record_ref._name ไม่ใช่ 'hemms.ha.report'
  • Q5.9 PDF เทมเพลตสาธิต — ship เป็น base64 ในไฟล์ข้อมูล XML, noupdate=1 (เหมือน Q4 D8) ใช้ PDF A4 ง่าย ๆ พร้อมกล่องลายเซ็น placeholder 3 กล่อง
  • Q5.9 ใช้ role_hospital_signer ซ้ำ — Q4 seed นี้ไว้แล้วด้วย partner_selection_policy='empty' Q5 ใช้ตามเดิมสำหรับช่องผู้อำนวยการ; partner_id ส่งชัดเจนผ่าน Command.create() (ตรงกับรูปแบบ Q4)
  • Q5.10 stub completion ของ sign_oca — ตรวจว่า _helper_sign_request_complete() ของ Q4.6 มีใน roots_hemms_signature/tests/common.py (ไม่ใช่แค่ในไฟล์ทดสอบ) ถ้าเป็น private/ขาด, ยกขึ้นใน commit Q5.10 ก่อนพึ่งพา
  • Q5.10 gate DB คู่ — ต้องรันทั้ง hemms_demo AND hemms_private Q3 มีการทดสอบ I1 supplier-domain ที่ถูกข้ามเพราะ dep purchase; ตรวจว่าไม่ต้องข้ามแบบเดียวกันที่นี่
  • Q5.11 การจัดลำดับเอกสารdocs/modules/ha-report/index.md ต้องเพิ่มใน nav ของ mkdocs.yml; มิฉะนั้นจะไม่ render
  • Q5.12 dep ข้อมูลสาธิต — depends on Q1 PM demo + maintenance.equipment demo สร้างหลังทั้งสองโมดูลติดตั้งสะอาด; ตรวจว่า compliance_pct ลงที่ ~78% ตามตั้งใจเพื่อให้การสาธิตสมจริง

10. ลำดับ commit (Q5.1 → Q5.12)

# ข้อความ commit หัวเรื่อง
Q5.1 chore(ha): skeleton + manifest + sequence + paperformat [Q5.1] โมดูลติดตั้งได้สะอาด Sequence + paperformat พร้อม
Q5.2 feat(ha): hemms.ha.device.class + MoPH 83-device seed [Q5.2] โมเดลคำศัพท์ + seed 83 อุปกรณ์; smoke test สำหรับจำนวน + การกระจายระดับ
Q5.3 feat(ha): equipment risk-tier + EM-score sliders [Q5.3] ส่วนขยาย maintenance.equipment; section Risk Assessment แบบยุบได้
Q5.4 feat(ha): hemms.ha.report header + state machine [Q5.4] โมเดล header, 3 สถานะ, ยอดรวม, mail.thread, list/form, เมนู
Q5.5 feat(ha): hemms.ha.report.line + per-equipment compute [Q5.5] โมเดล line + จำนวนที่ derive + result enum
Q5.6 feat(ha): snapshot + lock-on-submit [Q5.6] โมเดลสแน็ปช็อต JSON + action_submit freeze
Q5.7 feat(ha): generate wizard [Q5.7] วิซาร์ดปีงบประมาณ + แผนก; สร้าง line จากข้อมูล PM
Q5.8 feat(ha): QWeb report with appendices [Q5.8] PDF รูปแบบราชการ 7-section + fallback ลายเซ็นกระดาษ
Q5.9 feat(ha): sign_oca bridge + roles + demo template [Q5.9] ส่วนขยาย sign.oca.request + action ผู้ลงนาม 3 คน + 2 role seed + เทมเพลตสาธิต + ป้ายเซ็นแล้ว
Q5.10 test(ha): 8 unit + 12 integration tests [Q5.10] 20 การทดสอบ; DB คู่เขียว
Q5.11 docs(ha): 5-page module docs + plan [Q5.11] docs/modules/ha-report/ + q5-ha-report-plan.md + nav mkdocs.yml
Q5.12 chore(ha): demo data — 1 FY hospital scenario [Q5.12] 30 เครื่องมือแพทย์ × 3 แผนก, 78% การปฏิบัติตามแผน, 3 ข้อยกเว้น

11. คำกระตุ้นเพื่อทำงานต่อ

เมื่อผู้ใช้พูด "เริ่ม Q5.1" / "start Q5" / "ship Q5" / ทำแผนนี้ต่อ:

  1. อ่านแผนนี้ซ้ำ + project_q5_status.md เพื่อ context เต็ม
  2. ยืนยันว่า dependency ติดตั้งสะอาด:
  3. Q1 (roots_hemms_pm) — แหล่งเหตุการณ์ PM
  4. Q3 (roots_hemms_service_contracts) — ทางอ้อมผ่าน Q4
  5. Q4 (roots_hemms_signature) — primitive ของสะพานการลงนาม
  6. ดำเนินการ Q5.1 — โครงโมดูล + manifest + sequence + paperformat
  7. หลังแต่ละ commit: pre-commit run --all-files; รันการทดสอบโมดูล (หลัง Q5.10); smoke-install บนทั้ง hemms_demo และ hemms_private
  8. ตรวจขั้นสุดท้ายที่ Q5.12: สาธิต end-to-end เต็มรูปแบบ — วิซาร์ดสร้าง → ทบทวน line → submit → ส่งลงนาม → ครบทั้ง 3 ลงนาม → PDF สุดท้ายใน chatter