Service Contracts: Configuration¶
This page covers every configurable aspect of the Service Contracts module.
Contract types¶
hemms.contract.type is the small master vocabulary that classifies every contract. The module ships with 5 seed types (admin-extensible):
| Code | English Name | Thai Name | Typical use |
|---|---|---|---|
warranty | Manufacturer Warranty | รับประกันจากผู้ผลิต | bundled at purchase, 1–3 years |
ext_warranty | Extended Warranty | รับประกันแบบขยายเวลา | purchased extension past base warranty |
ma | Maintenance Agreement (MA) | สัญญาบำรุงรักษา | comprehensive PM + corrective; common for MRI/CT |
spare_only | Spare Parts Only | เฉพาะอะไหล่ | vendor supplies parts, hospital does labor |
labor_only | Labor Only | เฉพาะค่าแรง | vendor provides expertise, parts billed at use |
Adding a custom contract type¶
- Navigate to :menuselection:
Maintenance --> Configuration --> Contract Types - Click :guilabel:
New - Fill in:
- Name (translatable, English)
- Thai Name (
roots_name_th) - Code — unique stable identifier in lowercase, no spaces (used by downstream logic such as the Q3.5 banner copy and Q4 routing)
- Description — when to use this type
- Sequence — display ordering
- Save
Codes drive logic — pick stable values
The code field is referenced by downstream logic (e.g. the _WARRANTY_CODES = ("warranty", "ext_warranty") constant in maintenance_equipment.py determines whether the Under-Warranty badge appears on the equipment form). Renaming a code after data exists requires a one-off migration script.
Archiving an unused type¶
Toggle Active off on a contract type to hide it from new contract dropdowns. Existing contracts of that type are unaffected.
Service Contract sequence (SC/2026/00001)¶
Contract references are assigned at create time from an ir.sequence record (code hemms.service.contract).
Default format¶
| Setting | Value |
|---|---|
| Code | hemms.service.contract |
| Prefix | SC/%(year)s/ |
| Padding | 5 |
| Company | (shared across companies — company_id=False) |
Customising the prefix¶
The sequence is admin-editable through:
:menuselection:Settings --> Technical --> Sequences & Identifiers --> Sequences
Search for HEMMS Service Contract. Common customisations:
- Add the company code:
SC/%(year)s/HMS/→SC/2026/HMS/00001 - Switch to Thai Buddhist year: prefix
SC/2569/(you'll need to update it yearly; or write a server action that flips the prefix on 1 January) - Bigger padding for hospitals that issue thousands of contracts: set padding to 7
Per-company sequences
To keep one sequence per company, duplicate the sequence record, set company_id on each copy, and Odoo will route by the active company on create.
SLA tier¶
Every contract has a roots_sla_tier Selection with four levels:
| Tier | Typical response | Use case |
|---|---|---|
| Bronze | 24-72 hours | low-risk equipment, ward-level monitors |
| Silver | 8-24 hours | imaging, lab analysers |
| Gold | 4-8 hours | OR equipment, ventilators |
| Platinum | <4 hours | life-support, ICU |
The free-form roots_sla_response_hours (Float) lets you record the exact vendor commitment. Q3 displays these on the contract form and search filters; SLA breach detection is Q4.
Renewal alert¶
Each contract carries roots_renewal_alert_days (Integer, default 60) — the number of days before date_end at which the daily cron will fire a renewal activity.
To customise per contract:
- Open the contract form
- In the Validity group, change Renewal Alert (days before end)
- The Alert On field re-computes to
date_end - roots_renewal_alert_days - Save
To customise globally, set the default in the hemms.service.contract model definition (requires a custom module or ir.default record). Multi-stage thresholds (90/60/30/7) are deferred to Q4.
Daily cron¶
HEMMS Service Contract — daily state + renewal alert runs once a day and does two things in one transaction:
- State transitions (draft → active → expired) based on
date_start/date_end. Cancelled is sticky. - Renewal alerts for active contracts at or past their alert date, provided
roots_renewal_alerted=False.
To pause the cron, edit it via :menuselection:Settings --> Technical --> Automation --> Scheduled Actions and toggle Active off.
Bilingual settings¶
The module exposes Thai labels on three records:
| Field | Bilingual? | Where |
|---|---|---|
hemms.contract.type.name | translatable | per type seed |
hemms.contract.type.roots_name_th | yes | per type seed |
hemms.service.contract.name | not translated (English) | per contract |
hemms.service.contract.roots_name_th | yes | per contract |
Search on hemms.service.contract looks at reference + name + roots_name_th, so a user typing Thai text will find the contract.
To add your firm's languages, install the matching base language pack and translate the contract type Name field in each locale.
ACL / security groups¶
Two access rules ship with the module:
| Group | Read | Write | Create | Unlink |
|---|---|---|---|---|
base.group_user (any internal user) | ✅ | ❌ | ❌ | ❌ |
maintenance.group_equipment_manager | ✅ | ✅ | ✅ | ✅ |
The same pattern applies to all three models (hemms.contract.type, hemms.service.contract, hemms.service.contract.coverage.line).
Restricting contract visibility further
For larger hospitals with multiple BME teams, layer a record rule on top of the ACL — e.g. only show contracts where user_id = uid or the user belongs to a team. Add it via :menuselection:Settings --> Technical --> Security --> Record Rules.
Vendor filter — supplier domain deferred¶
The module currently does not restrict the Vendor picker to "supplier" partners. The supplier_rank field comes from the optional purchase module, which is not in this module's depends. Two ways to add the filter when you need it:
- Add
purchaseto depends — heaviest option; full PO workflow becomes available - Add a
roots_is_vendorBoolean onres.partnerfrom a small follow-up module — lighter, hospital-specific
Both options are tracked as a Q3 follow-up.