Import a whole facility through one vendor-neutral interchange path
Data Interchange is the single way inventory enters Ovahol. Paste or upload a supplier CSV/JSON and the convert step stages a candidate bundle in the Medical Device Lifecycle Interchange standard (v0.1.0); or bring an exported bundle directly. A Super Admin, Org Admin, or Facility Admin picks the target facility, validates, dry-runs, then imports — everything commits in one atomic transaction.
By the end of this stage: One standard bundle carries devices, catalog references, locations, maintenance history, lifecycle events, and preserved source fields into the chosen facility — with no per-source import code.
Modules involved: Data Interchange, Device Records, PM Schedules, Work Orders, Fault Reports, Performance Checks, Recalls & Incidents, Transfers, Retirement & Disposal, Spare Parts, Training
What to do
1. Choose the target facility
On Admin → Data Interchange, pick the facility the import applies to. Facility Admins are locked to their own facility, Org Admins see their organization, and Super Admins see every facility. The backend enforces the same scope, so a picker can never widen access.
2. Convert foreign inventory (optional)
Paste or upload a CSV/JSON export from your current system. The converter maps headers, normalizes names, and stages a candidate interchange bundle — nothing is written yet. Attach a column mapping for unusual headers; unmapped fields are preserved as source data.
3. Validate and dry-run
Run validation for structural errors, then a dry run. The dry run executes the real apply path inside a rolled-back transaction, so its created/linked counts and per-record errors predict the import exactly.
4. Import atomically
Execute the import. Locations, catalog entries, device records, work orders, faults, and lifecycle history all commit together — if anything fails, nothing is written.
Bundle shape
| Field | Top-level | What it imports |
|---|---|---|
assets[] | Devices | One per physical device: identifiers (serial, asset tag, UDI), modelRef / deviceDefinitionRef, locationRef, operational condition, provenance, and preserved sourceData. |
deviceDefinitions[] · models[] · brands[] · manufacturers[] | Catalog | The dictionary records assets point at. Names are matched against the shared catalog; unmatched names can be staged as review recommendations. |
locations[] · departments[] | Places | Facility locations and departments. Existing names are reused; missing ones are created inside the target facility during import. |
workOrders[] · faultReports[] · maintenanceActivities[] | Maintenance | Maintenance history linked to assets by assetRef, including status, priority, failure codes, and the work actually performed. |
lifecycleEvents[] | Lifecycle | Recalls, incidents, transfers, retirement reviews, and disposition events, with from/to location refs and reasons. |
extensions[] | Extensions | Ovahol-specific data the standard has no field for (spare parts, training sessions, decommission chains), versioned by extension URL. |
Skeleton
One asset with a catalog reference and identifiers:
{
"format": "medical-device-lifecycle-interchange",
"formatVersion": "0.1.0",
"exportedAt": "2026-01-01T00:00:00Z",
"source": { "system": "legacy-cmms" },
"facility": { "id": "facility-1", "name": "Main Hospital" },
"deviceDefinitions": [
{ "id": "d1", "name": "Infusion Pump" }
],
"models": [
{ "id": "m1", "modelName": "Plum 360",
"deviceDefinitionRef": { "ref": "d1" } }
],
"locations": [
{ "id": "l1", "name": "ICU",
"facilityRef": { "ref": "facility-1" } }
],
"assets": [
{ "id": "a1",
"modelRef": { "ref": "m1" },
"locationRef": { "ref": "l1" },
"identifiers": [
{ "system": "legacy-cmms:serial-number", "value": "SN-001" },
{ "system": "legacy-cmms:asset-tag", "value": "TAG-001" }
] }
]
}Good to know
- Every
*Refpoints at an id declared in the same bundle (deviceDefinitions,models,locations, …), so the bundle is self-contained. - Identity identifiers use a
:serial-number,:asset-tag, or:udisuffix; importing the same device again links it instead of duplicating it. - Dates use ISO-8601 (
YYYY-MM-DDor a full timestamp). Every list is optional exceptassets. - Import is atomic: if any record fails, the whole bundle is rolled back and nothing is written.