barkick 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +5 -0
- data/README.md +37 -14
- data/lib/barkick.rb +1 -1
- data/lib/barkick/gtin.rb +259 -0
- data/lib/barkick/version.rb +1 -1
- metadata +13 -21
- data/.gitignore +0 -17
- data/Gemfile +0 -4
- data/Rakefile +0 -8
- data/barkick.gemspec +0 -24
- data/lib/gtin.rb +0 -254
- data/test/gtin_test.rb +0 -49
- data/test/test_helper.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9b5dbcc3cbd3c1beefb0f273820de7c49cb53571c9835e04d2297d10f43f6c0d
|
4
|
+
data.tar.gz: aec8454c2c892ae270cd6dae72b7addcacf5350fe56a4e31591b6fb7c0aebaac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61276d24be0bec862262e3daabbf9fe4fb4b21715c57d83bfd6309315da5f226b6188783f6c97bc8a4f93bb17695a8fe930f324cad5d2ba7186148104f331087
|
7
|
+
data.tar.gz: ccdcc7ba14612a379ee382eadb09898ad8f6715cbb7cc01e2bed4c01c01181886aa43be165aa97f2d475ab80b175310f085b8e2048a67589bf289b537658c2f1
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -4,17 +4,17 @@ Barcodes made easy
|
|
4
4
|
|
5
5
|
Works with:
|
6
6
|
|
7
|
-
- [UPC](
|
8
|
-
- [EAN](
|
9
|
-
- [GTIN](
|
10
|
-
- [ISBN](
|
7
|
+
- [UPC](https://en.wikipedia.org/wiki/Universal_Product_Code) (UPC-A and UPC-E)
|
8
|
+
- [EAN](https://en.wikipedia.org/wiki/International_Article_Number_%28EAN%29) (EAN-13 and EAN-8)
|
9
|
+
- [GTIN](https://en.wikipedia.org/wiki/Global_Trade_Item_Number)
|
10
|
+
- [ISBN](https://en.wikipedia.org/wiki/International_Standard_Book_Number)
|
11
11
|
|
12
12
|
For PLU codes, check out the [plu gem](https://github.com/ankane/plu)
|
13
13
|
|
14
14
|
## How To Use
|
15
15
|
|
16
16
|
```ruby
|
17
|
-
gtin = GTIN.new("016000275263")
|
17
|
+
gtin = Barkick::GTIN.new("016000275263")
|
18
18
|
gtin.valid? # true
|
19
19
|
gtin.gtin14 # "00016000275263"
|
20
20
|
gtin.ean13 # "0016000275263"
|
@@ -27,7 +27,7 @@ gtin.country_code # "US"
|
|
27
27
|
Variable items
|
28
28
|
|
29
29
|
```ruby
|
30
|
-
gtin = GTIN.new("299265108631")
|
30
|
+
gtin = Barkick::GTIN.new("299265108631")
|
31
31
|
gtin.variable? # true
|
32
32
|
gtin.restricted? # true
|
33
33
|
gtin.price # 8.63
|
@@ -37,22 +37,31 @@ gtin.base_gtin14 # "00299265000003"
|
|
37
37
|
UPC-E
|
38
38
|
|
39
39
|
```ruby
|
40
|
-
gtin = GTIN.new("03744806")
|
40
|
+
gtin = Barkick::GTIN.new("03744806", type: :upc_e)
|
41
41
|
gtin.base_gtin14 # "00037000004486"
|
42
42
|
```
|
43
43
|
|
44
|
+
EAN-8
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
gtin = Barkick::GTIN.new("01234565", type: :ean8)
|
48
|
+
gtin.base_gtin14 # "00000001234565"
|
49
|
+
```
|
50
|
+
|
44
51
|
Calculate check digit
|
45
52
|
|
46
53
|
```ruby
|
47
|
-
GTIN.check_digit("01600027526") # "3"
|
54
|
+
Barkick::GTIN.check_digit("01600027526") # "3"
|
48
55
|
```
|
49
56
|
|
57
|
+
> For UPC-E, convert to UPC-A before passing to this method
|
58
|
+
|
50
59
|
## Installation
|
51
60
|
|
52
61
|
Add this line to your Gemfile:
|
53
62
|
|
54
63
|
```ruby
|
55
|
-
gem
|
64
|
+
gem 'barkick'
|
56
65
|
```
|
57
66
|
|
58
67
|
And run:
|
@@ -61,10 +70,24 @@ And run:
|
|
61
70
|
bundle
|
62
71
|
```
|
63
72
|
|
73
|
+
## Upgrading
|
74
|
+
|
75
|
+
### 0.1.0
|
76
|
+
|
77
|
+
There a few breaking changes to be aware of:
|
78
|
+
|
79
|
+
- `GTIN` is now `Barkick::GTIN`
|
80
|
+
- 8-digit codes now raise an `ArgumentError` if `type` is not specified
|
81
|
+
|
82
|
+
## History
|
83
|
+
|
84
|
+
View the [changelog](https://github.com/ankane/barkick/blob/master/CHANGELOG.md)
|
85
|
+
|
64
86
|
## Contributing
|
65
87
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
88
|
+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
89
|
+
|
90
|
+
- [Report bugs](https://github.com/ankane/barkick/issues)
|
91
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/barkick/pulls)
|
92
|
+
- Write, clarify, or fix documentation
|
93
|
+
- Suggest or add new features
|
data/lib/barkick.rb
CHANGED
data/lib/barkick/gtin.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
module Barkick
|
2
|
+
class GTIN
|
3
|
+
def initialize(number, type: nil)
|
4
|
+
@number = number.to_s
|
5
|
+
|
6
|
+
if @number.length == 8
|
7
|
+
raise ArgumentError, "Must specify type for 8-digit codes" unless type
|
8
|
+
|
9
|
+
if type == :upc_e
|
10
|
+
upc_a =
|
11
|
+
case @number[-2]
|
12
|
+
when "0"
|
13
|
+
"#{@number[1..2]}00000#{@number[3..5]}"
|
14
|
+
when "1", "2"
|
15
|
+
"#{@number[1..2]}#{@number[-2]}0000#{@number[3..5]}"
|
16
|
+
when "3"
|
17
|
+
"#{@number[1..3]}00000#{@number[4..5]}"
|
18
|
+
when "4"
|
19
|
+
"#{@number[1..4]}00000#{@number[5]}"
|
20
|
+
else
|
21
|
+
"#{@number[1..5]}0000#{@number[-2]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
upc_a = "0#{upc_a}#{@number[-1]}"
|
25
|
+
|
26
|
+
if self.class.check_digit(upc_a[0..-2]) == @number[-1]
|
27
|
+
@number = upc_a
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
@type = type
|
33
|
+
end
|
34
|
+
|
35
|
+
def gtin14
|
36
|
+
if valid?
|
37
|
+
@number.rjust(14, "0")
|
38
|
+
else
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def gtin13
|
44
|
+
gtin14[0] == "0" ? gtin14[1..-1] : nil
|
45
|
+
end
|
46
|
+
alias_method :ean13, :gtin13
|
47
|
+
|
48
|
+
def gtin12
|
49
|
+
gtin14[0..1] == "00" ? gtin14[2..-1] : nil
|
50
|
+
end
|
51
|
+
alias_method :upc, :gtin12
|
52
|
+
|
53
|
+
def check_digit
|
54
|
+
gtin14[-1]
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid?
|
58
|
+
@number =~ /\A\d{8}(\d{4,6})?\z/ && self.class.check_digit(@number.rjust(14, "0")[0..-2]) == @number[-1]
|
59
|
+
end
|
60
|
+
|
61
|
+
def base_gtin14
|
62
|
+
if variable?
|
63
|
+
base = gtin14[0..-7] + "00000"
|
64
|
+
base + self.class.check_digit(base)
|
65
|
+
else
|
66
|
+
gtin14
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# prefix
|
71
|
+
|
72
|
+
def prefix
|
73
|
+
gtin14[1..3]
|
74
|
+
end
|
75
|
+
|
76
|
+
# https://www.gs1.org/barcodes/support/prefix_list
|
77
|
+
def prefix_name
|
78
|
+
case prefix.to_i
|
79
|
+
when 0..19, 30..39, 60..139
|
80
|
+
if @type == :ean8
|
81
|
+
nil # GTIN-8
|
82
|
+
else
|
83
|
+
"GS1 US"
|
84
|
+
end
|
85
|
+
when 20..29, 40..49, 200..299 then "Restricted distribution"
|
86
|
+
when 50..59 then "Coupons"
|
87
|
+
when 300..379 then "GS1 France"
|
88
|
+
when 380 then "GS1 Bulgaria"
|
89
|
+
when 383 then "GS1 Slovenija"
|
90
|
+
when 385 then "GS1 Croatia"
|
91
|
+
when 387 then "GS1 BIH (Bosnia-Herzegovina)"
|
92
|
+
when 389 then "GS1 Montenegro"
|
93
|
+
when 400..440 then "GS1 Germany"
|
94
|
+
when 450..459, 490..499 then "GS1 Japan"
|
95
|
+
when 460..469 then "GS1 Russia"
|
96
|
+
when 470 then "GS1 Kyrgyzstan"
|
97
|
+
when 471 then "GS1 Taiwan"
|
98
|
+
when 474 then "GS1 Estonia"
|
99
|
+
when 475 then "GS1 Latvia"
|
100
|
+
when 476 then "GS1 Azerbaijan"
|
101
|
+
when 477 then "GS1 Lithuania"
|
102
|
+
when 478 then "GS1 Uzbekistan"
|
103
|
+
when 479 then "GS1 Sri Lanka"
|
104
|
+
when 480 then "GS1 Philippines"
|
105
|
+
when 481 then "GS1 Belarus"
|
106
|
+
when 482 then "GS1 Ukraine"
|
107
|
+
when 484 then "GS1 Moldova"
|
108
|
+
when 485 then "GS1 Armenia"
|
109
|
+
when 486 then "GS1 Georgia"
|
110
|
+
when 487 then "GS1 Kazakstan"
|
111
|
+
when 488 then "GS1 Tajikistan"
|
112
|
+
when 489 then "GS1 Hong Kong"
|
113
|
+
when 500..509 then "GS1 UK"
|
114
|
+
when 520..521 then "GS1 Association Greece"
|
115
|
+
when 528 then "GS1 Lebanon"
|
116
|
+
when 529 then "GS1 Cyprus"
|
117
|
+
when 530 then "GS1 Albania"
|
118
|
+
when 531 then "GS1 MAC (FYR Macedonia)"
|
119
|
+
when 535 then "GS1 Malta"
|
120
|
+
when 539 then "GS1 Ireland"
|
121
|
+
when 540..549 then "GS1 Belgium & Luxembourg"
|
122
|
+
when 560 then "GS1 Portugal"
|
123
|
+
when 569 then "GS1 Iceland"
|
124
|
+
when 570..579 then "GS1 Denmark"
|
125
|
+
when 590 then "GS1 Poland"
|
126
|
+
when 594 then "GS1 Romania"
|
127
|
+
when 599 then "GS1 Hungary"
|
128
|
+
when 600..601 then "GS1 South Africa"
|
129
|
+
when 603 then "GS1 Ghana"
|
130
|
+
when 604 then "GS1 Senegal"
|
131
|
+
when 608 then "GS1 Bahrain"
|
132
|
+
when 609 then "GS1 Mauritius"
|
133
|
+
when 611 then "GS1 Morocco"
|
134
|
+
when 613 then "GS1 Algeria"
|
135
|
+
when 615 then "GS1 Nigeria"
|
136
|
+
when 616 then "GS1 Kenya"
|
137
|
+
when 618 then "GS1 Ivory Coast"
|
138
|
+
when 619 then "GS1 Tunisia"
|
139
|
+
when 620 then "GS1 Tanzania"
|
140
|
+
when 621 then "GS1 Syria"
|
141
|
+
when 622 then "GS1 Egypt"
|
142
|
+
when 623 then "GS1 Brunei"
|
143
|
+
when 624 then "GS1 Libya"
|
144
|
+
when 625 then "GS1 Jordan"
|
145
|
+
when 626 then "GS1 Iran"
|
146
|
+
when 627 then "GS1 Kuwait"
|
147
|
+
when 628 then "GS1 Saudi Arabia"
|
148
|
+
when 629 then "GS1 Emirates"
|
149
|
+
when 640..649 then "GS1 Finland"
|
150
|
+
when 690..699 then "GS1 China"
|
151
|
+
when 700..709 then "GS1 Norway"
|
152
|
+
when 729 then "GS1 Israel"
|
153
|
+
when 730..739 then "GS1 Sweden"
|
154
|
+
when 740 then "GS1 Guatemala"
|
155
|
+
when 741 then "GS1 El Salvador"
|
156
|
+
when 742 then "GS1 Honduras"
|
157
|
+
when 743 then "GS1 Nicaragua"
|
158
|
+
when 744 then "GS1 Costa Rica"
|
159
|
+
when 745 then "GS1 Panama"
|
160
|
+
when 746 then "GS1 Republica Dominicana"
|
161
|
+
when 750 then "GS1 Mexico"
|
162
|
+
when 754..755 then "GS1 Canada"
|
163
|
+
when 759 then "GS1 Venezuela"
|
164
|
+
when 760..769 then "GS1 Schweiz, Suisse, Svizzera"
|
165
|
+
when 770..771 then "GS1 Colombia"
|
166
|
+
when 773 then "GS1 Uruguay"
|
167
|
+
when 775 then "GS1 Peru"
|
168
|
+
when 777 then "GS1 Bolivia"
|
169
|
+
when 778..779 then "GS1 Argentina"
|
170
|
+
when 780 then "GS1 Chile"
|
171
|
+
when 784 then "GS1 Paraguay"
|
172
|
+
when 786 then "GS1 Ecuador"
|
173
|
+
when 789..790 then "GS1 Brasil"
|
174
|
+
when 800..839 then "GS1 Italy"
|
175
|
+
when 840..849 then "GS1 Spain"
|
176
|
+
when 850 then "GS1 Cuba"
|
177
|
+
when 858 then "GS1 Slovakia"
|
178
|
+
when 859 then "GS1 Czech"
|
179
|
+
when 860 then "GS1 Serbia"
|
180
|
+
when 865 then "GS1 Mongolia"
|
181
|
+
when 867 then "GS1 North Korea"
|
182
|
+
when 868..869 then "GS1 Turkey"
|
183
|
+
when 870..879 then "GS1 Netherlands"
|
184
|
+
when 880 then "GS1 South Korea"
|
185
|
+
when 884 then "GS1 Cambodia"
|
186
|
+
when 885 then "GS1 Thailand"
|
187
|
+
when 888 then "GS1 Singapore"
|
188
|
+
when 890 then "GS1 India"
|
189
|
+
when 893 then "GS1 Vietnam"
|
190
|
+
when 896 then "GS1 Pakistan"
|
191
|
+
when 899 then "GS1 Indonesia"
|
192
|
+
when 900..919 then "GS1 Austria"
|
193
|
+
when 930..939 then "GS1 Australia"
|
194
|
+
when 940..949 then "GS1 New Zealand"
|
195
|
+
when 950 then "GS1 Global Office"
|
196
|
+
when 951 then "GS1 Global Office (EPCglobal)"
|
197
|
+
when 955 then "GS1 Malaysia"
|
198
|
+
when 958 then "GS1 Macau"
|
199
|
+
when 960..969 then "Global Office (GTIN-8s)"
|
200
|
+
when 977 then "Serial publications (ISSN)"
|
201
|
+
when 978..979 then "Bookland"
|
202
|
+
when 980 then "Refund receipts"
|
203
|
+
when 981..984 then "GS1 coupon identification for common currency areas"
|
204
|
+
when 990..999 then "GS1 coupon identification"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def country_code
|
209
|
+
case prefix_name
|
210
|
+
when "GS1 US" then "US"
|
211
|
+
when "GS1 UK" then "GB"
|
212
|
+
when "GS1 Germany" then "DE"
|
213
|
+
when "GS1 Netherlands" then "NL"
|
214
|
+
when "GS1 Schweiz, Suisse, Svizzera" then "CH"
|
215
|
+
when "GS1 Italy" then "IT"
|
216
|
+
when "GS1 France" then "FR"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def book?
|
221
|
+
prefix_name == "Bookland"
|
222
|
+
end
|
223
|
+
|
224
|
+
def restricted?
|
225
|
+
prefix_name == "Restricted distribution"
|
226
|
+
end
|
227
|
+
|
228
|
+
# variable weight
|
229
|
+
|
230
|
+
def variable?
|
231
|
+
(20..29).cover?(prefix.to_i)
|
232
|
+
end
|
233
|
+
|
234
|
+
def price
|
235
|
+
if variable?
|
236
|
+
gtin14[-5..-2].to_f / 100
|
237
|
+
else
|
238
|
+
nil
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def self.check_digit(number)
|
243
|
+
number = number.to_s
|
244
|
+
if [7, 11, 12, 13].include?(number.length)
|
245
|
+
# https://www.gs1.org/barcodes/support/check_digit_calculator#how
|
246
|
+
digits = number.rjust(13, "0").split("").map(&:to_i)
|
247
|
+
# digit at position 0 is odd (first digit) for the purpose of this calculation
|
248
|
+
odd_digits, even_digits = digits.partition.each_with_index { |_digit, i| i.even? }
|
249
|
+
((10 - (sum(odd_digits) * 3 + sum(even_digits)) % 10) % 10).to_s
|
250
|
+
else
|
251
|
+
nil
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def self.sum(arr)
|
256
|
+
arr.inject { |sum, x| sum + x }
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
data/lib/barkick/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: barkick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,24 +52,18 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
description:
|
56
|
-
email:
|
57
|
-
- andrew@chartkick.com
|
55
|
+
description:
|
56
|
+
email: andrew@chartkick.com
|
58
57
|
executables: []
|
59
58
|
extensions: []
|
60
59
|
extra_rdoc_files: []
|
61
60
|
files:
|
62
|
-
-
|
63
|
-
- Gemfile
|
61
|
+
- CHANGELOG.md
|
64
62
|
- LICENSE.txt
|
65
63
|
- README.md
|
66
|
-
- Rakefile
|
67
|
-
- barkick.gemspec
|
68
64
|
- lib/barkick.rb
|
65
|
+
- lib/barkick/gtin.rb
|
69
66
|
- lib/barkick/version.rb
|
70
|
-
- lib/gtin.rb
|
71
|
-
- test/gtin_test.rb
|
72
|
-
- test/test_helper.rb
|
73
67
|
homepage: https://github.com/ankane/barkick
|
74
68
|
licenses:
|
75
69
|
- MIT
|
@@ -82,7 +76,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
76
|
requirements:
|
83
77
|
- - ">="
|
84
78
|
- !ruby/object:Gem::Version
|
85
|
-
version: '
|
79
|
+
version: '2.2'
|
86
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
81
|
requirements:
|
88
82
|
- - ">="
|
@@ -90,10 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
84
|
version: '0'
|
91
85
|
requirements: []
|
92
86
|
rubyforge_project:
|
93
|
-
rubygems_version: 2.
|
87
|
+
rubygems_version: 2.7.7
|
94
88
|
signing_key:
|
95
89
|
specification_version: 4
|
96
90
|
summary: Barcodes made easy
|
97
|
-
test_files:
|
98
|
-
- test/gtin_test.rb
|
99
|
-
- test/test_helper.rb
|
91
|
+
test_files: []
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/barkick.gemspec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'barkick/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "barkick"
|
8
|
-
spec.version = Barkick::VERSION
|
9
|
-
spec.authors = ["Andrew Kane"]
|
10
|
-
spec.email = ["andrew@chartkick.com"]
|
11
|
-
spec.description = %q{Barcodes made easy}
|
12
|
-
spec.summary = %q{Barcodes made easy}
|
13
|
-
spec.homepage = "https://github.com/ankane/barkick"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "minitest"
|
24
|
-
end
|
data/lib/gtin.rb
DELETED
@@ -1,254 +0,0 @@
|
|
1
|
-
class GTIN
|
2
|
-
|
3
|
-
def initialize(number)
|
4
|
-
@number = number.to_s
|
5
|
-
|
6
|
-
# could be upc-e
|
7
|
-
if @number.length == 8 and @number[0] == "0" and @number[1] != "0"
|
8
|
-
upc_a =
|
9
|
-
case @number[-2]
|
10
|
-
when "0"
|
11
|
-
"#{@number[1..2]}00000#{@number[3..5]}"
|
12
|
-
when "1", "2"
|
13
|
-
"#{@number[1..2]}#{@number[-2]}0000#{@number[3..5]}"
|
14
|
-
when "3"
|
15
|
-
"#{@number[1..3]}00000#{@number[4..5]}"
|
16
|
-
when "4"
|
17
|
-
"#{@number[1..4]}00000#{@number[5]}"
|
18
|
-
else
|
19
|
-
"#{@number[1..5]}0000#{@number[-2]}"
|
20
|
-
end
|
21
|
-
|
22
|
-
upc_a = "0#{upc_a}#{@number[-1]}"
|
23
|
-
|
24
|
-
if self.class.check_digit(upc_a[0..-2]) == @number[-1]
|
25
|
-
@number = upc_a
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def gtin14
|
31
|
-
if valid?
|
32
|
-
@number.rjust(14, "0")
|
33
|
-
else
|
34
|
-
nil
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def gtin13
|
39
|
-
gtin14[0] == "0" ? gtin14[1..-1] : nil
|
40
|
-
end
|
41
|
-
alias_method :ean13, :gtin13
|
42
|
-
|
43
|
-
def gtin12
|
44
|
-
gtin14[0..1] == "00" ? gtin14[2..-1] : nil
|
45
|
-
end
|
46
|
-
alias_method :upc, :gtin12
|
47
|
-
|
48
|
-
def check_digit
|
49
|
-
gtin14[-1]
|
50
|
-
end
|
51
|
-
|
52
|
-
def valid?
|
53
|
-
@number =~ /\A\d{8}(\d{4,6})?\z/ && self.class.check_digit(@number.rjust(14, "0")[0..-2]) == @number[-1]
|
54
|
-
end
|
55
|
-
|
56
|
-
def base_gtin14
|
57
|
-
if variable?
|
58
|
-
base = gtin14[0..-7] + "00000"
|
59
|
-
base + self.class.check_digit(base)
|
60
|
-
else
|
61
|
-
gtin14
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# prefix
|
66
|
-
|
67
|
-
def prefix
|
68
|
-
gtin14[1..3]
|
69
|
-
end
|
70
|
-
|
71
|
-
# http://www.gs1.org/barcodes/support/prefix_list
|
72
|
-
def prefix_name
|
73
|
-
case prefix.to_i
|
74
|
-
when 0..19, 30..39, 60..139
|
75
|
-
if @number.length == 8
|
76
|
-
nil # GTIN-8
|
77
|
-
else
|
78
|
-
"GS1 US"
|
79
|
-
end
|
80
|
-
when 20..29, 40..49, 200..299 then "Restricted distribution"
|
81
|
-
when 50..59 then "Coupons"
|
82
|
-
when 300..379 then "GS1 France"
|
83
|
-
when 380 then "GS1 Bulgaria"
|
84
|
-
when 383 then "GS1 Slovenija"
|
85
|
-
when 385 then "GS1 Croatia"
|
86
|
-
when 387 then "GS1 BIH (Bosnia-Herzegovina)"
|
87
|
-
when 389 then "GS1 Montenegro"
|
88
|
-
when 400..440 then "GS1 Germany"
|
89
|
-
when 450..459, 490..499 then "GS1 Japan"
|
90
|
-
when 460..469 then "GS1 Russia"
|
91
|
-
when 470 then "GS1 Kyrgyzstan"
|
92
|
-
when 471 then "GS1 Taiwan"
|
93
|
-
when 474 then "GS1 Estonia"
|
94
|
-
when 475 then "GS1 Latvia"
|
95
|
-
when 476 then "GS1 Azerbaijan"
|
96
|
-
when 477 then "GS1 Lithuania"
|
97
|
-
when 478 then "GS1 Uzbekistan"
|
98
|
-
when 479 then "GS1 Sri Lanka"
|
99
|
-
when 480 then "GS1 Philippines"
|
100
|
-
when 481 then "GS1 Belarus"
|
101
|
-
when 482 then "GS1 Ukraine"
|
102
|
-
when 484 then "GS1 Moldova"
|
103
|
-
when 485 then "GS1 Armenia"
|
104
|
-
when 486 then "GS1 Georgia"
|
105
|
-
when 487 then "GS1 Kazakstan"
|
106
|
-
when 488 then "GS1 Tajikistan"
|
107
|
-
when 489 then "GS1 Hong Kong"
|
108
|
-
when 500..509 then "GS1 UK"
|
109
|
-
when 520..521 then "GS1 Association Greece"
|
110
|
-
when 528 then "GS1 Lebanon"
|
111
|
-
when 529 then "GS1 Cyprus"
|
112
|
-
when 530 then "GS1 Albania"
|
113
|
-
when 531 then "GS1 MAC (FYR Macedonia)"
|
114
|
-
when 535 then "GS1 Malta"
|
115
|
-
when 539 then "GS1 Ireland"
|
116
|
-
when 540..549 then "GS1 Belgium & Luxembourg"
|
117
|
-
when 560 then "GS1 Portugal"
|
118
|
-
when 569 then "GS1 Iceland"
|
119
|
-
when 570..579 then "GS1 Denmark"
|
120
|
-
when 590 then "GS1 Poland"
|
121
|
-
when 594 then "GS1 Romania"
|
122
|
-
when 599 then "GS1 Hungary"
|
123
|
-
when 600..601 then "GS1 South Africa"
|
124
|
-
when 603 then "GS1 Ghana"
|
125
|
-
when 604 then "GS1 Senegal"
|
126
|
-
when 608 then "GS1 Bahrain"
|
127
|
-
when 609 then "GS1 Mauritius"
|
128
|
-
when 611 then "GS1 Morocco"
|
129
|
-
when 613 then "GS1 Algeria"
|
130
|
-
when 615 then "GS1 Nigeria"
|
131
|
-
when 616 then "GS1 Kenya"
|
132
|
-
when 618 then "GS1 Ivory Coast"
|
133
|
-
when 619 then "GS1 Tunisia"
|
134
|
-
when 620 then "GS1 Tanzania"
|
135
|
-
when 621 then "GS1 Syria"
|
136
|
-
when 622 then "GS1 Egypt"
|
137
|
-
when 623 then "GS1 Brunei"
|
138
|
-
when 624 then "GS1 Libya"
|
139
|
-
when 625 then "GS1 Jordan"
|
140
|
-
when 626 then "GS1 Iran"
|
141
|
-
when 627 then "GS1 Kuwait"
|
142
|
-
when 628 then "GS1 Saudi Arabia"
|
143
|
-
when 629 then "GS1 Emirates"
|
144
|
-
when 640..649 then "GS1 Finland"
|
145
|
-
when 690..699 then "GS1 China"
|
146
|
-
when 700..709 then "GS1 Norway"
|
147
|
-
when 729 then "GS1 Israel"
|
148
|
-
when 730..739 then "GS1 Sweden"
|
149
|
-
when 740 then "GS1 Guatemala"
|
150
|
-
when 741 then "GS1 El Salvador"
|
151
|
-
when 742 then "GS1 Honduras"
|
152
|
-
when 743 then "GS1 Nicaragua"
|
153
|
-
when 744 then "GS1 Costa Rica"
|
154
|
-
when 745 then "GS1 Panama"
|
155
|
-
when 746 then "GS1 Republica Dominicana"
|
156
|
-
when 750 then "GS1 Mexico"
|
157
|
-
when 754..755 then "GS1 Canada"
|
158
|
-
when 759 then "GS1 Venezuela"
|
159
|
-
when 760..769 then "GS1 Schweiz, Suisse, Svizzera"
|
160
|
-
when 770..771 then "GS1 Colombia"
|
161
|
-
when 773 then "GS1 Uruguay"
|
162
|
-
when 775 then "GS1 Peru"
|
163
|
-
when 777 then "GS1 Bolivia"
|
164
|
-
when 778..779 then "GS1 Argentina"
|
165
|
-
when 780 then "GS1 Chile"
|
166
|
-
when 784 then "GS1 Paraguay"
|
167
|
-
when 786 then "GS1 Ecuador"
|
168
|
-
when 789..790 then "GS1 Brasil"
|
169
|
-
when 800..839 then "GS1 Italy"
|
170
|
-
when 840..849 then "GS1 Spain"
|
171
|
-
when 850 then "GS1 Cuba"
|
172
|
-
when 858 then "GS1 Slovakia"
|
173
|
-
when 859 then "GS1 Czech"
|
174
|
-
when 860 then "GS1 Serbia"
|
175
|
-
when 865 then "GS1 Mongolia"
|
176
|
-
when 867 then "GS1 North Korea"
|
177
|
-
when 868..869 then "GS1 Turkey"
|
178
|
-
when 870..879 then "GS1 Netherlands"
|
179
|
-
when 880 then "GS1 South Korea"
|
180
|
-
when 884 then "GS1 Cambodia"
|
181
|
-
when 885 then "GS1 Thailand"
|
182
|
-
when 888 then "GS1 Singapore"
|
183
|
-
when 890 then "GS1 India"
|
184
|
-
when 893 then "GS1 Vietnam"
|
185
|
-
when 896 then "GS1 Pakistan"
|
186
|
-
when 899 then "GS1 Indonesia"
|
187
|
-
when 900..919 then "GS1 Austria"
|
188
|
-
when 930..939 then "GS1 Australia"
|
189
|
-
when 940..949 then "GS1 New Zealand"
|
190
|
-
when 950 then "GS1 Global Office"
|
191
|
-
when 951 then "GS1 Global Office (EPCglobal)"
|
192
|
-
when 955 then "GS1 Malaysia"
|
193
|
-
when 958 then "GS1 Macau"
|
194
|
-
when 960..969 then "Global Office (GTIN-8s)"
|
195
|
-
when 977 then "Serial publications (ISSN)"
|
196
|
-
when 978..979 then "Bookland"
|
197
|
-
when 980 then "Refund receipts"
|
198
|
-
when 981..984 then "GS1 coupon identification for common currency areas"
|
199
|
-
when 990..999 then "GS1 coupon identification"
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def country_code
|
204
|
-
case prefix_name
|
205
|
-
when "GS1 US" then "US"
|
206
|
-
when "GS1 UK" then "GB"
|
207
|
-
when "GS1 Germany" then "DE"
|
208
|
-
when "GS1 Netherlands" then "NL"
|
209
|
-
when "GS1 Schweiz, Suisse, Svizzera" then "CH"
|
210
|
-
when "GS1 Italy" then "IT"
|
211
|
-
when "GS1 France" then "FR"
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def book?
|
216
|
-
prefix_name == "Bookland"
|
217
|
-
end
|
218
|
-
|
219
|
-
def restricted?
|
220
|
-
prefix_name == "Restricted distribution"
|
221
|
-
end
|
222
|
-
|
223
|
-
# variable weight
|
224
|
-
|
225
|
-
def variable?
|
226
|
-
(20..29).cover?(prefix.to_i)
|
227
|
-
end
|
228
|
-
|
229
|
-
def price
|
230
|
-
if variable?
|
231
|
-
gtin14[-5..-2].to_f / 100
|
232
|
-
else
|
233
|
-
nil
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
def self.check_digit(number)
|
238
|
-
number = number.to_s
|
239
|
-
if [7, 11, 12, 13].include?(number.length)
|
240
|
-
# http://www.gs1.org/barcodes/support/check_digit_calculator#how
|
241
|
-
digits = number.rjust(13, "0").split("").map(&:to_i)
|
242
|
-
# digit at position 0 is odd (first digit) for the purpose of this calculation
|
243
|
-
odd_digits, even_digits = digits.partition.each_with_index{|digit, i| i.even? }
|
244
|
-
((10 - (sum(odd_digits) * 3 + sum(even_digits)) % 10) % 10).to_s
|
245
|
-
else
|
246
|
-
nil
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
def self.sum(arr)
|
251
|
-
arr.inject{|sum,x| sum + x }
|
252
|
-
end
|
253
|
-
|
254
|
-
end
|
data/test/gtin_test.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class TestGTIN < Minitest::Test
|
4
|
-
|
5
|
-
def test_gtin
|
6
|
-
gtin = GTIN.new("016000275263")
|
7
|
-
assert gtin.valid?
|
8
|
-
assert_equal "00016000275263", gtin.gtin14
|
9
|
-
assert_equal "0016000275263", gtin.gtin13
|
10
|
-
assert_equal "016000275263", gtin.gtin12
|
11
|
-
assert_equal "0016000275263", gtin.ean13
|
12
|
-
assert_equal "016000275263", gtin.upc
|
13
|
-
assert_equal "001", gtin.prefix
|
14
|
-
assert_equal "GS1 US", gtin.prefix_name
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_invalid
|
18
|
-
assert !GTIN.new("1").valid?
|
19
|
-
assert !GTIN.new(" 016000275263").valid?
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_variable
|
23
|
-
gtin = GTIN.new("299265108631")
|
24
|
-
assert gtin.valid?
|
25
|
-
assert gtin.variable?
|
26
|
-
assert gtin.restricted?
|
27
|
-
assert_equal 8.63, gtin.price
|
28
|
-
assert_equal "00299265000003", gtin.base_gtin14
|
29
|
-
assert GTIN.new(gtin.base_gtin14).valid?
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_upc_e
|
33
|
-
gtin = GTIN.new("03744806")
|
34
|
-
assert gtin.valid?
|
35
|
-
assert_equal "00037000004486", gtin.base_gtin14
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_coke_upc_e
|
39
|
-
gtin = GTIN.new("04963406")
|
40
|
-
assert gtin.valid?
|
41
|
-
assert_equal "00049000006346", gtin.base_gtin14
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_trader_joes
|
45
|
-
gtin = GTIN.new("00511292")
|
46
|
-
assert_equal "00000000511292", gtin.gtin14
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
data/test/test_helper.rb
DELETED