ekylibre-ofx-parser 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|