gs1 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,26 @@
1
+ module GS1
2
+ module Barcode
3
+ # Module for handling definitions.
4
+ #
5
+ module Definitions
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ # Adding defintion class methods.
11
+ #
12
+ module ClassMethods
13
+ attr_reader :records
14
+
15
+ def define_records(*records)
16
+ @records ||= []
17
+ @records = records
18
+
19
+ records.each do |record|
20
+ attr_reader record.underscore_name
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ module GS1
2
+ module Barcode
3
+ # Barcode for boxes in healthcare business.
4
+ #
5
+ class Healthcare < Base
6
+ define_records GTIN, ExpirationDate, Batch, SerialNumber
7
+
8
+ def to_s(level: AIDCMarketingLevels::ENHANCED)
9
+ return unless valid?(level: level)
10
+
11
+ [gtin.to_ai,
12
+ expiration_date&.to_ai,
13
+ batch&.to_ai,
14
+ serial_number&.to_ai].compact.join
15
+ end
16
+
17
+ def valid?(level: AIDCMarketingLevels::ENHANCED)
18
+ return false unless AIDCMarketingLevels::ALL.include?(level)
19
+
20
+ validate(level)
21
+
22
+ errors.empty?
23
+ end
24
+
25
+ private
26
+
27
+ def validate(level)
28
+ errors.clear
29
+
30
+ validate_minimum
31
+ return if level == AIDCMarketingLevels::MINIMUM
32
+
33
+ validate_enhanced
34
+ return if level == AIDCMarketingLevels::ENHANCED
35
+
36
+ validate_highest
37
+ end
38
+
39
+ def validate_minimum
40
+ errors << 'Invalid gtin' unless gtin.valid?
41
+ end
42
+
43
+ def validate_enhanced
44
+ errors << 'Invalid batch' unless batch&.valid?
45
+ errors << 'Invalid expiration date' unless expiration_date&.valid?
46
+ end
47
+
48
+ def validate_highest
49
+ errors << 'Invalid serial number' unless serial_number&.valid?
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,4 @@
1
+ require 'gs1/barcode/definitions'
2
+
3
+ require 'gs1/barcode/base'
4
+ require 'gs1/barcode/healthcare'
data/lib/gs1/batch.rb ADDED
@@ -0,0 +1,33 @@
1
+ module GS1
2
+ # Batch or lot number: AI (10)
3
+ #
4
+ # The GS1 Application Identifier (10) indicates that the GS1 Application Identifier data field contains a
5
+ # batch or lot number. The batch or lot number associates an item with information the manufacturer
6
+ # considers relevant for traceability of the trade item to which the element string is applied. The data may
7
+ # refer to the trade item itself or to items contained. The number may be, for example, a production lot
8
+ # number, a shift number, a machine number, a time, or an internal production code. The data is
9
+ # alphanumeric and may include all characters contained in figure 7.11-1.
10
+ #
11
+ # Note: The batch or lot number is not part of the unique identification of a trade item.
12
+ #
13
+ # Figure 3.4.1-1. Format of the element string
14
+ # |----|------------------------------------------------------|
15
+ # | AI | Batch or lot number |
16
+ # |----|------------------------------------------------------|
17
+ # | 10 | X1 -------------> variable length -------------> X20 |
18
+ # |----|------------------------------------------------------|
19
+ #
20
+ # The data transmitted by the barcode reader means that the element string denoting a batch or lot
21
+ # number has been captured. As this element string is an attribute of a particular item, it must be
22
+ # processed together with the GTIN of the trade item to which it relates. When indicating this element
23
+ # string in the non-HRI text section of a barcode label, the following data title SHOULD be used (see
24
+ # also section 3.2): BATCH/LOT
25
+ #
26
+ # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
27
+ #
28
+ class Batch < Record
29
+ AI = AI::BATCH_LOT
30
+
31
+ define :length, allowed: 1..20
32
+ end
33
+ end
@@ -0,0 +1,49 @@
1
+ module GS1
2
+ # GS1 check digit calculation
3
+ #
4
+ # Implementation of: http://www.gs1.org/how-calculate-check-digit-manually
5
+ # Notice! This class does not validate the format of the given sequence,
6
+ # only the length.
7
+ #
8
+ class CheckDigitCalculator
9
+ MULTIPLIER_ARRAY = [3, 1] * 9
10
+ VALID_LENGTHS = [7, 11, 12, 13, 17].freeze
11
+
12
+ def initialize(sequence)
13
+ @sequence = sequence
14
+ @reverse_sequence = sequence.chars.reverse
15
+
16
+ raise ArgumentError, 'Invalid length' unless VALID_LENGTHS.include?(sequence.size)
17
+ end
18
+
19
+ def self.from_sequence(sequence)
20
+ new(sequence).check_digit
21
+ end
22
+
23
+ def self.with_sequence(sequence)
24
+ new(sequence).calculate_sequence_with_digit
25
+ end
26
+
27
+ def check_digit
28
+ sub_from_nearest_higher_ten.to_s
29
+ end
30
+
31
+ def calculate_sequence_with_digit
32
+ sequence + check_digit
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :sequence, :reverse_sequence
38
+
39
+ def multiplied_sequence
40
+ @multiplied_sequence ||= reverse_sequence.each_with_index.map do |digit, idx|
41
+ digit.to_i * MULTIPLIER_ARRAY[idx]
42
+ end
43
+ end
44
+
45
+ def sub_from_nearest_higher_ten
46
+ (10 - (multiplied_sequence.inject(:+) % 10)) % 10
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,47 @@
1
+ module GS1
2
+ # Identification of trade items contained in a logistic unit: AI (02)
3
+ #
4
+ # The GS1 Application Identifier (02) indicates that the GS1 Application Identifier data field includes
5
+ # the GTIN of the contained trade items. The GTIN is used to identify trade items (see section 4).
6
+ #
7
+ # The GTIN for trade items may be a GTIN-8, GTIN-12, GTIN-13 or a GTIN-14. See section 2 for the
8
+ # rules for GTIN formats and mandatory or optional attributes in the various trade item applications.
9
+ #
10
+ # The GTIN of the trade items contained is the GTIN of the highest level of trade item contained in the
11
+ # logistic unit.
12
+ #
13
+ # Note: This element string SHALL be used only on a logistic unit if:
14
+ #
15
+ # - the logistic unit is not itself a trade item; and
16
+ # - all trade items that are contained at the highest level have the same GTIN
17
+ #
18
+ # The check digit is explained in section 7.9. Its verification, which must be carried out in the
19
+ # application software, ensures that the number is correctly composed.
20
+ #
21
+ # Figure 3.3.3-1. Format of the element string
22
+ # |----|-------------------------------------------------------------|
23
+ # | | Global Trade Item Number (GTIN) |
24
+ # | |-----------------------------------------------------|-------|
25
+ # | AI | GS1-8 Prefix or GS1 Company Prefix Item reference | Check |
26
+ # | | -----------------------------> <-----------------| digit |
27
+ # |----|-----------------------------------------------------|-------|
28
+ # GTIN-8 | 02 | 0 0 0 0 0 0 N1 N2 N3 N4 N5 N6 N7 | N8 |
29
+ # GTIN-12 | 02 | 0 0 N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 | N12 |
30
+ # GTIN-13 | 02 | 0 N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 | N13 |
31
+ # GTIN-14 | 02 | N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 N13 | N14 |
32
+ # |----|-----------------------------------------------------|-------|
33
+ #
34
+ # The data transmitted from the barcode reader means that the element string denoting the GTIN of
35
+ # trade items contained in a logistic unit has been captured. This element string must be processed
36
+ # together with the count of trade items, AI (37), which must appear on the same unit (see section
37
+ # 3.6.5). When indicating this element string in the non-HRI text section of a barcode label, the
38
+ # following data title SHOULD be used (see also section 3.2): CONTENT
39
+ #
40
+ # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
41
+ #
42
+ class Content < Record
43
+ include Extensions::GTIN
44
+
45
+ AI = AI::CONTENT
46
+ end
47
+ end
@@ -0,0 +1,79 @@
1
+ module GS1
2
+ # Module for handling definitions.
3
+ #
4
+ module Definitions
5
+ class UnknownDefinition < StandardError; end
6
+
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ # Adding defintion class methods.
12
+ #
13
+ module ClassMethods
14
+ attr_reader :definitions
15
+
16
+ DEFINITIONS = %i[check_digit date length].freeze
17
+
18
+ def define(key, options = {})
19
+ raise UnknownDefinition, "#{key} is not a valid definition" unless DEFINITIONS.include?(key)
20
+
21
+ @definitions ||= {}
22
+
23
+ definitions[key] = send("normalize_#{key}_options", options)
24
+ end
25
+
26
+ # Currently no support for options.
27
+ def normalize_check_digit_options(_options)
28
+ {}
29
+ end
30
+
31
+ # Currently no support for options.
32
+ def normalize_date_options(_options)
33
+ {}
34
+ end
35
+
36
+ # Defaults barcode length to allowed length if not explicitly defined, only
37
+ # if there is one significant allowed.
38
+ def normalize_length_options(options)
39
+ options[:allowed] = normalize_multiple_option(options[:allowed])
40
+ options[:barcode] = normalize_singlural_option(options[:barcode])
41
+ options[:max_barcode] = normalize_singlural_option(options[:barcode] || options[:allowed])
42
+
43
+ options
44
+ end
45
+
46
+ def normalize_multiple_option(option_value)
47
+ case option_value
48
+ when nil then nil
49
+ when Range then option_value.to_a
50
+ when Array then option_value
51
+ else [option_value]
52
+ end
53
+ end
54
+
55
+ def normalize_singlural_option(option_value)
56
+ case option_value
57
+ when Array then option_value.last
58
+ else option_value
59
+ end
60
+ end
61
+
62
+ def barcode_length
63
+ lengths[:barcode]
64
+ end
65
+
66
+ def barcode_max_length
67
+ lengths[:max_barcode]
68
+ end
69
+
70
+ def allowed_lengths
71
+ lengths[:allowed]
72
+ end
73
+
74
+ def lengths
75
+ definitions[:length]
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,55 @@
1
+ module GS1
2
+ # Expiration date: AI (17)
3
+ #
4
+ # The GS1 Application Identifier (17) indicates that the GS1 Application Identifier data fields contain
5
+ # an expiration date. The expiration date is the date that determines the limit of consumption or use
6
+ # of a product/coupon. Its meaning is determined based on the trade item context (e.g., for food, the
7
+ # date will indicate the possibility of a direct health risk resulting from use of the product after the
8
+ # date, for pharmaceutical products, it will indicate the possibility of an indirect health risk resulting
9
+ # from the ineffectiveness of the product after the date). It is often referred to as "use by date" or
10
+ # "maximum durability date."
11
+ #
12
+ # Note: A retailer may use this to determine a date that after which, they will no longer
13
+ # merchandise the product. Currently, there are implementations of best before date which are
14
+ # interpreted in their processes as date to Sell By.
15
+ #
16
+ # The structure is:
17
+ #
18
+ # - Year: the tens and units of the year (e.g., 2003 = 03), which is mandatory.
19
+ # - Month: the number of the month (e.g., January = 01), which is mandatory.
20
+ # - Day: the number of the day of the relevant month (e.g., second day = 02); if it is not necessary
21
+ # to specify the day, the field must be filled with two zeros.
22
+ #
23
+ # Note: When it is not necessary to specify the day (the Day field is filled with two zeros), the
24
+ # resultant data string SHALL be interpreted as the last day of the noted month including any
25
+ # adjustment for leap years (e.g., "130200" is "2013 February 28", "160200" is "2016 February
26
+ # 29", etc.).
27
+ #
28
+ # Note: This element string can only specify dates ranging from 49 years in the past to 50
29
+ # years in the future. Determination of the correct century is explained in section 7.12.
30
+ #
31
+ # Figure 3.4.5-1. Format of the element string
32
+ # |----|-----------------------------------|
33
+ # | | Best before date |
34
+ # | |-----------|-----------|-----------|
35
+ # | AI | Year | Month | Day |
36
+ # | | | | |
37
+ # |----|-----------|-----------|-----------|
38
+ # | 15 | N1 N2 | N3 N4 | N5 N6 |
39
+ # |----|-----------|-----------|-----------|
40
+ #
41
+ # The data transmitted from the barcode reader means that the element string denoting a best before
42
+ # date has been captured. As this element string is an attribute of a trade item, it must be processed
43
+ # together with the GTIN of the trade item to which it relates.
44
+ #
45
+ # When indicating this element string in the non-HRI text section of a barcode label, the following data
46
+ # title SHOULD be used (see also section 3.2): BEST BEFORE or BEST BY
47
+ #
48
+ # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
49
+ #
50
+ class ExpirationDate < Record
51
+ include Extensions::Date
52
+
53
+ AI = AI::USE_BY
54
+ end
55
+ end
@@ -0,0 +1,26 @@
1
+ require 'date'
2
+
3
+ module GS1
4
+ module Extensions
5
+ # Extension for a GS1 date. Ensures correct formating and validation.
6
+ #
7
+ module Date
8
+ def self.included(base)
9
+ base.define :date
10
+ base.define :length, barcode: 6
11
+ end
12
+
13
+ def to_s
14
+ return data.strftime('%y%m%d') if data.is_a?(::Date)
15
+
16
+ data
17
+ end
18
+
19
+ def to_date
20
+ return data if data.is_a?(::Date)
21
+
22
+ ::Date.parse(data)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module GS1
2
+ module Extensions
3
+ # Extension for a GS1 GTIN. Ensures correct formating and validation.
4
+ #
5
+ module GTIN
6
+ def self.included(base)
7
+ base.define :check_digit
8
+ base.define :length, allowed: [8, 12, 13, 14].freeze, barcode: 14
9
+
10
+ base.allowed_lengths.each do |length|
11
+ define_method "to_gtin_#{length}" do
12
+ data.to_s.rjust(length, '0')
13
+ end
14
+ end
15
+ end
16
+
17
+ # Default to GTIN-14 since it is the most common format.
18
+ def to_s
19
+ to_gtin_14
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,2 @@
1
+ require 'gs1/extensions/date'
2
+ require 'gs1/extensions/gtin'
data/lib/gs1/gtin.rb ADDED
@@ -0,0 +1,39 @@
1
+ module GS1
2
+ # Identification of a trade item (GTIN): AI (01)
3
+ #
4
+ # The GS1 Application Identifier (01) indicates that the GS1 Application Identifier data field contains a
5
+ # GTIN. The GTIN is used to identify trade items (see section 4).
6
+ #
7
+ # The GTIN for trade items may be a GTIN-8, GTIN-12, GTIN-13 or a GTIN-14. See section 2.1 for the
8
+ # rules for GTIN formats and mandatory or optional attributes in the various trade item applications.
9
+ #
10
+ # The check digit is explained in section 7.9. Its verification, which must be carried out in the
11
+ # application software, ensures that the number is correctly composed.
12
+ #
13
+ # Figure 3.3.2-1. Format of the element string
14
+ # |----|-------------------------------------------------------------|
15
+ # | | Global Trade Item Number (GTIN) |
16
+ # | |-----------------------------------------------------|-------|
17
+ # | AI | GS1-8 Prefix or GS1 Company Prefix Item reference | Check |
18
+ # | | -----------------------------> <-----------------| digit |
19
+ # |----|-----------------------------------------------------|-------|
20
+ # GTIN-8 | 02 | 0 0 0 0 0 0 N1 N2 N3 N4 N5 N6 N7 | N8 |
21
+ # GTIN-12 | 02 | 0 0 N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 | N12 |
22
+ # GTIN-13 | 02 | 0 N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 | N13 |
23
+ # GTIN-14 | 02 | N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 N13 | N14 |
24
+ # |----|-----------------------------------------------------|-------|
25
+ #
26
+ # The data transmitted from the barcode reader means that the element string denoting the GTIN of a
27
+ # fixed measure trade item has been captured.
28
+ #
29
+ # When indicating this element string in the non-HRI text section of a barcode label, the following data
30
+ # title SHOULD be used (see also section 3.2): GTIN
31
+ #
32
+ # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
33
+ #
34
+ class GTIN < Record
35
+ include Extensions::GTIN
36
+
37
+ AI = AI::GTIN
38
+ end
39
+ end
data/lib/gs1/record.rb ADDED
@@ -0,0 +1,55 @@
1
+ module GS1
2
+ # Base class for a GS1 record.
3
+ #
4
+ class Record
5
+ include Definitions
6
+ include Validations
7
+
8
+ attr_reader :data
9
+
10
+ def initialize(data)
11
+ super
12
+ @data = data
13
+ end
14
+
15
+ singleton_class.send(:attr_reader, :descendants)
16
+ @descendants = []
17
+
18
+ class << self
19
+ def inherited(subclass)
20
+ descendants << subclass
21
+ end
22
+
23
+ def ai
24
+ self::AI
25
+ end
26
+
27
+ def underscore_name
28
+ name.split('::')
29
+ .last
30
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
31
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
32
+ .tr('-', '_')
33
+ .downcase
34
+ .to_sym
35
+ end
36
+ end
37
+
38
+ def ai
39
+ self.class.ai
40
+ end
41
+
42
+ def to_s
43
+ data&.to_s
44
+ end
45
+
46
+ def to_ai
47
+ "#{ai}#{data}"
48
+ end
49
+
50
+ def ==(other)
51
+ self.class == other.class &&
52
+ to_s == other.to_s
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ module GS1
2
+ # Serial number: AI (21)
3
+ #
4
+ # The GS1 Application Identifier (21) indicates that the GS1 Application Identifier data field contains a
5
+ # serial number. A serial number is assigned to an entity for its lifetime. When combined with a GTIN,
6
+ # a serial number uniquely identifies an individual item. The serial number field is alphanumeric and
7
+ # may include all characters contained in figure 7.11-1. The manufacturer determines the serial
8
+ # number.
9
+ #
10
+ # Figure 3.5.2-1. Format of the element string
11
+ # |----|------------------------------------------------------|
12
+ # | AI | Serial number |
13
+ # |----|------------------------------------------------------|
14
+ # | 21 | X1 -------------> variable length -------------> X20 |
15
+ # |----|------------------------------------------------------|
16
+ #
17
+ # The data transmitted from the barcode reader means that the element string denoting a serial
18
+ # number has been captured. As this element string is an attribute of a trade item, it must be
19
+ # processed together with the GTIN of the trade item to which it relates.
20
+ #
21
+ # When indicating this element string in the non-HRI text section of a barcode label, the following data
22
+ # title SHOULD be used (see also section 3.2): SERIAL
23
+ #
24
+ # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
25
+ #
26
+ class SerialNumber < Record
27
+ AI = AI::SERIAL
28
+
29
+ define :length, allowed: 1..20
30
+ end
31
+ end
data/lib/gs1/sscc.rb ADDED
@@ -0,0 +1,43 @@
1
+ module GS1
2
+ #
3
+ # Identification of a logistic unit (SSCC): AI (00)
4
+ #
5
+ # The GS1 Application Identifier (00) indicates that the GS1 Application Identifier data field contains an
6
+ # SSCC (Serial Shipping Container Code). The SSCC is used to identify logistic units (see section 2.2).
7
+ #
8
+ # The extension digit is used to increase the capacity of the serial reference within the SSCC. It is
9
+ # assigned by the company that constructs the SSCC. The extension digit ranges from 0-9.
10
+ #
11
+ # The GS1 Company Prefix is allocated by GS1 Member Organisations to the company that allocates
12
+ # the SSCC - here the physical builder or the brand owner of the logistic unit (see section 1.4.4). It
13
+ # makes the SSCC unique worldwide but does not identify the origin of the unit.
14
+ #
15
+ # The structure and content of the serial reference is at the discretion of owner of the GS1 Company
16
+ # Prefix to uniquely identify each logistic unit.
17
+ #
18
+ # The check digit is explained in section 7.9. Its verification, which must be carried out in the
19
+ # application software, ensures that the number is correctly composed.
20
+ #
21
+ # Figure 3.3.1-1. Format of the element string
22
+ # |----|-----------------------------------------------------------------------------|
23
+ # | | SSCC (Serial Shipping Container Code) |
24
+ # | |-----------|---------------------------------------------------------|-------|
25
+ # | AI | Extension | GS1 Company Prefix Serial reference | Check |
26
+ # | | digit | --------------> <-----------------------| digit |
27
+ # |----|-----------|---------------------------------------------------------|-------|
28
+ # | 00 | N1 | N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 N13 N14 N15 N16 N17 | N18 |
29
+ # |----|-----------|---------------------------------------------------------|-------|
30
+ #
31
+ # The data transmitted from the barcode reader means that the element string denoting the SSCC of
32
+ # a logistic unit has been captured. When indicating this element string in the non-HRI text section of
33
+ # a barcode label, the following data title SHOULD be used (see also section 3.2): SSCC
34
+ #
35
+ # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
36
+ #
37
+ class SSCC < Record
38
+ AI = AI::SSCC
39
+
40
+ define :check_digit
41
+ define :length, allowed: 18
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ module GS1
2
+ module Validations
3
+ # Ensures correct check digit validation.
4
+ #
5
+ module CheckDigitValidation
6
+ def validate_check_digit
7
+ errors << 'Check digit mismatch' unless valid_check_digit?
8
+ end
9
+
10
+ def valid_check_digit?
11
+ GS1::CheckDigitCalculator.with_sequence(data[0..-2]) == data
12
+ rescue ArgumentError
13
+ false
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ require 'date'
2
+
3
+ module GS1
4
+ module Validations
5
+ # Ensures correct date validation.
6
+ #
7
+ module DateValidation
8
+ def validate_date(_options = {})
9
+ errors << 'Invalid date' unless valid_date?
10
+ end
11
+
12
+ def valid_date?
13
+ return true if data.is_a?(::Date)
14
+
15
+ ::Date.parse(data)
16
+
17
+ true
18
+ rescue TypeError, ArgumentError
19
+ false
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module GS1
2
+ module Validations
3
+ # Ensures correct length validation.
4
+ #
5
+ module LengthValidation
6
+ def validate_length
7
+ errors << 'Invalid length' unless valid_length?
8
+ end
9
+
10
+ def valid_length?
11
+ return false unless data
12
+
13
+ valid_barcode_length? || valid_allowed_length?
14
+ end
15
+
16
+ def valid_allowed_length?
17
+ self.class.allowed_lengths.include?(data.size)
18
+ end
19
+
20
+ def valid_barcode_length?
21
+ self.class.barcode_length == data.size if self.class.barcode_length
22
+ end
23
+ end
24
+ end
25
+ end