clieop 0.1.1

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.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ clieop-*.gem
2
+ .svn/
3
+ .DS_Store
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2009 Willem van Bergen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = CLIEOP
2
+
3
+ This library is a pure Ruby implementation of the *CLIEOP03* format. Currently,
4
+ it only supports writing CLIEOP files with accounts receivable transactions.
5
+ Accounts payable transactions, and reading existing CLIEOP files is planned to be
6
+ supported
7
+
8
+ This library is licensed under the MIT license.
9
+
10
+ == CLIEOP format
11
+
12
+ CLIEOP03 is a file format that is used for communication about cash transaction
13
+ between bank accounts. It is used in the Netherlands and is supported by the
14
+ banking software packages of the main banks. CLIEOP supports transactions in both
15
+ directions: accounts payable and accounts receivable. For accounts receivable,
16
+ you need proper authorization from your bank.
17
+
18
+ For more information about the CLIEOP file format, see:
19
+ http://www.ingbank.nl/ing/downloadables/eclieop1.pdf
20
+
21
+ == Usage
22
+
23
+ Run <tt>gem install clieop -s http://gemcutter.org</tt> to install the gem.
24
+
25
+ See the project's wiki at http://wiki.github.com/wvanbergen/clieop for an example
26
+ creating and writing a direct debt batch file.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ Dir['tasks/*.rake'].each { |file| load(file) }
2
+
3
+ GithubGem::RakeTasks.new(:gem)
4
+ task :default => [:spec]
data/clieop.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'clieop'
3
+
4
+ # Do not set version and date yourself, this will be done automatically
5
+ # by the gem release script.
6
+ s.version = "0.1.1"
7
+ s.date = "2009-10-10"
8
+
9
+ s.summary = "A pure Ruby implementation to write CLIEOP files"
10
+ s.description = "This library is a pure Ruby, MIT licensed implementation of the CLIEOP03 transaction format. CLIEOP03 can be used to communicate direct debt transactions with your (Dutch) bank."
11
+
12
+ s.authors = ['Willem van Bergen']
13
+ s.email = ['willem@vanbergen.org']
14
+ s.homepage = 'http://github.com/wvanbergen/clieop/wikis'
15
+
16
+ # Do not set files and test_files yourself, this will be done automatically
17
+ # by the gem release script.
18
+ s.files = %w(.gitignore lib/clieop/record.rb lib/clieop/file.rb lib/clieop/batch.rb lib/clieop.rb Rakefile MIT-LICENSE test/clieop_writer_test.rb tasks/github-gem.rake clieop.gemspec README.rdoc)
19
+ s.test_files = %w(test/clieop_writer_test.rb)
20
+ end
@@ -0,0 +1,102 @@
1
+ module Clieop
2
+
3
+ class Batch
4
+
5
+ attr_accessor :transactions, :batch_info
6
+
7
+ def initialize(batch_info)
8
+ raise "Required: :description, :account_nr, :account_owner" unless ([:description, :account_nr, :account_owner] - batch_info.keys).empty?
9
+ @transactions = []
10
+ @batch_info = batch_info
11
+ end
12
+
13
+ # Adds a transaction to the batch
14
+ #
15
+ # :amount The amount involved with this transaction
16
+ # :account_nr The bank account from the other party
17
+ # :account_owner The name of the owner of the bank account
18
+ # :reference_number A reference number to identify this transaction
19
+ # :description A description for this transaction (4 lines max)
20
+ def add_transaction (transaction)
21
+ raise "No :account_nr given" if transaction[:account_nr].nil?
22
+ raise "No :amount given" if transaction[:amount].nil?
23
+ raise "No :account_owner given" if transaction[:account_owner].nil?
24
+ @transactions << transaction
25
+ end
26
+
27
+ alias_method :<<, :add_transaction
28
+
29
+ def to_clieop
30
+
31
+ # generate batch header records
32
+ batch_data = ""
33
+ batch_data << Clieop::Record.new(:batch_header,
34
+ :transaction_group => @batch_info[:transaction_group] || 0,
35
+ :acount_nr => @batch_info[:account_nr] || 0,
36
+ :serial_nr => @batch_info[:serial_nr] || 1,
37
+ :currency => @batch_info[:currency] || "EUR").to_clieop
38
+
39
+ batch_data << Clieop::Record.new(:batch_description, :description => @batch_info[:description]).to_clieop
40
+ batch_data << Clieop::Record.new(:batch_owner,
41
+ :process_date => @batch_info[:process_date] || 0,
42
+ :owner => @batch_info[:account_owner]).to_clieop
43
+
44
+ # initialize checksums
45
+ total_account = @batch_info[:account_nr].to_i * @transactions.length
46
+ total_amount = 0
47
+
48
+ # add transactions to batch
49
+ @transactions.each do |tr|
50
+
51
+ # update checksums
52
+ total_account += tr[:account_nr].to_i
53
+ total_amount += (tr[:amount].to_f * 100).truncate
54
+
55
+ # prepare data for this transaction's records
56
+ transaction_type = @batch_info[:transaction_group] == 10 ? 1002 : 0
57
+ to_account = @batch_info[:transaction_group] == 10 ? @batch_info[:account_nr] : tr[:account_nr]
58
+ from_account = @batch_info[:transaction_group] == 10 ? tr[:account_nr] : @batch_info[:account_nr]
59
+ amount_in_cents = (tr[:amount].to_f * 100).truncate
60
+ name_record = @batch_info[:transaction_group] == 10 ? :invoice_name : :payment_name
61
+
62
+ # generate transaction record
63
+ batch_data << Clieop::Record.new(:transaction_info,
64
+ :transaction_type => transaction_type, :amount => amount_in_cents,
65
+ :to_account => to_account, :from_account => from_account).to_clieop
66
+
67
+ # generate record with transaction information
68
+ batch_data << Clieop::Record.new(name_record, :name => tr[:account_owner]).to_clieop
69
+ batch_data << Clieop::Record.new(:transaction_reference, :reference_number => tr[:reference_number]).to_clieop unless tr[:reference_number].nil?
70
+
71
+ # split discription into lines and make a record for the first 4 lines
72
+ unless tr[:description].nil? || tr[:description] == ''
73
+ tr[:description].split(/\r?\n/)[0, 4].each do |line|
74
+ batch_data << Clieop::Record.new(:transaction_description, :description => line.strip).to_s unless line == ''
75
+ end
76
+ end
77
+ end
78
+
79
+ # generate batch footer record including some checks
80
+ batch_data << Clieop::Record.new(:batch_footer, :tranasction_count => @transactions.length,
81
+ :total_amount => total_amount, :account_checksum => total_account.to_s[0..10]).to_clieop
82
+
83
+ end
84
+
85
+ def to_s
86
+ self.to_clieop
87
+ end
88
+
89
+ # creates a batch for payments from a given account
90
+ def self.payment_batch(batch_info = {})
91
+ batch_info[:transaction_group] ||= 0
92
+ Clieop::Batch.new(batch_info)
93
+ end
94
+
95
+ # creates a batch for invoices to a given account
96
+ def self.invoice_batch(batch_info = {})
97
+ batch_info[:transaction_group] ||= 10
98
+ Clieop::Batch.new(batch_info)
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,43 @@
1
+ module Clieop
2
+
3
+ class File
4
+
5
+ attr_accessor :batches
6
+ attr_reader :file_info
7
+
8
+ def initialize(file_info = {})
9
+ file_info[:date] = Date.today unless file_info[:date]
10
+ file_info[:date] = file_info[:date].strftime('%d%m%y') if file_info[:date].respond_to?(:strftime)
11
+ @file_info = file_info
12
+ @batches = []
13
+ end
14
+
15
+ # renders this file as a CLIEOP03 formatted string
16
+ def to_clieop
17
+ clieop_data = Clieop::Record.new(:file_header, @file_info).to_clieop
18
+ @batches.each { |batch| clieop_data << batch.to_clieop }
19
+ clieop_data << Clieop::Record.new(:file_footer).to_clieop
20
+ end
21
+
22
+ # Alias for to_clieop
23
+ alias :to_s :to_clieop
24
+
25
+ def payment_batch(options)
26
+ @payment << Clieop::Batch.payment_batch(options, block)
27
+ yield(@batches.last) if block_given?
28
+ return @batches.last
29
+ end
30
+
31
+ def invoice_batch(options)
32
+ @batches << Clieop::Batch.invoice_batch(options)
33
+ yield(@batches.last) if block_given?
34
+ return @batches.last
35
+ end
36
+
37
+ def save(filename)
38
+ File.open(filename, 'w') do |f|
39
+ f.write(self.to_clieop)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,115 @@
1
+ module Clieop
2
+
3
+ class Record
4
+
5
+ TYPE_DEFINITIONS = {
6
+ :file_header => [
7
+ [:record_code, :numeric, 4, 1],
8
+ [:record_variant, :alpha, 1, 'A'],
9
+ [:date, :numeric, 6],
10
+ [:filename, :alpha, 8, 'CLIEOP03'],
11
+ [:sender_identification, :alpha, 5],
12
+ [:file_identification, :alpha, 4],
13
+ [:duplicate_code, :numeric, 1, 1]
14
+ ],
15
+ :file_footer => [
16
+ [:record_code, :numeric, 4, 9999],
17
+ [:record_variant, :alpha, 1, 'A'],
18
+ ],
19
+ :batch_header => [
20
+ [:record_code, :numeric, 4, 10],
21
+ [:record_variant, :alpha, 1, 'B'],
22
+ [:transaction_group, :alpha, 2],
23
+ [:acount_nr, :numeric, 10],
24
+ [:serial_nr, :numeric, 4],
25
+ [:currency, :alpha, 3, 'EUR']
26
+ ],
27
+ :batch_footer => [
28
+ [:record_code, :numeric, 4, 9990],
29
+ [:record_variant, :alpha, 1, 'A'],
30
+ [:total_amount, :numeric, 18],
31
+ [:account_checksum, :numeric, 10],
32
+ [:tranasction_count, :numeric, 7],
33
+ ],
34
+ :batch_description => [
35
+ [:record_code, :numeric, 4, 20],
36
+ [:record_variant, :alpha, 1, 'A'],
37
+ [:description, :alpha, 32]
38
+ ],
39
+ :batch_owner => [
40
+ [:record_code, :numeric, 4, 30],
41
+ [:record_variant, :alpha, 1, 'B'],
42
+ [:naw_code, :numeric, 1, 1],
43
+ [:process_date, :numeric, 6, 0],
44
+ [:owner, :alpha, 35],
45
+ [:test, :alpha, 1, 'P']
46
+ ],
47
+ :transaction_info => [
48
+ [:record_code, :numeric, 4, 100],
49
+ [:record_variant, :alpha, 1, 'A'],
50
+ [:transaction_type, :numeric, 4, 1002],
51
+ [:amount, :numeric, 12],
52
+ [:from_account, :numeric, 10],
53
+ [:to_account, :numeric, 10],
54
+ ],
55
+ :invoice_name => [
56
+ [:record_code, :numeric, 4, 110],
57
+ [:record_variant, :alpha, 1, 'B'],
58
+ [:name, :alpha, 35],
59
+ ],
60
+ :payment_name =>[
61
+ [:record_code, :numeric, 4, 170],
62
+ [:record_variant, :alpha, 1, 'B'],
63
+ [:name, :alpha, 35],
64
+ ],
65
+ :transaction_reference => [
66
+ [:record_code, :numeric, 4, 150],
67
+ [:record_variant, :alpha, 1, 'A'],
68
+ [:reference_number, :numeric, 16],
69
+ ],
70
+ :transaction_description => [
71
+ [:record_code, :numeric, 4, 160],
72
+ [:record_variant, :alpha, 1, 'A'],
73
+ [:description, :alpha, 32],
74
+ ],
75
+ }
76
+
77
+ attr_accessor :definition, :data
78
+
79
+ def initialize record_type, record_data = {}
80
+
81
+ # load record definition
82
+ raise "Unknown record type" unless Clieop::Record::TYPE_DEFINITIONS[record_type.to_sym]
83
+ @definition = Clieop::Record::TYPE_DEFINITIONS[record_type.to_sym]
84
+
85
+ # set default values according to definition
86
+ @data = {}
87
+ @definition.each { |field| @data[field[0]] = field[3] if field[3] }
88
+
89
+ # set values for all the provided data
90
+ record_data.each { |field, value| @data[field] = value }
91
+ end
92
+
93
+ def to_clieop
94
+ line = ""
95
+ #format each field
96
+ @definition.each do |field|
97
+ fmt = '%'
98
+ fmt << (field[1] == :numeric ? '0' : '-')
99
+ fmt << (field[2].to_s)
100
+ fmt << (field[1] == :numeric ? 'd' : 's')
101
+ raw_data = (field[1] == :numeric) ? @data[field[0]].to_i : @data[field[0]]
102
+ value = sprintf(fmt, raw_data)
103
+ line << (field[1] == :numeric ? value[0 - field[2], field[2]] : value[0, field[2]])
104
+ end
105
+ # fill each line with spaces up to 50 characters and close with a CR/LF
106
+ line.ljust(50) + "\r\n"
107
+ end
108
+
109
+ def to_s
110
+ self.to_clieop
111
+ end
112
+
113
+ end
114
+
115
+ end
data/lib/clieop.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'date'
2
+ require 'clieop/record.rb'
3
+ require 'clieop/file.rb'
4
+ require 'clieop/batch.rb'
@@ -0,0 +1,323 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+ require 'date'
5
+ require 'git'
6
+
7
+ module GithubGem
8
+
9
+ # Detects the gemspc file of this project using heuristics.
10
+ def self.detect_gemspec_file
11
+ FileList['*.gemspec'].first
12
+ end
13
+
14
+ # Detects the main include file of this project using heuristics
15
+ def self.detect_main_include
16
+ if detect_gemspec_file =~ /^(\.*)\.gemspec$/ && File.exist?("lib/#{$1}.rb")
17
+ "lib/#{$1}.rb"
18
+ elsif FileList['lib/*.rb'].length == 1
19
+ FileList['lib/*.rb'].first
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ class RakeTasks
26
+
27
+ attr_reader :gemspec, :modified_files, :git
28
+ attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch
29
+
30
+ # Initializes the settings, yields itself for configuration
31
+ # and defines the rake tasks based on the gemspec file.
32
+ def initialize(task_namespace = :gem)
33
+ @gemspec_file = GithubGem.detect_gemspec_file
34
+ @task_namespace = task_namespace
35
+ @main_include = GithubGem.detect_main_include
36
+ @modified_files = []
37
+ @root_dir = Dir.pwd
38
+ @test_pattern = 'test/**/*_test.rb'
39
+ @spec_pattern = 'spec/**/*_spec.rb'
40
+ @local_branch = 'master'
41
+ @remote = 'origin'
42
+ @remote_branch = 'master'
43
+
44
+ yield(self) if block_given?
45
+
46
+ @git = Git.open(@root_dir)
47
+ load_gemspec!
48
+ define_tasks!
49
+ end
50
+
51
+ protected
52
+
53
+ # Define Unit test tasks
54
+ def define_test_tasks!
55
+ require 'rake/testtask'
56
+
57
+ namespace(:test) do
58
+ Rake::TestTask.new(:basic) do |t|
59
+ t.pattern = test_pattern
60
+ t.verbose = true
61
+ t.libs << 'test'
62
+ end
63
+ end
64
+
65
+ desc "Run all unit tests for #{gemspec.name}"
66
+ task(:test => ['test:basic'])
67
+ end
68
+
69
+ # Defines RSpec tasks
70
+ def define_rspec_tasks!
71
+ require 'spec/rake/spectask'
72
+
73
+ namespace(:spec) do
74
+ desc "Verify all RSpec examples for #{gemspec.name}"
75
+ Spec::Rake::SpecTask.new(:basic) do |t|
76
+ t.spec_files = FileList[spec_pattern]
77
+ end
78
+
79
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
80
+ Spec::Rake::SpecTask.new(:specdoc) do |t|
81
+ t.spec_files = FileList[spec_pattern]
82
+ t.spec_opts << '--format' << 'specdoc' << '--color'
83
+ end
84
+
85
+ desc "Run RCov on specs for #{gemspec.name}"
86
+ Spec::Rake::SpecTask.new(:rcov) do |t|
87
+ t.spec_files = FileList[spec_pattern]
88
+ t.rcov = true
89
+ t.rcov_opts = ['--exclude', '"spec/*,gems/*"', '--rails']
90
+ end
91
+ end
92
+
93
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
94
+ task(:spec => ['spec:specdoc'])
95
+ end
96
+
97
+ # Defines the rake tasks
98
+ def define_tasks!
99
+
100
+ define_test_tasks! if has_tests?
101
+ define_rspec_tasks! if has_specs?
102
+
103
+ namespace(@task_namespace) do
104
+ desc "Updates the filelist in the gemspec file"
105
+ task(:manifest) { manifest_task }
106
+
107
+ desc "Builds the .gem package"
108
+ task(:build => :manifest) { build_task }
109
+
110
+ desc "Sets the version of the gem in the gemspec"
111
+ task(:set_version => [:check_version, :check_current_branch]) { version_task }
112
+ task(:check_version => :fetch_origin) { check_version_task }
113
+
114
+ task(:fetch_origin) { fetch_origin_task }
115
+ task(:check_current_branch) { check_current_branch_task }
116
+ task(:check_clean_status) { check_clean_status_task }
117
+ task(:check_not_diverged => :fetch_origin) { check_not_diverged_task }
118
+
119
+ checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version]
120
+ checks.unshift('spec:basic') if has_specs?
121
+ checks.unshift('test:basic') if has_tests?
122
+ checks.push << [:check_rubyforge] if gemspec.rubyforge_project
123
+
124
+ desc "Perform all checks that would occur before a release"
125
+ task(:release_checks => checks)
126
+
127
+ release_tasks = [:release_checks, :set_version, :build, :github_release]
128
+ release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
129
+
130
+ desc "Release a new verison of the gem"
131
+ task(:release => release_tasks) { release_task }
132
+
133
+ task(:check_rubyforge) { check_rubyforge_task }
134
+ task(:rubyforge_release) { rubyforge_release_task }
135
+ task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task }
136
+ task(:tag_version) { tag_version_task }
137
+ task(:commit_modified_files) { commit_modified_files_task }
138
+
139
+ desc "Updates the gem release tasks with the latest version on Github"
140
+ task(:update_tasks) { update_tasks_task }
141
+ end
142
+ end
143
+
144
+ # Updates the files list and test_files list in the gemspec file using the list of files
145
+ # in the repository and the spec/test file pattern.
146
+ def manifest_task
147
+ # Load all the gem's files using "git ls-files"
148
+ repository_files = git.ls_files.keys
149
+ test_files = Dir[test_pattern] + Dir[spec_pattern]
150
+
151
+ update_gemspec(:files, repository_files)
152
+ update_gemspec(:test_files, repository_files & test_files)
153
+ end
154
+
155
+ # Builds the gem
156
+ def build_task
157
+ sh "gem build -q #{gemspec_file}"
158
+ Dir.mkdir('pkg') unless File.exist?('pkg')
159
+ sh "mv #{gemspec.name}-#{gemspec.version}.gem pkg/#{gemspec.name}-#{gemspec.version}.gem"
160
+ end
161
+
162
+ # Updates the version number in the gemspec file, the VERSION constant in the main
163
+ # include file and the contents of the VERSION file.
164
+ def version_task
165
+ update_gemspec(:version, ENV['VERSION']) if ENV['VERSION']
166
+ update_gemspec(:date, Date.today)
167
+
168
+ update_version_file(gemspec.version)
169
+ update_version_constant(gemspec.version)
170
+ end
171
+
172
+ def check_version_task
173
+ raise "#{ENV['VERSION']} is not a valid version number!" if ENV['VERSION'] && !Gem::Version.correct?(ENV['VERSION'])
174
+ proposed_version = Gem::Version.new(ENV['VERSION'] || gemspec.version)
175
+ # Loads the latest version number using the created tags
176
+ newest_version = git.tags.map { |tag| tag.name.split('-').last }.compact.map { |v| Gem::Version.new(v) }.max
177
+ raise "This version (#{proposed_version}) is not higher than the highest tagged version (#{newest_version})" if newest_version && newest_version >= proposed_version
178
+ end
179
+
180
+ # Checks whether the current branch is not diverged from the remote branch
181
+ def check_not_diverged_task
182
+ raise "The current branch is diverged from the remote branch!" if git.log.between('HEAD', git.remote(remote).branch(remote_branch).gcommit).any?
183
+ end
184
+
185
+ # Checks whether the repository status ic clean
186
+ def check_clean_status_task
187
+ raise "The current working copy contains modifications" if git.status.changed.any?
188
+ end
189
+
190
+ # Checks whether the current branch is correct
191
+ def check_current_branch_task
192
+ raise "Currently not on #{local_branch} branch!" unless git.branch.name == local_branch.to_s
193
+ end
194
+
195
+ # Fetches the latest updates from Github
196
+ def fetch_origin_task
197
+ git.fetch('origin')
198
+ end
199
+
200
+ # Commits every file that has been changed by the release task.
201
+ def commit_modified_files_task
202
+ if modified_files.any?
203
+ modified_files.each { |file| git.add(file) }
204
+ git.commit("Released #{gemspec.name} gem version #{gemspec.version}")
205
+ end
206
+ end
207
+
208
+ # Adds a tag for the released version
209
+ def tag_version_task
210
+ git.add_tag("#{gemspec.name}-#{gemspec.version}")
211
+ end
212
+
213
+ # Pushes the changes and tag to github
214
+ def github_release_task
215
+ git.push(remote, remote_branch, true)
216
+ end
217
+
218
+ # Checks whether Rubyforge is configured properly
219
+ def check_rubyforge_task
220
+ # Login no longer necessary when using rubyforge 2.0.0 gem
221
+ # raise "Could not login on rubyforge!" unless `rubyforge login 2>&1`.strip.empty?
222
+ output = `rubyforge names`.split("\n")
223
+ raise "Rubyforge group not found!" unless output.any? { |line| %r[^groups\s*\:.*\b#{Regexp.quote(gemspec.rubyforge_project)}\b.*] =~ line }
224
+ raise "Rubyforge package not found!" unless output.any? { |line| %r[^packages\s*\:.*\b#{Regexp.quote(gemspec.name)}\b.*] =~ line }
225
+ end
226
+
227
+ # Task to release the .gem file toRubyforge.
228
+ def rubyforge_release_task
229
+ sh 'rubyforge', 'add_release', gemspec.rubyforge_project, gemspec.name, gemspec.version.to_s, "pkg/#{gemspec.name}-#{gemspec.version}.gem"
230
+ end
231
+
232
+ # Gem release task.
233
+ # All work is done by the task's dependencies, so just display a release completed message.
234
+ def release_task
235
+ puts
236
+ puts '------------------------------------------------------------'
237
+ puts "Released #{gemspec.name} version #{gemspec.version}"
238
+ end
239
+
240
+ private
241
+
242
+ # Checks whether this project has any RSpec files
243
+ def has_specs?
244
+ FileList[spec_pattern].any?
245
+ end
246
+
247
+ # Checks whether this project has any unit test files
248
+ def has_tests?
249
+ FileList[test_pattern].any?
250
+ end
251
+
252
+ # Loads the gemspec file
253
+ def load_gemspec!
254
+ @gemspec = eval(File.read(@gemspec_file))
255
+ end
256
+
257
+ # Updates the VERSION file with the new version
258
+ def update_version_file(version)
259
+ if File.exists?('VERSION')
260
+ File.open('VERSION', 'w') { |f| f << version.to_s }
261
+ modified_files << 'VERSION'
262
+ end
263
+ end
264
+
265
+ # Updates the VERSION constant in the main include file if it exists
266
+ def update_version_constant(version)
267
+ if main_include && File.exist?(main_include)
268
+ file_contents = File.read(main_include)
269
+ if file_contents.sub!(/^(\s+VERSION\s*=\s*)[^\s].*$/) { $1 + version.to_s.inspect }
270
+ File.open(main_include, 'w') { |f| f << file_contents }
271
+ modified_files << main_include
272
+ end
273
+ end
274
+ end
275
+
276
+ # Updates an attribute of the gemspec file.
277
+ # This function will open the file, and search/replace the attribute using a regular expression.
278
+ def update_gemspec(attribute, new_value, literal = false)
279
+
280
+ unless literal
281
+ new_value = case new_value
282
+ when Array then "%w(#{new_value.join(' ')})"
283
+ when Hash, String then new_value.inspect
284
+ when Date then new_value.strftime('%Y-%m-%d').inspect
285
+ else raise "Cannot write value #{new_value.inspect} to gemspec file!"
286
+ end
287
+ end
288
+
289
+ spec = File.read(gemspec_file)
290
+ regexp = Regexp.new('^(\s+\w+\.' + Regexp.quote(attribute.to_s) + '\s*=\s*)[^\s].*$')
291
+ if spec.sub!(regexp) { $1 + new_value }
292
+ File.open(gemspec_file, 'w') { |f| f << spec }
293
+ modified_files << gemspec_file
294
+
295
+ # Reload the gemspec so the changes are incorporated
296
+ load_gemspec!
297
+ end
298
+ end
299
+
300
+ # Updates the tasks file using the latest file found on Github
301
+ def update_tasks_task
302
+ require 'net/http'
303
+
304
+ server = 'github.com'
305
+ path = '/wvanbergen/github-gem/raw/master/tasks/github-gem.rake'
306
+
307
+ Net::HTTP.start(server) do |http|
308
+ response = http.get(path)
309
+ open(__FILE__, "w") { |file| file.write(response.body) }
310
+ end
311
+
312
+ relative_file = File.expand_path(__FILE__).sub(%r[^#{git.dir.path}/], '')
313
+ if git.status[relative_file] && git.status[relative_file].type == 'M'
314
+ git.add(relative_file)
315
+ git.commit("Updated to latest gem release management tasks.")
316
+ puts "Updated to latest version of gem release management tasks."
317
+ else
318
+ puts "Release managament tasks already are at the latest version."
319
+ end
320
+ end
321
+
322
+ end
323
+ end
@@ -0,0 +1,33 @@
1
+ $:.unshift("#{File.dirname(__FILE__)}/../lib")
2
+
3
+ require 'test/unit'
4
+ require 'clieop'
5
+
6
+ class ClieopWriterTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ def test_basic_invoice_usage
15
+ file = Clieop::File.new
16
+ file.invoice_batch({:description => 'some description', :account_nr => 123, :account_owner => 'me'}) do |batch|
17
+
18
+ batch << { :account_nr => 123456, :account_owner => 'you', :amount => 133.0,
19
+ :description => "Testing a CLIEOP direct debt transaction\nCharging your bank account" }
20
+
21
+ batch << { :account_nr => 654321, :account_owner => 'somebody else', :amount => 233.0,
22
+ :description => 'Some description for the other guy' }
23
+
24
+ end
25
+
26
+ clieop_data = file.to_clieop
27
+
28
+ #TODO: more tests
29
+ assert_kind_of String, clieop_data
30
+
31
+ end
32
+
33
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clieop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Willem van Bergen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-10 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: This library is a pure Ruby, MIT licensed implementation of the CLIEOP03 transaction format. CLIEOP03 can be used to communicate direct debt transactions with your (Dutch) bank.
17
+ email:
18
+ - willem@vanbergen.org
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - .gitignore
27
+ - lib/clieop/record.rb
28
+ - lib/clieop/file.rb
29
+ - lib/clieop/batch.rb
30
+ - lib/clieop.rb
31
+ - Rakefile
32
+ - MIT-LICENSE
33
+ - test/clieop_writer_test.rb
34
+ - tasks/github-gem.rake
35
+ - clieop.gemspec
36
+ - README.rdoc
37
+ has_rdoc: true
38
+ homepage: http://github.com/wvanbergen/clieop/wikis
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: A pure Ruby implementation to write CLIEOP files
65
+ test_files:
66
+ - test/clieop_writer_test.rb