paperless_to_xero 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Matt Patterson
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,3 +1,4 @@
1
+ require "rubygems"
1
2
  require 'rake'
2
3
  require 'rake/rdoctask'
3
4
  gem 'rspec'
@@ -39,101 +40,30 @@ namespace :spec do
39
40
  end
40
41
  end
41
42
 
42
- require "rubygems"
43
- require "rake/gempackagetask"
44
-
45
- # This builds the actual gem. For details of what all these options
46
- # mean, and other ones you can add, check the documentation here:
47
- #
48
- # http://rubygems.org/read/chapter/20
49
- #
50
- spec = Gem::Specification.new do |s|
51
-
52
- # Change these as appropriate
53
- s.name = "paperless_to_xero"
54
- s.version = PaperlessToXero::Version()
55
- s.summary = "Convert Paperless CSV exports to Xero invoice import CSV"
56
- s.description = File.read('README.rdoc')
57
- s.author = "Matt Patterson"
58
- s.email = "matt@reprocessed.org"
59
- s.homepage = "http://reprocessed.org/"
60
-
61
- s.has_rdoc = true
62
- s.extra_rdoc_files = %w(README.rdoc)
63
- s.rdoc_options = %w(--main README.rdoc)
64
-
65
- # Add any extra files to include in the gem
66
- s.files = %w(Rakefile README.rdoc) + Dir.glob("{bin,spec,lib}/**/*")
67
- s.executables = FileList["bin/**"].map { |f| File.basename(f) }
68
-
69
- s.require_paths = ["lib"]
70
-
71
- # If you want to depend on other gems, add them here, along with any
72
- # relevant versions
73
-
74
- s.add_development_dependency("rspec") # add any other gems for testing/development
43
+ begin
44
+ require 'jeweler'
45
+ Jeweler::Tasks.new do |s|
46
+ s.name = "paperless_to_xero"
47
+ s.summary = "Convert Paperless CSV exports to Xero invoice import CSV"
48
+ s.description = File.read('README.rdoc')
49
+ s.authors = ["Matt Patterson"]
50
+ s.email = "matt@reprocessed.org"
51
+ s.homepage = "http://github.com/fidothe/paperless_to_xero/"
52
+
53
+ s.extra_rdoc_files = %w(README.rdoc)
54
+ s.rdoc_options = %w(--main README.rdoc)
75
55
 
76
- # If you want to publish automatically to rubyforge, you'll may need
77
- # to tweak this, and the publishing task below too.
78
- s.rubyforge_project = "paperless_to_xero"
79
- end
56
+ s.require_paths = ["lib"]
80
57
 
81
- # This task actually builds the gem. We also regenerate a static
82
- # .gemspec file, which is useful if something (i.e. GitHub) will
83
- # be automatically building a gem for this project. If you're not
84
- # using GitHub, edit as appropriate.
85
- Rake::GemPackageTask.new(spec) do |pkg|
86
- pkg.gem_spec = spec
87
-
88
- # Generate the gemspec file for github.
89
- file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
90
- File.open(file, "w") {|f| f << spec.to_ruby }
91
- end
58
+ # If you want to depend on other gems, add them here, along with any
59
+ # relevant versions
92
60
 
93
- desc 'Clear out RDoc and generated packages'
94
- task :clean => [:clobber_rdoc, :clobber_package] do
95
- rm "#{spec.name}.gemspec"
96
- end
61
+ s.add_development_dependency("rspec") # add any other gems for testing/development
97
62
 
