global_collect 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/HISTORY +7 -0
  2. data/Rakefile +2 -1
  3. data/VERSION +1 -1
  4. data/examples/parse_collection_report.rb +13 -0
  5. data/examples/parse_financial_statement.rb +8 -0
  6. data/examples/parse_payment_report.rb +8 -0
  7. data/examples/set_payment.rb +1 -1
  8. data/global_collect.gemspec +38 -2
  9. data/lib/global_collect.rb +12 -0
  10. data/lib/global_collect/log_parsing/collection_report/appendix_report_file.rb +72 -0
  11. data/lib/global_collect/log_parsing/collection_report/fields.rb +161 -0
  12. data/lib/global_collect/log_parsing/collection_report/parser.rb +68 -0
  13. data/lib/global_collect/log_parsing/collection_report/report_file.rb +32 -0
  14. data/lib/global_collect/log_parsing/financial_statement/report_file.rb +96 -0
  15. data/lib/global_collect/log_parsing/payment_report/fields.rb +709 -0
  16. data/lib/global_collect/log_parsing/payment_report/parser.rb +105 -0
  17. data/lib/global_collect/log_parsing/payment_report/report_file.rb +31 -0
  18. data/lib/global_collect/responses/base.rb +0 -2
  19. data/lib/global_collect/test_helper.rb +8 -4
  20. data/spec/log_parsing/collection_report/appendix_report_file_spec.rb +96 -0
  21. data/spec/log_parsing/collection_report/parser_spec.rb +42 -0
  22. data/spec/log_parsing/collection_report/report_file_spec.rb +17 -0
  23. data/spec/log_parsing/financial_statement/report_file_spec.rb +51 -0
  24. data/spec/log_parsing/payment_report/parser_spec.rb +37 -0
  25. data/spec/log_parsing/payment_report/report_file_spec.rb +23 -0
  26. data/spec/support/55550141.wr1 +7 -0
  27. data/spec/support/555520100602.csv +4 -0
  28. data/spec/support/555555550145.mt1 +3 -0
  29. data/spec/support/FS55550148COMPANY.asc +12 -0
  30. metadata +64 -6
data/HISTORY CHANGED
@@ -1,3 +1,10 @@
1
+ v0.2.0 (2010-06-07)
2
+ ===================
3
+ * add reporting log parsing
4
+ * Financial Statement
5
+ * Collection Report + Appendix
6
+ * Payment Report
7
+
1
8
  v0.1.5 (2010-05-04)
2
9
  ===================
3
10
  * add two helper methods to GET_ORDERSTATUS v2.0 response:
data/Rakefile CHANGED
@@ -22,9 +22,10 @@ END
22
22
  gemspec.email = "timon.karnezos@gmail.com"
23
23
  gemspec.homepage = "http://github.com/timonk/global_collect"
24
24
  gemspec.authors = ["Timon Karnezos"]
25
- gemspec.version = "0.1.5"
26
25
  gemspec.add_dependency('httparty', '>= 0.5.2')
27
26
  gemspec.add_dependency('builder', '>= 2.0')
27
+ gemspec.add_dependency('fastercsv', '>= 1.5.3')
28
+ gemspec.add_dependency('fixed_width', '>= 0.2.1')
28
29
 
29
30
  gemspec.add_development_dependency('fakeweb', '>= 1.2.8')
30
31
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.2.0
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require File.join(File.dirname(__FILE__), '..', "lib", "global_collect")
3
+ require 'pp'
4
+
5
+ path = "something.mt1"
6
+ report = GlobalCollect::LogParsing::CollectionReport::ReportFile.new(path)
7
+ report.parse
8
+ pp report.data
9
+
10
+ path = "something.csv"
11
+ report = GlobalCollect::LogParsing::CollectionReport::AppendixReportFile.new(path)
12
+ report.parse
13
+ pp report.data
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require File.join(File.dirname(__FILE__), '..', "lib", "global_collect")
3
+ require 'pp'
4
+
5
+ path = "something.asc"
6
+ report = GlobalCollect::LogParsing::FinancialStatement::ReportFile.new(path)
7
+ report.parse
8
+ pp report.data
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require File.join(File.dirname(__FILE__), '..', "lib", "global_collect")
3
+ require 'pp'
4
+
5
+ path = "something.wr1"
6
+ report = GlobalCollect::LogParsing::PaymentReport::ReportFile.new(path)
7
+ report.parse
8
+ pp report.data
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require File.join(File.dirname(__FILE__), '..', "lib", "global_collect")
3
3
 
