GS1.Code (gs1_barcode v0.1.2)

View Source

Utilities for detecting, validating, creating and normalizing GS1 codes.

Handles GTIN-8 (EAN-8 symbology), GTIN-12 (UPC-A symbology), GTIN-13 (GLN, EAN-13 symbology), GTIN-14 (ITF-14 symbology) and SSCC-18.

Summary

Types

Detected code type.

Detect error reason.

Generate error reason.

Normalize error reason.

Functions

Generates a valid SSCC (Serial Shipping Container Code) from the Extension Digit, GS1 Company Prefix (GCP), and Serial Reference.

Bang version of build_sscc/3. Raises ArgumentError if invalid arguments passed.

Lookups country (MO) based on the code prefix. Returns nil non-country ranges and for GTIN-8 as they use a distinct prefix list.

Checks if valid code is a coupon. Detects various coupon formats, including global coupons and restricted circulation coupons often used within specific geographic regions.

Checks if valid code is in range reserved for demonstration or testing.

Detects valid GS1 code and returns type.

Bang version of detect/1. Raises an ArgumentError if the code is invalid .

Generates a complete GS1 code GTIN-8,12,13 from integer key. For GTIN-14 and SSCC, use the corresponding dedicated functions.

Bang version of generate/2. Raises an ArgumentError if the code cannot be generated (e.g., key is out of bounds, invalid type, or attempts to generate SSCC/GTIN-14).

Checks if valid code is an ISBN (International Standard Book Number).

Checks if valid code is an ISSN (International Standard Serial Number).

Returns payload (part without check digit) of valid code.

Bang version of payload/1. Raises ArgumentError if code is invalid (detect error).

Lookups usage range of the valid code.

Checks if the valid code belongs to a Restricted Circulation Number (RCN) range.

Checks if valid code is a Refund Receipt.

Normalizes valid GTIN-8 to a GTIN-12 Returns error if the input is not a valid GTIN or cannot be normalized to this dimension.

Bang version of to_gtin12/1. Raises ArgumentError if the code cannot be detected or normalized.

Normalizes valid GTIN-8,12 to a GTIN-13.

Bang version of to_gtin13/1. Raises ArgumentError if the code cannot be detected or normalized.

Normalizes a valid GTIN-8, 12, or 13 to a GTIN-14 with a given Packaging Level Indicator (PLI).

Bang version of to_gtin14/1. Raises ArgumentError if the code cannot be detected or normalized.

Casts a valid GS1 GTIN code to its pure base integer representation by stripping necessary prefixes and check digit.

Bang version of to_key/1. Raises ArgumentError if the code cannot be detected or normalized.

Types

code_type()

@type code_type() :: :gtin8 | :gtin12 | :gtin13 | :gtin14 | :sscc

Detected code type.

detect_error()

@type detect_error() :: :invalid_length | :invalid_input | :invalid_digit_or_checksum

Detect error reason.

generate_error()

@type generate_error() ::
  :invalid_key
  | :invalid_type
  | :key_out_of_bounds
  | :use_to_gtin14
  | :use_build_sscc

Generate error reason.

normalize_error()

@type normalize_error() :: :cannot_normalize | :sscc_has_no_product_id

Normalize error reason.

Functions

build_sscc(ext, gcp, serial)

@spec build_sscc(non_neg_integer() | char(), String.t(), String.t()) ::
  {:error, :gcp_or_serial_too_long | :invalid} | {:ok, String.t()}

Generates a valid SSCC (Serial Shipping Container Code) from the Extension Digit, GS1 Company Prefix (GCP), and Serial Reference.

SSCC is an 18-digit number used to identify logistics units, with structure:

  1. Extension Digit: 1 digit (0-9).
  2. GS1 Company Prefix: variable length.
  3. Serial Reference: variable length (padded with leading zeros if needed).
  4. Check Digit: 1 digit.

Function ensures that the combined length of GCP and Serial doesn't exceeds 16 digits, and returns an error if the provided serial is too long to fit within the remaining space allowed by the GCP.

Examples

iex> GS1.Code.build_sscc(1, "4006381", "12345")
{:ok, "140063810000123454"}

# Accepts Extension Digit as char or integer
iex> GS1.Code.build_sscc(?0, "4006381", "12345")
{:ok, "040063810000123457"}

iex> GS1.Code.build_sscc(1, "1234567890123456", "1")
{:error, :gcp_or_serial_too_long}

build_sscc!(ext, gcp, serial)

@spec build_sscc!(non_neg_integer() | char(), String.t(), String.t()) :: String.t()

