ekylibre-ofx-parser 1.2.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.
- checksums.yaml +7 -0
- data/README.rdoc +105 -0
- data/lib/mcc.rb +670 -0
- data/lib/ofx-parser.rb +191 -0
- data/lib/ofx-parser/version.rb +3 -0
- data/lib/ofx.rb +204 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6c544df27ac669391390610586894417f96db85a
|
4
|
+
data.tar.gz: de9425a7659732a011e8bd8687d4bd6c6551ac94
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9b7e6e6694bbef0b5d35d0d827ae4ec6ff2f26888a435a916d9c52a7177787c247d15c4728ca63253e2bd4aa25a5f157d609fb659333f8df6d43afd0a65bfd60
|
7
|
+
data.tar.gz: b267f6862965eda3038d7bd530f37e4e1387c05d621a5ffed20e24d0a3bb5753129a8e4efff44e08a74ee4a4214982a1f7951ee52265f4d341f030ca691840a9
|
data/README.rdoc
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
== ofx-parser
|
2
|
+
by Andrew A. Smith
|
3
|
+
|
4
|
+
http://ofx-parser.rubyforge.org/
|
5
|
+
http://rubyforge.org/projects/ofx-parser/
|
6
|
+
|
7
|
+
== DESCRIPTION:
|
8
|
+
|
9
|
+
ofx-parser is a ruby library to parse a realistic subset of the lengthy OFX 1.x specification.
|
10
|
+
|
11
|
+
== FEATURES/PROBLEMS:
|
12
|
+
|
13
|
+
* Reads OFX responses - i.e. those downloaded from financial institutions and
|
14
|
+
puts it into a usable object graph.
|
15
|
+
* Supports the 3 main message sets: banking, credit card and investment
|
16
|
+
accounts, as well as the required 'sign on' set.
|
17
|
+
* Knows about SIC codes - if your institution provides them.
|
18
|
+
See http://www.eeoc.gov/stats/jobpat/siccodes.html
|
19
|
+
* Monetary amounts can be retrieved either as a raw string, or in pennies.
|
20
|
+
* Supports OFX timestamps.
|
21
|
+
|
22
|
+
== SYNOPSIS:
|
23
|
+
|
24
|
+
Supports bank accounts:
|
25
|
+
|
26
|
+
require 'rubygems'
|
27
|
+
require 'ofx-parser'
|
28
|
+
|
29
|
+
ofx = OfxParser::OfxParser.parse(open("bank-statement.ofx"))
|
30
|
+
bank_acct = ofx.bank_accounts.first
|
31
|
+
|
32
|
+
bank_acct.number # => '103333333333'
|
33
|
+
bank_acct.routing_number # => '033000033'
|
34
|
+
bank_acct.balance # => '123.45'
|
35
|
+
bank_acct.balance_in_pennies # => 12345
|
36
|
+
|
37
|
+
bank_acct.statement.start_date # => DateTime
|
38
|
+
bank_acct.statement.end_date # => DateTime
|
39
|
+
|
40
|
+
bank_acct.statement.transactions.size # => 4
|
41
|
+
|
42
|
+
bank_acct.statement.transactions.first.payee # => "FOO, INC."
|
43
|
+
bank_acct.statement.transactions.first.type # => :DEBIT
|
44
|
+
bank_acct.statement.transactions.first.amount # => '-11.11'
|
45
|
+
bank_acct.statement.transactions.first.amount_in_pennies # => -1111
|
46
|
+
|
47
|
+
Also supports credit cards...
|
48
|
+
|
49
|
+
ofx = OfxParser::OfxParser.parse(open("creditcard-statement.ofx"))
|
50
|
+
credit_card = ofx.credit_accounts.first
|
51
|
+
|
52
|
+
credit_card.remaining_credit # => '19000.0'
|
53
|
+
credit_card.remaining_credit_in_pennies # => '1900000'
|
54
|
+
|
55
|
+
credit_card.statement.start_date # => DateTime
|
56
|
+
credit_card.statement.end_date # => DateTime
|
57
|
+
|
58
|
+
credit_card.statement.transactions.size # => 10
|
59
|
+
|
60
|
+
credit_card.statement.transactions.first.type # => :DEBIT
|
61
|
+
credit_card.statement.transactions.first.amount # => '-19.17'
|
62
|
+
credit_card.statement.transactions.first.amount_in_pennies # => '-1917'
|
63
|
+
credit_card.statement.transactions.first.sic # => '7933'
|
64
|
+
credit_card.statement.transactions.first.sic_desc # => 'BOWLING CENTERS'
|
65
|
+
credit_card.statement.transactions.first.payee # => 'SUNSET BOWLING'
|
66
|
+
|
67
|
+
Working on investment accounts...
|
68
|
+
|
69
|
+
== REQUIREMENTS:
|
70
|
+
|
71
|
+
* hpricot >= 0.6
|
72
|
+
|
73
|
+
== INSTALL:
|
74
|
+
|
75
|
+
* gem install ofx-parser
|
76
|
+
|
77
|
+
== LICENSE:
|
78
|
+
|
79
|
+
Copyright (c) 2007, Andrew A. Smith
|
80
|
+
All rights reserved.
|
81
|
+
|
82
|
+
Redistribution and use in source and binary forms, with or without modification,
|
83
|
+
are permitted provided that the following conditions are met:
|
84
|
+
|
85
|
+
* Redistributions of source code must retain the above copyright notice,
|
86
|
+
this list of conditions and the following disclaimer.
|
87
|
+
|
88
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
89
|
+
this list of conditions and the following disclaimer in the documentation
|
90
|
+
and/or other materials provided with the distribution.
|
91
|
+
|
92
|
+
* Neither the name of the copyright owner nor the names of its contributors
|
93
|
+
may be used to endorse or promote products derived from this software
|
94
|
+
without specific prior written permission.
|
95
|
+
|
96
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
97
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
98
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
99
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
100
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
101
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
102
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
103
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
104
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
105
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/lib/mcc.rb
ADDED
@@ -0,0 +1,670 @@
|
|
1
|
+
module OfxParser
|
2
|
+
# MCC: Merchant Category Codes from
|
3
|
+
# * http://www.purchasing.colostate.edu/pages/pdf/MCCS.pdf
|
4
|
+
# * http://www.ctlr.msu.edu/cashiers/MC%20IC%20Apr%2007.pdf
|
5
|
+
# * http://usa.visa.com/download/corporate/resources/mcc_booklet.pdf
|
6
|
+
module Mcc
|
7
|
+
CODES = {
|
8
|
+
'0742' => 'VETERINARY SERVICES',
|
9
|
+
'0763' => 'AGRICULTURAL COOPERATIVES',
|
10
|
+
'2741' => 'MISCELLANEOUS PUBLISHING AND PRINTING',
|
11
|
+
'2791' => 'TYPESETTING PLATE MAKING + RELATED SERVICES',
|
12
|
+
'2842' => 'SPECIALTY CLEANING POLISHING + SANITATION PREP.',
|
13
|
+
'4215' => 'COURIER SVC-AIR + GROUND FREIGHT FORWARDERS',
|
14
|
+
'4468' => 'MARINAS MARINE SERVICE-SUPPLIES',
|
15
|
+
'4812' => 'TELECOMMUNICATION EQUIPMENT INCL TELEPHONE SALES',
|
16
|
+
'4813' => 'KEY-ENTER TELECOM MERCHANT- (NO MAG STRIPE READ)',
|
17
|
+
'4814' => 'TELECOM SVC-LOC-LONG DIST CR CD + MAG STRIPE FAX',
|
18
|
+
'4815' => 'MONTHLY SUMMARY TELEPHONE CHARGES',
|
19
|
+
'4816' => 'COMPUTER NETWORK-INFORMATION SERVICES',
|
20
|
+
'4821' => 'TELEGRAPH SERVICES',
|
21
|
+
'4899' => 'CABLE SERVICES',
|
22
|
+
'4900' => 'UTILITIES-ELECTRIC GAS WATER SANITARY',
|
23
|
+
'5013' => 'MOTOR VEHICLE SUPPLIES AND NEW PARTS',
|
24
|
+
'5021' => 'OFFICE AND COMMERCIAL FURNITURE',
|
25
|
+
'5039' => 'CONSTRUCTION MATERIALS NOT ELSEWHERE CLASSIFIED',
|
26
|
+
'5044' => 'OFFICE PHOTOGRAPHIC PHOTOCOPY + MICROFILM EQUIPMT.',
|
27
|
+
'5045' => 'COMPUTERS COMPUTER PERIPHERAL EQUIPMENT SOFTWARE',
|
28
|
+
'5046' => 'COMMERCIAL EQUIPMENT NOT ELSEWHERE CLASSIFIED',
|
29
|
+
'5047' => 'LABORATORY-MEDICAL-DENTAL-OPHTHALMIC HOS. EQUI-SUP',
|
30
|
+
'5051' => 'METAL SERVICE CENTERS AND OFFICES',
|
31
|
+
'5065' => 'ELECTRICAL PARTS AND EQUIPMENT',
|
32
|
+
'5072' => 'HARDWARE EQUIPMENT AND SUPPLIES',
|
33
|
+
'5074' => 'PLUMBING AND HEATING EQUIPMENT',
|
34
|
+
'5085' => 'INDUSTRIAL SUPPLIES NOT ELSEWHERE CLASSIFIED',
|
35
|
+
'5094' => 'PRECIOUS STONES AND METALS WATCHES AND JEWELRY',
|
36
|
+
'5099' => 'DURABLE GOODS NOT ELSEWHERE CLASSIFIED',
|
37
|
+
'5111' => 'STATIONERY-OFFICE SUPPLIES-PRINTING + WRITING PAP.',
|
38
|
+
'5122' => 'DRUGS DRUG PROPRIETARIES AND DRUGGIST\'S SUPPLIES',
|
39
|
+
'5131' => 'PIECE GOODS NOTIONS AND OTHER DRY GOODS',
|
40
|
+
'5137' => 'MEN\'S-WOMEN\'S-CHILDREN\'S UNIFORMS-COMMERCIAL CLOTH',
|
41
|
+
'5139' => 'COMMERCIAL FOOTWEAR',
|
42
|
+
'5169' => 'CHEMICALS-ALLIED PRODUCTS NOT ELSEWHERE CLASSIFIED',
|
43
|
+
'5172' => 'PETROLEUM AND PETROLEUM PRODUCTS',
|
44
|
+
'5192' => 'BOOKS PERIODICALS AND NEWSPAPERS',
|
45
|
+
'5193' => 'FLORIST SUPPLIES NURSERY STOCK + FLOWERS',
|
46
|
+
'5198' => 'PAINTS VARNISHES AND SUPPLIES',
|
47
|
+
'5199' => 'NONDURABLE GOODS (NOT ELSEWHERE CLASSIFIED)',
|
48
|
+
'5200' => 'HOME SUPPLY WAREHOUSE',
|
49
|
+
'5211' => 'LUMBER BUILDING MATERIALS STORES',
|
50
|
+
'5231' => 'GLASS PAINT WALLPAPER STORES',
|
51
|
+
'5251' => 'HARDWARE STORES',
|
52
|
+
'5261' => 'NURSERIES LAWN GARDEN SUPPLY STORES',
|
53
|
+
'5300' => 'WHOLESALE CLUBS',
|
54
|
+
'5310' => 'DISCOUNT STORES',
|
55
|
+
'5311' => 'DEPARTMENT STORES',
|
56
|
+
'5331' => 'VARIETY STORES',
|
57
|
+
'5399' => 'MISCELLANEOUS GENERAL MERCHANDISE STORES',
|
58
|
+
'5411' => 'GROCERY STORES SUPERMARKETS',
|
59
|
+
'5422' => 'FREEZER LOCKER MEAT PROVISIONERS',
|
60
|
+
'5441' => 'CANDY NUT CONFECTIONERY STORES',
|
61
|
+
'5451' => 'DAIRY PRODUCTS STORES',
|
62
|
+
'5462' => 'BAKERIES',
|
63
|
+
'5499' => 'MISC FOOD STORES SPECIALTY MARKETS CONVENIENCE',
|
64
|
+
'5511' => 'AUTO + TRUCK DLRS NEW + USED SALES SVC PARTS',
|
65
|
+
'5531' => 'AUTO STORE HOME SUPPLY STORES',
|
66
|
+
'5532' => 'AUTOMOTIVE TIRE STORES',
|
67
|
+
'5533' => 'AUTOMOTIVE PARTS ACCESSORIES STORES',
|
68
|
+
'5541' => 'SERVICE STATIONS WITH OR WITHOUT ANCILLARY SERVICE',
|
69
|
+
'5551' => 'BOAT DEALERS',
|
70
|
+
'5561' => 'RECREATIONAL + UTILITY TRAILERS CAMPER DEALERS',
|
71
|
+
'5571' => 'MOTORCYCLE SHOPS AND DEALERS',
|
72
|
+
'5598' => 'SNOWMOBILE DEALERS',
|
73
|
+
'5599' => 'MISC-AUTO-AIRCRAFT-FARM EQUIP NOT ELSEWHERE CLASS',
|
74
|
+
'5611' => 'MEN\'S AND BOY\'S CLOTHING AND FURNISHINGS STORE',
|
75
|
+
'5621' => 'WOMEN\'S READY TO WEAR STORES',
|
76
|
+
'5631' => 'WOMEN\'S ACCESSORY AND SPECIALTY STORES',
|
77
|
+
'5641' => 'CHILDREN\'S AND INFANT\'S WEAR STORES',
|
78
|
+
'5651' => 'FAMILY CLOTHING STORES',
|
79
|
+
'5655' => 'SPORTS APPAREL RIDING APPAREL STORES',
|
80
|
+
'5661' => 'SHOE STORES',
|
81
|
+
'5691' => 'MEN\'S AND WOMEN\'S CLOTHING STORES',
|
82
|
+
'5697' => 'TAILORS SEAMSTRESSES MENDING ALTERATIONS',
|
83
|
+
'5698' => 'WIG AND TOUPEE SHOPS',
|
84
|
+
'5699' => 'MISCELLANEOUS APPAREL AND ACCESSORY STORES',
|
85
|
+
'5712' => 'FURNITURE HOME FURNISH + EQUIP EXCL APPLIANCES',
|
86
|
+
'5713' => 'FLOOR COVERING STORES',
|
87
|
+
'5714' => 'DRAPERY WINDOW COVERINGS AND UPHOLSTERY STORES',
|
88
|
+
'5718' => 'FIREPLACE FIREPLACE SCREENS + ACCESSORIES STORES',
|
89
|
+
'5719' => 'MISCELLANEOUS HOUSE FURNISHING SPECIALTY SHOPS',
|
90
|
+
'5722' => 'HOUSEHOLD APPLIANCE STORES',
|
91
|
+
'5732' => 'ELECTRONIC SALES',
|
92
|
+
'5733' => 'MUSIC STORES-INSTRUMENTS PIANOS SHEET MUSIC',
|
93
|
+
'5734' => 'COMPUTER SOFTWARE STORES',
|
94
|
+
'5735' => 'RECORD SHOPS',
|
95
|
+
'5912' => 'DRUG STORES PHARMACIES',
|
96
|
+
'5931' => 'USED MERCHANDISE STORES SECOND HAND STORES',
|
97
|
+
'5932' => 'ANTIQUE SHOPS-SALES REPAIRS RESTORATION SERVICES',
|
98
|
+
'5933' => 'PAWN SHOPS',
|
99
|
+
'5935' => 'WRECKING AND SALVAGE YARDS',
|
100
|
+
'5937' => 'ANTIQUE REPRODUCTION STORES',
|
101
|
+
'5940' => 'BICYCLE SHOPS-SALES AND SERVICE',
|
102
|
+
'5941' => 'SPORTING GOODS STORES',
|
103
|
+
'5942' => 'BOOK STORES',
|
104
|
+
'5943' => 'STATIONERY OFFICE AND SCHOOL SUPPLY STORES',
|
105
|
+
'5944' => 'JEWELRY-WATCHES CLOCKS AND SILVERWARE STORES',
|
106
|
+
'5945' => 'HOBBY TOY AND GAME SHOPS',
|
107
|
+
'5946' => 'CAMERA AND PHOTOGRAPHIC SUPPLY STORES',
|
108
|
+
'5947' => 'GIFT CARD NOVELTY AND SOUVENIR SHOPS',
|
109
|
+
'5948' => 'LUGGAGE AND LEATHER GOODS STORES',
|
110
|
+
'5949' => 'SEWING NEEDLEWORK FABRIC AND PIECE GOODS STORES',
|
111
|
+
'5950' => 'GLASSWARE AND CRYSTAL STORES',
|
112
|
+
'5964' => 'DIRECT MARKETING-CATALOG MERCHANTS',
|
113
|
+
'5965' => 'DIRECT MARKETING-COMBINATION CATALOG-RETAIL MERCH.',
|
114
|
+
'5966' => 'DIRECT MARKETING-OUTBOUND TELEMARKETING MERCHANTS',
|
115
|
+
'5967' => 'DIRECT MARKETING-INBOUND TELEMARKETING MERCHANTS',
|
116
|
+
'5968' => 'DIRECT MARKETING-CONTINUITY-SUBSCRIPTION MERCHANTS',
|
117
|
+
'5969' => 'DIRECT MARKETING-OTHER DIRECT MARKETERS-NOT ELSEW.',
|
118
|
+
'5970' => 'ARTIST SUPPLY STORES CRAFT SHOPS',
|
119
|
+
'5971' => 'ART DEALERS AND GALLERIES',
|
120
|
+
'5973' => 'RELIGIOUS GOODS STORES',
|
121
|
+
'5975' => 'HEARING AIDS-SALES SERVICE SUPPLY STORES',
|
122
|
+
'5976' => 'ORTHOPEDIC GOODS-ARTIFICIAL LIMB STORES',
|
123
|
+
'5977' => 'COSMETIC STORES',
|
124
|
+
'5978' => 'TYPEWRITER STORES-SALES SERVICE RENTALS',
|
125
|
+
'5983' => 'FUEL DEALERS-OIL WOOD COAL LIQUEFIED PETROLEUM',
|
126
|
+
'5992' => 'FLORISTS',
|
127
|
+
'5994' => 'NEWS DEALERS AND NEWSSTANDS',
|
128
|
+
'5995' => 'PET SHOPS - PET FOODS AND SUPPLIES',
|
129
|
+
'5996' => 'SWIMMING POOLS - SALES AND SUPPLIES',
|
130
|
+
'5997' => 'ELECTRIC RAZOR STORES - SALES AND SERVICE',
|
131
|
+
'5998' => 'TENT AND AWNING SHOPS',
|
132
|
+
'5999' => 'MISCELLANEOUS AND SPECIALTY RETAIL STORES',
|
133
|
+
'7032' => 'SPORTING AND RECREATIONAL CAMPS',
|
134
|
+
'7033' => 'TRAILER PARKS AND CAMPGROUNDS',
|
135
|
+
'7210' => 'LAUNDRY CLEANING AND GARMENT SERVICES',
|
136
|
+
'7211' => 'LAUNDRY SERVICES - FAMILY AND COMMERICAL',
|
137
|
+
'7216' => 'DRY CLEANERS',
|
138
|
+
'7217' => 'CARPET AND UPHOLSTERY CLEANING',
|
139
|
+
'7221' => 'PHOTOGRAPHIC STUDIOS',
|
140
|
+
'7230' => 'BEAUTY SHOPS AND BARBER SHOPS',
|
141
|
+
'7251' => 'SHOE REPAIR SHOPS SHOE SHINE HAT CLEANING',
|
142
|
+
'7278' => 'BUYING-SHOPPING SERVICES CLUBS',
|
143
|
+
'7296' => 'CLOTHING RENTAL-COSTUMES UNIFORMS FORMAL WEAR',
|
144
|
+
'7299' => 'OTHER SERVICES (NOT ELSEWHERE CLASSIFIED)',
|
145
|
+
'7311' => 'ADVERTISING SERVICES',
|
146
|
+
'7332' => 'BLUEPRINTING AND PHOTOCOPYING SERVICES',
|
147
|
+
'7333' => 'COMMERCIAL PHOTOGRAPHY ART GRAPHICS',
|
148
|
+
'7338' => 'QUICK COPY REPRODUCTION AND BLUEPRINTING SERVICES',
|
149
|
+
'7339' => 'STENOGRAPHIC AND SECRETARIAL SUPPORT SERVICES',
|
150
|
+
'7342' => 'EXTERMINATING AND DISINFECTING SERVICES',
|
151
|
+
'7349' => 'CLEANING AND MAINTENANCE JANITORIAL SERVICES',
|
152
|
+
'7361' => 'EMPLOYMENT AGENCIES TEMPORARY HELP SERVICES',
|
153
|
+
'7372' => 'COMPUTER AND DATA PROCESSING SERVICES',
|
154
|
+
'7375' => 'INFORMATION RETRIEVAL SERVICES',
|
155
|
+
'7379' => 'COMPUTER MAIN.-REPAIR-SERVICES NOT ELSEWHERE CLASS',
|
156
|
+
'7392' => 'MANAGEMENT CONSULTING AND PUBLIC RELATIONS SVCS',
|
157
|
+
'7393' => 'DETECTIVE + PROTECTIVE AGENCIES SECURITY SERVICES',
|
158
|
+
'7394' => 'EQUIP RENTAL + LEASING TOOL + FURNITURE RENTAL',
|
159
|
+
'7395' => 'PHOTOFINISHING LABORATORIES PHOTO DEVELOPING',
|
160
|
+
'7399' => 'BUSINESS SERVICES-NOT ELSEWHERE CLASSIFIED',
|
161
|
+
'7513' => 'TRUCK AND UTILITY TRAILER RENTAL',
|
162
|
+
'7519' => 'MOTOR HOME AND RECREATIONAL VEHICLE RENTAL',
|
163
|
+
'7523' => 'AUTOMOBILE PARKING LOTS AND GARAGES',
|
164
|
+
'7542' => 'CAR WASHES',
|
165
|
+
'7549' => 'TOWING SERVICES',
|
166
|
+
'7622' => 'ELECTRONIC REPAIR SHOPS',
|
167
|
+
'7623' => 'AIR CONDITIONING AND REFRIGERATION REPAIR SHOPS',
|
168
|
+
'7629' => 'ELECTRICAL AND SMALL APPLIANCE REPAIR SHOPS',
|
169
|
+
'7631' => 'WATCH CLOCK AND JEWELRY REPAIR SHOPS',
|
170
|
+
'7641' => 'REUPHOLSTERY AND FURNITURE REPAIR REFINISHING',
|
171
|
+
'7692' => 'WELDING REPAIR',
|
172
|
+
'7699' => 'MISCELLANEOUS REPAIR SHOPS AND RELATED SERVICES',
|
173
|
+
'7829' => 'MOTION PICTURE-VIDEO TAPE PRODUCTION-DISTRIBUTION',
|
174
|
+
'7832' => 'MOTION PICTURE THEATERS',
|
175
|
+
'7841' => 'VIDEO TAPE RENTAL STORES',
|
176
|
+
'7911' => 'DANCE HALLS STUDIOS AND SCHOOLS',
|
177
|
+
'7922' => 'THEATRICAL PRODUCERS-EXCL MOTION PIX TICKET AGNCY',
|
178
|
+
'7929' => 'BANDS ORCHESTRAS MISC ENTERTAINERS NOT ELSEWHERE',
|
179
|
+
'7933' => 'BOWLING ALLEYS',
|
180
|
+
'7941' => 'COMMERCIAL SPORTS PROFESSIONAL CLBS ATHLETIC FLD',
|
181
|
+
'7991' => 'TOURIST ATTRACTIONS AND EXHIBITS',
|
182
|
+
'7992' => 'GOLF COURSES-PUBLIC',
|
183
|
+
'7993' => 'VIDEO AMUSEMENT GAME SUPPLIES',
|
184
|
+
'7997' => 'MBRSHIP CLUBS COUNTRY CLUBS PRIVATE GOLF COURSES',
|
185
|
+
'7998' => 'AQUARIUMS SEAQUARIUMS AND DOLPHINARIUMS',
|
186
|
+
'7999' => 'RECREATION SERVICES (NOT ELSEWHERE CLASSIFIED)',
|
187
|
+
'8043' => 'OPTICIANS OPTICAL GOODS + EYEGLASSES',
|
188
|
+
'8044' => 'OPTICAL GOODS AND EYEGLASSES',
|
189
|
+
'8062' => 'HOSPITALS',
|
190
|
+
'8071' => 'MEDICAL AND DENTAL LABORATORIES',
|
191
|
+
'8099' => 'MEDICAL SVCS HEALTH PRACTICE-NOT CLASS ELSEWHERE',
|
192
|
+
'8211' => 'ELEMENTARY AND SECONDARY SCHOOLS',
|
193
|
+
'8220' => 'COLLEGES UNIV PRO SCHOOLS JUNIOR COLLEGES',
|
194
|
+
'8241' => 'CORRESPONDENCE SCHOOLS',
|
195
|
+
'8244' => 'BUSINESS AND SECRETARIAL SCHOOLS',
|
196
|
+
'8249' => 'VOCATIONAL AND TRADE SCHOOLS',
|
197
|
+
'8299' => 'SCHOOLS + EDUCATIONAL SVC-NOT ELSEWHERE CLASSIFIED',
|
198
|
+
'8398' => 'CHARITABLE AND SOCIAL SERVICE ORGANIZATIONS',
|
199
|
+
'8641' => 'CIVIC SOCIAL AND FRATERNAL ASSOCIATIONS',
|
200
|
+
'8699' => 'MEMBERSHIP ORGANIZATIONS-NOT ELSEWHERE CLASSIFIED',
|
201
|
+
'8734' => 'TESTING LABORATORIES (NON-MEDICAL)',
|
202
|
+
'8911' => 'ENGINEERING ARCHITECTURAL AND SURVEYING SERVICES',
|
203
|
+
'8931' => 'ACCOUNTING AUDITING AND BOOKKEEPING SERVICES',
|
204
|
+
'8999' => 'PROFESSIONAL SERVICES-NOT ELSEWHERE CLASSIFIED',
|
205
|
+
'9399' => 'GOVERNMENT SERVICES-NOT ELSEWHERE CLASSIFIED',
|
206
|
+
'9402' => 'POSTAL SERVICES-GOVERNMENT ONLY',
|
207
|
+
'9405' => 'INTRA GOVERNMENT PURCHASES',
|
208
|
+
'9702' => 'GCAS EMERGENCY SERVICES',
|
209
|
+
'9950' => 'INTRA COMPANY PURCHASES',
|
210
|
+
'0780' => 'LANDSCAPING AND HORTICULTURAL SERVICES',
|
211
|
+
'1520' => 'GENERAL CONTRACTORS-RESIDENTIAL BUILDINGS',
|
212
|
+
'1711' => 'HEATING PLUMBING AIR CONDITIONING CONTRACTORS',
|
213
|
+
'1731' => 'ELECTRICAL CONTRACTORS',
|
214
|
+
'1740' => 'MASONRY STONEWORK TILE SET PLASTER INSULATION',
|
215
|
+
'1750' => 'CARPENTRY CONTRACTORS',
|
216
|
+
'1761' => 'ROOFING + SIDING SHEET METAL WORK CONTRACTORS',
|
217
|
+
'1771' => 'CONCRETE WORK CONTRACTORS',
|
218
|
+
'1799' => 'SPECIAL TRADE CONTRACTORS-NOT ELSEWHERE CLASSIFIED',
|
219
|
+
'4214' => 'TRUCKING-LOCAL-LONG DIST- MOVING-STORAGE-LOC DEL',
|
220
|
+
'3501' => 'HOLIDAY INNS',
|
221
|
+
'3502' => 'BEST WESTERN HOTELS',
|
222
|
+
'3503' => 'SHERATON HOTELS',
|
223
|
+
'3504' => 'HILTON HOTELS',
|
224
|
+
'3505' => 'FORTE HOTELS',
|
225
|
+
'3506' => 'GOLDEN TULIP HOTELS',
|
226
|
+
'3507' => 'FRIENDSHIP INNS',
|
227
|
+
'3508' => 'QUALITY INNS',
|
228
|
+
'3509' => 'MARRIOTT',
|
229
|
+
'3510' => 'DAYS INNS',
|
230
|
+
'3511' => 'ARABELLA HOTELS',
|
231
|
+
'3512' => 'INTERCONTINENTAL HOTELS',
|
232
|
+
'3513' => 'WESTIN HOTELS',
|
233
|
+
'3514' => 'AMERISUITES',
|
234
|
+
'3515' => 'RODEWAY INNS',
|
235
|
+
'3516' => 'LA QUINTA MOTOR INNS',
|
236
|
+
'3517' => 'AMERICANA HOTELS',
|
237
|
+
'3518' => 'SOL HOTELS',
|
238
|
+
'3519' => 'PULLMAN INT\'L HOTELS',
|
239
|
+
'3520' => 'MERIDIEN HOTELS',
|
240
|
+
'3523' => 'PENINSULA HOTELS',
|
241
|
+
'3524' => 'WELCOMGROUP HOTELS',
|
242
|
+
'3525' => 'DUNFEY HOTELS',
|
243
|
+
'3526' => 'PRINCE HOTELS',
|
244
|
+
'3528' => 'RED LION INNS',
|
245
|
+
'3529' => 'CP (CANADIAN PACIFIC) HOTELS',
|
246
|
+
'3530' => 'RENAISSANCE HOTELS',
|
247
|
+
'3534' => 'SOUTHERN PACIFIC HOTELS',
|
248
|
+
'3535' => 'HILTON INTERNATIONAL',
|
249
|
+
'3536' => 'AMFAC HOTELS',
|
250
|
+
'3537' => 'ANA HOTELS',
|
251
|
+
'3538' => 'CONCORDE HOTELS',
|
252
|
+
'3539' => 'SUMMERFIELD SUITES HOTEL',
|
253
|
+
'3542' => 'ROYAL HOTELS',
|
254
|
+
'3543' => 'FOUR SEASONS HOTELS',
|
255
|
+
'3544' => 'CIGA HOTELS',
|
256
|
+
'3545' => 'SHANGRI-LA INTERNATIONAL',
|
257
|
+
'3546' => 'SIERRA SUITES HOTELS',
|
258
|
+
'3550' => 'REGAL 8 INNS',
|
259
|
+
'3553' => 'PARKS INNS INTERNATIONAL',
|
260
|
+
'3558' => 'JOLLY HOTELS',
|
261
|
+
'3562' => 'COMFORT INNS',
|
262
|
+
'3563' => 'JOURNEY\'S END MOTELS',
|
263
|
+
'3565' => 'RELAX INNS',
|
264
|
+
'3568' => 'LADBROKE HOTELS',
|
265
|
+
'3570' => 'FORUM HOTELS',
|
266
|
+
'3573' => 'SANDMAN HOTELS',
|
267
|
+
'3574' => 'VENTURE INN',
|
268
|
+
'3575' => 'VAGABOND HOTELS',
|
269
|
+
'3581' => 'DELTA HOTELS',
|
270
|
+
'3583' => 'SAS HOTELS',
|
271
|
+
'3584' => 'PRINCESS HOTELS INTERNATIONAL',
|
272
|
+
'3587' => 'DORAL HOTELS',
|
273
|
+
'3588' => 'HELMSLEY HOTELS',
|
274
|
+
'3590' => 'FAIRMONT HOTELS',
|
275
|
+
'3591' => 'SONESTA HOTELS',
|
276
|
+
'3592' => 'OMNI HOTELS',
|
277
|
+
'3593' => 'CUNARD HOTELS',
|
278
|
+
'3595' => 'HOSPITALITY INNS',
|
279
|
+
'3598' => 'REGENT INT\'L HOTEL',
|
280
|
+
'3599' => 'PANNONIA HOTELS',
|
281
|
+
'3612' => 'MOVENPICK HOTELS',
|
282
|
+
'3615' => 'TRAVELODGE',
|
283
|
+
'3622' => 'MERLIN HOTEL GROUP',
|
284
|
+
'3623' => 'DORINT HOTELS',
|
285
|
+
'3629' => 'DAN HOTELS',
|
286
|
+
'3631' => 'SLEEP INN',
|
287
|
+
'3633' => 'RANK HOTELS',
|
288
|
+
'3635' => 'RESO HOTEL',
|
289
|
+
'3636' => 'SAROVA HOTELS',
|
290
|
+
'3637' => 'RAMADA INNS',
|
291
|
+
'3638' => 'HOWARD JOHNSON',
|
292
|
+
'3640' => 'HYATT HOTELS',
|
293
|
+
'3641' => 'SOFITEL HOTELS',
|
294
|
+
'3642' => 'NOVOTEL HOTELS',
|
295
|
+
'3643' => 'STEIGENBERGER HOTELS',
|
296
|
+
'3644' => 'ECONOLODGES',
|
297
|
+
'3646' => 'SWALLOW HOTELS',
|
298
|
+
'3647' => 'HUSA HOTELS',
|
299
|
+
'3648' => 'DE VERA HOTELS',
|
300
|
+
'3649' => 'RADISSON HOTELS',
|
301
|
+
'3650' => 'RED ROOF INNS',
|
302
|
+
'3652' => 'EMBASSY HOTELS',
|
303
|
+
'3664' => 'FLAG INNS',
|
304
|
+
'3665' => 'HAMPTON INN HOTELS',
|
305
|
+
'3668' => 'MARITIM HOTELS',
|
306
|
+
'3670' => 'ARCADE HOTELS',
|
307
|
+
'3678' => 'CUMULUS HOTELS',
|
308
|
+
'3681' => 'ADAMS MARK HOTELS',
|
309
|
+
'3683' => 'BRADBURY SUITES',
|
310
|
+
'3684' => 'BUDGET HOST INNS',
|
311
|
+
'3685' => 'BUDGETEL INNS',
|
312
|
+
'3687' => 'CLARION HOTELS',
|
313
|
+
'3688' => 'COMPRI HOTELS',
|
314
|
+
'3689' => 'CONSORT HOTELS',
|
315
|
+
'3690' => 'COURTYARD INNS',
|
316
|
+
'3692' => 'DOUBLETREE HOTELS',
|
317
|
+
'3694' => 'ECONOMY INNS OF AMERICA',
|
318
|
+
'3695' => 'EMBASSY SUITES',
|
319
|
+
'3696' => 'EXCEL INN',
|
320
|
+
'3697' => 'FAIRFIELD HOTELS',
|
321
|
+
'3698' => 'HARLEY HOTELS',
|
322
|
+
'3700' => 'MOTEL 6',
|
323
|
+
'3702' => 'THE REGISTRY HOTELS',
|
324
|
+
'3703' => 'RESIDENCE INN',
|
325
|
+
'3704' => 'ROYCE HOTELS',
|
326
|
+
'3705' => 'SANDMAN INN',
|
327
|
+
'3706' => 'SHILO INN',
|
328
|
+
'3707' => 'SHONEY\'S INN',
|
329
|
+
'3709' => 'SUPER 8 MOTELS',
|
330
|
+
'3710' => 'THE RITZ CARLTON',
|
331
|
+
'3715' => 'FAIRFIELD INN',
|
332
|
+
'3716' => 'CARLTON HOTELS',
|
333
|
+
'3717' => 'CITY LODGE HOTELS',
|
334
|
+
'3718' => 'KAROS HOTELS',
|
335
|
+
'3719' => 'PROTEA HOTELS',
|
336
|
+
'3720' => 'SOUTHERN SUN HOTELS',
|
337
|
+
'3721' => 'CONRAD HOTELS',
|
338
|
+
'3722' => 'WYNDHAM HOTELS',
|
339
|
+
'3727' => 'BROADMOOR HOTEL',
|
340
|
+
'3730' => 'MGM GRAND',
|
341
|
+
'3734' => 'HARVEY BRISTOL HOTELS',
|
342
|
+
'3735' => 'MASTERS ECONOMY INNS',
|
343
|
+
'3740' => 'TOWNEPLACE SUITES',
|
344
|
+
'3743' => 'BILTMORE HOTEL AND SUITES',
|
345
|
+
'3745' => 'ST REGIS HOTEL',
|
346
|
+
'3746' => 'ELIOT HOTELS',
|
347
|
+
'3748' => 'WELLESLEY INNS',
|
348
|
+
'3750' => 'CROWNE PLAZA HOTELS',
|
349
|
+
'3751' => 'HOMEWOOD SUITES',
|
350
|
+
'3752' => 'PEABODY HOTELS',
|
351
|
+
'3770' => 'SPRINGHILL SUITES',
|
352
|
+
'4121' => 'TAXICABS-LIMOUSINES',
|
353
|
+
'7011' => 'LODGING-HOTELS MOTELS RESORTS',
|
354
|
+
'5811' => 'CATERERS',
|
355
|
+
'5812' => 'EATING PLACES RESTAURANTS',
|
356
|
+
'5813' => 'DRINKING PLACES-BARS-TAVERNS-NITECLB-LOUNGE-DISCO',
|
357
|
+
'5814' => 'FAST FOOD RESTAURANTS (QUICK PAY SERVICE PILOT)',
|
358
|
+
'3000' => 'UNITED AIRLINES',
|
359
|
+
'3001' => 'AMERICAN AIRLINES',
|
360
|
+
'3002' => 'PAN AMERICAN',
|
361
|
+
'3004' => 'TRANS WORLD AIRLINES',
|
362
|
+
'3005' => 'BRITISH AIRWAYS BRITISH AWYS',
|
363
|
+
'3006' => 'JAPAN AIR LINES',
|
364
|
+
'3007' => 'AIR FRANCE',
|
365
|
+
'3008' => 'LUFTHANSA',
|
366
|
+
'3009' => 'AIR CANADA',
|
367
|
+
'3010' => 'ROYAL DUTCH AIRLINES (KLM)',
|
368
|
+
'3011' => 'AEROFLOT',
|
369
|
+
'3012' => 'QANTAS',
|
370
|
+
'3013' => 'ALITALIA',
|
371
|
+
'3014' => 'SAUDI ARABIAN AIRLINES',
|
372
|
+
'3015' => 'SWISSAIR',
|
373
|
+
'3016' => 'SCANDINAVIAN AIRLINE SYSTEM (SAS)',
|
374
|
+
'3017' => 'SOUTH AFRICAN AIRWAYS',
|
375
|
+
'3018' => 'VARIG (BRAZIL)',
|
376
|
+
'3020' => 'AIR INDIA',
|
377
|
+
'3021' => 'AIR ALGERIE',
|
378
|
+
'3022' => 'PHILIPPINE AIRLINES',
|
379
|
+
'3023' => 'MEXICANA',
|
380
|
+
'3024' => 'PAKISTAN INTERNATIONAL',
|
381
|
+
'3025' => 'AIR NEW ZEALAND LIMITED INTERNATIONAL',
|
382
|
+
'3026' => 'EMIRATES AIRLINES (ABBR. EMIRATES)',
|
383
|
+
'3027' => 'UNION DE TRANSPORTS AERIENS',
|
384
|
+
'3028' => 'AIR MALTA',
|
385
|
+
'3029' => 'SABENA',
|
386
|
+
'3030' => 'AEROLINEAS ARGENTINAS',
|
387
|
+
'3031' => 'OLYMPIC AIRWAYS',
|
388
|
+
'3032' => 'EL AL',
|
389
|
+
'3033' => 'ANSETT AIRLINES',
|
390
|
+
'3034' => 'AUSTRALIAN AIRWAYS (TAA)',
|
391
|
+
'3035' => 'TAP (PORTUGAL)',
|
392
|
+
'3036' => 'VASP (BRAZIL)',
|
393
|
+
'3037' => 'EGYPTAIR',
|
394
|
+
'3038' => 'KUWAIT AIRWAYS',
|
395
|
+
'3039' => 'AVIANCA',
|
396
|
+
'3040' => 'GULF AIR (BAHRAIN)',
|
397
|
+
'3041' => 'BALKAN-BULGARIAN AIRLINES',
|
398
|
+
'3042' => 'FINNAIR',
|
399
|
+
'3043' => 'AER LINGUS',
|
400
|
+
'3044' => 'AIR LANKA (ABBR. AIR LANKA)',
|
401
|
+
'3045' => 'NIGERIA AIRWAYS',
|
402
|
+
'3046' => 'CRUZERIO DO SUL (BRAZIL)',
|
403
|
+
'3047' => 'THY (TURKEY)',
|
404
|
+
'3048' => 'ROYAL AIR MAROC',
|
405
|
+
'3049' => 'TUNIS AIR',
|
406
|
+
'3050' => 'ICELANDAIR',
|
407
|
+
'3051' => 'AUSTRIAN AIRLINES',
|
408
|
+
'3052' => 'LAN-CHILE',
|
409
|
+
'3053' => 'AVIACO (SPAIN)',
|
410
|
+
'3054' => 'LADECO (CHILE)',
|
411
|
+
'3055' => 'LAB (BOLIVIA)',
|
412
|
+
'3056' => 'QUEBECAIRE',
|
413
|
+
'3057' => 'EAST-WEST AIRLINES (AUSTRALIA)',
|
414
|
+
'3058' => 'DELTA',
|
415
|
+
'3060' => 'NORTHWEST',
|
416
|
+
'3061' => 'CONTINENTAL',
|
417
|
+
'3063' => 'USAIRWAYS',
|
418
|
+
'3064' => 'ADRIA AIRWAYS (ABBR- ADRIA)',
|
419
|
+
'3065' => 'AIR INTER',
|
420
|
+
'3066' => 'SOUTHWEST AIRLINES',
|
421
|
+
'3067' => 'VANGUARD AIRLINES (ABBR- VANGUARD)',
|
422
|
+
'3071' => 'AIR BRITISH COLUMBIA',
|
423
|
+
'3075' => 'SINGAPORE AIRLINES',
|
424
|
+
'3076' => 'AEROMEXICO',
|
425
|
+
'3077' => 'THAI AIRWAYS',
|
426
|
+
'3078' => 'CHINA AIRLINES',
|
427
|
+
'3081' => 'NORDAIR',
|
428
|
+
'3082' => 'KOREAN AIRLINES',
|
429
|
+
'3083' => 'AIR AFRIQUE (RK)',
|
430
|
+
'3084' => 'EVA AIRWAYS (BR)',
|
431
|
+
'3085' => 'MIDWEST EXPRESS AIRLINES',
|
432
|
+
'3086' => 'CARNIVAL AIRLINES (KW)',
|
433
|
+
'3087' => 'METRO AIRLINES',
|
434
|
+
'3088' => 'CROATIA AIR',
|
435
|
+
'3089' => 'TRANSAERO (ABBR. TRANSAERO)',
|
436
|
+
'3090' => 'UNI AIRWAYS',
|
437
|
+
'3092' => 'MIDWAY AIRLINES',
|
438
|
+
'3094' => 'ZAMBIA AIRWAYS',
|
439
|
+
'3095' => 'WARDAIR (CANADA)',
|
440
|
+
'3096' => 'AIR ZIMBABWE',
|
441
|
+
'3097' => 'SPANAIR',
|
442
|
+
'3098' => 'ASIANA AIRLINES',
|
443
|
+
'3099' => 'CATHAY PACIFIC',
|
444
|
+
'3100' => 'MALAYSIAN AIRLINE SYSTEM',
|
445
|
+
'3102' => 'IBERIA',
|
446
|
+
'3103' => 'GARUDA (INDONESIA)',
|
447
|
+
'3106' => 'BRAATHENS S.A.F.E. (NORWAY)',
|
448
|
+
'3110' => 'WINGS AIRWAYS',
|
449
|
+
'3111' => 'BRITISH MIDLAND',
|
450
|
+
'3112' => 'WINDWARD ISLAND',
|
451
|
+
'3115' => 'TOWER AIR',
|
452
|
+
'3117' => 'VENEZOLANA INTERNATIONAL DE AVIACION (VIASA)',
|
453
|
+
'3118' => 'VALLEY AIRLINES',
|
454
|
+
'3125' => 'TAN AIRLINES',
|
455
|
+
'3126' => 'TALAIR',
|
456
|
+
'3127' => 'TACA INTERNATIONAL',
|
457
|
+
'3129' => 'SURINAM AIRWAYS',
|
458
|
+
'3130' => 'SUNWORLD INTERNATIONAL AIRWAYS',
|
459
|
+
'3133' => 'SUNBELT AIRLINES',
|
460
|
+
'3135' => 'SUDAN AIRWAYS',
|
461
|
+
'3137' => 'SINGLETON AIR',
|
462
|
+
'3138' => 'SIMMONS AIRLINES',
|
463
|
+
'3143' => 'SCENIC AIRLINES',
|
464
|
+
'3144' => 'VIRGIN ATLANTIC',
|
465
|
+
'3145' => 'SAN JUAN AIRLINES',
|
466
|
+
'3146' => 'LUXAIR',
|
467
|
+
'3151' => 'AIR ZAIRE',
|
468
|
+
'3154' => 'PRINCEVILLE',
|
469
|
+
'3159' => 'PROVINCETOWN-BOSTON AIRWAYS (PBA)',
|
470
|
+
'3161' => 'ALL NIPPON AIRWAYS',
|
471
|
+
'3164' => 'NORONTAIR',
|
472
|
+
'3165' => 'NEW YORK HELICOPTER',
|
473
|
+
'3170' => 'MOUNT COOK',
|
474
|
+
'3171' => 'CANADIAN AIRLINES',
|
475
|
+
'3172' => 'NATION AIR',
|
476
|
+
'3175' => 'MIDDLE EAST AIR',
|
477
|
+
'3176' => 'METROFLIGHT AIRLINES',
|
478
|
+
'3178' => 'MESA AIR',
|
479
|
+
'3181' => 'MALEV HUNGARIAN AIRLINES',
|
480
|
+
'3182' => 'LOT - POLISH AIRLINES',
|
481
|
+
'3184' => 'LIAT',
|
482
|
+
'3185' => 'LAV LINEA AEROPOSTAL VENEZOLANA',
|
483
|
+
'3186' => 'LAP LINEAS AEREAS PARAGUAYAS',
|
484
|
+
'3187' => 'LACSA (COSTA RICA)',
|
485
|
+
'3190' => 'JUGOSLAV AIR',
|
486
|
+
'3191' => 'ISLAND AIRLINES',
|
487
|
+
'3192' => 'IRAN AIR',
|
488
|
+
'3193' => 'INDIAN AIRLINES',
|
489
|
+
'3196' => 'HAWAIIAN AIR',
|
490
|
+
'3197' => 'HAVASU AIRLINES',
|
491
|
+
'3200' => 'GUYANA AIRWAYS',
|
492
|
+
'3203' => 'GOLDEN PACIFIC AIR',
|
493
|
+
'3204' => 'FREEDOM AIRLINES',
|
494
|
+
'3206' => 'CHINA EASTERN AIRLINES (ABBR- CHINEASTAIR)',
|
495
|
+
'3212' => 'DOMINICANA DE AVIACION',
|
496
|
+
'3215' => 'DAN AIR SERVICES',
|
497
|
+
'3216' => 'CUMBERLAND AIRLINES',
|
498
|
+
'3217' => 'CSA CESKOSLOVENSKE AEROLINIE',
|
499
|
+
'3218' => 'CROWN AIR',
|
500
|
+
'3219' => 'COMPANIA PANAMENA DE AVIACION (COPA)',
|
501
|
+
'3220' => 'COMPANIA FAUCETT',
|
502
|
+
'3221' => 'TRANSPORTES AEREOS MILITARES ECUATORIANOS',
|
503
|
+
'3222' => 'COMMAND AIRWAYS',
|
504
|
+
'3223' => 'COMAIR',
|
505
|
+
'3228' => 'CAYMAN AIRWAYS',
|
506
|
+
'3229' => 'SAETA (SOCIEDAD ECUATORIANAS DE TRANSPORTES AEREO)',
|
507
|
+
'3231' => 'SAHSA (SERVICIO AERO DE HONDURAS)',
|
508
|
+
'3233' => 'CAPITOL AIR',
|
509
|
+
'3234' => 'BWIA INTERNATIONAL',
|
510
|
+
'3235' => 'BROCKWAY AIR',
|
511
|
+
'3238' => 'BEMIDJI AVIATION',
|
512
|
+
'3239' => 'BAR HARBOR AIRLINES',
|
513
|
+
'3240' => 'BAHAMASAIR',
|
514
|
+
'3241' => 'AVIATECA (GUATEMALA)',
|
515
|
+
'3242' => 'AVENSA',
|
516
|
+
'3243' => 'AUSTRIAN AIR SERVICE',
|
517
|
+
'3251' => 'ALOHA AIRLINES',
|
518
|
+
'3252' => 'ALM ANTILEAN AIRLINES',
|
519
|
+
'3253' => 'AMERICA WEST',
|
520
|
+
'3254' => 'US AIR SHUTTLE',
|
521
|
+
'3256' => 'ALASKA AIRLINES INC.',
|
522
|
+
'3259' => 'AMERICAN TRANS AIR ATA AIR',
|
523
|
+
'3261' => 'AIR CHINA',
|
524
|
+
'3262' => 'RENO AIR INC.',
|
525
|
+
'3263' => 'AERO SERVICIO CARABOBO',
|
526
|
+
'3266' => 'AIR SEYCHELLES',
|
527
|
+
'3267' => 'AIR PANAMA INTERNATIONAL',
|
528
|
+
'3280' => 'AIR JAMAICA',
|
529
|
+
'3282' => 'AIR DJIBOUTI',
|
530
|
+
'3284' => 'AERO VIRGIN ISLANDS',
|
531
|
+
'3285' => 'AERO PERU',
|
532
|
+
'3286' => 'AERO.NICARAGUENSES',
|
533
|
+
'3287' => 'AERO COACH AVIATION',
|
534
|
+
'3292' => 'CYPRUS AIRWAYS',
|
535
|
+
'3293' => 'EQUATORIANA',
|
536
|
+
'3294' => 'ETHIOPIAN AIRLINES',
|
537
|
+
'3295' => 'KENYA AIRWAYS',
|
538
|
+
'3297' => 'TAROM ROMANIAN AIR TRANSPORT',
|
539
|
+
'3298' => 'AIR MAURITIUS',
|
540
|
+
'3299' => 'WIDEROE\'S FLYVESELSKAP',
|
541
|
+
'3351' => 'AFFILIATED AUTO RENTAL',
|
542
|
+
'3352' => 'AMERICAN INT\'L',
|
543
|
+
'3353' => 'BROOKS RENT A CAR',
|
544
|
+
'3354' => 'ACTION AUTO RENTAL',
|
545
|
+
'3357' => 'HERTZ CORPORATION',
|
546
|
+
'3359' => 'PAYLESS CAR RENTAL',
|
547
|
+
'3360' => 'SNAPPY CAR RENTAL',
|
548
|
+
'3361' => 'AIRWAYS RENT-A-CAR',
|
549
|
+
'3362' => 'ALTRA AUTO RENTAL',
|
550
|
+
'3364' => 'AGENCY RENT-A-CAR',
|
551
|
+
'3366' => 'BUDGET RENT-A-CAR',
|
552
|
+
'3368' => 'HOLIDAY RENT-A-CAR',
|
553
|
+
'3370' => 'RENT A WRECK',
|
554
|
+
'3376' => 'AJAX RENT-A-CAR',
|
555
|
+
'3380' => 'TRIANGLE RENT A CAR',
|
556
|
+
'3381' => 'EUROPE CAR',
|
557
|
+
'3385' => 'TROPICAL RENT-A-CAR',
|
558
|
+
'3386' => 'SHOWCASE RENTAL CARS',
|
559
|
+
'3387' => 'ALAMO RENT-A-CAR',
|
560
|
+
'3389' => 'AVIS RENT A CAR',
|
561
|
+
'3390' => 'DOLLAR RENT A CAR',
|
562
|
+
'3391' => 'EUROPE BY CAR',
|
563
|
+
'3393' => 'NATIONAL CAR RENTAL',
|
564
|
+
'3394' => 'KEMWELL GROUP RENT-A-CAR',
|
565
|
+
'3395' => 'THRIFTY CAR RENTAL',
|
566
|
+
'3396' => 'TILDEN RENT-A-CAR',
|
567
|
+
'3398' => 'ECONO-CAR RENT-A-CAR',
|
568
|
+
'3400' => 'AUTO HOST CAR RENTAL',
|
569
|
+
'3405' => 'ENTERPRISE RENT-A-CAR',
|
570
|
+
'3409' => 'GENERAL RENT-A-CAR',
|
571
|
+
'3412' => 'A1 RENT-A-CAR',
|
572
|
+
'3414' => 'GODFREY NATIONAL RENT-A-CAR',
|
573
|
+
'3420' => 'ANSA INTERNATIONAL',
|
574
|
+
'3421' => 'ALLSTATE RENT-A-CAR',
|
575
|
+
'3423' => 'AVCAR RENT-A-CAR',
|
576
|
+
'3425' => 'AUTOMATE RENT-A-CAR',
|
577
|
+
'3427' => 'AVON RENT-A-CAR',
|
578
|
+
'3428' => 'CAREY RENT-A-CAR',
|
579
|
+
'3429' => 'INSURANCE RENT-A-CAR',
|
580
|
+
'3430' => 'MAJOR RENT A CAR',
|
581
|
+
'3431' => 'REPLACEMENT RENT-A-CAR',
|
582
|
+
'3432' => 'RESERVE RENT-A-CAR',
|
583
|
+
'3433' => 'UGLY DUCKLING RENT-A-CAR',
|
584
|
+
'3434' => 'USA RENT-A-CAR',
|
585
|
+
'3435' => 'VALUE RENT-A-CAR',
|
586
|
+
'3436' => 'AUTOHANSA RENT-A-CAR',
|
587
|
+
'3437' => 'CITE RENT-A-CAR',
|
588
|
+
'3438' => 'INTERENT RENT-A-CAR',
|
589
|
+
'3439' => 'MILLEVILLE RENT-A-CAR',
|
590
|
+
'3441' => 'ADVANTAGE RENT A CAR',
|
591
|
+
'4011' => 'RAILROADS',
|
592
|
+
'4111' => 'LOCAL + SUBURBAN PASS TRANSPORTATION INCL FERRIES',
|
593
|
+
'4112' => 'PASSENGER RAILWAYS',
|
594
|
+
'4119' => 'AMBULANCE SERVICES',
|
595
|
+
'4131' => 'BUS LINES',
|
596
|
+
'4225' => 'PUBLIC WAREHOUSING-FARM REFRIG GOODS HHG STORAGE',
|
597
|
+
'4411' => 'CRUISE LINES',
|
598
|
+
'4457' => 'BOAT RENTALS AND BOAT LEASES',
|
599
|
+
'4511' => 'AIRLINES AIR CARRIERS',
|
600
|
+
'4582' => 'AIRPORTS FLYING FIELDS AIRPORT TERMINALS',
|
601
|
+
'4722' => 'TRAVEL AGENCIES AND TOUR OPERATORS',
|
602
|
+
'4784' => 'TOLLS ROAD AND BRIDGE FEES',
|
603
|
+
'4789' => 'TRANSPORTATION SERVICES NOT ELSEWHERE CLASSIFIED',
|
604
|
+
'4829' => 'WIRE TRANSFER MONEY ORDERS (WTMOS)',
|
605
|
+
'5271' => 'MOBILE HOME DEALERS',
|
606
|
+
'5309' => 'DUTY FREE STORES',
|
607
|
+
'5521' => 'AUTO + TRUCK DLRS USED ONLY-SALES',
|
608
|
+
'5542' => 'AUTOMATED FUEL DISPENSER',
|
609
|
+
'5592' => 'MOTOR HOME DEALERS',
|
610
|
+
'5681' => 'FURRIERS AND FUR SHOPS',
|
611
|
+
'5921' => 'PACKAGE STORES BEER WINE LIQUOR',
|
612
|
+
'5960' => 'DIRECT MARKETING-INSURANCE SERVICES',
|
613
|
+
'5962' => 'DIRECT MARKETING-TRAVEL RELATED ARRANGEMENT SERVS.',
|
614
|
+
'5963' => 'DOOR-TO-DOOR SALES',
|
615
|
+
'5972' => 'STAMP + COIN STORES-PHILATELIC + NUMISMATIC SUPPLY',
|
616
|
+
'5993' => 'CIGAR STORES AND STANDS',
|
617
|
+
'6010' => 'FINANCIAL INSTITUTIONS-MANUAL CASH DISBURSEMENTS',
|
618
|
+
'6011' => 'FINANCIAL INSTITUTIONS-AUTOMATED CASH DISBURSEMENT',
|
619
|
+
'6012' => 'FINANCIAL INSTITUTIONS-MERCHANDISE SERVICES',
|
620
|
+
'6022' => 'FINANCIAL INSTITUTION (RCL INTERNAL)',
|
621
|
+
'6023' => 'STATE BANKS (RCL INTERNAL)',
|
622
|
+
'6025' => 'NATIONAL BANKS (RCL INTERNAL)',
|
623
|
+
'6026' => 'NATIONAL BANKS NON FEDERAL (RCL INTERNAL)',
|
624
|
+
'6028' => 'UNICORPORATED PRIVATE BANKS (RCL INTERNAL)',
|
625
|
+
'6051' => 'NON-FINANCIAL INST-FORN CURR-MO-TC',
|
626
|
+
'6211' => 'SECURITIES-BROKERS-DEALERS',
|
627
|
+
'6300' => 'INSURANCE SALES UNDERWRITING AND PREMIUMS',
|
628
|
+
'6381' => 'INSURANCE PREMIUMS',
|
629
|
+
'6399' => 'INSURANCE-CARRIERS NOT ELSEWHERE CLASSIFIED',
|
630
|
+
'7012' => 'TIMESHARES',
|
631
|
+
'7261' => 'FUNERAL SERVICE AND CREMATORIES',
|
632
|
+
'7273' => 'DATING AND ESCORT SERVICES',
|
633
|
+
'7276' => 'TAX PREPARATION SERVICE',
|
634
|
+
'7277' => 'COUNSELING SERVICE-DEBT MARRIAGE PERSONAL',
|
635
|
+
'7297' => 'MASSAGE PARLORS',
|
636
|
+
'7298' => 'HEALTH AND BEAUTY SPAS',
|
637
|
+
'7321' => 'CONSUMER CREDIT REPORTING AGENCIES',
|
638
|
+
'7511' => 'TRUCK STOP TRANSACTIONS',
|
639
|
+
'7512' => 'AUTOMOBILE RENTAL AND LEASING',
|
640
|
+
'7531' => 'AUTOMOTIVE BODY REPAIR SHOPS',
|
641
|
+
'7534' => 'TIRE RETREADING AND REPAIR SHOPS',
|
642
|
+
'7535' => 'AUTOMOTIVE PAINT SHOPS',
|
643
|
+
'7538' => 'AUTOMOTIVE SERVICE SHOPS',
|
644
|
+
'7932' => 'BILLIARD AND POOL ESTABLISHMENTS',
|
645
|
+
'7994' => 'VIDEO GAME ARCADES-ESTABLISHMENTS',
|
646
|
+
'7995' => 'BETTING-INCL LOTTERY GAMING CHIPS TRACK WAGERS',
|
647
|
+
'7996' => 'AMUSEMENT PARKS CIRCUSES CARNIVALS FORTUNE TLR',
|
648
|
+
'8011' => 'DOCTORS (NOT ELSEWHERE CLASSIFIED)',
|
649
|
+
'8021' => 'DENTISTS ORTHODONTISTS',
|
650
|
+
'8031' => 'OSTEOPATHIC PHYSICIANS',
|
651
|
+
'8041' => 'CHIROPRACTORS',
|
652
|
+
'8042' => 'OPTOMETRISTS OPHTHALMOLOGISTS',
|
653
|
+
'8049' => 'CHIROPODISTS PODIATRISTS',
|
654
|
+
'8050' => 'NURSING AND PERSONAL CARE FACILITIES',
|
655
|
+
'8111' => 'LEGAL SERVICES ATTORNEYS',
|
656
|
+
'8351' => 'CHILD CARE SERVICES',
|
657
|
+
'8651' => 'POLITICAL ORGANIZATIONS',
|
658
|
+
'8661' => 'RELIGIOUS ORGANIZATIONS',
|
659
|
+
'8675' => 'AUTOMOBILE ASSOCIATIONS',
|
660
|
+
'9211' => 'COURT COSTS INCLUDING ALIMONY AND CHILD SUPPORT',
|
661
|
+
'9222' => 'FINES',
|
662
|
+
'9223' => 'BAIL AND BOND PAYMENTS',
|
663
|
+
'9311' => 'TAX PAYMENTS',
|
664
|
+
'9401' => 'FOOD STAMPS',
|
665
|
+
'9751' => 'UK SUPERMARKETS ELECTRONIC HOT FILE',
|
666
|
+
'9752' => 'UK PETROLS STATIONS ELECTRONIC HOT FILE',
|
667
|
+
'9999' => 'MCC Invalid'
|
668
|
+
}.freeze
|
669
|
+
end
|
670
|
+
end
|
data/lib/ofx-parser.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hpricot'
|
3
|
+
require 'time'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
%w[ofx mcc].each do |fn|
|
7
|
+
require File.dirname(__FILE__) + "/#{fn}"
|
8
|
+
end
|
9
|
+
|
10
|
+
module OfxParser
|
11
|
+
class OfxParser
|
12
|
+
# Creates and returns an Ofx instance when given a well-formed OFX document,
|
13
|
+
# complete with the mandatory key:pair header.
|
14
|
+
def self.parse(ofx)
|
15
|
+
ofx = ofx.respond_to?(:read) ? ofx.read.to_s : ofx.to_s
|
16
|
+
|
17
|
+
return Ofx.new if ofx == ''
|
18
|
+
|
19
|
+
header, body = pre_process(ofx)
|
20
|
+
|
21
|
+
ofx_out = parse_body(body)
|
22
|
+
ofx_out.header = header
|
23
|
+
ofx_out
|
24
|
+
end
|
25
|
+
|
26
|
+
# Designed to make the main OFX body parsable. This means adding closing tags
|
27
|
+
# to the SGML to make it parsable by hpricot.
|
28
|
+
#
|
29
|
+
# Returns an array of 2 elements:
|
30
|
+
# * header as a hash,
|
31
|
+
# * body as an evily pre-processed string ready for parsing by hpricot.
|
32
|
+
def self.pre_process(ofx)
|
33
|
+
header, body = ofx.split(/\n{2,}|:?<OFX>/, 2)
|
34
|
+
|
35
|
+
header = begin
|
36
|
+
Hash[*header.gsub(/^\r?\n+/, '').split(/\r\n/).collect do |e|
|
37
|
+
e.split(/:/, 2)
|
38
|
+
end.flatten]
|
39
|
+
rescue
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
body.gsub!(/>\s+</m, '><')
|
44
|
+
body.gsub!(/\s+</m, '<')
|
45
|
+
body.gsub!(/>\s+/m, '>')
|
46
|
+
body.gsub!(/<([^>]+?)>([^<]+)/m, '<\1>\2</\1>')
|
47
|
+
|
48
|
+
[header, body]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Takes an OFX datetime string of the format:
|
52
|
+
# * YYYYMMDDHHMMSS.XXX[gmt offset:tz name]
|
53
|
+
# * YYYYMMDD
|
54
|
+
# * YYYYMMDDHHMMSS
|
55
|
+
# * YYYYMMDDHHMMSS.XXX
|
56
|
+
#
|
57
|
+
# Returns a DateTime object. Milliseconds (XXX) are ignored.
|
58
|
+
def self.parse_datetime(date)
|
59
|
+
DateTime.parse(date)
|
60
|
+
rescue
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def self.parse_body(body)
|
67
|
+
doc = Hpricot.XML(body)
|
68
|
+
|
69
|
+
ofx = Ofx.new
|
70
|
+
|
71
|
+
ofx.sign_on = build_signon((doc / 'SIGNONMSGSRSV1/SONRS'))
|
72
|
+
ofx.signup_account_info = build_info((doc / 'SIGNUPMSGSRSV1/ACCTINFOTRNRS'))
|
73
|
+
|
74
|
+
# Bank Accounts
|
75
|
+
bank_fragment = (doc / 'BANKMSGSRSV1/STMTTRNRS')
|
76
|
+
ofx.bank_accounts = bank_fragment.collect do |fragment|
|
77
|
+
build_bank(fragment)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Credit Cards
|
81
|
+
credit_card_fragment = (doc / 'CREDITCARDMSGSRSV1/CCSTMTTRNRS')
|
82
|
+
ofx.credit_accounts = credit_card_fragment.collect do |fragment|
|
83
|
+
build_credit(fragment)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Investments (?)
|
87
|
+
# build_investment((doc/"SIGNONMSGSRQV1"))
|
88
|
+
|
89
|
+
ofx
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.build_signon(doc)
|
93
|
+
sign_on = SignOn.new
|
94
|
+
sign_on.status = build_status((doc / 'STATUS'))
|
95
|
+
sign_on.date = parse_datetime((doc / 'DTSERVER').inner_text)
|
96
|
+
sign_on.language = (doc / 'LANGUAGE').inner_text
|
97
|
+
|
98
|
+
sign_on.institute = Institute.new
|
99
|
+
sign_on.institute.name = ((doc / 'FI') / 'ORG').inner_text
|
100
|
+
sign_on.institute.id = ((doc / 'FI') / 'FID').inner_text
|
101
|
+
sign_on
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.build_info(doc)
|
105
|
+
account_infos = []
|
106
|
+
|
107
|
+
(doc / 'ACCTINFO').each do |info_doc|
|
108
|
+
acc_info = AccountInfo.new
|
109
|
+
acc_info.desc = (info_doc / 'DESC').inner_text
|
110
|
+
acc_info.number = (info_doc / 'ACCTID').first.inner_text
|
111
|
+
acc_info.bank_id = (info_doc / 'BANKID').first.inner_text unless (info_doc / 'BANKID').empty?
|
112
|
+
acc_info.type = (info_doc / 'ACCTTYPE').first.inner_text unless (info_doc / 'ACCTTYPE').empty?
|
113
|
+
account_infos << acc_info
|
114
|
+
end
|
115
|
+
|
116
|
+
account_infos
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.build_bank(doc)
|
120
|
+
acct = BankAccount.new
|
121
|
+
|
122
|
+
acct.transaction_uid = (doc / 'TRNUID').inner_text.strip
|
123
|
+
acct.number = (doc / 'STMTRS/BANKACCTFROM/ACCTID').inner_text
|
124
|
+
acct.routing_number = (doc / 'STMTRS/BANKACCTFROM/BANKID').inner_text
|
125
|
+
acct.branch_number = (doc / 'STMTRS/BANKACCTFROM/BRANCHID').inner_text
|
126
|
+
acct.type = (doc / 'STMTRS/BANKACCTFROM/ACCTTYPE').inner_text.strip
|
127
|
+
acct.balance = (doc / 'STMTRS/LEDGERBAL/BALAMT').inner_text
|
128
|
+
acct.balance_date = parse_datetime((doc / 'STMTRS/LEDGERBAL/DTASOF').inner_text)
|
129
|
+
|
130
|
+
statement = Statement.new
|
131
|
+
statement.currency = (doc / 'STMTRS/CURDEF').inner_text
|
132
|
+
statement.start_date = parse_datetime((doc / 'STMTRS/BANKTRANLIST/DTSTART').inner_text)
|
133
|
+
statement.end_date = parse_datetime((doc / 'STMTRS/BANKTRANLIST/DTEND').inner_text)
|
134
|
+
acct.statement = statement
|
135
|
+
|
136
|
+
statement.transactions = (doc / 'STMTRS/BANKTRANLIST/STMTTRN').collect do |t|
|
137
|
+
build_transaction(t)
|
138
|
+
end
|
139
|
+
|
140
|
+
acct
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.build_credit(doc)
|
144
|
+
acct = CreditAccount.new
|
145
|
+
|
146
|
+
acct.number = (doc / 'CCSTMTRS/CCACCTFROM/ACCTID').inner_text
|
147
|
+
acct.transaction_uid = (doc / 'TRNUID').inner_text.strip
|
148
|
+
acct.balance = (doc / 'CCSTMTRS/LEDGERBAL/BALAMT').inner_text
|
149
|
+
acct.balance_date = parse_datetime((doc / 'CCSTMTRS/LEDGERBAL/DTASOF').inner_text)
|
150
|
+
acct.remaining_credit = (doc / 'CCSTMTRS/AVAILBAL/BALAMT').inner_text
|
151
|
+
acct.remaining_credit_date = parse_datetime((doc / 'CCSTMTRS/AVAILBAL/DTASOF').inner_text)
|
152
|
+
|
153
|
+
statement = Statement.new
|
154
|
+
statement.currency = (doc / 'CCSTMTRS/CURDEF').inner_text
|
155
|
+
statement.start_date = parse_datetime((doc / 'CCSTMTRS/BANKTRANLIST/DTSTART').inner_text)
|
156
|
+
statement.end_date = parse_datetime((doc / 'CCSTMTRS/BANKTRANLIST/DTEND').inner_text)
|
157
|
+
acct.statement = statement
|
158
|
+
|
159
|
+
statement.transactions = (doc / 'CCSTMTRS/BANKTRANLIST/STMTTRN').collect do |t|
|
160
|
+
build_transaction(t)
|
161
|
+
end
|
162
|
+
|
163
|
+
acct
|
164
|
+
end
|
165
|
+
|
166
|
+
# for credit and bank transactions.
|
167
|
+
def self.build_transaction(t)
|
168
|
+
transaction = Transaction.new
|
169
|
+
transaction.type = (t / 'TRNTYPE').inner_text
|
170
|
+
transaction.date = parse_datetime((t / 'DTPOSTED').inner_text)
|
171
|
+
transaction.date_initiated = parse_datetime((t / 'DTUSER').inner_text) unless (t / 'DTUSER').inner_text.empty?
|
172
|
+
transaction.amount = (t / 'TRNAMT').inner_text
|
173
|
+
transaction.fit_id = (t / 'FITID').inner_text
|
174
|
+
transaction.payee = (t / 'PAYEE').inner_text + (t / 'NAME').inner_text
|
175
|
+
transaction.memo = (t / 'MEMO').inner_text
|
176
|
+
transaction.sic = (t / 'SIC').inner_text
|
177
|
+
transaction.check_number = (t / 'CHECKNUM').inner_text unless (t / 'CHECKNUM').inner_text.empty?
|
178
|
+
transaction
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.build_investment(_doc); end
|
182
|
+
|
183
|
+
def self.build_status(doc)
|
184
|
+
status = Status.new
|
185
|
+
status.code = (doc / 'CODE').inner_text
|
186
|
+
status.severity = (doc / 'SEVERITY').inner_text
|
187
|
+
status.message = (doc / 'MESSAGE').inner_text
|
188
|
+
status
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
data/lib/ofx.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
module OfxParser
|
2
|
+
module MonetaryClassSupport
|
3
|
+
attr_accessor :monies
|
4
|
+
|
5
|
+
def monetary_vars(*methods) #:nodoc:
|
6
|
+
self.monies ||= []
|
7
|
+
self.monies += methods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module MonetarySupport
|
12
|
+
# Returns pennies for a given string amount, i.e:
|
13
|
+
# '-.45' => -45
|
14
|
+
# '-123.45' => -12345
|
15
|
+
# '123' => 12300
|
16
|
+
def pennies_for(amount)
|
17
|
+
return nil if amount == ''
|
18
|
+
int, fraction = amount.scan(/\d+/)
|
19
|
+
if amount =~ /^-?\./
|
20
|
+
fraction = int
|
21
|
+
int = 0
|
22
|
+
end
|
23
|
+
i = fraction.to_s.strip =~ /[1-9]/ ? "#{int}#{fraction[0, 2]}".to_i : int.to_i * 100
|
24
|
+
amount =~ /^\s*-\s*.?\d+/ ? -i : i
|
25
|
+
end
|
26
|
+
|
27
|
+
def original_method(meth) #:nodoc:
|
28
|
+
meth.to_s.sub('_in_pennies', '').to_sym
|
29
|
+
rescue
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def monetary_method_call?(meth) #:nodoc:
|
34
|
+
orig = original_method(meth)
|
35
|
+
self.class.monies.include?(orig) && meth.to_s == "#{orig}_in_pennies"
|
36
|
+
end
|
37
|
+
|
38
|
+
def method_missing(meth, *args) #:nodoc:
|
39
|
+
if monetary_method_call?(meth)
|
40
|
+
pennies_for(send(original_method(meth)))
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def respond_to?(meth) #:nodoc:
|
47
|
+
monetary_method_call?(meth) ? true : super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# This class is returned when a parse is successful.
|
52
|
+
# == General Notes
|
53
|
+
# * currency symbols are an iso4217 3-letter code
|
54
|
+
# * language is defined by iso639 3-letter code
|
55
|
+
class Ofx
|
56
|
+
attr_accessor :header, :sign_on, :signup_account_info,
|
57
|
+
:bank_accounts, :credit_accounts,
|
58
|
+
:investment_accounts
|
59
|
+
|
60
|
+
def accounts
|
61
|
+
[bank_accounts, credit_accounts, investment_accounts].flatten!.compact!
|
62
|
+
end
|
63
|
+
|
64
|
+
def bank_account #:nodoc:
|
65
|
+
warn 'DEPRECATION WARNING: bank_account() is deprecated and may be removed from future releases, use bank_accounts() instead.'
|
66
|
+
bank_accounts.first
|
67
|
+
end
|
68
|
+
|
69
|
+
def credit_card #:nodoc:
|
70
|
+
warn 'DEPRECATION WARNING: credit_card() is deprecated and may be removed from future releases, use credit_accounts() instead.'
|
71
|
+
credit_accounts.first
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class SignOn
|
76
|
+
attr_accessor :status, :date, :language, :institute
|
77
|
+
end
|
78
|
+
|
79
|
+
class AccountInfo
|
80
|
+
attr_accessor :desc, :number, :bank_id, :type
|
81
|
+
end
|
82
|
+
|
83
|
+
class Account
|
84
|
+
attr_accessor :number, :statement, :transaction_uid, :routing_number
|
85
|
+
end
|
86
|
+
|
87
|
+
class BankAccount < Account
|
88
|
+
TYPE = %i[CHECKING SAVINGS MONEYMRKT CREDITLINE].freeze
|
89
|
+
attr_accessor :type, :balance, :balance_date, :branch_number
|
90
|
+
|
91
|
+
include MonetarySupport
|
92
|
+
extend MonetaryClassSupport
|
93
|
+
monetary_vars :balance
|
94
|
+
|
95
|
+
undef type
|
96
|
+
def type
|
97
|
+
@type.to_s.upcase.to_sym
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class CreditAccount < Account
|
102
|
+
attr_accessor :remaining_credit, :remaining_credit_date, :balance, :balance_date
|
103
|
+
|
104
|
+
include MonetarySupport
|
105
|
+
extend MonetaryClassSupport
|
106
|
+
monetary_vars :remaining_credit, :balance
|
107
|
+
end
|
108
|
+
|
109
|
+
class InvestmentAccount < Account
|
110
|
+
attr_accessor :broker_id, :positions, :margin_balance, :short_balance, :cash_balance
|
111
|
+
|
112
|
+
include MonetarySupport
|
113
|
+
extend MonetaryClassSupport
|
114
|
+
monetary_vars :margin_balance, :short_balance, :cash_balance
|
115
|
+
end
|
116
|
+
|
117
|
+
class Statement
|
118
|
+
attr_accessor :currency, :transactions, :start_date, :end_date
|
119
|
+
end
|
120
|
+
|
121
|
+
class Transaction
|
122
|
+
attr_accessor :type, :date, :date_initiated, :amount, :fit_id, :check_number, :sic, :memo, :payee
|
123
|
+
|
124
|
+
include MonetarySupport
|
125
|
+
extend MonetaryClassSupport
|
126
|
+
monetary_vars :amount
|
127
|
+
|
128
|
+
TYPE = {
|
129
|
+
CREDIT: 'Generic credit',
|
130
|
+
DEBIT: 'Generic debit',
|
131
|
+
INT: 'Interest earned or paid ',
|
132
|
+
DIV: 'Dividend',
|
133
|
+
FEE: 'FI fee',
|
134
|
+
SRVCHG: 'Service charge',
|
135
|
+
DEP: 'Deposit',
|
136
|
+
ATM: 'ATM debit or credit',
|
137
|
+
POS: 'Point of sale debit or credit ',
|
138
|
+
XFER: 'Transfer',
|
139
|
+
CHECK: 'Check',
|
140
|
+
PAYMENT: 'Electronic payment',
|
141
|
+
CASH: 'Cash withdrawal',
|
142
|
+
DIRECTDEP: 'Direct deposit',
|
143
|
+
DIRECTDEBIT: 'Merchant initiated debit',
|
144
|
+
REPEATPMT: 'Repeating payment/standing order',
|
145
|
+
OTHER: 'Other'
|
146
|
+
}.freeze
|
147
|
+
|
148
|
+
def type_desc
|
149
|
+
TYPE[type]
|
150
|
+
end
|
151
|
+
|
152
|
+
undef type
|
153
|
+
def type
|
154
|
+
@type.to_s.strip.upcase.to_sym
|
155
|
+
end
|
156
|
+
|
157
|
+
undef sic
|
158
|
+
def sic
|
159
|
+
@sic == '' ? nil : @sic
|
160
|
+
end
|
161
|
+
|
162
|
+
def sic_desc
|
163
|
+
Mcc::CODES[sic]
|
164
|
+
end
|
165
|
+
|
166
|
+
def eql?(other)
|
167
|
+
fit_id == other.fit_id
|
168
|
+
end
|
169
|
+
|
170
|
+
def hash
|
171
|
+
fit_id.hash
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class Position
|
176
|
+
end
|
177
|
+
|
178
|
+
# Status of a sign on
|
179
|
+
class Status
|
180
|
+
attr_accessor :code, :severity, :message
|
181
|
+
|
182
|
+
CODES = {
|
183
|
+
'0' => 'Success',
|
184
|
+
'2000' => 'General error',
|
185
|
+
'15000' => 'Must change USERPASS',
|
186
|
+
'15500' => 'Signon invalid',
|
187
|
+
'15501' => 'Customer account already in use',
|
188
|
+
'15502' => 'USERPASS Lockout'
|
189
|
+
}.freeze
|
190
|
+
|
191
|
+
def code_desc
|
192
|
+
CODES[code]
|
193
|
+
end
|
194
|
+
|
195
|
+
undef code
|
196
|
+
def code
|
197
|
+
@code.to_s.strip
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class Institute
|
202
|
+
attr_accessor :name, :id
|
203
|
+
end
|
204
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ekylibre-ofx-parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew A. Smith
|
8
|
+
- Louis Coquio
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-05-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hpricot
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.6'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.6'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rdoc
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '3.10'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '3.10'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: hoe
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '3.3'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '3.3'
|
56
|
+
description: |-
|
57
|
+
== DESCRIPTION:
|
58
|
+
|
59
|
+
ofx-parser is a ruby library to parse a realistic subset of the lengthy OFX 1.x specification.
|
60
|
+
|
61
|
+
== FEATURES/PROBLEMS:
|
62
|
+
|
63
|
+
* Reads OFX responses - i.e. those downloaded from financial institutions and
|
64
|
+
puts it into a usable object graph.
|
65
|
+
* Supports the 3 main message sets: banking, credit card and investment
|
66
|
+
accounts, as well as the required 'sign on' set.
|
67
|
+
* Knows about SIC codes - if your institution provides them.
|
68
|
+
See http://www.eeoc.gov/stats/jobpat/siccodes.html
|
69
|
+
* Monetary amounts can be retrieved either as a raw string, or in pennies.
|
70
|
+
* Supports OFX timestamps.
|
71
|
+
email: andy@tinnedfruit.org
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- README.rdoc
|
77
|
+
- lib/mcc.rb
|
78
|
+
- lib/ofx-parser.rb
|
79
|
+
- lib/ofx-parser/version.rb
|
80
|
+
- lib/ofx.rb
|
81
|
+
homepage: https://github.com/ekylibre/ofx-parser
|
82
|
+
licenses: []
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.4.5.1
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: ofx-parser is a ruby library for parsing OFX 1.x data.
|
104
|
+
test_files: []
|