98
- # If you want to publish to RubyForge automatically, here's a simple
99
- # task to help do that. If you don't, just get rid of this.
100
- # Be sure to set up your Rubyforge account details with the Rubyforge
101
- # gem; you'll need to run `rubyforge setup` and `rubyforge config` at
102
- # the very least.
103
- begin
104
- require "rake/contrib/sshpublisher"
105
- namespace :rubyforge do
106
-
107
- desc "Release gem and RDoc documentation to RubyForge"
108
- task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
109
-
110
- namespace :release do
111
- desc "Release a new version of this gem"
112
- task :gem => [:package] do
113
- require 'rubyforge'
114
- rubyforge = RubyForge.new
115
- rubyforge.configure
116
- rubyforge.login
117
- rubyforge.userconfig['release_notes'] = spec.summary
118
- path_to_gem = File.join(File.dirname(__FILE__), "pkg", "#{spec.name}-#{spec.version}.gem")
119
- puts "Publishing #{spec.name}-#{spec.version.to_s} to Rubyforge..."
120
- rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version.to_s, path_to_gem)
121
- end
122
-
123
- desc "Publish RDoc to RubyForge."
124
- task :docs => [:rdoc] do
125
- config = YAML.load(
126
- File.read(File.expand_path('~/.rubyforge/user-config.yml'))
127
- )
128
-
129
- host = "#{config['username']}@rubyforge.org"
130
- remote_dir = "/var/www/gforge-projects/coop_to_ofx/" # Should be the same as the rubyforge project name
131
- local_dir = 'rdoc'
132
-
133
- Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
134
- end
135
- end
63
+ # If you want to publish automatically to rubyforge, you'll may need
64
+ # to tweak this, and the publishing task below too.
65
+ s.rubyforge_project = "paperless_to_xero"
136
66
  end
137
67
  rescue LoadError
138
- puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
68
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
139
69
  end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.2.0
@@ -1,8 +1,12 @@
1
1
  require 'csv'
2
2
  require 'date'
3
+ require 'paperless_to_xero/errors'
3
4
 
4
5
  module PaperlessToXero
6
+ PAPERLESS_HEADER_ROW = ["Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"]
5
7
  class Converter
8
+ VAT_RATE_CHANGE_2008_12_01 = Date.parse('2008-12-01')
9
+ VAT_RATE_CHANGE_2010_01_01 = Date.parse('2010-01-01')
6
10
  attr_reader :input_path, :output_path
7
11
 
8
12
  def initialize(input_path, output_path)
@@ -13,12 +17,17 @@ module PaperlessToXero
13
17
  @invoices ||= []
14
18
  end
15
19
 
20
+ def verify_header_row!(row)
21
+ raise UnknownHeaderRow unless row == PaperlessToXero::PAPERLESS_HEADER_ROW
22
+ end
23
+
16
24
  def parse
17
25
  input_csv = CSV.read(input_path)
18
- # remove Paperless header row
19
- input_csv.shift
26
+ # verify Paperless header row
27
+ verify_header_row!(input_csv.shift)
20
28
 
21
- input_csv.each do |row|
29
+ input_csv.each_with_index do |row, index|
30
+ line_number = index + 1
22
31
  date, merchant, paperless_currency, amount, vat, category, payment_method, notes_field, description, reference, status, *extras = row
23
32
  negative = amount.index('--') == 0
24
33
  category = category[0..2] unless category.nil?
@@ -30,17 +39,25 @@ module PaperlessToXero
30
39
  total_vat = vat.nil? ? "0.00" : vat
31
40
  invoice = PaperlessToXero::Invoice.new(extract_date(date), merchant, reference, amount, total_vat, inc_vat?(notes), extract_currency(notes))
32
41
  if extras.empty?
33
- invoice.add_item(description, amount, vat, category, extract_vat_note(vat, notes))
42
+ begin
43
+ invoice.add_item(description, amount, vat, category, extract_vat_note(invoice.date, vat, notes))
44
+ rescue
45
+ raise BadItem.new(line_number, row, "Couldn't process this item")
46
+ end
34
47
  else
35
- raise RangeError, "input CSV row is badly formatted" unless extras.size % 6 == 0
48
+ raise IncorrectNumberOfColumns.new(line_number, row, "Extra items are badly formatted") unless extras.size % 6 == 0
36
49
  items = chunk_extras(extras)
37
50
  items.each do |item|
38
- description, paperless_currency, amount, unknown, category, notes_field = item
39
- category = category[0..2]
40
- notes = extract_notes(notes_field)
41
- vat_amount = extract_vat_amount(notes)
42
- vat_note = extract_vat_note(vat_amount, notes)
43
- invoice.add_item(description, amount, vat_amount, category, vat_note)
51
+ begin
52
+ description, paperless_currency, amount, unknown, category, notes_field = item
53
+ category = category[0..2]
54
+ notes = extract_notes(notes_field)
55
+ vat_amount = extract_vat_amount(notes)
56
+ vat_note = extract_vat_note(invoice.date, vat_amount, notes)
57
+ invoice.add_item(description, amount, vat_amount, category, vat_note)
58
+ rescue
59
+ raise BadItem.new(line_number, row, "Couldn't process this item")
60
+ end
44
61
  end