Bang version of build_sscc/3. Raises ArgumentError if invalid arguments passed.

Examples

iex> GS1.Code.build_sscc!(1, "4006381", "12345")
"140063810000123454"

country(code)

@spec country(String.t()) :: GS1.CompanyPrefix.country_mo() | {:error, detect_error()}

Lookups country (MO) based on the code prefix. Returns nil non-country ranges and for GTIN-8 as they use a distinct prefix list.

Examples

iex> GS1.Code.country("4006381333931")
[{"Germany", "DE", "DEU", "276"}]

coupon?(code)

@spec coupon?(String.t()) :: boolean()

Checks if valid code is a coupon. Detects various coupon formats, including global coupons and restricted circulation coupons often used within specific geographic regions.

Examples

iex> GS1.Code.coupon?("9812345678902")
true

demo?(code)

@spec demo?(String.t()) :: boolean()

Checks if valid code is in range reserved for demonstration or testing.

Examples

iex> GS1.Code.demo?("9529999199997")
true

detect(code)

@spec detect(String.t()) :: {:ok, code_type()} | {:error, detect_error()}

Detects valid GS1 code and returns type.

Examples

iex> GS1.Code.detect("4006381333931")
{:ok, :gtin13}

iex> GS1.Code.detect("123")
{:error, :invalid_length}

detect!(code)

@spec detect!(String.t()) :: code_type()

Bang version of detect/1. Raises an ArgumentError if the code is invalid .

Examples

iex> GS1.Code.detect!("4006381333931")
:gtin13

iex> GS1.Code.detect!("123")
** (ArgumentError) invalid_length

generate(code_type, key)

@spec generate(code_type(), pos_integer()) ::
  {:error, generate_error()} | {:ok, String.t()}

Generates a complete GS1 code GTIN-8,12,13 from integer key. For GTIN-14 and SSCC, use the corresponding dedicated functions.

This function is primarily intended for restoring from key representation or generating codes in RCN (Restricted Circulation Number) ranges (e.g., prefixes 02, 04, 20-29) and other private ranges, which are used for internal company purposes, variable measure items, or region-specific applications.

Standard GTINs for commercial use must be obtained from local GS1 MO. This function does not validate if the generated code falls within an allocated prefix range.

Returns {:ok, code} on success, or {:error, generate_error()} on failure.

Examples

iex> GS1.Code.generate(:gtin13, 200000000034)
{:ok, "2000000000343"}

iex> GS1.Code.generate(:gtin14, 200000000034)
{:error, :use_to_gtin14}

generate!(code_type, key)

@spec generate!(code_type(), pos_integer()) :: String.t()

Bang version of generate/2. Raises an ArgumentError if the code cannot be generated (e.g., key is out of bounds, invalid type, or attempts to generate SSCC/GTIN-14).

Examples

iex> GS1.Code.generate!(:gtin13, 200000000034)
"2000000000343"

iex> GS1.Code.generate!(:gtin14, 200000000034)
** (ArgumentError) use_to_gtin14

isbn?(code)

@spec isbn?(String.t()) :: boolean()

Checks if valid code is an ISBN (International Standard Book Number).

Examples

iex> GS1.Code.isbn?("9783161484100")
true

issn?(code)

@spec issn?(String.t()) :: boolean()

Checks if valid code is an ISSN (International Standard Serial Number).

Examples

iex> GS1.Code.issn?("9771234567003")
true

payload(code)

@spec payload(String.t()) :: {:ok, String.t()} | {:error, detect_error()}

Returns payload (part without check digit) of valid code.

Examples

iex> GS1.Code.payload("4006381333931")
{:ok, "400638133393"}

payload!(code)

@spec payload!(String.t()) :: String.t()

Bang version of payload/1. Raises ArgumentError if code is invalid (detect error).

Examples

iex> GS1.Code.payload!("4006381333931")
"400638133393"

range(code)

@spec range(String.t()) ::
  {:ok, GS1.CompanyPrefix.range_type()} | {:error, detect_error()}

Lookups usage range of the valid code.

Returns {:ok, range_type} if found, {:ok, nil} if code valid but not in special range, or {:error, reason} if the code detection failed

Examples

iex> GS1.Code.range("2000000000039")
{:ok, :rcn}

iex> GS1.Code.range("9781449369996")
{:ok, :isbn}

iex> GS1.Code.range("4006381333931") # GTIN for product with country code prefix
{:ok, nil}

rcn?(code)

@spec rcn?(String.t()) :: boolean()

Checks if the valid code belongs to a Restricted Circulation Number (RCN) range.

