Commerce, travel and health codes
On this page
These are the codes trade, transport and healthcare use: barcodes, ISBNs, container numbers, delivery terms, airport codes, blood types, diagnosis codes. Each is checked by its standard's pattern or check digit, and the closed lists are enums.
Here a till scans a product's barcode, a supplier's order names its delivery term in whatever case its system writes, and a dock prints each container's number as its side is painted:
type ScannedText = Text {}type NotAProductCode = Failure { kind: FailureKind.invalid_value}type UnknownTradeTerm = Failure { kind: FailureKind.invalid_value}/// The product a till's scanner read: 13 digits, the last GS1's check/// digit.function scanned_product(raw: ScannedText) fails NotAProductCode -> Ean13 { var till_scan: Ean13 = attempt Ean13(raw) { format: NotAProductCode } return till_scan}/// The delivery term a supplier's order names, by its Incoterms code.function agreed_term(raw: ScannedText) fails UnknownTradeTerm -> Incoterm { var trade_term: Incoterm = attempt text.parse(raw, as: Incoterm) { malformed: UnknownTradeTerm } return trade_term}/// A container on the dock's manifest, as its side is painted.function container_label(shipped_in: ContainerNumber, viewer: Locale) -> PresentationText { return text.format(shipped_in, locale: viewer)}
test "a code is checked by its check digit as it is built" { var till_scan: Ean13 = attempt scanned_product("4006381333931") assert till_scan == Ean13("4006381333931") assert scanned_product("4006381333932") fails NotAProductCode assert scanned_product("400638133393") fails NotAProductCode assert container_label(ContainerNumber("CSQU3054383"), Locale.en_gb) == "CSQU 305438 3" assert text.format(UnNumber("UN1203"), locale: Locale.en_gb) == "UN 1203"}test "a closed list reads its codes in either case" { var trade_term: Incoterm = attempt agreed_term("fob") assert trade_term == Incoterm.fob assert agreed_term("Free On Board") fails UnknownTradeTerm assert text.from(BloodType.o_negative) == "O-" assert text.format(CabinClass.premium_economy, locale: Locale.fr_fr) == "Premium economy" assert list.count(Incoterm.all) == 11 assert list.count(Allergen.all) == 14}
Codes held as text
The codes are held as text, as the payment numbers are. Each is a pattern and, where the table under Groups with the baseline only names one, a named validator. Its canonical text is the value, in upper case where the standard writes it so and never read in another case. None is ordered.
Check digits
Where each check comes from:
- GS1's mod 10 (General Specifications 7.9) for
Ean13,UpcA,SsccandIsbn. An ISBN is its 13 digits with the prefix 978 or 979 and no hyphens, because where the hyphens go depends on the ISBN agency's ranges. - ISO 6346's for
ContainerNumber. - ISO 7064 MOD 11-2 for
Orcid. - Verhoeff's for
SnomedConcept, with a concept's partition identifier (00, or10in an extension), so a description's identifier is refused. - Elexon's primes for an
Mpancore. - A
Vin's check digit is checked where 49 CFR 565 requires it: for a manufacturer whose identifier starts 1 to 5, in North America. Elsewhere ISO 3779 leaves the ninth character to the manufacturer, and European VINs often don't carry a check digit, so checking every VIN would refuse real ones.
Patterns only
- a
Skuis 1 to 64 characters with no space or control character, kept as written; - a
LotNumberand aSerialNumberare 1 to 20 characters of GS1's character set 82 (Application Identifiers 10 and 21); - an
HsCode, a customs tariff code, is six to ten digits from chapter 01, as a tariff writes it without dots; - a
Carrieris its Standard Carrier Alpha Code, two to four capitals; - an
Icd10Codeis its letter, two digits and, after the dot, up to four more, which covers ICD-10-CM; - an
IataAirlineis two letters, or a letter and a digit; - a
BookingReferenceis six capitals and digits; - a
UnNumber, which names a dangerous good, isUNand four digits; - an
Mprn, a UK gas supply's number, is 6 to 10 digits.
Lists that aren't shipped
IATA's airport and airline codes and ICAO's location indicators are sold
under licence. WHO's ICD-10 may be used, but not redistributed in
software without its permission. So IataAirport, IcaoAirport,
IataAirline and Icd10Code are checked by pattern only, as UnLocode
is. An application that holds a licence checks against its own copy.
A SNOMED CT concept's term belongs to its release, under SNOMED
International's licence, so SnomedConcept is its identifier alone,
without a term.
Shown to people
A container number is shown as its side is painted, CSQU 305438 3, and
a UN number as a transport document writes it, UN 1203. The rest are
shown as their canonical text.
The closed lists
Each of these is a built-in enum, sorted by its code. Its code is read
ignoring case and stored as written (O-, FOB):
Incoterm: Incoterms 2020's eleven delivery terms, withDAT,DAF,DES,DEQandDDUfrom earlier editions retired;BloodType: ABO and RhD,A+toO-, whose variants spell the sign out,BloodType.o_negative;Allergen: the 14 that the UK's Food Information Regulations 2014 and the EU's Regulation 1169/2011 name, without regional additions;CabinClass: economy, premium economy, business and first;CefrLevel: language levelsA1toC2;EpcRating: energy performance bandsAtoG, without a score;Tenure: freehold, leasehold and commonhold, as HM Land Registry registers land in England and Wales; a share of a freehold is a leasehold with a share;LawfulBasis: GDPR Article 6(1)'s six lawful bases.
Where codes are words (premium_economy), each variant's code is its
own name, as Continent's are.
Shown by code or by the authority's wording. CLDR names none of these
lists. A list whose codes are written the same in every language (FOB,
B2, O-, C) is shown by its code. A list whose codes are words is
shown by its authority's English wording in every locale
(FormatKey::Names, as a card brand is), just as a subdivision is shown
by its English name: "Premium economy", "Cereals containing gluten",
"Legitimate interests". To show them in another language, word them in
your app's own messages.
None is ordered, not even CefrLevel and EpcRating. A match can
say their order. The contract orders only what it lists.
Personal data and test values
Personal data: an Icd10Code, a SnomedConcept and a BloodType
are health; an Orcid is identifying, as a username is; an Mpan and
an Mprn are contact, as a Uprn is, because each names a home's
supply. An Allergen isn't personal data: a menu's allergens describe
food, and a person's allergy is your application's own field, which you
mark.
Test values are published ones where a standard publishes them: GS1's, the ISBN Users' Manual's, NHTSA's, ISO 6346's, ORCID's, SNOMED CT's, and UPS's sample tracking number. Where a standard publishes none, they are made up to the rules. Each type's entry says which.
Markdown for agents: /docs/commerce-travel-and-health-codes.md.Built from Jadpo main at a707efb.