45
62
  end
46
63
  invoices << invoice
@@ -117,7 +134,7 @@ module PaperlessToXero
117
134
  nil
118
135
  end
119
136
 
120
- def extract_vat_note(vat_amount, notes)
137
+ def extract_vat_note(date, vat_amount, notes)
121
138
  notes.each do |item|
122
139
  return item if item.match(/^VAT/)
123
140
  end
@@ -128,7 +145,8 @@ module PaperlessToXero
128
145
  when nil
129
146
  'No VAT'
130
147
  else
131
- 'VAT - 15%'
148
+ return 'VAT - 15%' if date >= VAT_RATE_CHANGE_2008_12_01 && date < VAT_RATE_CHANGE_2010_01_01
149
+ 'VAT - 17.5%'
132
150
  end
133
151
  end
134
152
  end
@@ -0,0 +1,15 @@
1
+ module PaperlessToXero
2
+ class UnknownHeaderRow < StandardError; end
3
+ class RowError < StandardError
4
+ def initialize(line_number, row, explanation = "")
5
+ @line_number, @row, @explanation = line_number, row, explanation
6
+ end
7
+
8
+ def to_s
9
+ "Error processing line #{@line_number.to_s}: #{@explanation}. Row was #{@row.inspect}"
10
+ end
11
+ end
12
+
13
+ class IncorrectNumberOfColumns < RowError; end
14
+ class BadItem < RowError; end
15
+ end
@@ -17,6 +17,7 @@ module PaperlessToXero
17
17
  '21.5% (Ireland, VAT on expenses)' => 1.215.to_d,
18
18
  '15% (EU VAT ID)' => 1.15.to_d,
19
19
  '15% (VAT on expenses)' => 1.15.to_d,
20
+ '17.5% (VAT on expenses)' => 1.175.to_d,
20
21
  'Zero Rated Expenses' => 0,
21
22
  '15% (Luxembourg, VAT on expenses)' => 1.15.to_d
22
23
  }
@@ -76,6 +77,8 @@ module PaperlessToXero
76
77
  '15% (EU VAT ID)'
77
78
  when 'VAT - 15%'
78
79
  '15% (VAT on expenses)'
80
+ when 'VAT - 17.5%'
81
+ '17.5% (VAT on expenses)'
79
82
  when 'VAT - 0%'
80
83
  'Zero Rated Expenses'
81
84
  when 'No VAT'
