codeset

package
v0.1.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package codeset holds mapping tables that outlive the channel that first needed one.

The domain tax is largely re-deriving a mapping somebody already derived. A site's sex codes, patient classes, order statuses and facility identifiers get translated the same way in every channel that touches them, and today each of those translations is a separate table inside a separate channel. Forty channels means forty copies and forty places to fix the next time the receiving system changes.

So a table becomes a named object referenced by name. That much is obvious and it is the smaller half of the value.

The half nobody builds

The larger half is provenance. Most of what makes an interface hard to maintain is not the mapping - it is that nobody knows *why*. "We strip leading zeros because the lab's MRN column is numeric" is knowledge that exists in one person's head and leaves the building when they retire, and the mapping that remains becomes something nobody dares change and nobody dares delete.

So every table records who decided and when, every entry may record its own reason, and both survive into the file that goes into version control. A mapping with a reason can be argued with. A mapping without one becomes superstition.

Why the file is separate from the channel

Because it is shared. A table inside a channel is a table only that channel can use, which is the problem. And a shared table needs its own history: "who changed the sex mapping, and when" is a question about the table, not about whichever channel happened to be edited that day.

Index

Constants

View Source
const (
	StatusApproved = "approved"
	StatusDraft    = "draft"
	StatusRetired  = "retired"
)

Statuses of a table edition.

Variables

This section is empty.

Functions

func Today

func Today() string

Today is the date format used for Since and DecidedOn.

A plain date rather than a timestamp: the useful granularity for "when was this decided" is the day, and a timestamp implies a precision that a human decision does not have.

Types

type Diff added in v0.1.17

type Diff struct {
	Added   []Entry       `json:"added"`
	Removed []Entry       `json:"removed"`
	Changed []EntryChange `json:"changed"`
}

Diff compares two editions: what was added, removed, and mapped to something else.

func Compare added in v0.1.17

func Compare(a, b *Table) Diff

Compare says how edition b differs from edition a.

type Entry

type Entry struct {
	// From is the incoming value.
	From string `yaml:"from" json:"from"`

	// To is what it becomes.
	To string `yaml:"to" json:"to"`

	// Why records why this particular entry exists, when it is not obvious.
	//
	// Per entry rather than only per table, because the unobvious ones are usually individual: a table of
	// twelve sex codes has one strange row, and that row is the one somebody will want to delete in three
	// years.
	Why string `yaml:"why,omitempty" json:"why,omitempty"`

	// Since records when this entry was added, for a table that grew over time.
	Since string `yaml:"since,omitempty" json:"since,omitempty"`
}

Entry is one mapping, with the reason it exists.

type EntryChange added in v0.1.17

type EntryChange struct {
	From   string `json:"from"`
	Before string `json:"before"`
	After  string `json:"after"`
}

EntryChange is a value whose mapping changed between editions.

type Set

type Set struct {
	Tables []Table `yaml:"tables" json:"tables"`

	// Observe, when set, is told every value a map step could not find in a table, so unmapped codes can be listed for
	// somebody to map. Called on the message's goroutine; it must not block.
	Observe func(table, value string) `yaml:"-" json:"-"`
	// contains filtered or unexported fields
}

Set is a collection of tables loaded together.

func (*Set) Compile

func (s *Set) Compile()

Compile indexes the set for lookup by name.

func (*Set) Editions added in v0.1.17

func (s *Set) Editions(name string) []*Table

Editions lists every edition of a table, earliest start first, drafts and retired ones included.

func (*Set) Has added in v0.1.17

func (s *Set) Has(name string) bool

Has reports whether any edition of a table exists, whatever its status or dates.

func (*Set) Names

func (s *Set) Names() []string

Names lists the tables, sorted.

func (*Set) NoteUnmapped added in v0.1.17

func (s *Set) NoteUnmapped(table, value string)

NoteUnmapped tells Observe about a value a table did not have.

func (*Set) Table

func (s *Set) Table(name string) (*Table, bool)

Table returns the edition of a table in force today (UTC).

func (*Set) TableAt added in v0.1.17

func (s *Set) TableAt(name string, at time.Time) (*Table, bool)

TableAt returns the edition in force at a moment: of the approved editions whose dates cover that day, the one that started latest. Drafts and retired editions are never returned.

func (*Set) Validate

func (s *Set) Validate() []error

Validate checks every table and the set as a whole.

type Table