4
- GlobalCollect.merchant_id = "5393"
4
+ GlobalCollect.merchant_id = ""
5
5
  GlobalCollect.authentication_scheme = :ip_check
6
6
  GlobalCollect.environment = :test
7
7
  GlobalCollect.ip_address = ""
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{global_collect}
8
- s.version = "0.1.5"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Timon Karnezos"]
12
- s.date = %q{2010-05-04}
12
+ s.date = %q{2010-06-08}
13
13
  s.description = %q{Gives minimally intrusive access to Global Collect's payment processing API.
14
14
  Currently implements a very small segment of the full API but is built with
15
15
  extensibility in mind.
@@ -29,6 +29,9 @@ extensibility in mind.
29
29
  "examples/convert_amount.rb",
30
30
  "examples/get_order_status.rb",
31
31
  "examples/insert_order_with_payment.rb",
32
+ "examples/parse_collection_report.rb",
33
+ "examples/parse_financial_statement.rb",
34
+ "examples/parse_payment_report.rb",
32
35
  "examples/process_challenged.rb",
33
36
  "examples/set_payment.rb",
34
37
  "examples/test_connection.rb",
@@ -46,6 +49,14 @@ extensibility in mind.
46
49
  "lib/global_collect/const/payment_product.rb",
47
50
  "lib/global_collect/const/payment_status.rb",
48
51
  "lib/global_collect/field_validator.rb",
52
+ "lib/global_collect/log_parsing/collection_report/appendix_report_file.rb",
53
+ "lib/global_collect/log_parsing/collection_report/fields.rb",
54
+ "lib/global_collect/log_parsing/collection_report/parser.rb",
55
+ "lib/global_collect/log_parsing/collection_report/report_file.rb",
56
+ "lib/global_collect/log_parsing/financial_statement/report_file.rb",
57
+ "lib/global_collect/log_parsing/payment_report/fields.rb",
58
+ "lib/global_collect/log_parsing/payment_report/parser.rb",
59
+ "lib/global_collect/log_parsing/payment_report/report_file.rb",
49
60
  "lib/global_collect/request_models/base.rb",
50
61
  "lib/global_collect/request_models/do_refund/credit_card_payment.rb",
51
62
  "lib/global_collect/request_models/do_refund/payment.rb",
@@ -86,6 +97,12 @@ extensibility in mind.
86
97
  "spec/const/payment_status_spec.rb",
87
98
  "spec/field_validator_spec.rb",
88
99
  "spec/global_collect_spec.rb",
100
+ "spec/log_parsing/collection_report/appendix_report_file_spec.rb",
101
+ "spec/log_parsing/collection_report/parser_spec.rb",
102
+ "spec/log_parsing/collection_report/report_file_spec.rb",
103
+ "spec/log_parsing/financial_statement/report_file_spec.rb",
104
+ "spec/log_parsing/payment_report/parser_spec.rb",
105
+ "spec/log_parsing/payment_report/report_file_spec.rb",
89
106
  "spec/request_models/base_spec.rb",
90
107
  "spec/request_models/insert_order_with_payment/credit_card_online_payment_spec.rb",
91
108
  "spec/request_models/insert_order_with_payment/hosted_credit_card_online_payment_spec.rb",
@@ -103,6 +120,10 @@ extensibility in mind.
103
120
  "spec/responses/insert_order_with_payment/hosted_merchant_link_payment_response_methods_spec.rb",
104
121
  "spec/responses/succcess_row_spec.rb",
105
122
  "spec/spec_helper.rb",
123
+ "spec/support/55550141.wr1",
124
+ "spec/support/555520100602.csv",
125
+ "spec/support/555555550145.mt1",
126
+ "spec/support/FS55550148COMPANY.asc",
106
127
  "spec/support/challenged_iowp_v1_response.xml",
107
128
  "spec/support/successful_cancel_payment_v1_response.xml",
108
129
  "spec/support/successful_convert_amount_v1_response.xml",
@@ -135,6 +156,12 @@ extensibility in mind.
135
156
  "spec/const/payment_status_spec.rb",
136
157
  "spec/field_validator_spec.rb",
137
158
  "spec/global_collect_spec.rb",
159
+ "spec/log_parsing/collection_report/appendix_report_file_spec.rb",
160
+ "spec/log_parsing/collection_report/parser_spec.rb",
161
+ "spec/log_parsing/collection_report/report_file_spec.rb",
162
+ "spec/log_parsing/financial_statement/report_file_spec.rb",
163
+ "spec/log_parsing/payment_report/parser_spec.rb",
164
+ "spec/log_parsing/payment_report/report_file_spec.rb",
138
165
  "spec/request_models/base_spec.rb",
139
166
  "spec/request_models/insert_order_with_payment/credit_card_online_payment_spec.rb",
140
167
  "spec/request_models/insert_order_with_payment/hosted_credit_card_online_payment_spec.rb",
@@ -156,6 +183,9 @@ extensibility in mind.
156
183
  "examples/convert_amount.rb",
157
184
  "examples/get_order_status.rb",
158
185
  "examples/insert_order_with_payment.rb",
186
+ "examples/parse_collection_report.rb",
187
+ "examples/parse_financial_statement.rb",
188
+ "examples/parse_payment_report.rb",
159
189
  "examples/process_challenged.rb",
160
190
  "examples/set_payment.rb",
161
191
  "examples/test_connection.rb",
@@ -169,15 +199,21 @@ extensibility in mind.
169
199
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
170
200
  s.add_runtime_dependency(%q<httparty>, [">= 0.5.2"])
171
201
  s.add_runtime_dependency(%q<builder>, [">= 2.0"])
202
+ s.add_runtime_dependency(%q<fastercsv>, [">= 1.5.3"])
203
+ s.add_runtime_dependency(%q<fixed_width>, [">= 0.2.1"])
172
204
  s.add_development_dependency(%q<fakeweb>, [">= 1.2.8"])
173
205
  else
174
206
  s.add_dependency(%q<httparty>, [">= 0.5.2"])
175
207
  s.add_dependency(%q<builder>, [">= 2.0"])
208
+ s.add_dependency(%q<fastercsv>, [">= 1.5.3"])
209
+ s.add_dependency(%q<fixed_width>, [">= 0.2.1"])
176
210
  s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
177
211
  end
178
212
  else
179
213
  s.add_dependency(%q<httparty>, [">= 0.5.2"])
180
214
  s.add_dependency(%q<builder>, [">= 2.0"])
215
+ s.add_dependency(%q<fastercsv>, [">= 1.5.3"])
216
+ s.add_dependency(%q<fixed_width>, [">= 0.2.1"])
181
217
  s.add_dependency(%q<fakeweb>, [">= 1.2.8"])
182
218
  end
183
219
  end
@@ -1,11 +1,15 @@
1
+ require 'time'
1
2
  require 'builder'
2
3
  require 'httparty'
3
4
  require 'find'
4
5
  require 'logger'
5
6
  require 'benchmark'
7
+ require 'fixed_width'
8
+ require 'fastercsv'
6
9
 
7
10
  module GlobalCollect;end
8
11
  module GlobalCollect::Builders;end
12
+ module GlobalCollect::LogParsing;end
9
13
  module GlobalCollect::RequestModels;end
10
14
  module GlobalCollect::Responses;end
11
15
 
@@ -22,6 +26,14 @@ lib_dir = File.dirname(__FILE__)
22
26
  %w[const payment_product] ,
23
27
  %w[const payment_status] ,
24
28
  %w[field_validator] ,
29
+ %w[log_parsing collection_report fields] ,
30
+ %w[log_parsing collection_report parser] ,
31
+ %w[log_parsing collection_report report_file] ,
32
+ %w[log_parsing collection_report appendix_report_file] ,
33
+ %w[log_parsing financial_statement report_file] ,
34
+ %w[log_parsing payment_report fields] ,
35
+ %w[log_parsing payment_report parser] ,
36
+ %w[log_parsing payment_report report_file] ,
25
37
  %w[request_models base] ,
26
38
  %w[request_models insert_order_with_payment order] ,
27
39
  %w[request_models insert_order_with_payment payment] ,
@@ -0,0 +1,72 @@
1
+ module GlobalCollect::LogParsing::CollectionReport
2
+ class AppendixReportFile
3
+ attr_reader :path, :account_id, :date, :data, :environment
4
+
5
+ # RG - Ch9 => Technical aspects => File name
6
+ # 4 chars numeric account id, 8 chars date in YYYMMDD
7
+ FILENAME_FORMAT = /^(\d{4})(\d{8})\.csv$/
8
+ def initialize(path)
9
+ @path = path
10
+ if File.basename(path) =~ FILENAME_FORMAT
11
+ @account_id = $1
12
+ @date = Date.strptime($2, "%Y%m%d")
13
+ @environment = :production
14
+ else
15
+ raise ArgumentError.new("Unparseable path '#{path}'!")
16
+ end
17
+ end
18
+
19
+ def parse
20
+ begin
21
+ file = File.open(@path, "r")
22
+ csv = FasterCSV.new(file,
23
+ :col_sep => ";",
24
+ :headers => FIELDS.map(&:first)
25
+ )
26
+ @data = {:data_records => csv.map{|l| convert_line(l) }}
27
+ ensure
28
+ file.close
29
+ end
30
+ end
31
+
32
+ private
33
+ RECORD_TYPE = {
34
+ "ON" => :settlement ,
35
+ "CR" => :refund ,
36
+ "CB" => :chargeback
37
+ }
38
+ PAYMENT_METHOD = {
39
+ "BA" => :bank_payment,
40
+ "CC" => :credit_card,
41
+ "CH" => :cheque,
42
+ "DD" => :direct_debit
43
+ }
44
+ PAYMENT_TYPE = {
45
+ "P" => :payment,
46
+ "R" => :refund_or_reversal
47
+ }
48
+ STRIP_LAMBDA = lambda {|x| x.strip }
49
+ FIELDS = [
50
+ [:record_category , STRIP_LAMBDA ],
51
+ [:record_type , lambda{|x| RECORD_TYPE[x] } ],
52
+ [:merchant_id , lambda {|x| x.to_i } ],
53
+ [:date_due , lambda{|x| Date.strptime(x, "%Y%m%d") }],
54
+ [:currency_due , STRIP_LAMBDA ],
55
+ [:amount_due , lambda {|x| x.to_f } ],
56
+ [:order_currency , STRIP_LAMBDA ],
57
+ [:order_amount , lambda {|x| x.to_f } ],
58
+ [:payment_method , lambda{|x| PAYMENT_METHOD[x] } ],
59
+ [:credit_card_company , STRIP_LAMBDA ],
60
+ [:cross_border_indicator , STRIP_LAMBDA ],
61
+ [:globalcollect_payment_reference, STRIP_LAMBDA ],
62
+ [:merchant_reference , STRIP_LAMBDA ],
63
+ [:invoice_number , STRIP_LAMBDA ],
64
+ [:customer_id , STRIP_LAMBDA ],
65
+ [:filename_data_delivery , STRIP_LAMBDA ],
66
+ [:payment_type , lambda{|x| PAYMENT_TYPE[x] } ]
67
+ ]
68
+ def convert_line(line)
69
+ FIELDS.inject({}) {|memo, pair| memo[pair.first] = pair.last.call(line[pair.first]); memo }
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,161 @@
1
+ module GlobalCollect::LogParsing::CollectionReport
2
+ HEADER_TRAILER_FIELDS = [
3
+ {
4
+ :type =>"N",
5
+ :length =>"4",
6
+ :position =>"0004-0007",
7
+ :name =>"account_id",
8
+ :field =>"021"
9
+ },
10
+ {
11
+ :type =>"AN",
12
+ :length =>"12",
13
+ :position =>"0008-0019",
14
+ :name =>"filename",
15
+ :field =>"022"
16
+ },
17
+ {
18
+ :type =>"AN",
19
+ :length =>"3",
20
+ :position =>"0020-0022",
21
+ :name =>"filename_extension",
22
+ :field =>"023"
23
+ },
24
+ {
25
+ :type =>"D",
26
+ :length =>"8",
27
+ :position =>"0023-0030",
28
+ :name =>"date_production",
29
+ :field =>"024"
30
+ },
31
+ {
32
+ :type =>"D",
33
+ :length =>"8",
34
+ :position =>"0031-0038",
35
+ :name =>"period_from",
36
+ :field =>"025"
37
+ },
38
+ {
39
+ :type =>"D",
40
+ :length =>"8",
41
+ :position =>"0039-0046",
42
+ :name =>"period_to",
43
+ :field =>"026"
44
+ }
45
+ ]
46
+
47
+ DATA_FIELDS = [
48
+ {
49
+ :type =>"N",
50
+ :length =>"4",
51
+ :position =>"0004-0007",
52
+ :name =>"merchant_id",
53
+ :field =>"051"
54
+ },
55
+ {
56
+ :type =>"D",
57
+ :length =>"8",
58
+ :position =>"0008-0015",
59
+ :name =>"match_date",
60
+ :field =>"062"
61
+ },
62
+ {
63
+ :type =>"N",
64
+ :length =>"4",
65
+ :position =>"0016-0019",
66
+ :name =>"report_year",
67
+ :field =>"053"
68
+ },
69
+ {
70
+ :type =>"N",
71
+ :length =>"3",
72
+ :position =>"0020-0022",
73
+ :name =>"report_serial_number",
74
+ :field =>"054"
75
+ },
76
+ {
77
+ :type =>"D",
78
+ :length =>"8",
79
+ :position =>"0023-0030",
80
+ :name =>"report_date_from",
81
+ :field =>"055"
82
+ },
83
+ {
84
+ :type =>"D",
85
+ :length =>"8",
86
+ :position =>"0031-0038",
87
+ :name =>"report_date_to",
88
+ :field =>"056"
89
+ },
90
+ {
91
+ :type =>"AN",
92
+ :length =>"4",
93
+ :position =>"0039-0042",
94
+ :name =>"currency_due",
95
+ :field =>"057"
96
+ },
97
+ {
98
+ :type =>"N",
99
+ :length =>"12",
100
+ :position =>"0043-0054",
101
+ :name =>"amount_due",
102
+ :field =>"058"
103
+ },
104
+ {
105
+ :type =>"AN",
106
+ :length =>"1",
107
+ :position =>"0055-0055",
108
+ :name =>"amount_due_sign",
109
+ :field =>"910"
110
+ },
111
+ {
112
+ :type =>"AN",
113
+ :length =>"4",
114
+ :position =>"0056-0059",
115
+ :name =>"currency_paid",
116
+ :field =>"059"
117
+ },
118
+ {
119
+ :type =>"N",
120
+ :length =>"12",
121
+ :position =>"0060-0071",
122
+ :name =>"amount_paid",
123
+ :field =>"060"
124
+ },
125
+ {
126
+ :type =>"AN",
127
+ :length =>"1",
128
+ :position =>"0072-0072",
129
+ :name =>"amount_paid_sign",
130
+ :field =>"910"
131
+ },
132
+ {
133
+ :type =>"XR",
134
+ :length =>"16",
135
+ :position =>"0073-0088",
136
+ :name =>"exchange_rate",
137
+ :field =>"061"
138
+ },
139
+ {
140
+ :type =>"N",
141
+ :length =>"5",
142
+ :position =>"0089-0093",
143
+ :name =>"rate_units",
144
+ :field =>"063"
145
+ },
146
+ {
147
+ :type =>"N",
148
+ :length =>"6",
149
+ :position =>"0094-0099",
150
+ :name =>"number_of_transactions",
151
+ :field =>"062"
152
+ },
153
+ {
154
+ :type =>"AN",
155
+ :length =>"301",
156
+ :position =>"0100-0400",
157
+ :name =>"filler",
158
+ :field =>"999"
159
+ }
160
+ ]
161
+ end
@@ -0,0 +1,68 @@
1
+ module GlobalCollect::LogParsing::CollectionReport
2
+ class Parser
3
+ def self.parse(file)
4
+ FixedWidth.parse(file, :collection_report)
5
+ end
6
+
7
+ private
8
+
9
+ RECORD_TYPE = {
10
+ "HDR" => :file_header,
11
+ "POV" => :data_record,
12
+ "TRL" => :file_trailer
13
+ }
14
+
15
+ # RG - Ch8 => Technical aspects => Field Format
16
+ # Exchange rates always have 8 decimal places of precision.
17
+ EXCHANGE_RATE_LAMBDA = lambda{|x| "#{x[0..-9]}.#{x[-8..-1]}".to_f }
18
+ DATE_LAMBDA = lambda {|d| Date.strptime(d, "%Y%m%d") }
19
+ def self.options_for_format(format)
20
+ case format
21
+ when "N" then { :align => :right, :parser => :to_i }
22
+ when "AN" then { :align => :left }
23
+ when "D" then { :parser => DATE_LAMBDA }
24
+ when "XR" then { :parser => EXCHANGE_RATE_LAMBDA }
25
+ else raise ArgumentError.new("Unknown field format '#{format.inspect}'!")
26
+ end
27
+ end
28
+
29
+ SPACERS = ['reserved', 'filler']
30
+ def self.make_column(section, field, options={})
31
+ if SPACERS.include?(field[:name])
32
+ section.spacer(field[:length].to_i, ' ')
33
+ else
34
+ section.column(field[:name].to_sym, field[:length].to_i, options_for_format(field[:type]).merge(options))
35
+ end
36
+ end
37
+
38
+ DEFINITION = FixedWidth.define(:collection_report, :nil_blank => true) do |pr|
39
+ pr.template :record_info do |ri|
40
+ ri.record_type 3, :parser => lambda{|x| RECORD_TYPE[x] }
41
+ end
42
+ pr.template :header_trailer do |hf|
43
+ HEADER_TRAILER_FIELDS.each {|field| make_column(hf, field) }
44
+ end
45
+
46
+ pr.header(:singular => true) do |h|
47
+ h.trap { |line| line[0,3] == 'HDR' }
48
+ h.template :record_info
49
+ h.template :header_trailer
50
+ h.spacer 354
51
+ end
52
+
53
+ pr.data_records(:optional => true) do |d|
54
+ d.trap { |line| line[0,3] == "POV" }
55
+ d.template :record_info
56
+ DATA_FIELDS.each {|field| make_column(d, field) }
57
+ end
58
+
59
+ pr.trailer(:singular => true) do |t|
60
+ t.trap { |line| line[0,3] == 'TRL' }
61
+ t.template :record_info
62
+ t.template :header_trailer
63
+ t.column :number_of_records, 8, :parser => :to_i
64
+ t.spacer 346
65
+ end
66
+ end
67
+ end
68
+ end