Architecture¶
HEMMS is not a single monolithic Odoo addon — it is a stack of three layers that compose around Odoo's built-in maintenance module. Each layer answers a different question and can evolve independently.
The three-layer model¶
┌─────────────────────────────────────────────────────────────────┐
│ Layer 3 — roots_hemms_* (Hospital lens) │
│ ─────────────────────────────────────── │
│ Governance, compliance, Thai-specific workflow, HA Thailand audit │
│ • roots_hemms_workflow request lifecycle + SLA + audit │
│ • roots_hemms_criticality value × risk matrix │
│ • roots_hemms_asset_master brand/model + Ref. No. │
│ • roots_hemms_asset_inspection annual stock-check (ปจป.) │
│ • roots_hemms_pm hospital PM kinds + stage │
└─────────────────────────────────────────────────────────────────┘
▲
│ extends
┌─────────────────────────────────────────────────────────────────┐
│ Layer 2 — OCA building blocks │
│ ────────────────────────────── │
│ Generic, configurable, community-maintained │
│ • maintenance_plan PM scheduling engine │
│ • maintenance_stock spare parts ↔ stock │
│ • maintenance_partner external service providers │
│ • sign_oca e-signature engine (OCA/sign) │
│ • ...vendored modules in addons/oca/ (see addons/oca/README.md) │
└─────────────────────────────────────────────────────────────────┘
▲
│ extends
┌─────────────────────────────────────────────────────────────────┐
│ Layer 1 — Odoo Base │
│ ────────────────── │
│ maintenance.request, maintenance.equipment, maintenance.stage, │
│ res.partner, res.users, hr.employee, hr.department │
└─────────────────────────────────────────────────────────────────┘
Layer 1 — What Odoo Base gives us¶
Odoo Community Edition's maintenance app:
maintenance.request— the work itemmaintenance.equipment— the assetmaintenance.stage— workflow stages (4 default: New / In Progress / Repaired / Scrap)- Kanban / list / form views
- Basic team assignment via
maintenance.team
What's missing for a hospital:
- No bilingual labels
- No SLA tracking per stage
- No structured audit log (only
mail.messagemixed with chatter) - No criticality/risk model
- No annual asset inspection workflow
- No government Ref. No. (รหัสครุภัณฑ์)
- No PM scheduling
Layer 2 — What OCA building blocks add¶
The OCA maintenance repo (vendored under addons/oca/) provides domain extensions, each as a separate, opt-in module. Think of them as Lego bricks — pick what you need.
| Module | Adds | Why a hospital cares |
|---|---|---|
maintenance_plan | maintenance.plan + maintenance.kind + cron | Auto-create PM requests on calendar interval |
maintenance_stock | links maintenance.request to stock.picking | Track spare parts consumption per repair |
maintenance_partner | links to res.partner | Track external service vendors per equipment |
sign_oca (OCA/sign) | sign.oca.template / request / role + audit log | e-Signature engine for ปจป. inspection + service contracts (Q4) |
maintenance_equipment_ref | adds ref field | Government inventory Ref. No. (รหัสครุภัณฑ์) |
maintenance_equipment_category_hierarchy | parent/child categories | Hierarchical equipment grouping |
... see addons/oca/README.md for the full vendored list | ... | ... |
OCA modules are generic and configurable — they don't impose a hospital workflow. They give us building blocks; we compose them.
Layer 3 — What roots_hemms_* layers add¶
The roots_hemms_* modules wrap OCA building blocks with hospital-specific governance and Thai compliance. They are the "Hospital Lens" on top of generic maintenance.
| Module | Adds | Governance concern |
|---|---|---|
roots_hemms_workflow | 5-stage Thai BME workflow + SLA + audit log | Operational: who did what, when, was SLA met |
roots_hemms_criticality | Value × Risk matrix → criticality color | Prioritization: which equipment matters most |
roots_hemms_asset_master | Brand / Model master + current_condition | Master data: what equipment do we own |
roots_hemms_asset_inspection | Annual stock-check workflow (ปจป.) | Compliance: HA Thailand annual audit |
roots_hemms_pm | Hospital PM kinds + PM Scheduled stage | Compliance: scheduled preventive maintenance |
How the layers compose: a PM request example¶
Worked example showing all three layers in action.
Step 1 — Setup (admin, one-time)¶
- Layer 1 — Equipment record exists for "Vital Signs Monitor #5"
- Layer 3 —
roots_hemms_criticalitycomputescriticality_color = red(high value × high risk because ICU equipment) - Layer 2 —
maintenance_planadmin attaches a plan: kind = Calibration, interval = 6 months, start_date = today - Layer 3 —
roots_hemms_pmprovides the "Calibration" kind as seed data (admin doesn't have to type it from scratch)
Step 2 — Scheduling (cron, daily)¶
- Layer 2 —
maintenance_plan._cron_generate_requests()runs at 06:00 - For each plan, the cron walks forward by
intervaluntil it hits theplanning_horizonwindow - For each date in the window, it creates a
maintenance.requestwithmaintenance_type = "preventive"andmaintenance_plan_idset - Layer 3 —
roots_hemms_pm.maintenance.request.create()overrides the stage assignment: ifmaintenance_plan_idis set, route to the "PM Scheduled" stage instead of the default "Submitted"
Step 3 — Execution (technician, daily ops)¶
- Layer 1 — Request appears in kanban under "PM Scheduled" column
- Layer 3 —
roots_hemms_workflowpropagates equipment criticality to the request, so the card shows a red dot - Layer 3 — Technician moves stage: PM Scheduled → Pending Review → In Repair → Awaiting Pickup → Received
- Layer 3 — Every stage transition creates a row in
hemms.stage.transition.log(audit trail) - Layer 3 — If a stage exceeds
roots_sla_hours, the request appears in[("roots_is_sla_breached", "=", True)]search
Step 4 — Reporting (manager, end of period)¶
- Layer 3 —
roots_hemms_workflowprovides SLA dashboards (operational metric) - Layer 3 —
roots_hemms_asset_inspectionprovides annual stock-check PDF reports (compliance metric) - Layer 3 —
roots_hemms_criticalityprovides red/yellow/green classification for prioritization
Why this layering matters¶
1. We don't fight Odoo or OCA¶
By extending instead of replacing, we get:
- Bug fixes from Odoo SA flow into our code automatically
- New features from OCA are opt-in (we can add another module without rework)
- Standard Odoo training applies to our users (kanban, list, search, etc.)
2. Hospital concerns live in one layer¶
If we ever need to support a non-hospital deployment (e.g., manufacturing), we can swap roots_hemms_* for roots_manufacturing_* — Layers 1+2 stay the same. Hospital logic is not entangled into the maintenance request model.
3. Compliance is auditable¶
Every Layer 3 module is small, focused, and easy to map to a compliance requirement:
- "Show me the audit trail for this request" →
hemms.stage.transition.log - "Show me all overdue PM on critical equipment" → join
criticality_color+roots_is_sla_breached+maintenance_type=preventive - "Show me last year's annual inspection report" →
hemms.asset.inspectionwith state = submitted
4. Each module can be versioned independently¶
A change to PM kinds doesn't force a release of the workflow module. A schema migration in roots_hemms_workflow doesn't ripple into the inspection module unless explicitly depended on.
Field naming convention¶
Hospital-specific fields use a roots_ prefix to avoid collision with Odoo or OCA fields, and to make them easy to spot in fields_get() output.
# ✅ Hospital-specific
roots_value_tier = fields.Selection(...)
roots_criticality_color = fields.Selection(...)
roots_sla_hours = fields.Float(...)
roots_stage_entered_at = fields.Datetime(...)
# ✅ Inherited / standard (no prefix)
name = fields.Char(...)
state = fields.Selection(...)
maintenance_kind_id = fields.Many2one(...) # comes from OCA
# ❌ Avoid
hospital_priority = ... # too vague; not prefix-discoverable
priority_v2 = ... # version in a field name is a smell
When inheriting a base Odoo / OCA model and adding fields, always prefix roots_. When defining a brand-new model owned by HEMMS, the _name is prefix-enough; individual fields don't need redundant prefixing.
OCA vs roots_hemms_* decision matrix¶
When adding a new feature, ask:
| Question | Layer |
|---|---|
| Is this generic maintenance functionality? (e.g., link to inventory, time tracking) | Look for an existing OCA module first |
| Is this hospital-specific compliance? (e.g., HA Thailand audit, Thai BME workflow) | Build in roots_hemms_* |
| Is this a UI-only tweak? | Inherit the view, don't write a new model |
| Is this configurable per installation? | Use ir.config_parameter or a setting, not a hardcoded constant |
Rule of thumb¶
Default to OCA. Only build new in roots_hemms_* when OCA doesn't have it AND the requirement is hospital/Thai-specific AND it's worth the maintenance burden.
Past examples of this decision:
- "We need PM scheduling" → ✅ OCA
maintenance_plan(don't build) - "We need spare parts tracking" → ✅ OCA
maintenance_stock(don't build) - "We need 5-stage Thai BME workflow with SLA breach detection" → ✅ Build
roots_hemms_workflow(OCA only has 4 generic stages without SLA) - "We need annual ปจป. PDF report in Thai format" → ✅ Build
roots_hemms_asset_inspection(no equivalent in OCA) - "We need bilingual maintenance kinds" → ✅ Build
roots_hemms_pmto extend OCA'smaintenance.kindwithroots_name_th(lightweight wrapper)
Module dependency graph¶
maintenance (Odoo base)
▲
│
base_maintenance (OCA)
▲
│
maintenance_plan (OCA)
▲
│
│ ┌──────────────────────────┐
├───┤ roots_hemms_asset_master │
│ └──────────────────────────┘
│ ▲
│ │
│ ┌──────────────────────────┐
├───┤ roots_hemms_criticality │
│ └──────────────────────────┘
│ ▲
│ │
│ ┌──────────────────────────┐
├───┤ roots_hemms_workflow │
│ └──────────────────────────┘
│ ▲
│ │
│ ┌──────────────────────────────┐
├───┤ roots_hemms_asset_inspection │
│ └──────────────────────────────┘
│ ▲
│ │
│ ┌──────────────────────────┐
└───┤ roots_hemms_pm │ (Q1)
└──────────────────────────┘
Glossary¶
| Term | Meaning |
|---|---|
| Layer 1 | Odoo CE base maintenance module |
| Layer 2 | OCA-vendored building blocks (addons/oca/) |
| Layer 3 | HEMMS hospital extensions (addons/roots/) |
| BME | Biomedical Engineering — hospital department maintaining medical equipment |
| HA Thailand | Healthcare Accreditation Institute (Thailand) — sets hospital accreditation standards |
| ปจป. | Annual asset inspection report (ตรวจสอบพัสดุประจำปี) |
| SLA | Service Level Agreement — max hours a request should spend in a stage |
| Criticality | Equipment importance — value × risk → red/yellow/green |
Related pages¶
- Module Development — how to add a new module to HEMMS
- Session 1 Build Notes — design decisions from initial build
- Roadmap — Quick Win Q1-Q7 sequencing