Workflows¶
Workflow 1 — ปจป. inspection committee sign-off¶
Three internal Odoo users (chair + 2 members) sign the annual ปจป. inspection report from inside the app. End-to-end this replaces the old paper round-trip with a chained-hash audit trail suitable for HA Thailand evidence.
Preconditions¶
- Inspection record is in state Submitted (committee can only sign after the lines are locked)
- Chair + Member 1 + Member 2 are all set on the inspection
- Each committee member is an
hr.employeewith a linkedres.users(so ares.partnercan be resolved for the signer record)
Steps¶
┌─────────────────────────────────────────────────────────────────┐
│ 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. │
└─────────────────────────────────────────────────────────────────┘
Roll-back / re-do¶
To re-do the signing (e.g. wrong committee picked), open the existing sign.oca.request and Cancel, then click "Send for Signature" again on the inspection. The bridge will create a new request; the inspection's sign_request_count will reflect both (cancelled + new).
There's no automatic prevention of duplicate-active requests — the button stays visible only while sign_request_count == 0, but if all prior requests are cancelled it reappears.
Workflow 2 — Service contract vendor + hospital sign-off¶
External vendor signs via portal email link; hospital authorized signer co-signs in-app. Two signers total.
Preconditions¶
- Vendor partner has an email address set (required for the portal sign link)
roots_hospital_signer_idis set on the contract (anyres.userswith a linkedres.partner)
Steps¶
┌─────────────────────────────────────────────────────────────────┐
│ 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)". │
└─────────────────────────────────────────────────────────────────┘
When signing fails¶
The bridge's _check_*_signers_resolvable guards raise UserError with a clear message naming the offending slot:
| Error | Cause | Fix |
|---|---|---|
| "Committee Member N — not set" | Inspection has fewer than 3 committee members assigned | Set all 3 on the inspection form |
| "Committee Member N (name) — no linked Odoo user" | The employee has no user_id | Create a res.users for that employee and link it via Employees → Related User |
| "Hospital Authorized Signer — not set" | Contract has no signer | Set roots_hospital_signer_id on the contract form |
| "Vendor (name) — has no email address" | Vendor partner is missing email | Edit the vendor partner and add an email |
The _check_signed hook itself is wrapped in a defensive try/except — if the parent write or chatter post fails (e.g. ACL collision, mail config issue), the signer still gets a successful "signed" experience. The error is logged server-side; the signed PDF remains available on the sign.oca.request record itself.
What's intentionally NOT in V1¶
See the index page for the full deferral list. Notably:
- No sequential signing — any signer can sign first (OQ2)
- No state gating — signing does not advance the parent's state (OQ3)
- No bridge on
maintenance.request— BME Manager / Ward / PM monthly sign-offs stay on paper for V1 (OQ1)