type Table struct {
	// Name is how channels refer to it.
	Name string `yaml:"name" json:"name"`

	// Describes says what this table is for, in words.
	//
	// Required, not optional. A table called "sex" tells the next person nothing about whether it maps into the
	// hospital's codes or out of them, and getting that backwards is a silent data error rather than a
	// failure.
	Describes string `yaml:"describes" json:"describes"`

	// Entries are the mappings.
	Entries []Entry `yaml:"entries" json:"entries"`

	// Default applies when a value is not in the table. Empty means keep the original.
	Default string `yaml:"default,omitempty" json:"default,omitempty"`

	// Strict makes an unmapped value an error rather than a pass-through.
	Strict bool `yaml:"strict,omitempty" json:"strict,omitempty"`

	// DecidedBy and DecidedOn are the provenance of the table as a whole.
	//
	// Free text, deliberately. A name, a team, a ticket number and "the 2019 migration" are all real answers,
	// and a schema that only accepted one of them would get an empty field or a lie.
	DecidedBy string `yaml:"decided_by,omitempty" json:"decidedBy,omitempty"`
	DecidedOn string `yaml:"decided_on,omitempty" json:"decidedOn,omitempty"`

	// Source records where the mapping came from - a specification, a conversation, an observed feed.
	Source string `yaml:"source,omitempty" json:"source,omitempty"`

	// Version names this edition of the table, so several can be kept under one name: the one in force, a draft waiting
	// for sign-off, and the ones before. Empty is a table with one edition.
	Version string `yaml:"version,omitempty" json:"version,omitempty"`

	// EffectiveFrom is the first day (YYYY-MM-DD, UTC) this edition is used; empty means from the start. A later approved
	// edition's EffectiveFrom ends this one, so a new mapping can be approved today and take over on the first of the month.
	EffectiveFrom string `yaml:"effective_from,omitempty" json:"effectiveFrom,omitempty"`

	// EffectiveUntil is the last day this edition is used, inclusive; empty means until a later edition takes over.
	EffectiveUntil string `yaml:"effective_until,omitempty" json:"effectiveUntil,omitempty"`

	// Status is approved (the default: in use within its dates), draft (written, waiting for sign-off, never used) or
	// retired (kept for the record, never used).
	Status string `yaml:"status,omitempty" json:"status,omitempty"`

	// Author is the account that saved this edition from the console, which sign-off is checked against.
	Author string `yaml:"author,omitempty" json:"author,omitempty"`

	// ApprovedBy and ApprovedOn record the sign-off of an edition that needed one.
	ApprovedBy string `yaml:"approved_by,omitempty" json:"approvedBy,omitempty"`
	ApprovedOn string `yaml:"approved_on,omitempty" json:"approvedOn,omitempty"`

	// SourceSystem and TargetSystem name the code systems of From and To (http://loinc.org, http://snomed.info/sct, a
	// local URL), so the console can check each entry against an imported code system and FHIR can publish the map.
	SourceSystem string `yaml:"source_system,omitempty" json:"sourceSystem,omitempty"`
	TargetSystem string `yaml:"target_system,omitempty" json:"targetSystem,omitempty"`
	// contains filtered or unexported fields
}

Table is a named mapping.

func (*Table) Compile

func (t *Table) Compile()

Compile builds the lookup index.

func (*Table) Describe

func (t *Table) Describe() string

Describe renders a table for a specification document.

Includes the provenance, because a specification that says what a field becomes without saying why invites the receiving team to argue with the mapping - and the answer to that argument is usually "because you asked us to, in 2019".

func (*Table) InForce added in v0.1.17

func (t *Table) InForce(day string) bool

InForce reports whether an approved edition's own dates cover day (YYYY-MM-DD). A later edition may still take over; see Set.TableAt.

func (*Table) InUse added in v0.1.17

func (t *Table) InUse() bool

InUse reports whether the edition may be used at all (approved, not draft or retired).

func (*Table) Lookup

func (t *Table) Lookup(value string) (result string, entry Entry, mapped bool)

Lookup translates one value.

Returns the entry as well as the result, so a caller can report the reason a value was changed. That is what makes a transformation traceable: "PID-8 M became 1" is a fact, and "because the lab's interface predates the HL7 table, per the 2019 migration" is an explanation.

func (*Table) Strictly

func (t *Table) Strictly(value string) (string, error)

Strictly translates a value and reports an error when it is unmapped and the table is strict.

func (*Table) Validate

func (t *Table) Validate() []error

Validate checks a table.

func (*Table) Values

func (t *Table) Values() []string

Values returns the permitted outputs, sorted.

Useful for generating a contract expectation from a table: if a channel maps a field through a table, the set of values that can leave is knowable, and a contract can assert it. That is the two domain-tax features meeting - the mapping knows what it produces, and the contract can check nothing else appears.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL