gs1 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e9fad86db4d7ac36e936b37b63976378628f9b8d
4
- data.tar.gz: 1eeca0b54c00df6f1ff54108ad5aa799477c1df5
3
+ metadata.gz: 2f15d386486f27cc92e1ba01d9c3d03f0633c7ac
4
+ data.tar.gz: e4f0b5717132652127aafeeccdda4253d68a8201
5
5
  SHA512:
6
- metadata.gz: 6b2a4ec9172a6c31a435c8feb3a2e73a03e134269d1bf9f8fc2227a2074a404b06893e47f1053f91c17f497f4ed145385007b825c2b8f5e314a8f129a40dae5f
7
- data.tar.gz: 84e62c678aa22a165c63ccbb31ac89a69ce507ad49193127cd035f42482c86398fc5e14dc35b2d6518820750e97e9804a3e0227add72354d2bab4841780eef43
6
+ metadata.gz: 3d3f0d9472329eafe49f3bdbf6326672c442d74b8132f07d3a21d0083d7d617fd1309af82d24ba78bd3585d61b7f6daf5ecec8fcad5f72595a29d2024afdea16
7
+ data.tar.gz: 03d8e6d2faf2249b3077c38d67d90535f6a82d6d2fb1aec42c71e90cf9054497ab122a89014478840420c23f0c969ea1fa2c9316ebd933e623c5d395c5521c64
data/README.md CHANGED
@@ -22,6 +22,17 @@ Or install it yourself as:
22
22
 
23
23
  Follow the examples below to start using the gem.
24
24
 
25
+ ### Configuration
26
+
27
+ There are some configuration you can do before start using this lib.
28
+
29
+ ```ruby
30
+ GS1.configure do |config|
31
+ config.company_prefix = '123456789'
32
+ config.barcode_separator = '~' # Default is "\u001E"
33
+ end
34
+ ```
35
+
25
36
  ### Application identifiers
26
37
 
27
38
  To access the defined application identifier:
@@ -18,19 +18,19 @@ module GS1
18
18
  end
19
19
 
20
20
  class << self
21
- def from_scan!(barcode, separator: DEFAULT_SEPARATOR)
21
+ def from_scan!(barcode, separator: GS1.configuration.barcode_separator)
22
22
  new(scan_to_params!(barcode, separator: separator))
23
23
  end
24
24
 
25
- def from_scan(barcode, separator: DEFAULT_SEPARATOR)
25
+ def from_scan(barcode, separator: GS1.configuration.barcode_separator)
26
26
  new(scan_to_params(barcode, separator: separator))
27
27
  end
28
28
 
29
- def scan_to_params!(barcode, separator: DEFAULT_SEPARATOR)
29
+ def scan_to_params!(barcode, separator: GS1.configuration.barcode_separator)
30
30
  Tokenizer.new(barcode, separator: separator).to_params!
31
31
  end
32
32
 
33
- def scan_to_params(barcode, separator: DEFAULT_SEPARATOR)
33
+ def scan_to_params(barcode, separator: GS1.configuration.barcode_separator)
34
34
  Tokenizer.new(barcode, separator: separator).to_params
35
35
  end
36
36
  end
@@ -5,7 +5,7 @@ module GS1
5
5
  class Healthcare < Base
6
6
  define_records GTIN, ExpirationDate, Batch, SerialNumber
7
7
 
8
- def to_s(level: AIDCMarketingLevels::ENHANCED, separator: DEFAULT_SEPARATOR)
8
+ def to_s(level: AIDCMarketingLevels::ENHANCED, separator: GS1.configuration.barcode_separator)
9
9
  return unless valid?(level: level)
10
10
 
11
11
  [
@@ -5,7 +5,7 @@ module GS1
5
5
  class Segment
6
6
  attr_reader :data, :separator
7
7
 
8
- def initialize(data, separator: DEFAULT_SEPARATOR)
8
+ def initialize(data, separator: GS1.configuration.barcode_separator)
9
9
  @data = data.chars
10
10
  @separator = separator
11
11
  end
@@ -6,7 +6,7 @@ module GS1
6
6
  class Tokenizer
7
7
  attr_reader :data, :separator, :params
8
8
 
9
- def initialize(data, separator: DEFAULT_SEPARATOR)
9
+ def initialize(data, separator: GS1.configuration.barcode_separator)
10
10
  @data = data
11
11
  @separator = separator
12
12
  @params = {}
@@ -15,7 +15,7 @@ module GS1
15
15
  module ClassMethods
16
16
  attr_reader :definitions
17
17
 
18
- DEFINITIONS = %i[check_digit date length].freeze
18
+ DEFINITIONS = %i[check_digit date date_month_based length].freeze
19
19
 
20
20
  def define(key, options = {})
21
21
  raise UnknownDefinition, "#{key} is not a valid definition" unless DEFINITIONS.include?(key)
@@ -35,6 +35,11 @@ module GS1
35
35
  {}
36
36
  end
37
37
 
38
+ # Currently no support for options.
39
+ def normalize_date_month_based_options(_options)
40
+ {}
41
+ end
42
+
38
43
  # Defaults barcode length to allowed length if not explicitly defined, only
39
44
  # if there is one significant allowed.
40
45
  def normalize_length_options(options)
@@ -48,7 +48,7 @@ module GS1
48
48
  # Source: https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf
49
49
  #
50
50
  class ExpirationDate < Record
51
- include Extensions::Date
51
+ include Extensions::DateMonthBased
52
52
 
53
53
  AI = AI::USE_BY
54
54
  end
@@ -0,0 +1,60 @@
1
+ require 'date'
2
+
3
+ module GS1
4
+ module Extensions
5
+ # Extension for a GS1 date. Ensures correct formating and validation.
6
+ #
7
+ # OBS! Month-based expiry
8
+ #
9
+ # Expiry dates for a batch of medicinal product are generally set by month, rather than day. If a batch
10
+ # expires in March 2021, for example, it expires at the very end of the month. From the 1st April 2021, the EMVS
11
+ # will report that the pack identifier has expired if it has not already been decommissioned for some other reason.
12
+ #
13
+ # Manufacturers represent expiry by month in one of two ways. They either set the expiry date to be the last day of
14
+ # the month or they set the day component of the date (DD) to '00'. Examples are shown below:
15
+ #
16
+ # Format A: 210331
17
+ # Format B: 210300
18
+ #
19
+ # These two formats effectively indicate the same expiry date. The first specifies a specific day (the last day of
20
+ # the month). The second specifies only the month of expiry.
21
+ #
22
+ # The format used in the barcodes must be exactly the same as the format used within the EMVS. If the manufacturer
23
+ # uploads batch data to the European Hub using one format, but prints the barcodes using the other, the dates will
24
+ # not match and the national system will raise 'potential falsified medicine' alerts. In this case, the packs
25
+ # cannot be supplied until the manufacturer corrects the data within the EMVS.
26
+ #
27
+ module DateMonthBased
28
+ def self.included(base)
29
+ base.define :date_month_based
30
+ base.define :length, barcode: 6
31
+ end
32
+
33
+ def initialize(date)
34
+ if date.respond_to?(:strftime)
35
+ super(date.strftime('%y%m%d'))
36
+ else
37
+ super(date)
38
+ end
39
+ end
40
+
41
+ def to_date
42
+ to_date_format_a || to_date_format_b
43
+ end
44
+
45
+ private
46
+
47
+ def to_date_format_a
48
+ ::Date.strptime(data, '%y%m%d')
49
+ rescue TypeError, ArgumentError
50
+ nil
51
+ end
52
+
53
+ def to_date_format_b
54
+ ::Date.strptime(data, '%y%m00').next_month.prev_day
55
+ rescue TypeError, ArgumentError
56
+ nil
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,2 +1,3 @@
1
1
  require 'gs1/extensions/date'
2
+ require 'gs1/extensions/date_month_based'
2
3
  require 'gs1/extensions/gtin'
@@ -9,6 +9,10 @@ module GS1
9
9
  errors << 'Invalid date' unless valid_date?
10
10
  end
11
11
 
12
+ def validate_date_month_based(_options = {})
13
+ errors << 'Invalid date' unless valid_month_based_date?
14
+ end
15
+
12
16
  def valid_date?
13
17
  return true if data.is_a?(::Date)
14
18
 
@@ -18,6 +22,31 @@ module GS1
18
22
  rescue TypeError, ArgumentError
19
23
  false
20
24
  end
25
+
26
+ def valid_month_based_date?
27
+ return true if data.is_a?(::Date)
28
+
29
+ valid_format_a?(data) || valid_format_b?(data)
30
+ end
31
+
32
+ def valid_format_a?(data)
33
+ valid_date_format?(data, '%y%m%d')
34
+ end
35
+
36
+ # Read more about this date format in the GS1::Extensions::MonthBasedDate class.
37
+ def valid_format_b?(data)
38
+ valid_date_format?(data, '%y%m00')
39
+ end
40
+
41
+ private
42
+
43
+ def valid_date_format?(data, pattern)
44
+ ::Date.strptime(data, pattern)
45
+
46
+ true
47
+ rescue TypeError, ArgumentError
48
+ false
49
+ end
21
50
  end
22
51
  end
23
52
  end
data/lib/gs1/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module GS1
2
- VERSION = '0.1.5'.freeze
2
+ VERSION = '0.1.6'.freeze
3
3
  end
data/lib/gs1.rb CHANGED
@@ -20,19 +20,28 @@ require 'gs1/barcode'
20
20
  #
21
21
  module GS1
22
22
  class << self
23
- def configure
23
+ def configuration
24
24
  @configuration ||= Configuration.new
25
-
26
- yield @configuration
27
25
  end
28
26
 
29
- attr_reader :configuration
27
+ def configure
28
+ if block_given?
29
+ yield configuration
30
+ else
31
+ configuration
32
+ end
33
+ end
30
34
  end
31
35
 
32
36
  # Configuration holds custom configuration parameters.
33
37
  #
34
38
  class Configuration
35
39
  attr_accessor :company_prefix
40
+ attr_writer :barcode_separator
41
+
42
+ def barcode_separator
43
+ @barcode_separator || GS1::Barcode::DEFAULT_SEPARATOR
44
+ end
36
45
  end
37
46
 
38
47
  AI_CLASSES = GS1::Record.descendants.each_with_object({}) do |klass, hash|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gs1
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Åhman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-16 00:00:00.000000000 Z
11
+ date: 2018-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -143,6 +143,7 @@ files:
143
143
  - lib/gs1/expiration_date.rb
144
144
  - lib/gs1/extensions.rb
145
145
  - lib/gs1/extensions/date.rb
146
+ - lib/gs1/extensions/date_month_based.rb
146
147
  - lib/gs1/extensions/gtin.rb
147
148
  - lib/gs1/gtin.rb
148
149
  - lib/gs1/record.rb