elia_ruby 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,126 @@
1
+ # ISO 18245 MCC Ranges
2
+ # Defines the standard industry classification ranges for Merchant Category Codes
3
+ # Source: ISO 18245 Standard
4
+ ---
5
+ - start: "0000"
6
+ end: "0699"
7
+ name: "Reserved"
8
+ description: "Reserved for ISO use"
9
+ reserved: true
10
+
11
+ - start: "0700"
12
+ end: "0999"
13
+ name: "Agricultural Services"
14
+ description: "Agricultural services including veterinary and horticultural services"
15
+ reserved: false
16
+
17
+ - start: "1000"
18
+ end: "1499"
19
+ name: "Reserved"
20
+ description: "Reserved for future use"
21
+ reserved: true
22
+
23
+ - start: "1500"
24
+ end: "2999"
25
+ name: "Contracted Services"
26
+ description: "Contracted services including general and specialty construction contractors"
27
+ reserved: false
28
+
29
+ - start: "3000"
30
+ end: "3350"
31
+ name: "Airlines"
32
+ description: "Specific airline codes for major carriers"
33
+ reserved: false
34
+ private_use: true
35
+
36
+ - start: "3351"
37
+ end: "3500"
38
+ name: "Car Rentals"
39
+ description: "Specific car rental company codes"
40
+ reserved: false
41
+ private_use: true
42
+
43
+ - start: "3501"
44
+ end: "3999"
45
+ name: "Lodging"
46
+ description: "Specific hotel and lodging establishment codes"
47
+ reserved: false
48
+ private_use: true
49
+
50
+ - start: "4000"
51
+ end: "4799"
52
+ name: "Transportation"
53
+ description: "Transportation services including railroads, airlines, buses, and freight"
54
+ reserved: false
55
+
56
+ - start: "4800"
57
+ end: "4999"
58
+ name: "Utilities"
59
+ description: "Utility services including telecommunications, electricity, gas, and water"
60
+ reserved: false
61
+
62
+ - start: "5000"
63
+ end: "5599"
64
+ name: "Retail Outlets"
65
+ description: "Retail outlets including wholesale, department stores, and specialty retail"
66
+ reserved: false
67
+
68
+ - start: "5600"
69
+ end: "5699"
70
+ name: "Clothing Outlets"
71
+ description: "Clothing and apparel stores"
72
+ reserved: false
73
+
74
+ - start: "5700"
75
+ end: "5999"
76
+ name: "Miscellaneous Retail"
77
+ description: "Miscellaneous retail stores including food service, pharmacies, and specialty shops"
78
+ reserved: false
79
+
80
+ - start: "6000"
81
+ end: "7299"
82
+ name: "Service Providers"
83
+ description: "Service provider businesses including financial services, lodging, and personal services"
84
+ reserved: false
85
+
86
+ - start: "7300"
87
+ end: "7529"
88
+ name: "Business Services"
89
+ description: "Business services including advertising, consulting, and equipment rental"
90
+ reserved: false
91
+
92
+ - start: "7530"
93
+ end: "7799"
94
+ name: "Repair Services"
95
+ description: "Repair and automotive services"
96
+ reserved: false
97
+
98
+ - start: "7800"
99
+ end: "7999"
100
+ name: "Entertainment"
101
+ description: "Amusement and entertainment including gambling, recreation, and sports"
102
+ reserved: false
103
+
104
+ - start: "8000"
105
+ end: "8999"
106
+ name: "Professional Services"
107
+ description: "Professional services and membership organizations including healthcare, legal, and education"
108
+ reserved: false
109
+
110
+ - start: "9000"
111
+ end: "9199"
112
+ name: "Reserved for ISO"
113
+ description: "Reserved for ISO use"
114
+ reserved: true
115
+
116
+ - start: "9200"
117
+ end: "9402"
118
+ name: "Government Services"
119
+ description: "Government services including courts, fines, taxes, and postal services"
120
+ reserved: false
121
+
122
+ - start: "9403"
123
+ end: "9999"
124
+ name: "Other"
125
+ description: "Other services and intra-company purchases"
126
+ reserved: false
@@ -0,0 +1,293 @@
1
+ # Risk-Based MCC Categories for Payment Control
2
+ # These categories are commonly used for merchant restrictions, spend controls,
3
+ # and risk management in payment systems.
4
+ ---
5
+ airlines:
6
+ name: "Airlines"
7
+ description: "Airlines and air carriers only"
8
+ codes:
9
+ - "3000-3350" # Specific airline codes (United, Delta, American, etc.)
10
+ - "4415" # Air Courier Services
11
+ - "4511" # Airlines, Air Carriers
12
+
13
+ gambling:
14
+ name: "Gambling"
15
+ description: "Casinos, betting, lottery, and gaming"
16
+ codes:
17
+ - "7800" # Government Owned Lotteries (US only)
18
+ - "7801" # Government Licensed Casinos (Online Gambling)
19
+ - "7802" # Government Licensed Horse/Dog Racing
20
+ - "7995" # Betting/Casino Gambling
21
+ - "9406" # Government-owned Lottery (non-US)
22
+
23
+ adult:
24
+ name: "Adult Entertainment"
25
+ description: "Adult content and services"
26
+ codes:
27
+ - "5967" # Direct Marketing - Inbound Teleservices Merchant
28
+ - "7273" # Dating/Escort Services
29
+ - "7297" # Massage Parlors
30
+
31
+ crypto:
32
+ name: "Cryptocurrency"
33
+ description: "Cryptocurrency and digital asset exchanges"
34
+ codes:
35
+ - "6051" # Non-FI Money Orders, Foreign Currency, Cryptocurrency
36
+ - "6211" # Security Brokers/Dealers
37
+
38
+ high_risk:
39
+ name: "High Risk"
40
+ description: "Industries with high chargeback or fraud rates"
41
+ codes:
42
+ - "5962" # Direct Marketing - Travel Related
43
+ - "5966" # Direct Marketing - Outbound Telemarketing
44
+ - "5967" # Direct Marketing - Inbound Teleservices
45
+ - "5968" # Direct Marketing - Subscription
46
+ - "7841" # Video Tape Rental Stores
47
+ - "5933" # Pawn Shops
48
+ - "5935" # Wrecking and Salvage Yards
49
+
50
+ travel:
51
+ name: "Travel"
52
+ description: "Travel services (excluding airlines)"
53
+ codes:
54
+ - "3351-3500" # Car Rentals
55
+ - "3501-3999" # Hotels and Lodging
56
+ - "4411" # Cruise Lines
57
+ - "4722" # Travel Agencies
58
+ - "4723" # Package Tour Operators
59
+ - "7011" # Hotels and Motels
60
+ - "7012" # Timeshares
61
+ - "7032" # Sporting and Recreational Camps
62
+ - "7033" # Trailer Parks and Campgrounds
63
+ - "7512" # Car Rental
64
+
65
+ fuel:
66
+ name: "Fuel"
67
+ description: "Gas stations and fuel dispensers"
68
+ codes:
69
+ - "5172" # Petroleum Products
70
+ - "5541" # Service Stations
71
+ - "5542" # Automated Fuel Dispensers
72
+ - "5983" # Fuel Dealers
73
+
74
+ financial:
75
+ name: "Financial Services"
76
+ description: "Banks, money orders, wire transfers, and stored value"
77
+ codes:
78
+ - "6010" # Financial Institutions - Manual Cash
79
+ - "6011" # Financial Institutions - Automated Cash
80
+ - "6012" # Financial Institutions - Merchandise and Services
81
+ - "6050" # Quasi Cash - Financial Institutions
82
+ - "6051" # Non-FI Money Orders
83
+ - "6211" # Security Brokers/Dealers
84
+ - "6300" # Insurance Sales
85
+ - "6513" # Real Estate Agents
86
+ - "6540" # Non-FI Stored Value Card
87
+ - "4829" # Wire Transfers and Money Orders
88
+
89
+ legal_services:
90
+ name: "Legal Services"
91
+ description: "Attorneys, bail bonds, legal services"
92
+ codes:
93
+ - "8111" # Legal Services and Attorneys
94
+ - "9223" # Bail and Bond Payments
95
+
96
+ healthcare:
97
+ name: "Healthcare"
98
+ description: "Medical services, hospitals, and pharmacies"
99
+ codes:
100
+ - "4119" # Ambulance Services
101
+ - "5122" # Drugs and Proprietary
102
+ - "5912" # Drug Stores and Pharmacies
103
+ - "8011" # Doctors
104
+ - "8021" # Dentists and Orthodontists
105
+ - "8031" # Osteopaths
106
+ - "8041" # Chiropractors
107
+ - "8042" # Optometrists
108
+ - "8043" # Opticians
109
+ - "8049" # Podiatrists
110
+ - "8050" # Nursing and Personal Care Facilities
111
+ - "8062" # Hospitals
112
+ - "8071" # Medical and Dental Laboratories
113
+ - "8099" # Medical Services
114
+
115
+ government:
116
+ name: "Government"
117
+ description: "Government services, fines, and taxes"
118
+ codes:
119
+ - "9211" # Court Costs
120
+ - "9222" # Fines
121
+ - "9223" # Bail and Bond Payments
122
+ - "9311" # Tax Payments
123
+ - "9399" # Government Services
124
+ - "9402" # Postal Services - Government Only
125
+ - "9405" # Intra-Government Purchases
126
+
127
+ food_and_dining:
128
+ name: "Food and Dining"
129
+ description: "Restaurants, fast food, and grocery stores"
130
+ codes:
131
+ - "5411" # Grocery Stores, Supermarkets
132
+ - "5422" # Freezer and Locker Meat Provisioners
133
+ - "5441" # Candy, Nut, Confectionery
134
+ - "5451" # Dairy Products
135
+ - "5462" # Bakeries
136
+ - "5499" # Miscellaneous Food Stores
137
+ - "5811" # Caterers
138
+ - "5812" # Eating Places, Restaurants
139
+ - "5813" # Drinking Places (Bars)
140
+ - "5814" # Fast Food Restaurants
141
+
142
+ retail:
143
+ name: "General Retail"
144
+ description: "General merchandise and department stores"
145
+ codes:
146
+ - "5300" # Wholesale Clubs
147
+ - "5309" # Duty Free Stores
148
+ - "5310" # Discount Stores
149
+ - "5311" # Department Stores
150
+ - "5331" # Variety Stores
151
+ - "5399" # Miscellaneous General Merchandise
152
+
153
+ electronics:
154
+ name: "Electronics"
155
+ description: "Electronics and computer stores"
156
+ codes:
157
+ - "5045" # Computers and Peripherals
158
+ - "5732" # Electronics Stores
159
+ - "5734" # Computer Software Stores
160
+ - "5815" # Digital Goods - Media
161
+ - "5816" # Digital Goods - Games
162
+ - "5817" # Digital Goods - Applications
163
+ - "5818" # Digital Goods - Large Volume
164
+
165
+ office_supplies:
166
+ name: "Office Supplies"
167
+ description: "Office equipment and supplies"
168
+ codes:
169
+ - "5021" # Office and Commercial Furniture
170
+ - "5044" # Office, Photographic Equipment
171
+ - "5111" # Stationery, Office Supplies
172
+ - "5943" # Stationery, Office and School Supply Stores
173
+
174
+ education:
175
+ name: "Education"
176
+ description: "Schools and educational services"
177
+ codes:
178
+ - "8211" # Elementary and Secondary Schools
179
+ - "8220" # Colleges, Universities
180
+ - "8241" # Correspondence Schools
181
+ - "8244" # Business and Secretarial Schools
182
+ - "8249" # Trade and Vocational Schools
183
+ - "8299" # Educational Services
184
+ - "8351" # Child Care Services
185
+
186
+ professional_services:
187
+ name: "Professional Services"
188
+ description: "Consulting, accounting, and other professional services"
189
+ codes:
190
+ - "7311" # Advertising Services
191
+ - "7321" # Credit Reporting Agencies
192
+ - "7322" # Collection Agencies
193
+ - "7372" # Computer Programming
194
+ - "7375" # Information Retrieval Services
195
+ - "7379" # Computer Maintenance
196
+ - "7392" # Management Consulting
197
+ - "8911" # Architectural, Engineering Services
198
+ - "8931" # Accounting, Auditing, Bookkeeping
199
+ - "8999" # Professional Services
200
+
201
+ entertainment:
202
+ name: "Entertainment"
203
+ description: "Recreation and entertainment (excluding gambling)"
204
+ codes:
205
+ - "7829" # Motion Picture Production
206
+ - "7832" # Motion Picture Theaters
207
+ - "7841" # Video Tape Rentals
208
+ - "7911" # Dance Halls, Studios
209
+ - "7922" # Theatrical Producers, Ticket Agencies
210
+ - "7929" # Bands, Orchestras
211
+ - "7932" # Billiard and Pool
212
+ - "7933" # Bowling Alleys
213
+ - "7941" # Sports Clubs
214
+ - "7991" # Tourist Attractions
215
+ - "7992" # Golf Courses
216
+ - "7993" # Video Amusement Game Supplies
217
+ - "7994" # Video Game Arcades
218
+ - "7996" # Amusement Parks
219
+ - "7997" # Country Clubs
220
+ - "7998" # Aquariums
221
+ - "7999" # Recreation Services
222
+
223
+ automotive:
224
+ name: "Automotive"
225
+ description: "Automotive sales, service, and parts"
226
+ codes:
227
+ - "5013" # Motor Vehicle Supplies
228
+ - "5511" # Car and Truck Dealers (New and Used)
229
+ - "5521" # Car and Truck Dealers (Used Only)
230
+ - "5531" # Auto and Home Supply
231
+ - "5532" # Automotive Tire Stores
232
+ - "5533" # Automotive Parts
233
+ - "5541" # Service Stations
234
+ - "5542" # Automated Fuel Dispensers
235
+ - "5551" # Boat Dealers
236
+ - "5561" # Camper, Trailer Dealers
237
+ - "5571" # Motorcycle Shops
238
+ - "5592" # Motor Home Dealers
239
+ - "5598" # Snowmobile Dealers
240
+ - "5599" # Misc. Automotive Dealers
241
+ - "7512" # Car Rental
242
+ - "7513" # Truck Rental
243
+ - "7519" # Motor Home Rental
244
+ - "7523" # Parking Lots
245
+ - "7531" # Automotive Body Repair
246
+ - "7534" # Tire Repair
247
+ - "7535" # Automotive Paint
248
+ - "7538" # Automotive Service Shops
249
+ - "7542" # Car Washes
250
+ - "7549" # Towing Services
251
+
252
+ charities:
253
+ name: "Charities and Non-Profits"
254
+ description: "Charitable organizations and religious groups"
255
+ codes:
256
+ - "8398" # Charitable and Social Service Organizations
257
+ - "8641" # Civic, Social, Fraternal Associations
258
+ - "8651" # Political Organizations
259
+ - "8661" # Religious Organizations
260
+ - "8699" # Membership Organizations
261
+
262
+ telecom:
263
+ name: "Telecommunications"
264
+ description: "Telephone and internet services"
265
+ codes:
266
+ - "4812" # Telecommunication Equipment
267
+ - "4813" # Key-entry Telecom
268
+ - "4814" # Telecommunication Services
269
+ - "4815" # Monthly Summary Telephone
270
+ - "4816" # Computer Network Services
271
+ - "4821" # Telegraph Services
272
+ - "4899" # Cable and Pay Television
273
+
274
+ utilities:
275
+ name: "Utilities"
276
+ description: "Electric, gas, and water services"
277
+ codes:
278
+ - "4900" # Utilities - Electric, Gas, Water
279
+
280
+ construction:
281
+ name: "Construction"
282
+ description: "General and specialty contractors"
283
+ codes:
284
+ - "1520" # General Contractors
285
+ - "1711" # Heating, Plumbing, A/C Contractors
286
+ - "1731" # Electrical Contractors
287
+ - "1740" # Masonry, Plastering Contractors
288
+ - "1750" # Carpentry Contractors
289
+ - "1761" # Roofing, Siding Contractors
290
+ - "1771" # Concrete Work Contractors
291
+ - "1799" # Special Trade Contractors
292
+ - "5039" # Construction Materials
293
+ - "5211" # Lumber and Building Materials
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Elia
4
+ module Mcc
5
+ # Base error class for all MCC-related errors
6
+ class Error < StandardError; end
7
+
8
+ # Raised when an MCC code is not found in the registry
9
+ class NotFound < Error
10
+ def initialize(code)
11
+ super("MCC code not found: #{code.inspect}")
12
+ end
13
+ end
14
+
15
+ # Raised when an invalid MCC code format is provided
16
+ class InvalidCode < Error
17
+ def initialize(code)
18
+ super("Invalid MCC code format: #{code.inspect}. Expected a 4-digit string or integer.")
19
+ end
20
+ end
21
+
22
+ # Raised when an invalid range is specified
23
+ class InvalidRange < Error
24
+ def initialize(message = "Invalid MCC range specified")
25
+ super
26
+ end
27
+ end
28
+
29
+ # Raised when configuration is invalid
30
+ class ConfigurationError < Error; end
31
+
32
+ # Raised when data files cannot be loaded
33
+ class DataLoadError < Error
34
+ def initialize(file_path, original_error = nil)
35
+ message = "Failed to load MCC data from: #{file_path}"
36
+ message += " (#{original_error.message})" if original_error
37
+ super(message)
38
+ end
39
+ end
40
+
41
+ # Raised when a category is not found
42
+ class CategoryNotFound < Error
43
+ def initialize(category)
44
+ super("Category not found: #{category.inspect}")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Elia
4
+ module Mcc
5
+ # Rails integration for the Elia::Mcc module
6
+ #
7
+ # Provides automatic setup when used within a Rails application,
8
+ # including configuration and ActiveModel integration.
9
+ class Railtie < Rails::Railtie
10
+ initializer "elia_mcc.configure" do |app|
11
+ # Allow custom data path from Rails config directory
12
+ Elia::Mcc.configure do |config|
13
+ if app.root
14
+ custom_data_path = app.root.join("config", "mcc_data")
15
+ config.data_path = custom_data_path.to_s if custom_data_path.exist?
16
+ end
17
+ end
18
+ end
19
+
20
+ # Load ActiveModel validator when ActiveModel is loaded
21
+ initializer "elia_mcc.active_model" do
22
+ ActiveSupport.on_load(:active_model) do
23
+ require "elia/mcc/active_model_validator"
24
+ end
25
+ end
26
+
27
+ # Eager load MCC data after initialization if caching is enabled
28
+ config.after_initialize do
29
+ if Elia::Mcc.configuration.cache_enabled
30
+ # Touch the collection to trigger lazy loading
31
+ Elia::Mcc.count
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Elia
4
+ module Mcc
5
+ # Represents an ISO 18245 MCC range
6
+ #
7
+ # Ranges define groups of related MCC codes by industry segment
8
+ # according to the ISO 18245 standard.
9
+ class Range
10
+ # @return [String] the starting MCC code (inclusive)
11
+ attr_reader :start_code
12
+
13
+ # @return [String] the ending MCC code (inclusive)
14
+ attr_reader :end_code
15
+
16
+ # @return [String] the name of this range
17
+ attr_reader :name
18
+
19
+ # @return [String] description of this range
20
+ attr_reader :description
21
+
22
+ # @return [Boolean] whether this range is reserved
23
+ attr_reader :reserved
24
+
25
+ # Creates a new Range instance
26
+ #
27
+ # @param attributes [Hash] the range attributes
28
+ # @option attributes [String, Integer] :start the starting MCC code
29
+ # @option attributes [String, Integer] :end the ending MCC code
30
+ # @option attributes [String] :name the name of the range
31
+ # @option attributes [String] :description description of the range
32
+ # @option attributes [Boolean] :reserved whether the range is reserved
33
+ # @raise [InvalidRange] if the range is invalid
34
+ def initialize(attributes = {})
35
+ attributes = attributes.transform_keys(&:to_sym)
36
+
37
+ @start_code = normalize_code(attributes[:start] || attributes[:start_code])
38
+ @end_code = normalize_code(attributes[:end] || attributes[:end_code])
39
+ @name = attributes[:name].to_s
40
+ @description = attributes[:description].to_s
41
+ @reserved = attributes[:reserved] == true
42
+
43
+ validate!
44
+ end
45
+
46
+ # Returns whether the given code falls within this range
47
+ #
48
+ # @param mcc [String, Integer, Code] the code to check
49
+ # @return [Boolean] true if the code is within the range
50
+ def include?(mcc)
51
+ code = mcc.respond_to?(:mcc) ? mcc.mcc : mcc
52
+ normalized = normalize_code(code)
53
+ normalized.between?(start_code, end_code)
54
+ end
55
+
56
+ alias cover? include?
57
+
58
+ # Returns whether this range is reserved
59
+ #
60
+ # @return [Boolean] true if reserved
61
+ def reserved?
62
+ @reserved == true
63
+ end
64
+
65
+ # Returns the number of codes in this range
66
+ #
67
+ # @return [Integer] the count of codes
68
+ def size
69
+ end_code.to_i - start_code.to_i + 1
70
+ end
71
+
72
+ alias count size
73
+ alias length size
74
+
75
+ # Returns all codes in this range as an array of strings
76
+ #
77
+ # @return [Array<String>] all codes in the range
78
+ def to_a
79
+ (start_code.to_i..end_code.to_i).map { |n| n.to_s.rjust(4, "0") }
80
+ end
81
+
82
+ # Iterates over each code in the range
83
+ #
84
+ # @yield [String] each code in the range
85
+ # @return [Enumerator] if no block given
86
+ def each(&block)
87
+ return to_enum(:each) unless block_given?
88
+
89
+ to_a.each(&block)
90
+ end
91
+
92
+ # Returns whether this range equals another
93
+ #
94
+ # @param other [Range] the range to compare
95
+ # @return [Boolean] true if the ranges are equal
96
+ def ==(other)
97
+ return false unless other.is_a?(self.class)
98
+
99
+ start_code == other.start_code && end_code == other.end_code
100
+ end
101
+
102
+ alias eql? ==
103
+
104
+ # Returns a hash code for this instance
105
+ #
106
+ # @return [Integer] the hash code
107
+ def hash
108
+ [start_code, end_code].hash
109
+ end
110
+
111
+ # Returns a human-readable representation
112
+ #
113
+ # @return [String] the inspection string
114
+ def inspect
115
+ "#<#{self.class.name} #{start_code}..#{end_code} name=#{name.inspect} reserved=#{reserved?}>"
116
+ end
117
+
118
+ # Returns the range as a string
119
+ #
120
+ # @return [String] the range representation
121
+ def to_s
122
+ "#{start_code}-#{end_code}"
123
+ end
124
+
125
+ # Returns a hash representation
126
+ #
127
+ # @return [Hash] the range as a hash
128
+ def to_h
129
+ {
130
+ start_code: start_code,
131
+ end_code: end_code,
132
+ name: name,
133
+ description: description,
134
+ reserved: reserved,
135
+ }
136
+ end
137
+
138
+ private
139
+
140
+ # Validates that the range is valid
141
+ #
142
+ # @raise [InvalidRange] if the range is invalid
143
+ def validate!
144
+ return unless start_code.to_i > end_code.to_i
145
+
146
+ raise InvalidRange, "Start code (#{start_code}) cannot be greater than end code (#{end_code})"
147
+ end
148
+
149
+ # Normalizes a code value to a 4-digit string
150
+ #
151
+ # @param value [String, Integer] the value to normalize
152
+ # @return [String] the normalized 4-digit string
153
+ def normalize_code(value)
154
+ value.to_s.strip.rjust(4, "0")
155
+ end
156
+ end
157
+ end
158
+ end