@@ -0,0 +1,91 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{paperless_to_xero}
8
+ s.version = "1.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matt Patterson"]
12
+ s.date = %q{2010-02-27}
13
+ s.default_executable = %q{paperless_to_xero}
14
+ s.description = %q{= Paperless-to-Xero
15
+
16
+ A simple translator which takes a CSV file from Mariner's Paperless receipt/document management software and makes a Xero accounts payable invoice CSV, for import into Xero.
17
+
18
+ Formatting in Paperless is very important, so you probably want to wait until I've written the docs}
19
+ s.email = %q{matt@reprocessed.org}
20
+ s.executables = ["paperless_to_xero"]
21
+ s.extra_rdoc_files = [
22
+ "README.rdoc"
23
+ ]
24
+ s.files = [
25
+ "MIT-LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bin/paperless_to_xero",
30
+ "lib/paperless_to_xero.rb",
31
+ "lib/paperless_to_xero/converter.rb",
32
+ "lib/paperless_to_xero/decimal_helpers.rb",
33
+ "lib/paperless_to_xero/errors.rb",
34
+ "lib/paperless_to_xero/invoice.rb",
35
+ "lib/paperless_to_xero/invoice_item.rb",
36
+ "lib/paperless_to_xero/version.rb",
37
+ "paperless_to_xero.gemspec",
38
+ "spec/fixtures/dodgy-header.csv",
39
+ "spec/fixtures/end_to_end-input.csv",
40
+ "spec/fixtures/end_to_end-output.csv",
41
+ "spec/fixtures/multi-ex-vat.csv",
42
+ "spec/fixtures/multi-foreign.csv",
43
+ "spec/fixtures/multi-item-mixed_vat_and_exempt.csv",
44
+ "spec/fixtures/multi-item.csv",
45
+ "spec/fixtures/single-1000.csv",
46
+ "spec/fixtures/single-basic.csv",
47
+ "spec/fixtures/single-dkk.csv",
48
+ "spec/fixtures/single-foreign.csv",
49
+ "spec/fixtures/single-no-vat.csv",
50
+ "spec/fixtures/single-vat-2008-11-30.csv",
51
+ "spec/fixtures/single-vat-2008-12-01.csv",
52
+ "spec/fixtures/single-vat-2009-12-31.csv",
53
+ "spec/fixtures/single-vat-2009.csv",
54
+ "spec/fixtures/single-vat-2010-01-01.csv",
55
+ "spec/fixtures/single-vat-pre-2008-12.csv",
56
+ "spec/fixtures/single-zero_rated.csv",
57
+ "spec/paperless_to_xero/converter_spec.rb",
58
+ "spec/paperless_to_xero/errors_spec.rb",
59
+ "spec/paperless_to_xero/invoice_item_spec.rb",
60
+ "spec/paperless_to_xero/invoice_spec.rb",
61
+ "spec/spec.opts",
62
+ "spec/spec_helper.rb"
63
+ ]
64
+ s.homepage = %q{http://github.com/fidothe/paperless_to_xero/}
65
+ s.rdoc_options = ["--main", "README.rdoc"]
66
+ s.require_paths = ["lib"]
67
+ s.rubyforge_project = %q{paperless_to_xero}
68
+ s.rubygems_version = %q{1.3.6}
69
+ s.summary = %q{Convert Paperless CSV exports to Xero invoice import CSV}
70
+ s.test_files = [
71
+ "spec/paperless_to_xero/converter_spec.rb",
72
+ "spec/paperless_to_xero/errors_spec.rb",
73
+ "spec/paperless_to_xero/invoice_item_spec.rb",
74
+ "spec/paperless_to_xero/invoice_spec.rb",
75
+ "spec/spec_helper.rb"
76
+ ]
77
+
78
+ if s.respond_to? :specification_version then
79
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
80
+ s.specification_version = 3
81
+
82
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
83
+ s.add_development_dependency(%q<rspec>, [">= 0"])
84
+ else
85
+ s.add_dependency(%q<rspec>, [">= 0"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<rspec>, [">= 0"])
89
+ end
90
+ end
91
+
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 26/01/2009,"Fastlane Cabs","£","4.50",,"493 - Travel National","Cash",,"Taxi in Nottingham","2009-01-26-03",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 23/07/2009,"Post Office","£","3.55","0.29","425 - Postage, Freight & Courier","Credit Card",,,"2009-07-23-03",,"Envelopes","£","2.19",,"429 - General Expenses","0.29; VAT - 15%","Postage","£","1.36",,"425 - Postage, Freight & Courier","VAT - 0%"
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 30/11/2008,"Apple Store, Regent Street","£","117.50","17.50","429 - General Expenses","Debit Card",,"Phone case","2008-11-30-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 01/12/2008,"Apple Store, Regent Street","£","115","15","429 - General Expenses","Debit Card",,"Phone case","2008-12-01-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 31/12/2009,"Apple Store, Regent Street","£","115","15","429 - General Expenses","Debit Card",,"Phone case","2009-12-31-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 01/06/2009,"Apple Store, Regent Street","£","115","15","429 - General Expenses","Debit Card",,"Phone case","2009-06-01-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 01/01/2010,"Apple Store, Regent Street","£","117.50","17.50","429 - General Expenses","Debit Card",,"Phone case","2010-01-01-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 18/05/2008,"Apple Store, Regent Street","£","117.50","17.50","429 - General Expenses","Debit Card",,"Phone case","2008-05-18-05",
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
  require 'tempfile'
3
3
 
4
4
  Spec::Matchers.define :have_detail_matching do |key, value|
@@ -48,6 +48,13 @@ describe PaperlessToXero::Converter do
48
48
  end
49
49
  end
50
50
 
51
+ describe "checking the header row" do
52
+ it "should raise an UnknownHeaderRow error if it doesn't recognise the header..." do
53
+ @converter.stubs(:input_path).returns(fixture_path('dodgy-header'))
54
+ lambda { @converter.parse }.should raise_error(PaperlessToXero::UnknownHeaderRow)
55
+ end
56
+ end
57
+
51
58
  describe "single item inputs" do
52
59
  it "should able to create an invoice for a basic single-item invoice" do
53
60
  @converter.stubs(:input_path).returns(fixture_path('single-basic'))
@@ -133,6 +140,110 @@ describe PaperlessToXero::Converter do
133
140
  ]
134
141
  )
135
142
  end
143
+
144
+ describe "UK VAT rate changes" do
145
+ describe "pre 2008-12 17.5% VAT" do
146
+ it "correctly handles days in that VAT rate" do
147
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-pre-2008-12'))
148
+ @converter.parse
149
+
150
+ verify_invoice_details(
151
+ :invoice => {:date => Date.parse('2008-05-18'), :merchant => 'Apple Store, Regent Street',
152
+ :reference_id => '2008-05-18-05', :inc_vat_total => '117.50', :vat_total => '17.50',
153
+ :ex_vat_total => '100.00', :currency => 'GBP'},
154
+ :vat_inclusive => true,
155
+ :line_items => [
156
+ {:description => 'Phone case', :category => '429', :vat_type => '17.5% (VAT on expenses)',
157
+ :vat_inclusive_amount => '117.50', :vat_exclusive_amount => '100.00', :vat_amount => '17.50'}
158
+ ]
159
+ )
160
+ end
161
+
162
+ it "correctly handles the last day of that VAT rate" do
163
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2008-11-30'))
164
+ @converter.parse
165
+
166
+ verify_invoice_details(
167
+ :invoice => {:date => Date.parse('2008-11-30'), :merchant => 'Apple Store, Regent Street',
168
+ :reference_id => '2008-11-30-05', :inc_vat_total => '117.50', :vat_total => '17.50',
169
+ :ex_vat_total => '100.00', :currency => 'GBP'},
170
+ :vat_inclusive => true,
171
+ :line_items => [
172
+ {:description => 'Phone case', :category => '429', :vat_type => '17.5% (VAT on expenses)',
173
+ :vat_inclusive_amount => '117.50', :vat_exclusive_amount => '100.00', :vat_amount => '17.50'}
174
+ ]
175
+ )
176
+ end
177
+ end
178
+
179
+ describe "2009's 15% VAT rate" do
180
+ it "correctly handles the first day of that VAT rate" do
181
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2008-12-01'))
182
+ @converter.parse
183
+
184
+ verify_invoice_details(
185
+ :invoice => {:date => Date.parse('2008-12-01'), :merchant => 'Apple Store, Regent Street',
186
+ :reference_id => '2008-12-01-05', :inc_vat_total => '115.00', :vat_total => '15.00',
187
+ :ex_vat_total => '100.00', :currency => 'GBP'},
188
+ :vat_inclusive => true,
189
+ :line_items => [
190
+ {:description => 'Phone case', :category => '429', :vat_type => '15% (VAT on expenses)',
191
+ :vat_inclusive_amount => '115.00', :vat_exclusive_amount => '100.00', :vat_amount => '15.00'}
192
+ ]
193
+ )
194
+ end
195
+
196
+ it "correctly handles days in that VAT rate" do
197
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2009'))
198
+ @converter.parse
199
+
200
+ verify_invoice_details(
201
+ :invoice => {:date => Date.parse('2009-06-01'), :merchant => 'Apple Store, Regent Street',
202
+ :reference_id => '2009-06-01-05', :inc_vat_total => '115.00', :vat_total => '15.00',
203
+ :ex_vat_total => '100.00', :currency => 'GBP'},
204
+ :vat_inclusive => true,
205
+ :line_items => [
206
+ {:description => 'Phone case', :category => '429', :vat_type => '15% (VAT on expenses)',
207
+ :vat_inclusive_amount => '115.00', :vat_exclusive_amount => '100.00', :vat_amount => '15.00'}
208
+ ]
209
+ )
210
+ end
211
+
212
+ it "correctly handles the last day of that VAT rate" do
213
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2009-12-31'))
214
+ @converter.parse
215
+
216
+ verify_invoice_details(
217
+ :invoice => {:date => Date.parse('2009-12-31'), :merchant => 'Apple Store, Regent Street',
218
+ :reference_id => '2009-12-31-05', :inc_vat_total => '115.00', :vat_total => '15.00',
219
+ :ex_vat_total => '100.00', :currency => 'GBP'},
220
+ :vat_inclusive => true,
221
+ :line_items => [
222
+ {:description => 'Phone case', :category => '429', :vat_type => '15% (VAT on expenses)',
223
+ :vat_inclusive_amount => '115.00', :vat_exclusive_amount => '100.00', :vat_amount => '15.00'}
224
+ ]
225
+ )
226
+ end
227
+ end
228
+
229
+ describe "2010-01-01's return to 17.5% VAT" do
230
+ it "correctly handles the first day of that VAT rate" do
231
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2010-01-01'))
232
+ @converter.parse
233
+
234
+ verify_invoice_details(
235
+ :invoice => {:date => Date.parse('2010-01-01'), :merchant => 'Apple Store, Regent Street',
236
+ :reference_id => '2010-01-01-05', :inc_vat_total => '117.50', :vat_total => '17.50',
237
+ :ex_vat_total => '100.00', :currency => 'GBP'},
238
+ :vat_inclusive => true,
239
+ :line_items => [
240
+ {:description => 'Phone case', :category => '429', :vat_type => '17.5% (VAT on expenses)',
241
+ :vat_inclusive_amount => '117.50', :vat_exclusive_amount => '100.00', :vat_amount => '17.50'}
242
+ ]
243
+ )
244
+ end
245
+ end
246
+ end
136
247
  end
137
248
 
138
249
  describe "multi-item inputs" do
@@ -192,6 +303,24 @@ describe PaperlessToXero::Converter do
192
303
  ]
