global_collect 0.1.5 → 0.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.
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