RCNs are used for internal purposes (e.g., variable measure items like meat/produce sold by weight, or internal company codes) and should not be used in open trade.

Examples

iex> GS1.Code.rcn?("2001234567893")
true

iex> GS1.Code.rcn?("4006381333931") # Standard trade item
false

refund?(code)

@spec refund?(String.t()) :: boolean()

Checks if valid code is a Refund Receipt.

Examples

iex> GS1.Code.refund?("9800004500008")
true

to_gtin12(code)

@spec to_gtin12(String.t()) ::
  {:ok, String.t()} | {:error, detect_error() | normalize_error()}

Normalizes valid GTIN-8 to a GTIN-12 Returns error if the input is not a valid GTIN or cannot be normalized to this dimension.

Examples

iex> GS1.Code.to_gtin12("40052441")
{:ok, "000040052441"}

to_gtin12!(code)

@spec to_gtin12!(String.t()) :: String.t()

Bang version of to_gtin12/1. Raises ArgumentError if the code cannot be detected or normalized.

Examples

iex> GS1.Code.to_gtin12!("40052441")
"000040052441"

to_gtin13(code)

@spec to_gtin13(String.t()) ::
  {:ok, String.t()} | {:error, detect_error() | normalize_error()}

Normalizes valid GTIN-8,12 to a GTIN-13.

GTIN-14 is reduced to GTIN-13 by stripping 1-digit Packaging Level Indicator (PLI) and payload with check digit calculation. No additional PLI logic check applied.

Returns error if the input is not a valid GTIN or cannot be normalized to this dimension.

Examples

iex> GS1.Code.to_gtin13("12345670")
{:ok, "0000012345670"}

# GTIN-14 is reduced to GTIN-13 (payload + new check digit calculated)
iex> GS1.Code.to_gtin13("10123456789019")
{:ok, "0123456789012"}

to_gtin13!(code)

@spec to_gtin13!(String.t()) :: String.t()

Bang version of to_gtin13/1. Raises ArgumentError if the code cannot be detected or normalized.

Examples

iex> GS1.Code.to_gtin13!("12345670")
"0000012345670"

to_gtin14(pli, code)

@spec to_gtin14(non_neg_integer() | char(), String.t()) ::
  {:ok, String.t()} | {:error, detect_error() | normalize_error()}

Normalizes a valid GTIN-8, 12, or 13 to a GTIN-14 with a given Packaging Level Indicator (PLI).

A PLI can be an int [0, 9] or its character representation.

  • PLI 0: Simply pads the input to 14 digits (preserves existing check digit).
  • PLI 1-9: Constructs a new hierarchical code and recalculates the Check Digit.

Returns error if the input is not a valid GTIN or cannot be normalized.

Examples

iex> GS1.Code.to_gtin14(1, "4006381333931")
{:ok, "14006381333938"}

iex> GS1.Code.to_gtin14(0, "4006381333931")
{:ok, "04006381333931"}

to_gtin14!(pli, code)

@spec to_gtin14!(non_neg_integer() | char(), String.t()) :: String.t()

Bang version of to_gtin14/1. Raises ArgumentError if the code cannot be detected or normalized.

Examples

iex> GS1.Code.to_gtin14!(0, "4006381333931")
"04006381333931"

to_key(code)

@spec to_key(String.t()) ::
  {:error, :invalid_key_type | detect_error()} | {:ok, pos_integer()}

Casts a valid GS1 GTIN code to its pure base integer representation by stripping necessary prefixes and check digit.

This representation is the core identification number suitable for storage in a database or use as a unique int key for data lookup.

Logic for extracting the base int is dependent on the detected code type:

  • SSCC: cannot be reduced to a key because it doesn't contains product GTIN. Returns {:error, :invalid_key_type}.
  • GTIN-14: base number is derived by stripping both the first char Indicator (PLI) and trailing check digit (last character).
  • Other GTIN codes: base number is derived by stripping only the trailing Check Digit. The remaining digits are converted to an int.

Examples

iex> GS1.Code.to_key("11234567890125")
{:ok, 123456789012} # strips '1' (Indicator) and '8' (Check Digit)

iex> GS1.Code.to_key("1234567890128")
{:ok, 123456789012} # strips '8' (Check Digit)

iex> GS1.Code.to_key("012345679999999997")  # SSCC cannot be converted
{:error, :invalid_key_type}

to_key!(code)

@spec to_key!(String.t()) :: pos_integer()

Bang version of to_key/1. Raises ArgumentError if the code cannot be detected or normalized.

Examples

iex> GS1.Code.to_key!("1234567890128")
123456789012