193
304
  )
194
305
  end
306
+
307
+ it "should be able to cope with an multi-line invoice with mixed VAT and VAT-exempt lines" do
308
+ @converter.stubs(:input_path).returns(fixture_path('multi-item-mixed_vat_and_exempt'))
309
+ @converter.parse
310
+
311
+ verify_invoice_details(
312
+ :invoice => {:date => Date.parse('2009-07-23'), :merchant => 'Post Office',
313
+ :reference_id => '2009-07-23-03', :inc_vat_total => '3.55', :vat_total => '0.29',
314
+ :ex_vat_total => '3.26', :currency => 'GBP'},
315
+ :vat_inclusive => false,
316
+ :line_items => [
317
+ {:description => 'Envelopes', :category => '429', :vat_type => '15% (VAT on expenses)',
318
+ :vat_inclusive_amount => '2.19', :vat_exclusive_amount => '1.90', :vat_amount => '0.29'},
319
+ {:description => 'Postage', :category => '425', :vat_type => 'Zero Rated Expenses',
320
+ :vat_inclusive_amount => '1.36', :vat_exclusive_amount => '1.36', :vat_amount => '0.00'}
321
+ ]
322
+ )
323
+ end
195
324
  end
196
325
 
197
326
  describe "end-to-end" do
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe PaperlessToXero::RowError do
4
+ it "should be able to be instantiated with the line number, row contents and error message" do
5
+ PaperlessToXero::RowError.new(1, ["thing", "other thing"], "Bad thing happened").should be_instance_of(PaperlessToXero::RowError)
6
+ end
7
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe PaperlessToXero::InvoiceItem do
4
4
  describe "the creation basics" do
