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

เวิร์กโฟลว์

เวิร์กโฟลว์ 1 — การลงนามอนุมัติของคณะกรรมการตรวจสอบ ปจป.

ผู้ใช้ Odoo ภายในสามคน (ประธาน + กรรมการ 2 ท่าน) ลงนามรายงานการตรวจสอบ ประจำปี ปจป. จากภายในแอป ตั้งแต่ต้นจนจบ กระบวนการนี้แทนที่การส่งกระดาษ ไปกลับแบบเดิมด้วยร่องรอยการตรวจสอบแบบ chained-hash ที่เหมาะสำหรับหลักฐาน HA Thailand

เงื่อนไขเบื้องต้น

  • เรกคอร์ดการตรวจสอบอยู่ในสถานะ Submitted (คณะกรรมการลงนามได้ก็ต่อ เมื่อรายการถูกล็อกแล้วเท่านั้น)
  • ประธาน + กรรมการ 1 + กรรมการ 2 ถูกตั้งค่าครบบนการตรวจสอบ
  • กรรมการแต่ละท่านเป็น hr.employee ที่มี res.users เชื่อมโยง (เพื่อให้ สามารถจับคู่ res.partner สำหรับเรกคอร์ดผู้ลงนามได้)

ขั้นตอน

┌─────────────────────────────────────────────────────────────────┐
│ 1. Officer opens the submitted inspection                         │
│ 2. Officer clicks  [ Send for Signature ]                         │
│                                                                   │
│    Bridge:                                                        │
│      a. Renders ปจป. PDF via the existing qweb report             │
│      b. Resolves 3 partners from chair/member_1/member_2          │
│         (.user_id.partner_id)                                     │
│      c. Creates sign.oca.request:                                 │
│           record_ref = "hemms.asset.inspection,<id>"              │
│           signer_ids = [chair, member_1, member_2]                │
│      d. Opens the request form for review                         │
│                                                                   │
│ 3. Officer reviews signers, optionally clicks  [ Configure        │
│    Document ]  to drag signature fields onto the PDF (the         │
│    bridge does NOT pre-place fields)                              │
│                                                                   │
│ 4. Officer clicks  [ Send ]                                       │
│      → request.state: 1_draft → 0_sent                            │
│      → notification emails sent to all 3 signers                  │
│                                                                   │
│ 5. Chair clicks 📝 pencil icon (systray)                          │
│      → opens the request                                          │
│      → reviews the PDF                                            │
│      → clicks  [ Sign ]                                           │
│      → draws signature in canvas                                  │
│      → submits                                                    │
│      Chair's signer record: signed_on populated, hash computed    │
│                                                                   │
│ 6. Member 1 + Member 2 follow the same path (any order — no       │
│    workflow ordering per OQ2)                                     │
│                                                                   │
│ 7. As the 3rd signer submits:                                     │
│      Upstream sign.oca.request._check_signed():                   │
│        all(signer_ids.signed_on) → state := 2_signed              │
│      Our Q4.5 extension fires:                                    │
│        - inspection.roots_signed_pdf := request.data              │
│        - inspection.roots_signed_pdf_filename := AI-2026-00001-   │
│          signed.pdf                                               │
│        - inspection.message_post(body="✅ Document signed by all  │
│          parties...", attachments=[(filename, raw_pdf)])          │
│      Inspection.state STAYS 'submitted' (OQ3/OQ2 — no auto-       │
│      advance)                                                     │
│                                                                   │
│ 8. Print the report. The signature footer now shows the green     │
│    "✅ ลงนามดิจิทัลครบถ้วน" stamp pointing to the signed PDF in     │
│    chatter. Filed paper printouts before this point keep the      │
│    legacy 3-box signature footer.                                 │
└─────────────────────────────────────────────────────────────────┘

การย้อนกลับ / ทำใหม่

หากต้องการลงนามใหม่ (เช่น เลือกคณะกรรมการผิด) ให้เปิด sign.oca.request ที่มีอยู่แล้วคลิก Cancel จากนั้นคลิก "Send for Signature" บนการตรวจสอบ อีกครั้ง บริดจ์จะสร้างคำขอใหม่; sign_request_count ของการตรวจสอบจะ สะท้อนทั้งสอง (ที่ยกเลิก + ใหม่)

ไม่มีการป้องกันคำขอที่ active ซ้ำกันโดยอัตโนมัติ — ปุ่มจะปรากฏก็ต่อเมื่อ sign_request_count == 0 แต่ถ้าคำขอก่อนหน้าทั้งหมดถูกยกเลิก ปุ่มจะปรากฏ อีกครั้ง

เวิร์กโฟลว์ 2 — การลงนามอนุมัติสัญญาบริการโดยผู้ขาย + โรงพยาบาล

ผู้ขายภายนอกลงนามผ่านลิงก์อีเมลพอร์ทัล; ผู้มีอำนาจลงนามฝั่งโรงพยาบาล ร่วมลงนามในระบบ รวมผู้ลงนามสองคน

เงื่อนไขเบื้องต้น

  • พาร์ตเนอร์ผู้ขายมี ที่อยู่อีเมล ตั้งค่าไว้ (จำเป็นสำหรับลิงก์ลงนาม ผ่านพอร์ทัล)
  • roots_hospital_signer_id ถูกตั้งค่าบนสัญญา (res.users ใด ๆ ที่มี res.partner เชื่อมโยง)

ขั้นตอน

┌─────────────────────────────────────────────────────────────────┐
│ 1. BME Manager opens the contract                                 │
│ 2. BME Manager clicks  [ Send for Signature ]                     │
│                                                                   │
│    Bridge:                                                        │
│      a. Renders contract qweb summary PDF                         │
│         (report_hemms_service_contract_summary_document)          │
│      b. Resolves partners:                                        │
│           vendor signer = contract.partner_id                     │
│           hospital signer = roots_hospital_signer_id.partner_id   │
│      c. Creates sign.oca.request with 2 signers                   │
│      d. Opens the request form                                    │
│                                                                   │
│ 3. BME Manager clicks [ Configure Document ] → drags signature    │
│    fields for vendor + hospital onto the PDF                      │
│                                                                   │
│ 4. BME Manager clicks  [ Send ]                                   │
│      → request.state: 1_draft → 0_sent                            │
│      → vendor receives an email with a portal link                │
│      → hospital signer sees a 📝 icon in their systray            │
│                                                                   │
│ 5. Vendor clicks the email link → portal page opens with the      │
│    PDF preview → vendor reviews + signs + submits                 │
│      (No Odoo login required — portal access is granted by the    │
│       per-request access_token)                                   │
│                                                                   │
│ 6. Hospital signer opens via systray → signs                      │
│      (Order doesn't matter — vendor can sign first or hospital    │
│       first, per OQ2)                                             │
│                                                                   │
│ 7. As the 2nd signer submits, the Q4.5 hook fires:                │
│      - contract.roots_signed_pdf := request.data                  │
│      - contract.roots_signed_pdf_filename := SC-2026-00001-       │
│        signed.pdf                                                 │
│      - contract.message_post(body="✅ Document signed by all      │
│        parties...", attachments=[...])                            │
│      Contract.state UNCHANGED (OQ3 — signing is parallel to       │
│      the date-driven draft/active/expired lifecycle)              │
│                                                                   │
│ 8. The signed-PDF download widget appears on the contract form    │
│    under "ลงนามดิจิทัล (Digital Signature)".                       │
└─────────────────────────────────────────────────────────────────┘

เมื่อการลงนามล้มเหลว

การ์ด _check_*_signers_resolvable ของบริดจ์จะยก UserError พร้อม ข้อความที่ชัดเจนซึ่งระบุช่องที่มีปัญหา:

ข้อผิดพลาด สาเหตุ วิธีแก้
"Committee Member N — not set" การตรวจสอบมีกรรมการน้อยกว่า 3 ท่าน ตั้งค่าครบทั้ง 3 ท่านบนฟอร์มการตรวจสอบ
"Committee Member N (name) — no linked Odoo user" พนักงานไม่มี user_id สร้าง res.users สำหรับพนักงานท่านนั้นและเชื่อมโยงผ่าน Employees → Related User
"Hospital Authorized Signer — not set" สัญญาไม่มีผู้ลงนาม ตั้งค่า roots_hospital_signer_id บนฟอร์มสัญญา
"Vendor (name) — has no email address" พาร์ตเนอร์ผู้ขายขาด email แก้ไขพาร์ตเนอร์ผู้ขายและเพิ่มอีเมล

hook _check_signed เองถูกห่อด้วย try/except เชิงป้องกัน — หากการเขียน เรกคอร์ดแม่หรือการโพสต์แชตเตอร์ (chatter) ล้มเหลว (เช่น การชนกันของ ACL, ปัญหาการตั้งค่าเมล) ผู้ลงนามยังคงได้รับประสบการณ์ "signed" ที่สำเร็จ ข้อผิดพลาดจะถูกบันทึกฝั่งเซิร์ฟเวอร์; PDF ที่ลงนามแล้วยังคงพร้อมใช้งานบน เรกคอร์ด sign.oca.request เอง

สิ่งที่ตั้งใจจะ "ไม่" รวมไว้ใน V1

ดู หน้า index สำหรับรายการที่เลื่อนออกไปทั้งหมด ที่น่าสังเกต:

  • ไม่มีการลงนามแบบเรียงลำดับ — ผู้ลงนามคนใดก็ลงนามก่อนได้ (OQ2)
  • ไม่มีการควบคุมสถานะ — การลงนามไม่เลื่อนสถานะของเรกคอร์ดแม่ (OQ3)
  • ไม่มีบริดจ์บน maintenance.request — การลงนามอนุมัติรายเดือนของ BME Manager / Ward / PM ยังคงอยู่บนกระดาษสำหรับ V1 (OQ1)