@@ -144,6 +144,7 @@ describe PaperlessToXero::InvoiceItem do
144
144
  'VAT - Luxembourg' => '15% (Luxembourg, VAT on expenses)',
145
145
  'VAT - EU' => '15% (EU VAT ID)',
146
146
  'VAT - EU - EU372000063' => '15% (EU VAT ID)',
147
+ 'VAT - 17.5%' => '17.5% (VAT on expenses)',
147
148
  'VAT - 15%' => '15% (VAT on expenses)',
148
149
  'VAT - 0%' => 'Zero Rated Expenses',
149
150
  'VAT' => '15% (VAT on expenses)',
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe PaperlessToXero::Invoice do
4
4
  describe "the creation basics" do
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paperless_to_xero
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 2
8
+ - 0
9
+ version: 1.2.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Matt Patterson
@@ -9,19 +14,21 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-07-22 00:00:00 +01:00
13
- default_executable:
17
+ date: 2010-02-27 00:00:00 +00:00
18
+ default_executable: paperless_to_xero
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: rspec
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
23
29
  version: "0"
24
- version:
30
+ type: :development
31
+ version_requirements: *id001
25
32
  description: |-
26
33
  = Paperless-to-Xero
27
34
 
@@ -36,33 +43,46 @@ extensions: []
36
43
  extra_rdoc_files:
37
44
  - README.rdoc
38
45
  files:
39
- - Rakefile
46
+ - MIT-LICENSE
40
47
  - README.rdoc
48
+ - Rakefile
49
+ - VERSION
41
50
  - bin/paperless_to_xero
51
+ - lib/paperless_to_xero.rb
52
+ - lib/paperless_to_xero/converter.rb
53
+ - lib/paperless_to_xero/decimal_helpers.rb
54
+ - lib/paperless_to_xero/errors.rb
55
+ - lib/paperless_to_xero/invoice.rb
56
+ - lib/paperless_to_xero/invoice_item.rb
57
+ - lib/paperless_to_xero/version.rb
58
+ - paperless_to_xero.gemspec
59
+ - spec/fixtures/dodgy-header.csv
42
60
  - spec/fixtures/end_to_end-input.csv
43
61
  - spec/fixtures/end_to_end-output.csv
44
62
  - spec/fixtures/multi-ex-vat.csv
45
63
  - spec/fixtures/multi-foreign.csv
64
+ - spec/fixtures/multi-item-mixed_vat_and_exempt.csv
46
65
  - spec/fixtures/multi-item.csv
47
66
  - spec/fixtures/single-1000.csv
48
67
  - spec/fixtures/single-basic.csv
49
68
  - spec/fixtures/single-dkk.csv
50
69
  - spec/fixtures/single-foreign.csv
51
70
  - spec/fixtures/single-no-vat.csv
71
+ - spec/fixtures/single-vat-2008-11-30.csv
72
+ - spec/fixtures/single-vat-2008-12-01.csv
73
+ - spec/fixtures/single-vat-2009-12-31.csv
74
+ - spec/fixtures/single-vat-2009.csv
75
+ - spec/fixtures/single-vat-2010-01-01.csv
76
+ - spec/fixtures/single-vat-pre-2008-12.csv
52
77
  - spec/fixtures/single-zero_rated.csv
53
78
  - spec/paperless_to_xero/converter_spec.rb
79
+ - spec/paperless_to_xero/errors_spec.rb
54
80
  - spec/paperless_to_xero/invoice_item_spec.rb
55
81
  - spec/paperless_to_xero/invoice_spec.rb
56
82
  - spec/spec.opts
57
83
  - spec/spec_helper.rb
58
- - lib/paperless_to_xero/converter.rb
59
- - lib/paperless_to_xero/decimal_helpers.rb
60
- - lib/paperless_to_xero/invoice.rb
61
- - lib/paperless_to_xero/invoice_item.rb
62
- - lib/paperless_to_xero/version.rb
63
- - lib/paperless_to_xero.rb
64
84
  has_rdoc: true
65
- homepage: http://reprocessed.org/
85
+ homepage: http://github.com/fidothe/paperless_to_xero/
66
86
  licenses: []
67
87
 
68
88
  post_install_message:
@@ -75,20 +95,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
95
  requirements:
76
96
  - - ">="
77
97
  - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
78
100
  version: "0"
79
- version:
80
101
  required_rubygems_version: !ruby/object:Gem::Requirement
81
102
  requirements:
82
103
  - - ">="
83
104
  - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
84
107
  version: "0"
85
- version:
86
108
  requirements: []
87
109
 
88
110
  rubyforge_project: paperless_to_xero
89
- rubygems_version: 1.3.4
111
+ rubygems_version: 1.3.6
90
112
  signing_key:
91
113
  specification_version: 3
92
114
  summary: Convert Paperless CSV exports to Xero invoice import CSV
93
- test_files: []
94
-
115
+ test_files:
116
+ - spec/paperless_to_xero/converter_spec.rb
117
+ - spec/paperless_to_xero/errors_spec.rb
118
+ - spec/paperless_to_xero/invoice_item_spec.rb
119
+ - spec/paperless_to_xero/invoice_spec.rb
120
+ - spec/spec_helper.rb